[FIX] point_of_sale,pos_sale: correctly set analytic_distribution

Current behavior:
When you create a sale order with an analytic account, and settle it in
the POS, the analytic account is not set on the POS order invoice lines.

Steps to reproduce:
- Create a sale order with an analytic account (in other info tab)
- Confirm the sale order
- Go to the POS and settle the order
- Pay and invoice the order
- Go to the invoice and check the analytic account on the invoice lines

Note:
I based my fix on what was already done in the sale_order creation to
set the analytic distribution correctly on the invoice lines.

opw-3635140

closes odoo/odoo#147737

Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
This commit is contained in:
roen-odoo
2024-01-15 11:11:24 +00:00
parent 9eaecfa062
commit 179475a54e
5 changed files with 77 additions and 18 deletions
+14 -9
View File
@@ -233,6 +233,18 @@ class PosOrder(models.Model):
self.ensure_one()
return self.lines._prepare_tax_base_line_values(sign=sign)
@api.model
def _get_invoice_lines_values(self, line_values, pos_order_line):
return {
'product_id': line_values['product'].id,
'quantity': line_values['quantity'],
'discount': line_values['discount'],
'price_unit': line_values['price_unit'],
'name': line_values['name'],
'tax_ids': [(6, 0, line_values['taxes'].ids)],
'product_uom_id': line_values['uom'].id,
}
def _prepare_invoice_lines(self):
""" Prepare a list of orm commands containing the dictionaries to fill the
'invoice_line_ids' field when creating an invoice.
@@ -244,15 +256,8 @@ class PosOrder(models.Model):
invoice_lines = []
for line_values in line_values_list:
line = line_values['record']
invoice_lines.append((0, None, {
'product_id': line_values['product'].id,
'quantity': line_values['quantity'],
'discount': line_values['discount'],
'price_unit': line_values['price_unit'],
'name': line_values['name'],
'tax_ids': [(6, 0, line_values['taxes'].ids)],
'product_uom_id': line_values['uom'].id,
}))
invoice_lines_values = self._get_invoice_lines_values(line_values, line)
invoice_lines.append((0, None, invoice_lines_values))
if line.order_id.pricelist_id.discount_policy == 'without_discount' and float_compare(line.price_unit, line.product_id.lst_price, precision_rounding=self.currency_id.rounding) < 0:
invoice_lines.append((0, None, {
'name': _('Price discount from %s -> %s',
+8
View File
@@ -113,6 +113,14 @@ class PosOrder(models.Model):
'domain': [('id', 'in', linked_orders.ids)],
}
def _get_invoice_lines_values(self, line_values, pos_line):
inv_line_vals = super()._get_invoice_lines_values(line_values, pos_line)
if pos_line.sale_order_origin_id:
origin_line = pos_line.sale_order_line_id
origin_line._set_analytic_distribution(inv_line_vals)
return inv_line_vals
class PosOrderLine(models.Model):
_inherit = 'pos.order.line'
@@ -170,3 +170,19 @@ registry
].flat(),
});
registry
.category("web_tour.tours")
.add('PosSettleAndInvoiceOrder', {
test: true,
url: '/pos/ui',
steps: () => [
ProductScreen.confirmOpeningPopup(),
ProductScreen.clickQuotationButton(),
ProductScreen.selectFirstOrder(),
ProductScreen.clickPayButton(),
PaymentScreen.clickPaymentMethod("Bank"),
PaymentScreen.clickInvoiceButton(),
PaymentScreen.clickValidate(),
].flat(),
});
@@ -361,3 +361,30 @@ class TestPoSSale(TestPointOfSaleHttpCommon):
self.main_pos_config.open_ui()
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'PosSettleOrderWithNote', login="accountman")
def test_pos_invoice_analytic_account(self):
#create a sale order with product_a
self.analytic_plan_projects = self.env['account.analytic.plan'].create({'name': 'Projects'})
self.analytic_plan_departments = self.env['account.analytic.plan'].create({'name': 'Departments test'})
self.analytic_account_partner_a_1 = self.env['account.analytic.account'].create({
'name': 'analytic_account_partner_a_1',
'partner_id': self.partner_a.id,
'plan_id': self.analytic_plan_projects.id,
})
self.env['sale.order'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'order_line': [(0, 0, {
'product_id': self.desk_pad.id,
'name': self.desk_pad.name,
'product_uom_qty': 3.5,
'product_uom': self.desk_pad.uom_id.id,
'price_unit': self.desk_pad.lst_price,
})],
'analytic_account_id': self.analytic_account_partner_a_1.id,
})
self.main_pos_config.open_ui()
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'PosSettleAndInvoiceOrder', login="accountman")
pos_order = self.env['pos.order'].search([], order='id desc', limit=1)
self.assertTrue(pos_order.account_move.line_ids[0].analytic_distribution, "Analytic distribution should be set on the invoice line")
self.assertEqual(pos_order.account_move.line_ids[0].analytic_distribution.get(str(self.analytic_account_partner_a_1.id)), 100)
+12 -9
View File
@@ -1127,21 +1127,24 @@ class SaleOrderLine(models.Model):
'sale_line_ids': [Command.link(self.id)],
'is_downpayment': self.is_downpayment,
}
analytic_account_id = self.order_id.analytic_account_id.id
if self.analytic_distribution and not self.display_type:
res['analytic_distribution'] = self.analytic_distribution
if analytic_account_id and not self.display_type:
analytic_account_id = str(analytic_account_id)
if 'analytic_distribution' in res:
res['analytic_distribution'][analytic_account_id] = res['analytic_distribution'].get(analytic_account_id, 0) + 100
else:
res['analytic_distribution'] = {analytic_account_id: 100}
self._set_analytic_distribution(res, **optional_values)
if optional_values:
res.update(optional_values)
if self.display_type:
res['account_id'] = False
return res
def _set_analytic_distribution(self, inv_line_vals, **optional_values):
analytic_account_id = self.order_id.analytic_account_id.id
if self.analytic_distribution and not self.display_type:
inv_line_vals['analytic_distribution'] = self.analytic_distribution
if analytic_account_id and not self.display_type:
analytic_account_id = str(analytic_account_id)
if 'analytic_distribution' in inv_line_vals:
inv_line_vals['analytic_distribution'][analytic_account_id] = inv_line_vals['analytic_distribution'].get(analytic_account_id, 0) + 100
else:
inv_line_vals['analytic_distribution'] = {analytic_account_id: 100}
def _prepare_procurement_values(self, group_id=False):
""" Prepare specific key for moves or other components that will be created from a stock rule
coming from a sale order line. This method could be override in order to add other custom key that could