initial odoo 19 changes

This commit is contained in:
admin.suherdy 2025-11-12 16:00:05 +07:00
parent 3328179534
commit f7ffb8b16d
28 changed files with 469 additions and 462 deletions

View File

@ -1,26 +1,26 @@
# Purchase Advance Payment # Purchase Advance Payment
This module allows linking payments to purchase orders as advance payments. This module allows linking payments to purchase orders as advance payments.
## Features ## Features
- Link payments to purchase orders as advance payments - Link payments to purchase orders as advance payments
- Automatically subtract advance payments from the total when the PO is fully billed - Automatically subtract advance payments from the total when the PO is fully billed
- Create deposit products on the PO so the final invoice includes the deposit product - Create deposit products on the PO so the final invoice includes the deposit product
- Track advance payments linked to purchase orders - Track advance payments linked to purchase orders
## Usage ## Usage
1. Create a purchase order 1. Create a purchase order
2. Create a payment and link it to the purchase order as an advance payment 2. Create a payment and link it to the purchase order as an advance payment
3. When the payment is posted, it will automatically be applied as a deposit to the purchase order 3. When the payment is posted, it will automatically be applied as a deposit to the purchase order
4. The deposit will appear as a negative line item on the purchase order 4. The deposit will appear as a negative line item on the purchase order
5. When creating the vendor bill, the deposit will be included 5. When creating the vendor bill, the deposit will be included
## Configuration ## Configuration
No additional configuration is required. No additional configuration is required.
## Known Issues ## Known Issues
- None - None

View File

@ -1,2 +1,2 @@
from . import models from . import models
from . import wizard from . import wizard

View File

@ -1,25 +1,25 @@
{ {
'name': 'Purchase Advance Payment', 'name': 'Purchase Advance Payment',
'version': '17.0.1.0.0', 'version': '19.0.1.0.0',
'category': 'Purchase', 'category': 'Purchase',
'summary': 'Link payments to purchase orders as advance payments', 'summary': 'Link payments to purchase orders as advance payments',
'description': """ 'description': """
This module allows linking payments to purchase orders as advance payments. This module allows linking payments to purchase orders as advance payments.
When a PO is fully billed, the total is subtracted by the advance payment made. When a PO is fully billed, the total is subtracted by the advance payment made.
After payment is linked to the PO, a deposit product is created so the final After payment is linked to the PO, a deposit product is created so the final
invoice/vendor bills will include the deposit product. invoice/vendor bills will include the deposit product.
""", """,
'author': 'Suherdy Yacob', 'author': 'Suherdy Yacob',
'depends': ['purchase', 'account'], 'depends': ['purchase', 'account'],
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'data/product_data.xml', 'data/product_data.xml',
'wizard/link_advance_payment_wizard_views.xml', 'wizard/link_advance_payment_wizard_views.xml',
'views/purchase_advance_payment_views.xml', 'views/purchase_advance_payment_views.xml',
'views/purchase_order_views.xml', 'views/purchase_order_views.xml',
'views/res_config_settings_views.xml', 'views/res_config_settings_views.xml',
], ],
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': False,
'license': 'LGPL-3', 'license': 'LGPL-3',
} }

Binary file not shown.

Binary file not shown.

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<!-- Product Category for Deposit Products --> <!-- Product Category for Deposit Products -->
<record id="product_category_deposit" model="product.category"> <record id="product_category_deposit" model="product.category">
<field name="name">Deposit</field> <field name="name">Deposit</field>
<field name="parent_id" ref="product.product_category_all"/> <field name="parent_id" ref="product.product_category_all"/>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@ -1,3 +1,3 @@
from . import purchase_order from . import purchase_order
from . import account_payment from . import account_payment
from . import res_config_settings from . import res_config_settings

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,31 +1,31 @@
from odoo import models, fields, api from odoo import models, fields, api
class AccountPayment(models.Model): class AccountPayment(models.Model):
_inherit = 'account.payment' _inherit = 'account.payment'
purchase_order_id = fields.Many2one( purchase_order_id = fields.Many2one(
'purchase.order', 'purchase.order',
string='Purchase Order', string='Purchase Order',
domain="[('partner_id', '=', partner_id), ('state', 'in', ('purchase', 'done'))]" domain="[('partner_id', '=', partner_id), ('state', 'in', ('purchase', 'done'))]"
) )
is_advance_payment = fields.Boolean( is_advance_payment = fields.Boolean(
string='Is Advance Payment', string='Is Advance Payment',
default=False, default=False,
help='Identifies if this payment is an advance payment for a purchase order' help='Identifies if this payment is an advance payment for a purchase order'
) )
@api.onchange('purchase_order_id') @api.onchange('purchase_order_id')
def _onchange_purchase_order_id(self): def _onchange_purchase_order_id(self):
if self.purchase_order_id: if self.purchase_order_id:
self.amount = self.purchase_order_id.amount_residual self.amount = self.purchase_order_id.amount_residual
def action_post(self): def action_post(self):
res = super().action_post() res = super().action_post()
# When an advance payment is posted, link it to the purchase order # When an advance payment is posted, link it to the purchase order
for payment in self: for payment in self:
if payment.is_advance_payment and payment.purchase_order_id: if payment.is_advance_payment and payment.purchase_order_id:
# Apply the deposit to the purchase order # Apply the deposit to the purchase order
payment.purchase_order_id.action_apply_deposit() payment.purchase_order_id.action_apply_deposit()
return res return res

View File

@ -1,187 +1,187 @@
from odoo import models, fields, api from odoo import models, fields, api
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.tools import float_compare from odoo.tools import float_compare
class PurchaseOrder(models.Model): class PurchaseOrder(models.Model):
_inherit = 'purchase.order' _inherit = 'purchase.order'
advance_payment_ids = fields.One2many( advance_payment_ids = fields.One2many(
'account.payment', 'account.payment',
'purchase_order_id', 'purchase_order_id',
string='Advance Payments', string='Advance Payments',
domain=[('state', '=', 'posted')] domain=[('state', '=', 'posted')]
) )
advance_payment_total = fields.Monetary( advance_payment_total = fields.Monetary(
string='Advance Payment Total', string='Advance Payment Total',
compute='_compute_advance_payment_total', compute='_compute_advance_payment_total',
store=True store=True
) )
amount_residual = fields.Monetary( amount_residual = fields.Monetary(
string='Amount Residual', string='Amount Residual',
compute='_compute_amount_residual', compute='_compute_amount_residual',
store=True store=True
) )
deposit_product_id = fields.Many2one( deposit_product_id = fields.Many2one(
'product.product', 'product.product',
string='Deposit Product', string='Deposit Product',
help='Product used for advance payment deposit' help='Product used for advance payment deposit'
) )
@api.depends('advance_payment_ids', 'advance_payment_ids.state', 'advance_payment_ids.amount') @api.depends('advance_payment_ids', 'advance_payment_ids.state', 'advance_payment_ids.amount')
def _compute_advance_payment_total(self): def _compute_advance_payment_total(self):
for order in self: for order in self:
order.advance_payment_total = sum( order.advance_payment_total = sum(
payment.amount for payment in order.advance_payment_ids.filtered(lambda p: p.state == 'posted') payment.amount for payment in order.advance_payment_ids.filtered(lambda p: p.state == 'posted')
) )
@api.depends('amount_total', 'advance_payment_total') @api.depends('amount_total', 'advance_payment_total')
def _compute_amount_residual(self): def _compute_amount_residual(self):
for order in self: for order in self:
order.amount_residual = order.amount_total - order.advance_payment_total order.amount_residual = order.amount_total - order.advance_payment_total
def action_view_advance_payments(self): def action_view_advance_payments(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('account.action_account_payments').sudo().read()[0] action = self.env.ref('account.action_account_payments').sudo().read()[0]
action['domain'] = [('id', 'in', self.advance_payment_ids.ids)] action['domain'] = [('id', 'in', self.advance_payment_ids.ids)]
action['context'] = { action['context'] = {
'default_purchase_order_id': self.id, 'default_purchase_order_id': self.id,
'default_partner_id': self.partner_id.id, 'default_partner_id': self.partner_id.id,
'default_payment_type': 'outbound', 'default_payment_type': 'outbound',
'default_partner_type': 'supplier', 'default_partner_type': 'supplier',
} }
return action return action
def action_create_deposit_product(self): def action_create_deposit_product(self):
"""Create a deposit product for this purchase order""" """Create a deposit product for this purchase order"""
self.ensure_one() self.ensure_one()
# Check if there's a default deposit product in settings # Check if there's a default deposit product in settings
default_deposit_product = self.env['ir.config_parameter'].sudo().get_param( default_deposit_product = self.env['ir.config_parameter'].sudo().get_param(
'purchase_advance_payment.deposit_product_id') 'purchase_advance_payment.deposit_product_id')
if default_deposit_product: if default_deposit_product:
self.deposit_product_id = int(default_deposit_product) self.deposit_product_id = int(default_deposit_product)
return self.deposit_product_id return self.deposit_product_id
# If no default product, create one # If no default product, create one
if not self.deposit_product_id: if not self.deposit_product_id:
product_vals = { product_vals = {
'name': f'Deposit for PO {self.name}', 'name': f'Deposit for PO {self.name}',
'type': 'service', 'type': 'service',
'purchase_ok': True, 'purchase_ok': True,
'sale_ok': False, 'sale_ok': False,
'invoice_policy': 'order', # Ordered quantities for deposit 'invoice_policy': 'order', # Ordered quantities for deposit
'supplier_taxes_id': [(6, 0, [])], # No supplier taxes 'supplier_taxes_id': [(6, 0, [])], # No supplier taxes
} }
deposit_product = self.env['product.product'].create(product_vals) deposit_product = self.env['product.product'].create(product_vals)
self.deposit_product_id = deposit_product.id self.deposit_product_id = deposit_product.id
return self.deposit_product_id return self.deposit_product_id
def button_draft(self): def button_draft(self):
res = super().button_draft() res = super().button_draft()
# Remove deposit lines when resetting to draft # Remove deposit lines when resetting to draft
for order in self: for order in self:
deposit_lines = order.order_line.filtered(lambda l: l.is_deposit) deposit_lines = order.order_line.filtered(lambda l: l.is_deposit)
deposit_lines.unlink() deposit_lines.unlink()
return res return res
def action_apply_deposit(self): def action_apply_deposit(self):
"""Apply advance payment as deposit line in the purchase order""" """Apply advance payment as deposit line in the purchase order"""
self.ensure_one() self.ensure_one()
if self.advance_payment_total <= 0: if self.advance_payment_total <= 0:
raise UserError("No advance payment found for this purchase order.") raise UserError("No advance payment found for this purchase order.")
# Create or update deposit product # Create or update deposit product
if not self.deposit_product_id: if not self.deposit_product_id:
self.action_create_deposit_product() self.action_create_deposit_product()
# Check if deposit line already exists # Check if deposit line already exists
existing_deposit_line = self.order_line.filtered(lambda l: l.is_deposit) existing_deposit_line = self.order_line.filtered(lambda l: l.is_deposit)
if existing_deposit_line: if existing_deposit_line:
# Update existing deposit line # Update existing deposit line
existing_deposit_line.write({ existing_deposit_line.write({
'product_qty': 1, 'product_qty': 1,
'price_unit': -self.advance_payment_total, # Negative value for deposit 'price_unit': -self.advance_payment_total, # Negative value for deposit
'taxes_id': [(6, 0, [])], # No taxes 'taxes_id': [(6, 0, [])], # No taxes
}) })
else: else:
# Create new deposit line # Create new deposit line
deposit_vals = { deposit_vals = {
'order_id': self.id, 'order_id': self.id,
'product_id': self.deposit_product_id.id, 'product_id': self.deposit_product_id.id,
'name': f'Deposit payment for PO {self.name}', 'name': f'Deposit payment for PO {self.name}',
'product_qty': 1, 'product_qty': 1,
'product_uom': self.deposit_product_id.uom_id.id, 'product_uom': self.deposit_product_id.uom_id.id,
'price_unit': -self.advance_payment_total, # Negative value for deposit 'price_unit': -self.advance_payment_total, # Negative value for deposit
'is_deposit': True, 'is_deposit': True,
'date_planned': fields.Datetime.now(), 'date_planned': fields.Datetime.now(),
'taxes_id': [(6, 0, [])], # No taxes 'taxes_id': [(6, 0, [])], # No taxes
} }
self.env['purchase.order.line'].create(deposit_vals) self.env['purchase.order.line'].create(deposit_vals)
return True return True
def action_create_invoice(self): def action_create_invoice(self):
"""Override to ensure deposit line is included in vendor bill""" """Override to ensure deposit line is included in vendor bill"""
# Apply deposit before creating invoice # Apply deposit before creating invoice
for order in self: for order in self:
if order.advance_payment_total > 0: if order.advance_payment_total > 0:
order.action_apply_deposit() order.action_apply_deposit()
# Call super to create the invoice # Call super to create the invoice
invoices = super().action_create_invoice() invoices = super().action_create_invoice()
# Ensure deposit lines have quantity 1 in the created invoices # Ensure deposit lines have quantity 1 in the created invoices
if 'res_id' in invoices and invoices['res_id']: if 'res_id' in invoices and invoices['res_id']:
# Single invoice # Single invoice
invoice = self.env['account.move'].browse(invoices['res_id']) invoice = self.env['account.move'].browse(invoices['res_id'])
self._fix_deposit_line_quantities(invoice) self._fix_deposit_line_quantities(invoice)
elif 'domain' in invoices and invoices['domain']: elif 'domain' in invoices and invoices['domain']:
# Multiple invoices # Multiple invoices
invoice_ids = self.env['account.move'].search(invoices['domain']) invoice_ids = self.env['account.move'].search(invoices['domain'])
for invoice in invoice_ids: for invoice in invoice_ids:
self._fix_deposit_line_quantities(invoice) self._fix_deposit_line_quantities(invoice)
return invoices return invoices
def _fix_deposit_line_quantities(self, invoice): def _fix_deposit_line_quantities(self, invoice):
"""Fix deposit line quantities in the invoice""" """Fix deposit line quantities in the invoice"""
for line in invoice.invoice_line_ids: for line in invoice.invoice_line_ids:
if line.purchase_line_id and line.purchase_line_id.is_deposit: if line.purchase_line_id and line.purchase_line_id.is_deposit:
line.write({ line.write({
'quantity': 1.0, 'quantity': 1.0,
'tax_ids': [(6, 0, [])] # No taxes 'tax_ids': [(6, 0, [])] # No taxes
}) })
class PurchaseOrderLine(models.Model): class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line' _inherit = 'purchase.order.line'
is_deposit = fields.Boolean( is_deposit = fields.Boolean(
string='Is Deposit', string='Is Deposit',
default=False, default=False,
help='Identifies if this line is a deposit payment' help='Identifies if this line is a deposit payment'
) )
def _prepare_account_move_line(self, move=False): def _prepare_account_move_line(self, move=False):
"""Override to ensure deposit lines have correct quantity in vendor bill""" """Override to ensure deposit lines have correct quantity in vendor bill"""
self.ensure_one() self.ensure_one()
res = super()._prepare_account_move_line(move) res = super()._prepare_account_move_line(move)
# If this is a deposit line, ensure quantity is 1 and no taxes # If this is a deposit line, ensure quantity is 1 and no taxes
if self.is_deposit: if self.is_deposit:
res['quantity'] = 1 res['quantity'] = 1
res['tax_ids'] = [(6, 0, [])] # No taxes res['tax_ids'] = [(6, 0, [])] # No taxes
return res return res
def _get_invoice_qty(self): def _get_invoice_qty(self):
"""Override to ensure deposit lines have correct quantity for invoicing""" """Override to ensure deposit lines have correct quantity for invoicing"""
self.ensure_one() self.ensure_one()
if self.is_deposit: if self.is_deposit:
# For deposit lines, always invoice quantity 1 regardless of received qty # For deposit lines, always invoice quantity 1 regardless of received qty
return 1.0 return 1.0
return super()._get_invoice_qty() return super()._get_invoice_qty()

View File

@ -1,13 +1,13 @@
from odoo import models, fields, api from odoo import models, fields, api
class ResConfigSettings(models.TransientModel): class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings' _inherit = 'res.config.settings'
deposit_product_id = fields.Many2one( deposit_product_id = fields.Many2one(
'product.product', 'product.product',
string='Default Deposit Product', string='Default Deposit Product',
domain=[('type', '=', 'service')], domain=[('type', '=', 'service')],
config_parameter='purchase_advance_payment.deposit_product_id', config_parameter='purchase_advance_payment.deposit_product_id',
help='Default product used for advance payment deposits' help='Default product used for advance payment deposits'
) )

View File

@ -1,2 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_link_advance_payment_wizard,access.link.advance.payment.wizard,model_link_advance_payment_wizard,base.group_user,1,1,1,1 access_link_advance_payment_wizard,access.link.advance.payment.wizard,model_link_advance_payment_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_link_advance_payment_wizard access.link.advance.payment.wizard model_link_advance_payment_wizard base.group_user 1 1 1 1

View File

@ -1,40 +1,40 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data> <data>
<!-- Account Payment Form View --> <!-- Account Payment Form View -->
<record id="view_account_payment_form_inherit_advance_payment" model="ir.ui.view"> <record id="view_account_payment_form_inherit_advance_payment" model="ir.ui.view">
<field name="name">account.payment.form.inherit.advance.payment</field> <field name="name">account.payment.form.inherit.advance.payment</field>
<field name="model">account.payment</field> <field name="model">account.payment</field>
<field name="inherit_id" ref="account.view_account_payment_form"/> <field name="inherit_id" ref="account.view_account_payment_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//sheet/group[2]" position="after"> <xpath expr="//sheet/group[2]" position="after">
<group> <group>
<field name="is_advance_payment" invisible="1"/> <field name="is_advance_payment" invisible="1"/>
<field name="purchase_order_id" <field name="purchase_order_id"
invisible="not is_advance_payment" invisible="not is_advance_payment"
required="is_advance_payment"/> required="is_advance_payment"/>
</group> </group>
</xpath> </xpath>
<xpath expr="//header" position="inside"> <xpath expr="//header" position="inside">
<button name="%(purchase_advance_payment.action_link_advance_payment_wizard_payment)d" <button name="%(purchase_advance_payment.action_link_advance_payment_wizard_payment)d"
string="Link to PO" string="Link to PO"
type="action" type="action"
class="btn-primary" class="btn-primary"
invisible="state != 'draft' or is_advance_payment"/> invisible="state != 'draft' or is_advance_payment"/>
</xpath> </xpath>
</field> </field>
</record> </record>
<!-- Account Payment Tree View --> <!-- Account Payment List View -->
<record id="view_account_payment_tree_inherit_advance_payment" model="ir.ui.view"> <record id="view_account_payment_tree_inherit_advance_payment" model="ir.ui.view">
<field name="name">account.payment.tree.inherit.advance.payment</field> <field name="name">account.payment.tree.inherit.advance.payment</field>
<field name="model">account.payment</field> <field name="model">account.payment</field>
<field name="inherit_id" ref="account.view_account_payment_tree"/> <field name="inherit_id" ref="account.view_account_payment_tree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//tree/field[@name='partner_id']" position="after"> <xpath expr="//list/field[@name='partner_id']" position="after">
<field name="purchase_order_id"/> <field name="purchase_order_id"/>
</xpath> </xpath>
</field> </field>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@ -1,56 +1,56 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data> <data>
<!-- Purchase Order Form View --> <!-- Purchase Order Form View -->
<record id="view_purchase_order_form_inherit_advance_payment" model="ir.ui.view"> <record id="view_purchase_order_form_inherit_advance_payment" model="ir.ui.view">
<field name="name">purchase.order.form.inherit.advance.payment</field> <field name="name">purchase.order.form.inherit.advance.payment</field>
<field name="model">purchase.order</field> <field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/> <field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//sheet/group/group[2]" position="after"> <xpath expr="//sheet/group/group[2]" position="after">
<group> <group>
<field name="deposit_product_id" invisible="1"/> <field name="deposit_product_id" invisible="1"/>
</group> </group>
</xpath> </xpath>
<xpath expr="//sheet/notebook" position="inside"> <xpath expr="//sheet/notebook" position="inside">
<page string="Advance Payments" name="advance_payments"> <page string="Advance Payments" name="advance_payments">
<group> <group>
<field name="advance_payment_total" widget="monetary"/> <field name="advance_payment_total" widget="monetary"/>
<field name="amount_residual" widget="monetary"/> <field name="amount_residual" widget="monetary"/>
</group> </group>
<group> <group>
<button name="action_apply_deposit" <button name="action_apply_deposit"
string="Apply Deposit" string="Apply Deposit"
type="object" type="object"
class="btn-primary" class="btn-primary"
invisible="advance_payment_total &lt;= 0"/> invisible="advance_payment_total &lt;= 0"/>
<button name="%(purchase_advance_payment.action_link_advance_payment_wizard)d" <button name="%(purchase_advance_payment.action_link_advance_payment_wizard)d"
string="Link Advance Payment" string="Link Advance Payment"
type="action" type="action"
class="btn-secondary" class="btn-secondary"
context="{'default_purchase_order_id': active_id}"/> context="{'default_purchase_order_id': id}"/>
</group> </group>
<field name="advance_payment_ids"> <field name="advance_payment_ids">
<tree> <list>
<field name="name"/> <field name="name"/>
<field name="date"/> <field name="date"/>
<field name="amount" widget="monetary"/> <field name="amount" widget="monetary"/>
<field name="state"/> <field name="state"/>
<field name="journal_id"/> <field name="journal_id"/>
</tree> </list>
</field> </field>
</page> </page>
</xpath> </xpath>
<xpath expr="//field[@name='order_line']/tree/field[@name='price_unit']" position="after"> <xpath expr="//field[@name='order_line']/list/field[@name='price_unit']" position="after">
<field name="is_deposit" invisible="1"/> <field name="is_deposit" invisible="1"/>
</xpath> </xpath>
<xpath expr="//field[@name='order_line']/form//field[@name='price_unit']" position="after"> <xpath expr="//field[@name='order_line']/form//field[@name='price_unit']" position="after">
<field name="is_deposit" invisible="1"/> <field name="is_deposit" invisible="1"/>
</xpath> </xpath>
</field> </field>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@ -1,34 +1,34 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data> <data>
<record id="res_config_settings_view_form_purchase_advance_payment" model="ir.ui.view"> <record id="res_config_settings_view_form_purchase_advance_payment" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.purchase.advance.payment</field> <field name="name">res.config.settings.view.form.inherit.purchase.advance.payment</field>
<field name="model">res.config.settings</field> <field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/> <field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//form" position="inside"> <xpath expr="//form" position="inside">
<div class="app_settings_block" data-string="Purchase" string="Purchase" data-key="purchase"> <div class="app_settings_block" data-string="Purchase" string="Purchase" data-key="purchase">
<h2>Advance Payment</h2> <h2>Advance Payment</h2>
<div class="row mt16 o_settings_container"> <div class="row mt16 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box"> <div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane" /> <div class="o_setting_left_pane" />
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label <label
for="deposit_product_id" for="deposit_product_id"
string="Advance Payments" string="Advance Payments"
/> />
<div class="text-muted"> <div class="text-muted">
Default product used for advance payment deposits Default product used for advance payment deposits
</div> </div>
<div class="text-muted"> <div class="text-muted">
<field name="deposit_product_id" /> <field name="deposit_product_id" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</xpath> </xpath>
</field> </field>
</record> </record>
</data> </data>
</odoo> </odoo>

Binary file not shown.

Binary file not shown.

View File

@ -30,15 +30,22 @@ class LinkAdvancePaymentWizard(models.TransientModel):
def default_get(self, fields): def default_get(self, fields):
res = super().default_get(fields) res = super().default_get(fields)
# Handle context from purchase order # Handle context from purchase order
if self._context.get('active_model') == 'purchase.order' and self._context.get('active_id'): if self.env.context.get('active_model') == 'purchase.order' and self.env.context.get('active_id'):
po = self.env['purchase.order'].browse(self._context['active_id']) po = self.env['purchase.order'].browse(self.env.context['active_id'])
res['purchase_order_id'] = po.id res['purchase_order_id'] = po.id
res['currency_id'] = po.currency_id.id res['currency_id'] = po.currency_id.id
if 'amount' in fields: if 'amount' in fields:
res['amount'] = po.amount_residual res['amount'] = po.amount_residual
# Handle context from purchase order when called from the button (using default_purchase_order_id)
elif self.env.context.get('default_purchase_order_id'):
po = self.env['purchase.order'].browse(self.env.context['default_purchase_order_id'])
res['purchase_order_id'] = po.id
res['currency_id'] = po.currency_id.id
if 'amount' in fields and 'amount' not in res:
res['amount'] = po.amount_residual
# Handle context from payment # Handle context from payment
elif self._context.get('active_model') == 'account.payment' and self._context.get('active_id'): elif self.env.context.get('active_model') == 'account.payment' and self.env.context.get('active_id'):
payment = self.env['account.payment'].browse(self._context['active_id']) payment = self.env['account.payment'].browse(self.env.context['active_id'])
res['payment_id'] = payment.id res['payment_id'] = payment.id
res['currency_id'] = payment.currency_id.id res['currency_id'] = payment.currency_id.id
if 'amount' in fields: if 'amount' in fields:

View File

@ -1,41 +1,41 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data> <data>
<!-- Link Advance Payment Wizard Form View --> <!-- Link Advance Payment Wizard Form View -->
<record id="view_link_advance_payment_wizard_form" model="ir.ui.view"> <record id="view_link_advance_payment_wizard_form" model="ir.ui.view">
<field name="name">link.advance.payment.wizard.form</field> <field name="name">link.advance.payment.wizard.form</field>
<field name="model">link.advance.payment.wizard</field> <field name="model">link.advance.payment.wizard</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Link Advance Payment"> <form string="Link Advance Payment">
<group> <group>
<field name="purchase_order_id"/> <field name="purchase_order_id"/>
<field name="payment_id" domain="[('state', '=', 'draft'), ('payment_type', '=', 'outbound')]"/> <field name="payment_id" domain="[('state', '=', 'draft'), ('payment_type', '=', 'outbound')]"/>
<field name="amount"/> <field name="amount"/>
<field name="currency_id" invisible="1"/> <field name="currency_id" invisible="1"/>
</group> </group>
<footer> <footer>
<button string="Link Payment" name="action_link_payment" type="object" class="btn-primary"/> <button string="Link Payment" name="action_link_payment" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/> <button string="Cancel" class="btn-secondary" special="cancel"/>
</footer> </footer>
</form> </form>
</field> </field>
</record> </record>
<!-- Link Advance Payment Wizard Action --> <!-- Link Advance Payment Wizard Action -->
<record id="action_link_advance_payment_wizard" model="ir.actions.act_window"> <record id="action_link_advance_payment_wizard" model="ir.actions.act_window">
<field name="name">Link Advance Payment</field> <field name="name">Link Advance Payment</field>
<field name="res_model">link.advance.payment.wizard</field> <field name="res_model">link.advance.payment.wizard</field>
<field name="view_mode">form</field> <field name="view_mode">form</field>
<field name="target">new</field> <field name="target">new</field>
</record> </record>
<!-- Link Advance Payment Wizard Action from Payment --> <!-- Link Advance Payment Wizard Action from Payment -->
<record id="action_link_advance_payment_wizard_payment" model="ir.actions.act_window"> <record id="action_link_advance_payment_wizard_payment" model="ir.actions.act_window">
<field name="name">Link to Purchase Order</field> <field name="name">Link to Purchase Order</field>
<field name="res_model">link.advance.payment.wizard</field> <field name="res_model">link.advance.payment.wizard</field>
<field name="view_mode">form</field> <field name="view_mode">form</field>
<field name="target">new</field> <field name="target">new</field>
<field name="context">{'active_model': 'account.payment', 'active_id': active_id}</field> <field name="context">{'active_model': 'account.payment', 'active_id': active_id}</field>
</record> </record>
</data> </data>
</odoo> </odoo>