[MIG] sale_down_payment to v14
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
# Copyright 2019 Akretion France (http://www.akretion.com)
|
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
|
||||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Sale Down Payment',
|
'name': 'Sale Down Payment',
|
||||||
'version': '12.0.1.0.0',
|
'version': '14.0.1.0.0',
|
||||||
'category': 'Sales',
|
'category': 'Sales',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
'summary': 'Link payment to sale orders',
|
'summary': 'Link payment to sale orders',
|
||||||
@@ -14,7 +14,7 @@ Sale Down Payment
|
|||||||
|
|
||||||
This module adds a link between payments and sale orders. It allows to see down payments directly on the sale order form view.
|
This module adds a link between payments and sale orders. It allows to see down payments directly on the sale order form view.
|
||||||
|
|
||||||
After processing a bank statement, you can start a wizard to link unreconciled incoming payments to a sale order. There is also a button *Register Payment* on the sale order.
|
After processing a bank statement, you can start a wizard to link unreconciled incoming payments to a sale order (NOT ported to v14 so far). There is also a button *Register Payment* on the sale order.
|
||||||
|
|
||||||
This module targets B2B companies that don't want to generate a down payment invoice for an advanced payment.
|
This module targets B2B companies that don't want to generate a down payment invoice for an advanced payment.
|
||||||
|
|
||||||
@@ -25,11 +25,13 @@ This module has been written by Alexis de Lattre from Akretion
|
|||||||
'website': 'http://www.akretion.com',
|
'website': 'http://www.akretion.com',
|
||||||
'depends': ['sale'],
|
'depends': ['sale'],
|
||||||
'data': [
|
'data': [
|
||||||
'wizard/account_bank_statement_sale_view.xml',
|
'security/ir.model.access.csv',
|
||||||
'views/account_bank_statement.xml',
|
'wizard/account_payment_register_sale_view.xml',
|
||||||
|
# 'wizard/account_bank_statement_sale_view.xml',
|
||||||
|
# 'views/account_bank_statement.xml',
|
||||||
'views/sale.xml',
|
'views/sale.xml',
|
||||||
'views/account_move_line.xml',
|
'views/account_move_line.xml',
|
||||||
'views/account_payment.xml',
|
'views/account_payment.xml',
|
||||||
],
|
],
|
||||||
'installable': False,
|
'installable': True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
from . import sale
|
from . import sale
|
||||||
|
from . import account_move
|
||||||
from . import account_move_line
|
from . import account_move_line
|
||||||
from . import account_payment
|
from . import account_payment
|
||||||
|
|||||||
26
sale_down_payment/models/account_move.py
Normal file
26
sale_down_payment/models/account_move.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Copyright 2023-2024 Akretion France (http://www.akretion.com)
|
||||||
|
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import models
|
||||||
|
|
||||||
|
|
||||||
|
class AccountMove(models.Model):
|
||||||
|
_inherit = 'account.move'
|
||||||
|
|
||||||
|
def _post(self, soft=True):
|
||||||
|
res = super()._post(soft=soft)
|
||||||
|
amlo = self.env['account.move.line']
|
||||||
|
for move in self:
|
||||||
|
if move.state == 'posted' and move.move_type == 'out_invoice':
|
||||||
|
sales = move.invoice_line_ids.sale_line_ids.order_id
|
||||||
|
if sales:
|
||||||
|
mlines = amlo.search([('sale_id', 'in', sales.ids)])
|
||||||
|
if mlines:
|
||||||
|
mlines_to_reconcile = move.line_ids.filtered(
|
||||||
|
lambda line: line.account_id ==
|
||||||
|
move.commercial_partner_id.property_account_receivable_id)
|
||||||
|
mlines_to_reconcile |= mlines
|
||||||
|
mlines_to_reconcile.remove_move_reconcile()
|
||||||
|
mlines_to_reconcile.reconcile()
|
||||||
|
return res
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2019 Akretion France (http://www.akretion.com)
|
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
|
||||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
@@ -9,24 +9,23 @@ from odoo.exceptions import ValidationError
|
|||||||
class AccountMoveLine(models.Model):
|
class AccountMoveLine(models.Model):
|
||||||
_inherit = 'account.move.line'
|
_inherit = 'account.move.line'
|
||||||
|
|
||||||
sale_id = fields.Many2one('sale.order', string='Sale Order')
|
sale_id = fields.Many2one(
|
||||||
account_internal_type = fields.Selection(
|
'sale.order', string='Sale Order', check_company=True,
|
||||||
related='account_id.user_type_id.type', store=True,
|
domain="[('partner_invoice_id', 'child_of', partner_id), ('state', '!=', 'cancel'), ('invoice_status', '!=', 'invoiced'), ('company_id', '=', company_id)]")
|
||||||
string='Account Internal Type')
|
|
||||||
|
|
||||||
@api.constrains('sale_id', 'account_id')
|
@api.constrains('sale_id', 'account_id')
|
||||||
def sale_id_check(self):
|
def _sale_id_check(self):
|
||||||
for line in self:
|
for line in self:
|
||||||
if line.sale_id and line.account_id.internal_type != 'receivable':
|
if line.sale_id and line.account_internal_type != 'receivable':
|
||||||
raise ValidationError(_(
|
raise ValidationError(_(
|
||||||
"The account move line '%s' is linked to sale order '%s' "
|
"The account move line '%s' is linked to sale order '%s' "
|
||||||
"but it uses account '%s' which is not a receivable "
|
"but it uses account '%s' which is not a receivable "
|
||||||
"account.")
|
"account.")
|
||||||
% (line.name,
|
% (line.display_name,
|
||||||
line.sale_id.name,
|
line.sale_id.display_name,
|
||||||
line.account_id.display_name))
|
line.account_id.display_name))
|
||||||
|
|
||||||
@api.onchange('account_id')
|
@api.onchange('account_id')
|
||||||
def sale_advance_payement_account_id_change(self):
|
def sale_advance_payement_account_id_change(self):
|
||||||
if self.sale_id and self.account_id.user_type_id.type != 'receivable':
|
if self.sale_id and self.account_internal_type != 'receivable':
|
||||||
self.sale_id = False
|
self.sale_id = False
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# Copyright 2019 Akretion France (http://www.akretion.com)
|
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
|
||||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import fields, models
|
from odoo import fields, models
|
||||||
from odoo.tools import float_round
|
|
||||||
|
|
||||||
|
|
||||||
class AccountPayment(models.Model):
|
class AccountPayment(models.Model):
|
||||||
@@ -11,49 +10,24 @@ class AccountPayment(models.Model):
|
|||||||
|
|
||||||
sale_id = fields.Many2one('sale.order', string='Sale Order')
|
sale_id = fields.Many2one('sale.order', string='Sale Order')
|
||||||
|
|
||||||
def action_validate_invoice_payment(self):
|
def _prepare_move_line_default_vals(self, write_off_line_vals=None):
|
||||||
if self.sale_id:
|
line_vals_list = super()._prepare_move_line_default_vals(
|
||||||
self.post()
|
write_off_line_vals=write_off_line_vals)
|
||||||
else:
|
# Add to the receivable/payable line
|
||||||
return super(AccountPayment, self).\
|
|
||||||
action_validate_invoice_payment()
|
|
||||||
|
|
||||||
def _get_counterpart_move_line_vals(self, invoice=False):
|
|
||||||
res = super(AccountPayment, self)._get_counterpart_move_line_vals(
|
|
||||||
invoice=invoice)
|
|
||||||
if self.sale_id:
|
|
||||||
res['sale_id'] = self.sale_id.id
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
class AccountAbstractPayment(models.AbstractModel):
|
|
||||||
_inherit = "account.abstract.payment"
|
|
||||||
|
|
||||||
def default_get(self, fields_list):
|
|
||||||
res = super(AccountAbstractPayment, self).default_get(fields_list)
|
|
||||||
if (
|
if (
|
||||||
self._context.get('active_model') == 'sale.order' and
|
self.sale_id and
|
||||||
self._context.get('active_id')):
|
len(line_vals_list) >= 2 and
|
||||||
so = self.env['sale.order'].browse(self._context['active_id'])
|
line_vals_list[1].get('account_id') == self.destination_account_id.id):
|
||||||
res.update({
|
line_vals_list[1]['sale_id'] = self.sale_id.id
|
||||||
'amount': so.amount_total,
|
return line_vals_list
|
||||||
'currency_id': so.currency_id.id,
|
|
||||||
'payment_type': 'inbound',
|
|
||||||
'partner_id': so.partner_invoice_id.commercial_partner_id.id,
|
|
||||||
'partner_type': 'customer',
|
|
||||||
'communication': so.name,
|
|
||||||
'sale_id': so.id,
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _compute_payment_amount(self, invoices=None, currency=None):
|
def action_post(self):
|
||||||
amount = super(AccountAbstractPayment, self)._compute_payment_amount(
|
super().action_post()
|
||||||
invoices=invoices, currency=currency)
|
for pay in self:
|
||||||
if self.sale_id:
|
if pay.sale_id and pay.payment_type == 'inbound':
|
||||||
payment_currency = currency
|
pay._sale_down_payment_hook()
|
||||||
if not payment_currency:
|
|
||||||
payment_currency = self.sale_id.currency_id
|
def _sale_down_payment_hook(self):
|
||||||
amount = float_round(
|
# can be used for notifications
|
||||||
self.sale_id.amount_total - self.sale_id.amount_down_payment,
|
# WAS on account.move.line on v12 ; is on account.payment on v14
|
||||||
precision_rounding=payment_currency.rounding)
|
self.ensure_one()
|
||||||
return amount
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2019 Akretion France (http://www.akretion.com)
|
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
|
||||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
@@ -9,8 +9,8 @@ from odoo.tools import float_round
|
|||||||
class SaleOrder(models.Model):
|
class SaleOrder(models.Model):
|
||||||
_inherit = 'sale.order'
|
_inherit = 'sale.order'
|
||||||
|
|
||||||
payment_line_ids = fields.One2many(
|
payment_ids = fields.One2many(
|
||||||
'account.move.line', 'sale_id', string='Advance Payments',
|
'account.payment', 'sale_id', string='Advance Payments',
|
||||||
readonly=True)
|
readonly=True)
|
||||||
amount_down_payment = fields.Monetary(
|
amount_down_payment = fields.Monetary(
|
||||||
compute='_compute_amount_down_payment', string='Down Payment Amount')
|
compute='_compute_amount_down_payment', string='Down Payment Amount')
|
||||||
@@ -19,30 +19,20 @@ class SaleOrder(models.Model):
|
|||||||
compute='_compute_amount_down_payment', string='Residual')
|
compute='_compute_amount_down_payment', string='Residual')
|
||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
'payment_line_ids.credit', 'payment_line_ids.debit',
|
'payment_ids.amount', 'payment_ids.currency_id', 'payment_ids.date',
|
||||||
'payment_line_ids.amount_currency', 'payment_line_ids.currency_id',
|
'payment_ids.state', 'currency_id')
|
||||||
'payment_line_ids.date', 'currency_id')
|
|
||||||
def _compute_amount_down_payment(self):
|
def _compute_amount_down_payment(self):
|
||||||
for sale in self:
|
for sale in self:
|
||||||
down_payment = 0.0
|
down_payment = 0.0
|
||||||
sale_currency = sale.pricelist_id.currency_id
|
sale_currency = sale.currency_id
|
||||||
if sale_currency == sale.company_id.currency_id:
|
prec_rounding = sale_currency.rounding or 0.01
|
||||||
for pl in sale.payment_line_ids:
|
for payment in sale.payment_ids:
|
||||||
down_payment -= pl.balance
|
if payment.payment_type == 'inbound' and payment.state == 'posted':
|
||||||
else:
|
down_payment += payment.currency_id._convert(
|
||||||
for pl in sale.payment_line_ids:
|
payment.amount, sale_currency, sale.company_id,
|
||||||
if (
|
payment.date)
|
||||||
pl.currency_id and
|
|
||||||
pl.currency_id == sale_currency and
|
|
||||||
pl.amount_currency):
|
|
||||||
down_payment -= pl.amount_currency
|
|
||||||
else:
|
|
||||||
down_payment -= sale.company_id.currency_id._convert(
|
|
||||||
pl.balance, sale_currency, sale.company_id,
|
|
||||||
pl.date)
|
|
||||||
down_payment = float_round(
|
down_payment = float_round(
|
||||||
down_payment, precision_rounding=sale.currency_id.rounding)
|
down_payment, precision_rounding=prec_rounding)
|
||||||
sale.amount_down_payment = down_payment
|
sale.amount_down_payment = down_payment
|
||||||
sale.amount_residual = float_round(
|
sale.amount_residual = float_round(
|
||||||
sale.amount_total - down_payment,
|
sale.amount_total - down_payment, precision_rounding=prec_rounding)
|
||||||
precision_rounding=sale.currency_id.rounding)
|
|
||||||
|
|||||||
2
sale_down_payment/security/ir.model.access.csv
Normal file
2
sale_down_payment/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_account_payment_register_sale,Full access on account.payment.register.sale,model_account_payment_register_sale,account.group_account_invoice,1,1,1,1
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2019 Akretion France (http://www.akretion.com/)
|
Copyright 2019-2024 Akretion France (http://www.akretion.com/)
|
||||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
-->
|
-->
|
||||||
@@ -13,10 +13,12 @@
|
|||||||
<field name="model">account.move.line</field>
|
<field name="model">account.move.line</field>
|
||||||
<field name="inherit_id" ref="account.view_move_line_form"/>
|
<field name="inherit_id" ref="account.view_move_line_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="invoice_id" position="after">
|
<xpath expr="//field[@name='blocked']/.." position="after">
|
||||||
<field name="sale_id" attrs="{'invisible': [('account_internal_type', '!=', 'receivable')]}" domain="['|', ('partner_id', 'child_of', partner_id), ('partner_invoice_id', 'child_of', partner_id), ('state', '!=', 'cancel'), ('invoice_status', '!=', 'invoiced')]"/>
|
<group string="Sale Order" name="sale" attrs="{'invisible': [('account_internal_type', '!=', 'receivable')]}">
|
||||||
|
<field name="sale_id"/>
|
||||||
<field name="account_internal_type" invisible="1"/>
|
<field name="account_internal_type" invisible="1"/>
|
||||||
</field>
|
</group>
|
||||||
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2018 Akretion France (http://www.akretion.com/)
|
Copyright 2018-2024 Akretion France (http://www.akretion.com/)
|
||||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
-->
|
-->
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
|
|
||||||
<record id="view_account_payment_sale_form" model="ir.ui.view">
|
<record id="view_account_payment_form" model="ir.ui.view">
|
||||||
<field name="name">account.payment.sale.form</field>
|
<field name="name">account.payment.sale.form</field>
|
||||||
<field name="model">account.payment</field>
|
<field name="model">account.payment</field>
|
||||||
<field name="inherit_id" ref="account.view_account_payment_invoice_form"/>
|
<field name="inherit_id" ref="account.view_account_payment_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="invoice_ids" position="after">
|
<field name="destination_account_id" position="after">
|
||||||
<field name="sale_id" invisible="1"/>
|
<field name="sale_id" attrs="{'invisible': [('is_internal_transfer', '=', True)]}"/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2019 Akretion France (http://www.akretion.com/)
|
Copyright 2019-2024 Akretion France (http://www.akretion.com/)
|
||||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
-->
|
-->
|
||||||
@@ -8,14 +8,6 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
|
|
||||||
<record id="sale_account_payment_action" model="ir.actions.act_window">
|
|
||||||
<field name="name">Register Payment</field>
|
|
||||||
<field name="res_model">account.payment</field>
|
|
||||||
<field name="view_mode">form</field>
|
|
||||||
<field name="view_id" ref="account.view_account_payment_invoice_form"/>
|
|
||||||
<field name="target">new</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="view_order_form" model="ir.ui.view">
|
<record id="view_order_form" model="ir.ui.view">
|
||||||
<field name="name">advance_payment.sale.order.form</field>
|
<field name="name">advance_payment.sale.order.form</field>
|
||||||
<field name="model">sale.order</field>
|
<field name="model">sale.order</field>
|
||||||
@@ -23,7 +15,7 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<notebook position="inside">
|
<notebook position="inside">
|
||||||
<page name="advance_payment" string="Advance Payments">
|
<page name="advance_payment" string="Advance Payments">
|
||||||
<field name="payment_line_ids" nolabel="1"/>
|
<field name="payment_ids" nolabel="1" colspan="2"/>
|
||||||
<field name="amount_residual" invisible="1"/>
|
<field name="amount_residual" invisible="1"/>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
@@ -34,7 +26,7 @@
|
|||||||
<field name="amount_down_payment" nolabel="1" class="oe_subtotal_footer_separator"/>
|
<field name="amount_down_payment" nolabel="1" class="oe_subtotal_footer_separator"/>
|
||||||
</field>
|
</field>
|
||||||
<button name="action_cancel" position="before">
|
<button name="action_cancel" position="before">
|
||||||
<button type="action" name="%(sale_account_payment_action)d" string="Register Payment" attrs="{'invisible': ['|', ('amount_residual', '<=', 0), ('invoice_status', '=', 'invoiced')]}"/>
|
<button type="action" name="%(sale_down_payment.account_payment_register_sale_action)d" string="Register Payment" attrs="{'invisible': ['|', ('amount_residual', '<=', 0), ('invoice_status', '=', 'invoiced')]}"/>
|
||||||
</button>
|
</button>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
from . import account_bank_statement_sale
|
from . import account_payment_register_sale
|
||||||
|
# from . import account_bank_statement_sale
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ class AccountBankStatementSale(models.TransientModel):
|
|||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
for line in self.line_ids:
|
for line in self.line_ids:
|
||||||
if line.move_line_id.sale_id != line.sale_id:
|
if line.move_line_id.sale_id != line.sale_id:
|
||||||
line.move_line_id.sale_id = line.sale_id.id
|
line.move_line_id.write({'sale_id': line.sale_id.id or False})
|
||||||
|
if line.sale_id:
|
||||||
|
line.move_line_id._sale_down_payment_hook()
|
||||||
|
|
||||||
|
|
||||||
class AccountBankStatementSaleLine(models.TransientModel):
|
class AccountBankStatementSaleLine(models.TransientModel):
|
||||||
|
|||||||
62
sale_down_payment/wizard/account_payment_register_sale.py
Normal file
62
sale_down_payment/wizard/account_payment_register_sale.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Copyright 2024 Akretion France (http://www.akretion.com/)
|
||||||
|
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class AccountPaymentRegisterSale(models.TransientModel):
|
||||||
|
_name = 'account.payment.register.sale'
|
||||||
|
_description = "Register a payment from a sale.order"
|
||||||
|
_check_company_auto = True
|
||||||
|
|
||||||
|
sale_id = fields.Many2one(
|
||||||
|
"sale.order", string="Sale Order",
|
||||||
|
check_company=True, readonly=True, required=True)
|
||||||
|
company_id = fields.Many2one('res.company', required=True)
|
||||||
|
journal_id = fields.Many2one(
|
||||||
|
'account.journal', string="Journal", check_company=True, required=True,
|
||||||
|
domain="[('company_id', '=', company_id), ('type', 'in', ('bank', 'cash'))]")
|
||||||
|
amount = fields.Monetary(required=True)
|
||||||
|
currency_id = fields.Many2one('res.currency', required=True)
|
||||||
|
date = fields.Date(default=fields.Date.context_today, required=True)
|
||||||
|
ref = fields.Char()
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def default_get(self, fields_list):
|
||||||
|
res = super().default_get(fields_list)
|
||||||
|
if self._context.get('active_model') == 'sale.order' and self._context.get('active_id'):
|
||||||
|
sale = self.env['sale.order'].browse(self._context['active_id'])
|
||||||
|
res.update({
|
||||||
|
'sale_id': sale.id,
|
||||||
|
'company_id': sale.company_id.id,
|
||||||
|
'amount': sale.amount_total,
|
||||||
|
'currency_id': sale.currency_id.id,
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.ensure_one()
|
||||||
|
pay_vals = {
|
||||||
|
'company_id': self.company_id.id,
|
||||||
|
'sale_id': self.sale_id.id,
|
||||||
|
'date': self.date,
|
||||||
|
'amount': self.amount,
|
||||||
|
'payment_type': 'inbound',
|
||||||
|
'partner_type': 'customer',
|
||||||
|
'ref': self.ref,
|
||||||
|
'journal_id': self.journal_id.id,
|
||||||
|
'currency_id': self.currency_id.id,
|
||||||
|
'partner_id': self.sale_id.partner_invoice_id.commercial_partner_id.id,
|
||||||
|
'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
|
||||||
|
}
|
||||||
|
payment = self.env['account.payment'].create(pay_vals)
|
||||||
|
payment.action_post()
|
||||||
|
|
||||||
|
@api.onchange("journal_id")
|
||||||
|
def journal_id_change(self):
|
||||||
|
if (
|
||||||
|
self.journal_id and
|
||||||
|
self.journal_id.currency_id and
|
||||||
|
self.journal_id.currency_id != self.currency_id):
|
||||||
|
self.currency_id = self.journal_id.currency_id.id
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2024 Akretion France (http://www.akretion.com/)
|
||||||
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="account_payment_register_sale_form" model="ir.ui.view">
|
||||||
|
<field name="model">account.payment.register.sale</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form>
|
||||||
|
<group name="main">
|
||||||
|
<field name="sale_id" invisible="1"/>
|
||||||
|
<field name="company_id" invisible="1"/>
|
||||||
|
<field name="date"/>
|
||||||
|
<field name="journal_id" widget="selection"/>
|
||||||
|
<label for="amount"/>
|
||||||
|
<div name="amount" class="o_row">
|
||||||
|
<field name="amount"/>
|
||||||
|
<field name="currency_id" options="{'no_create': True, 'no_open': True}" groups="base.group_multi_currency"/>
|
||||||
|
</div>
|
||||||
|
<field name="ref"/>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button name="run" type="object" string="Register Payment" class="btn-primary"/>
|
||||||
|
<button special="cancel" string="Cancel"/>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="account_payment_register_sale_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Register Payment from Sale Order</field>
|
||||||
|
<field name="res_model">account.payment.register.sale</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user