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

1# © 2016 ADHOC SA 

2# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 

3 

4from odoo import Command, api, fields, models 

5 

6 

7class AccountMove(models.Model): 

8 _inherit = "account.move" 

9 

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 ) 

22 

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 ) 

31 

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" 

41 

42 payment_type = "inbound" 

43 payment_method = pay_journal._get_manual_payment_method_id(payment_type) 

44 

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 ) 

62 

63 # compute payment_difference here to avoid lazy evaluation issues 

64 difference = payment.payment_difference 

65 

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 

73 

74 payment.amount = abs(difference) 

75 payment.action_post() 

76 rec.write({"matched_payment_ids": [(4, payment.id)]}) 

77 

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 

83 

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() 

87 

88 def _post(self, soft=False): 

89 res = super()._post(soft=soft) 

90 self.pay_now() 

91 return res 

92 

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()