From a6c1d582edacfba4d37e7d2bcd33902dd7c4812b Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Mon, 9 Mar 2026 14:49:36 +0700 Subject: [PATCH] feat: Enable cross-company batch payments by overriding payment constraints, adjusting payment creation logic, and updating views to support multi-company contexts, while also adding a payment search debug logger. --- __pycache__/__init__.cpython-312.pyc | Bin 287 -> 269 bytes data/__pycache__/__init__.cpython-312.pyc | Bin 174 -> 185 bytes doc/__pycache__/__init__.cpython-312.pyc | Bin 173 -> 184 bytes models/__init__.py | 3 +- models/__pycache__/__init__.cpython-312.pyc | Bin 341 -> 368 bytes .../account_batch_payment.cpython-312.pyc | Bin 6696 -> 9805 bytes .../account_payment.cpython-312.pyc | Bin 2273 -> 2255 bytes models/account_batch_payment.py | 56 +++++++++++++++++- models/account_payment_debug.py | 22 +++++++ views/account_batch_payment_views.xml | 10 ++++ 10 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 models/account_payment_debug.py diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc index d6c2f9a82019a5d0c5ef621545b3031d7ae31dfb..fee86a419eed482e77a4305c4edc8a37ec3867e4 100644 GIT binary patch delta 37 rcmbQw)XT(unwOW00SI&ooF;NN^9Ac?zMG%qg~0}!ldIhQe!$4J>X#VV$tvLquvFF8LYH6}kLKi|+iCb_h@BtJJX XB_%(vIA&sw6kAM6Vo74m#2#G${%04y diff --git a/doc/__pycache__/__init__.cpython-312.pyc b/doc/__pycache__/__init__.cpython-312.pyc index 15b342d3c4aa06ba85793f9bb4183539c614b21a..990f4b80e27170490131569326950c7f7c5823f9 100644 GIT binary patch delta 79 zcmZ3>xPy`BG%qg~0}vP#IAu=cG13dy&&bbB)h{m1NG(dK)DNgE$;i)3&QD3z&riwE hH#FBzE-fy}&rM88$=g)jQreG v{o>M$)S{HiiFYHExq-rrKwK;cBt9@RGBQ48P`=9`dzV4&9)ofbCr}gsA518I delta 131 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 delta 1592 zcmZ8hOKclO7@o1$>-A&(w&Qo~q)BR;M-#Qsg4L!WG!P|eKtfG}Dr>vDjh))N>3A)0 zmCzo7C~&B%|3DKEm5{h_KwMH9KgTkUz&yQG%% zQpq;C|1p0nV1L7oF|6|U;B#jjNos+t z-YBa?Y4$fISwAyelNKbcU)K983jFE0fm862_hKwWDM^%yI!i^4v@tynMR5%0VOh-M z1biqy7Yb6d>7LgcM3bsCu_Oc7*R!8pnq-);0=%uv8_flkgsHt?H#tqJ?J6V-GrlFe zo8(~2cbLmkKji&`!3Taxmi2~a^gqPI>;4n|jOkXjdV{DXT~jIaC;tpR(vd((o2`H9_VzuOe%&78-Wp;+dy!R&#}NRSPG`{MHY_Lx{uDe{|xK$ zW*UA8rs2Eb5YH}9pSmT6e#STse}qdQN7_51p0w}s#C8(3rQR-IE#Gb5zZo0+K6Yp` zcIeCWx3S}w$F?99-Nz5cUHk4m4pY(9{OyEi!sotS3`~U4ov>>%V!xB_pY+=|{0_RF zDhM!=8R;V@=zcd5NziHc9b9b11pDfbQL&7+{N0zH-R2>aO}g%TU&4+#OcHQ5o5f$i zYuVGGb@!T$2GTJr*pTX&53y45dlbjI_mRg93+)MysQ45=wFlNXD7JTp)+3La%xgiD z3>uD7%7=Y2>$B`xW_QFWc@{QfVVncOmA1_W8EacyNl?z@BdQREgy;7%NGjDLQqs$4 zZTFaHHrmV-vapa#Vh_BPD@II#sOKBBaTQb0HASte^ex}Z$6`dJ5R*SvW5rUi5%z@S z6l~^);R9O$QXSRPyGD~&^qN%BOm32v#RYGx{YNE3eTXxiih5RRR1MNcSuO;}R9a=! zt+f6XtvGrZNzt`xlXSxmxdi;$(UBgpUHLYeLtObaJ#nAl9Wl5V; ziOOs*GVxFSon$H#=jm7f3&F&mqHD*&h4@S3+iv(|&vCDRX2;1T`MX?<8n~`=yoEjq zjjr*7))hx6)O1Yh^ck&Ew)p1tP#dr>1>%QK*(z}B!WoOzx SfP>f0UaziHe?xR>9rJJ7v5b=d diff --git a/models/__pycache__/account_payment.cpython-312.pyc b/models/__pycache__/account_payment.cpython-312.pyc index 2a5f2c0de856f077a52388665b6a8ec2380a122d..e0107a29c5c99a0a0051e0cdbadaefaee1b5d781 100644 GIT binary patch delta 40 ucmaDTcwUhEG%qg~0}$vJIBn#PW#LQI&&bbB)h{m1NG(dK+}yzu$pQf501M#& delta 58 zcmX>v_)w7hG%qg~0}%XJBDRq`mPMghKO;XkRlm42Bef`{Qm-;GIX}rEH?bfwPcJ!N MFEeFx8A~J!03>G 1: + raise ValidationError(_("All payments in the batch must share the same payment method.")) + if all_payment_methods and record.payment_method_id not in all_payment_methods: + raise ValidationError(_("The batch must have the same payment method as the payments it contains.")) + payment_null = record.payment_ids.filtered(lambda p: p.amount == 0) + if payment_null: + raise ValidationError(_('You cannot add payments with zero amount in a Batch Payment.')) + non_posted = record.payment_ids.filtered(lambda p: p.state != 'posted') + if non_posted: + raise ValidationError(_('You cannot add payments that are not posted.')) + class AccountBatchPaymentLine(models.Model): _name = "account.batch.payment.line" @@ -120,9 +165,15 @@ class AccountBatchPaymentLine(models.Model): required=True, ondelete='cascade' ) + company_id = fields.Many2one( + 'res.company', + string='Company', + default=lambda self: self.env.company + ) partner_id = fields.Many2one( 'res.partner', - string='Partner' + string='Partner', + check_company=True # Removed required=True to avoid constraint issues ) amount = fields.Monetary( @@ -138,6 +189,7 @@ class AccountBatchPaymentLine(models.Model): expense_account_id = fields.Many2one( 'account.account', string='Expense Account', + check_company=True, domain="[('account_type', 'not in', ('asset_receivable', 'liability_payable'))]" ) memo = fields.Char(string='Memo') diff --git a/models/account_payment_debug.py b/models/account_payment_debug.py new file mode 100644 index 0000000..1b014aa --- /dev/null +++ b/models/account_payment_debug.py @@ -0,0 +1,22 @@ +import logging +from odoo import models, api + +_logger = logging.getLogger(__name__) + +class AccountPayment(models.Model): + _inherit = "account.payment" + + @api.model + def search(self, args, offset=0, limit=None, order=None, count=False): + try: + with open('/tmp/odoo_payment_search.log', 'a') as f: + f.write(f"\\n{'='*40}\\n") + f.write(f"ACCOUNT PAYMENT SEARCH CALLED\\n") + f.write(f"Args: {args}\\n") + f.write(f"Context: {self.env.context}\\n") + f.write(f"{'='*40}\\n") + except Exception as e: + _logger.error(f"Failed to log to /tmp: {e}") + + return super(AccountPayment, self).search(args, offset, limit, order, count) + diff --git a/views/account_batch_payment_views.xml b/views/account_batch_payment_views.xml index 03b5cfd..6d7ee3b 100644 --- a/views/account_batch_payment_views.xml +++ b/views/account_batch_payment_views.xml @@ -9,6 +9,7 @@ + @@ -23,6 +24,15 @@