Coverage for ingadhoc-account-payment / account_payment_pro / models / account_move.py: 41%
39 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 19:54 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 19:54 +0000
1# © 2016 ADHOC SA
2# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
4from odoo import Command, api, fields, models
7class AccountMove(models.Model):
8 _inherit = "account.move"
10 open_move_line_ids = fields.One2many("account.move.line", compute="_compute_open_move_lines")
11 pay_now_journal_id = fields.Many2one(
12 "account.journal",
13 "Pay now Journal",
14 help="If you set a journal here, after invoice validation, the invoice"
15 " will be automatically paid with this journal. As manual payment"
16 "method is used, only journals with manual method are shown.",
17 # use copy false for two reasons:
18 # 1. when making refund it's safer to make pay now empty (specially if automatic refund validation is enable)
19 # 2. on duplicating an invoice it's safer also
20 copy=False,
21 )
23 @api.depends("line_ids.account_id.account_type", "line_ids.reconciled")
24 def _compute_open_move_lines(self):
25 for rec in self:
26 rec.open_move_line_ids = rec.line_ids.filtered(
27 lambda r: not r.reconciled
28 and r.parent_state == "posted"
29 and r.account_id.account_type in self.env["account.payment"]._get_valid_payment_account_types()
30 )
32 def pay_now(self):
33 for rec in self.filtered( 33 ↛ 36line 33 didn't jump to line 36 because the loop on line 33 never started
34 lambda x: x.pay_now_journal_id and x.state == "posted" and x.payment_state in ("not_paid", "patial")
35 ):
36 pay_journal = rec.pay_now_journal_id
37 if rec.move_type in ["in_invoice", "in_refund"]:
38 partner_type = "supplier"
39 else:
40 partner_type = "customer"
42 payment_type = "inbound"
43 payment_method = pay_journal._get_manual_payment_method_id(payment_type)
45 payment = (
46 rec.env["account.payment"]
47 .with_context(pay_now=True)
48 .create(
49 {
50 "date": rec.invoice_date,
51 "partner_id": rec.commercial_partner_id.id,
52 "partner_type": partner_type,
53 "payment_type": payment_type,
54 "company_id": rec.company_id.id,
55 "journal_id": pay_journal.id,
56 "payment_method_id": payment_method.id,
57 "to_pay_move_line_ids": [Command.set(rec.open_move_line_ids.ids)],
58 "memo": rec.payment_reference,
59 }
60 )
61 )
63 # compute payment_difference here to avoid lazy evaluation issues
64 difference = payment.payment_difference
66 # el difference es positivo para facturas (de cliente o proveedor) pero negativo para NC.
67 # para factura de proveedor o NC de cliente es outbound
68 # para factura de cliente o NC de proveedor es inbound
69 # igualmente lo hacemos con el difference y no con el type por las dudas de que facturas en negativo
70 if partner_type == "supplier" and difference >= 0.0 or partner_type == "customer" and difference < 0.0:
71 payment.payment_type = "outbound"
72 payment.payment_method_id = pay_journal._get_manual_payment_method_id(payment_type).id
74 payment.amount = abs(difference)
75 payment.action_post()
76 rec.write({"matched_payment_ids": [(4, payment.id)]})
78 @api.onchange("journal_id")
79 def _onchange_journal_reset_pay_now(self):
80 # while not always it should be reseted (only if changing company) it's not so usual to set pay now first
81 # and then change journal
82 self.pay_now_journal_id = False
84 def button_draft(self):
85 self.filtered(lambda x: x.state == "posted" and x.pay_now_journal_id).write({"pay_now_journal_id": False})
86 return super().button_draft()
88 def _post(self, soft=False):
89 res = super()._post(soft=soft)
90 self.pay_now()
91 return res
93 def _search_default_journal(self):
94 if self.env.context.get("default_company_id"):
95 self.env = self.env(context=dict(self.env.context, allowed_company_ids=self.company_id.ids))
96 return super()._search_default_journal()