summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/point_of_sale/__manifest__.py1
-rw-r--r--addons/point_of_sale/models/pos_order.py56
-rw-r--r--addons/point_of_sale/static/src/js/models.js4
-rw-r--r--addons/point_of_sale/tests/test_anglo_saxon.py11
-rw-r--r--addons/point_of_sale/tests/test_point_of_sale_flow.py247
-rw-r--r--addons/point_of_sale/views/pos_order_view.xml18
-rw-r--r--addons/point_of_sale/wizard/__init__.py1
-rw-r--r--addons/point_of_sale/wizard/pos_discount.py17
-rw-r--r--addons/point_of_sale/wizard/pos_discount.xml27
9 files changed, 158 insertions, 224 deletions
diff --git a/addons/point_of_sale/__manifest__.py b/addons/point_of_sale/__manifest__.py
index bdc5f4983ec..1cb4f10517e 100644
--- a/addons/point_of_sale/__manifest__.py
+++ b/addons/point_of_sale/__manifest__.py
@@ -16,7 +16,6 @@
'data/digest_data.xml',
'wizard/pos_box.xml',
'wizard/pos_details.xml',
- 'wizard/pos_discount.xml',
'wizard/pos_open_statement.xml',
'wizard/pos_payment.xml',
'views/pos_templates.xml',
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index 547fd76565e..4fa895bd939 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -43,6 +43,10 @@ class PosOrder(models.Model):
'date_order': ui_order['creation_date'],
'fiscal_position_id': ui_order['fiscal_position_id'],
'pricelist_id': ui_order['pricelist_id'],
+ 'amount_paid': ui_order['amount_paid'],
+ 'amount_total': ui_order['amount_total'],
+ 'amount_tax': ui_order['amount_tax'],
+ 'amount_return': ui_order['amount_return'],
}
def _payment_fields(self, ui_paymentline):
@@ -463,10 +467,11 @@ class PosOrder(models.Model):
default=lambda self: self.env.uid,
states={'done': [('readonly', True)], 'invoiced': [('readonly', True)]},
)
- amount_tax = fields.Float(compute='_compute_amount_all', string='Taxes', digits=0)
- amount_total = fields.Float(compute='_compute_amount_all', string='Total', digits=0)
- amount_paid = fields.Float(compute='_compute_amount_all', string='Paid', states={'draft': [('readonly', False)]}, readonly=True, digits=0)
- amount_return = fields.Float(compute='_compute_amount_all', string='Returned', digits=0)
+ amount_tax = fields.Float(string='Taxes', digits=0, readonly=True, required=True)
+ amount_total = fields.Float(string='Total', digits=0, readonly=True, required=True)
+ amount_paid = fields.Float(string='Paid', states={'draft': [('readonly', False)]},
+ readonly=True, digits=0, required=True)
+ amount_return = fields.Float(string='Returned', digits=0, required=True, readonly=True)
lines = fields.One2many('pos.order.line', 'order_id', string='Order Lines', states={'draft': [('readonly', False)]}, readonly=True, copy=True)
statement_ids = fields.One2many('account.bank.statement.line', 'pos_statement_id', string='Payments', states={'draft': [('readonly', False)]}, readonly=True)
pricelist_id = fields.Many2one('product.pricelist', string='Pricelist', required=True, states={
@@ -505,10 +510,9 @@ class PosOrder(models.Model):
states={'draft': [('readonly', False)]},
)
- @api.depends('statement_ids', 'lines.price_subtotal_incl', 'lines.discount')
- def _compute_amount_all(self):
+ @api.onchange('statement_ids', 'lines', 'lines')
+ def _onchange_amount_all(self):
for order in self:
- order.amount_paid = order.amount_return = order.amount_tax = 0.0
currency = order.pricelist_id.currency_id
order.amount_paid = sum(payment.amount for payment in order.statement_ids)
order.amount_return = sum(payment.amount < 0 and payment.amount or 0 for payment in order.statement_ids)
@@ -861,10 +865,12 @@ class PosOrder(models.Model):
def add_payment(self, data):
"""Create a new payment for the order"""
+ self.ensure_one()
args = self._prepare_bank_statement_line_payment_values(data)
context = dict(self.env.context)
context.pop('pos_session_id', False)
self.env['account.bank.statement.line'].with_context(context).create(args)
+ self.amount_paid = sum(payment.amount for payment in self.statement_ids)
return args.get('statement_id', False)
@api.multi
@@ -882,6 +888,9 @@ class PosOrder(models.Model):
'date_order': fields.Datetime.now(),
'pos_reference': order.pos_reference,
'lines': False,
+ 'amount_tax': -order.amount_tax,
+ 'amount_total': -order.amount_total,
+ 'amount_paid': 0,
})
for line in order.lines:
clone_line = line.copy({
@@ -889,6 +898,8 @@ class PosOrder(models.Model):
'name': line.name + _(' REFUND'),
'order_id': clone.id,
'qty': -line.qty,
+ 'price_subtotal': -line.price_subtotal,
+ 'price_subtotal_incl': -line.price_subtotal_incl,
})
PosOrder += clone
@@ -931,8 +942,10 @@ class PosOrderLine(models.Model):
product_id = fields.Many2one('product.product', string='Product', domain=[('sale_ok', '=', True)], required=True, change_default=True)
price_unit = fields.Float(string='Unit Price', digits=0)
qty = fields.Float('Quantity', digits=dp.get_precision('Product Unit of Measure'), default=1)
- price_subtotal = fields.Float(compute='_compute_amount_line_all', digits=0, string='Subtotal w/o Tax')
- price_subtotal_incl = fields.Float(compute='_compute_amount_line_all', digits=0, string='Subtotal')
+ price_subtotal = fields.Float(string='Subtotal w/o Tax', digits=0,
+ readonly=True, required=True)
+ price_subtotal_incl = fields.Float(string='Subtotal', digits=0,
+ readonly=True, required=True)
discount = fields.Float(string='Discount (%)', digits=0, default=0.0)
order_id = fields.Many2one('pos.order', string='Order Ref', ondelete='cascade')
create_date = fields.Datetime(string='Creation Date', readonly=True)
@@ -965,17 +978,22 @@ class PosOrderLine(models.Model):
values['name'] = self.env['ir.sequence'].next_by_code('pos.order.line')
return super(PosOrderLine, self).create(values)
- @api.depends('price_unit', 'tax_ids', 'qty', 'discount', 'product_id')
- def _compute_amount_line_all(self):
+ @api.onchange('price_unit', 'tax_ids', 'qty', 'discount', 'product_id')
+ def _onchange_amount_line_all(self):
for line in self:
- fpos = line.order_id.fiscal_position_id
- tax_ids_after_fiscal_position = fpos.map_tax(line.tax_ids, line.product_id, line.order_id.partner_id) if fpos else line.tax_ids
- price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
- taxes = tax_ids_after_fiscal_position.compute_all(price, line.order_id.pricelist_id.currency_id, line.qty, product=line.product_id, partner=line.order_id.partner_id)
- line.update({
- 'price_subtotal_incl': taxes['total_included'],
- 'price_subtotal': taxes['total_excluded'],
- })
+ res = line._compute_amount_line_all()
+ line.update(res)
+
+ def _compute_amount_line_all(self):
+ self.ensure_one()
+ fpos = self.order_id.fiscal_position_id
+ tax_ids_after_fiscal_position = fpos.map_tax(self.tax_ids, self.product_id, self.order_id.partner_id) if fpos else self.tax_ids
+ price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
+ taxes = tax_ids_after_fiscal_position.compute_all(price, self.order_id.pricelist_id.currency_id, self.qty, product=self.product_id, partner=self.order_id.partner_id)
+ return {
+ 'price_subtotal_incl': taxes['total_included'],
+ 'price_subtotal': taxes['total_excluded'],
+ }
@api.onchange('product_id')
def _onchange_product_id(self):
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index 91e234dafc5..b4a1e0ff6ae 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -1530,6 +1530,8 @@ exports.Orderline = Backbone.Model.extend({
return {
qty: this.get_quantity(),
price_unit: this.get_unit_price(),
+ price_subtotal: this.get_price_without_tax(),
+ price_subtotal_incl: this.get_price_with_tax(),
discount: this.get_discount(),
product_id: this.get_product().id,
tax_ids: [[6, false, _.map(this.get_applicable_taxes(), function(tax){ return tax.id; })]],
@@ -2049,7 +2051,7 @@ exports.Order = Backbone.Model.extend({
}, this));
return {
name: this.get_name(),
- amount_paid: this.get_total_paid(),
+ amount_paid: this.get_total_paid() - this.get_change(),
amount_total: this.get_total_with_tax(),
amount_tax: this.get_total_tax(),
amount_return: this.get_change(),
diff --git a/addons/point_of_sale/tests/test_anglo_saxon.py b/addons/point_of_sale/tests/test_anglo_saxon.py
index b6d27af9505..7fae0de8b83 100644
--- a/addons/point_of_sale/tests/test_anglo_saxon.py
+++ b/addons/point_of_sale/tests/test_anglo_saxon.py
@@ -70,8 +70,14 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
'product_id': self.product.id,
'price_unit': 450,
'discount': 0.0,
- 'qty': 1.0
- })]
+ 'qty': 1.0,
+ 'price_subtotal': 450,
+ 'price_subtotal_incl': 450,
+ })],
+ 'amount_total': 450,
+ 'amount_tax': 0,
+ 'amount_paid': 0,
+ 'amount_return': 0,
})
# I make a payment to fully pay the order
@@ -87,6 +93,7 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
# I check that the order is marked as paid
self.assertEqual(self.pos_order_pos0.state, 'paid', 'Order should be in paid state.')
+ self.assertEqual(self.pos_order_pos0.amount_paid, 450, 'Amount paid for the order should be updated.')
# I close the current session to generate the journal entries
self.pos_config.current_session_id.action_pos_session_close()
diff --git a/addons/point_of_sale/tests/test_point_of_sale_flow.py b/addons/point_of_sale/tests/test_point_of_sale_flow.py
index 94db310f3e6..4f982486bf0 100644
--- a/addons/point_of_sale/tests/test_point_of_sale_flow.py
+++ b/addons/point_of_sale/tests/test_point_of_sale_flow.py
@@ -17,104 +17,6 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
# open all statements/cash registers
self.env['pos.open.statement'].create({}).open_statement()
- def test_order_to_payment(self):
- """
- In order to test the Point of Sale in module, I will do a full flow from the sale to the payment and invoicing.
- I will use two products, one with price including a 10% tax, the other one with 5% tax excluded from the price.
- """
- # I click on create a new session button
- self.pos_config.open_session_cb()
-
- # I create a PoS order with 2 units of PCSC234 at 450 EUR (Tax Incl)
- # and 3 units of PCSC349 at 300 EUR. (Tax Excl)
- self.pos_order_pos0 = self.PosOrder.create({
- 'company_id': self.company_id,
- 'pricelist_id': self.partner1.property_product_pricelist.id,
- 'partner_id': self.partner1.id,
- 'lines': [(0, 0, {
- 'name': "OL/0001",
- 'product_id': self.product3.id,
- 'price_unit': 450,
- 'discount': 0.0,
- 'qty': 2.0,
- 'tax_ids': [(6, 0, self.product3.taxes_id.ids)],
- }), (0, 0, {
- 'name': "OL/0002",
- 'product_id': self.product4.id,
- 'price_unit': 300,
- 'discount': 0.0,
- 'qty': 3.0,
- 'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
- })]
- })
-
- # I check that the total of the order is equal to 450*2 + 300*3*1.05
- # and the tax of the order is equal to 900 -(450 * 2 / 1.1) +
- # 300*0.05*3
- self.assertLess(
- abs(self.pos_order_pos0.amount_total - (450 * 2 + 300 * 3 * 1.05)),
- 0.01, 'The order has a wrong amount, tax included.')
-
- self.assertLess(
- abs(self.pos_order_pos0.amount_tax - (900 - (450 * 2 / 1.1) + 300 * 0.05 * 3)),
- 0.01, 'The order has a wrong tax amount.')
-
- # I want to add a global discount of 5 percent using the wizard
-
- self.pos_discount_0 = self.env['pos.discount'].create({'discount': 5.0})
-
- context = {"active_model": "pos.order", "active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
-
- # I click the apply button to set the discount on all lines
- self.pos_discount_0.with_context(context).apply_discount()
-
- # I check that the total of the order is now equal to (450*2 +
- # 300*3*1.05)*0.95
- self.assertLess(
- abs(self.pos_order_pos0.amount_total - (450 * 2 + 300 * 3 * 1.05) * 0.95),
- 0.01, 'The order has a wrong total including tax and discounts')
-
- # I click on the "Make Payment" wizard to pay the PoS order with a
- # partial amount of 100.0 EUR
- context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
- self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
- 'amount': 100.0
- })
-
- # I click on the validate button to register the payment.
- context_payment = {'active_id': self.pos_order_pos0.id}
- self.pos_make_payment_0.with_context(context_payment).check()
-
- # I check that the order is not marked as paid yet
- self.assertEqual(self.pos_order_pos0.state, 'draft', 'Order should be in draft state.')
-
- # On the second payment proposition, I check that it proposes me the
- # remaining balance which is 1790.0 EUR
- defs = self.pos_make_payment_0.with_context({'active_id': self.pos_order_pos0.id}).default_get(['amount'])
-
- self.assertLess(
- abs(defs['amount'] - ((450 * 2 + 300 * 3 * 1.05) * 0.95 - 100.0)), 0.01, "The remaining balance is incorrect.")
-
- #'I pay the remaining balance.
- context_make_payment = {
- "active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
-
- self.pos_make_payment_1 = self.PosMakePayment.with_context(context_make_payment).create({
- 'amount': (450 * 2 + 300 * 3 * 1.05) * 0.95 - 100.0
- })
-
- # I click on the validate button to register the payment.
- self.pos_make_payment_1.with_context(context_make_payment).check()
-
- # I check that the order is marked as paid
- self.assertEqual(self.pos_order_pos0.state, 'paid', 'Order should be in paid state.')
-
- # I generate the journal entries
- self.pos_order_pos0._create_account_move_line()
-
- # I test that the generated journal entry is attached to the PoS order
- self.assertTrue(self.pos_order_pos0.account_move, "Journal entry has not been attached to Pos order.")
-
def test_order_refund(self):
# I create a new PoS order with 2 lines
order = self.PosOrder.create({
@@ -128,6 +30,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 5.0,
'qty': 2.0,
'tax_ids': [(6, 0, self.product3.taxes_id.ids)],
+ 'price_subtotal': 450 * (1 - 5/100.0) * 2,
+ 'price_subtotal_incl': 450 * (1 - 5/100.0) * 2,
}), (0, 0, {
'name': "OL/0002",
'product_id': self.product4.id,
@@ -135,7 +39,13 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 5.0,
'qty': 3.0,
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
- })]
+ 'price_subtotal': 300 * (1 - 5/100.0) * 3,
+ 'price_subtotal_incl': 300 * (1 - 5/100.0) * 3,
+ })],
+ 'amount_total': 1710.0,
+ 'amount_tax': 0.0,
+ 'amount_paid': 1710.0,
+ 'amount_return': 0.0,
})
# I create a refund
@@ -163,11 +73,22 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
TODO: Check the negative picking after changing the picking relation to One2many (also for a mixed use case),
check the quantity, the locations and return picking logic
"""
+
+ def compute_tax(product, price, qty=1, taxes=None):
+ if taxes is None:
+ taxes = product.taxes_id.filtered(lambda t: t.company_id.id == self.env.user.id)
+ currency = self.pos_config.pricelist_id.currency_id
+ res = taxes.compute_all(price, currency, qty, product=product)
+ untax = res['total_excluded']
+ return untax, sum(tax.get('amount', 0.0) for tax in res['taxes'])
+
# I click on create a new session button
self.pos_config.open_session_cb()
# I create a PoS order with 2 units of PCSC234 at 450 EUR
# and 3 units of PCSC349 at 300 EUR.
+ untax1, atax1 = compute_tax(self.product3, 450, 2)
+ untax2, atax2 = compute_tax(self.product4, 300, 3)
self.pos_order_pos1 = self.PosOrder.create({
'company_id': self.company_id,
'pricelist_id': self.partner1.property_product_pricelist.id,
@@ -179,6 +100,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 0.0,
'qty': 2.0,
'tax_ids': [(6, 0, self.product3.taxes_id.ids)],
+ 'price_subtotal': untax1,
+ 'price_subtotal_incl': untax1 + atax1,
}), (0, 0, {
'name': "OL/0002",
'product_id': self.product4.id,
@@ -186,7 +109,13 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 0.0,
'qty': 3.0,
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
- })]
+ 'price_subtotal': untax2,
+ 'price_subtotal_incl': untax2 + atax2,
+ })],
+ 'amount_tax': atax1 + atax2,
+ 'amount_total': untax1 + untax2 + atax1 + atax2,
+ 'amount_paid': 0,
+ 'amount_return': 0,
})
context_make_payment = {
@@ -194,13 +123,13 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
"active_id": self.pos_order_pos1.id
}
self.pos_make_payment_2 = self.PosMakePayment.with_context(context_make_payment).create({
- 'amount': 1845
+ 'amount': untax1 + untax2 + atax1 + atax2
})
# I click on the validate button to register the payment.
context_payment = {'active_id': self.pos_order_pos1.id}
- self.pos_make_payment_2.with_context(context_payment).check()
+ self.pos_make_payment_2.with_context(context_payment).check()
# I check that the order is marked as paid
self.assertEqual(
self.pos_order_pos1.state,
@@ -208,18 +137,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'Order should be in paid state.'
)
- # I generate the journal entries
- self.pos_order_pos1._create_account_move_line()
-
- # I test that the generated journal entry is attached to the PoS order
- self.assertTrue(
- self.pos_order_pos1.account_move,
- "Journal entry has not been attached to Pos order."
- )
-
- # I test that the pickings are created as expected
+ # I test that the pickings are created as expected during payment
# One picking attached and having all the positive move lines in the correct state
- self.pos_order_pos1.create_picking()
self.assertEqual(
self.pos_order_pos1.picking_id.state,
'done',
@@ -231,6 +150,9 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'Move Lines should be in done state.'
)
+ # I create a second order
+ untax1, atax1 = compute_tax(self.product3, 450, -2)
+ untax2, atax2 = compute_tax(self.product4, 300, -3)
self.pos_order_pos2 = self.PosOrder.create({
'company_id': self.company_id,
'pricelist_id': self.partner1.property_product_pricelist.id,
@@ -242,6 +164,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 0.0,
'qty': (-2.0),
'tax_ids': [(6, 0, self.product3.taxes_id.ids)],
+ 'price_subtotal': untax1,
+ 'price_subtotal_incl': untax1 + atax1,
}), (0, 0, {
'name': "OL/0004",
'product_id': self.product4.id,
@@ -249,7 +173,13 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 0.0,
'qty': (-3.0),
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
- })]
+ 'price_subtotal': untax2,
+ 'price_subtotal_incl': untax2 + atax2,
+ })],
+ 'amount_tax': atax1 + atax2,
+ 'amount_total': untax1 + untax2 + atax1 + atax2,
+ 'amount_paid': 0,
+ 'amount_return': 0,
})
context_make_payment = {
@@ -257,7 +187,7 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
"active_id": self.pos_order_pos2.id
}
self.pos_make_payment_3 = self.PosMakePayment.with_context(context_make_payment).create({
- 'amount': (-1845)
+ 'amount': untax1 + untax2 + atax1 + atax2
})
# I click on the validate button to register the payment.
@@ -271,15 +201,6 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'Order should be in paid state.'
)
- # I generate the journal entries
- self.pos_order_pos2._create_account_move_line()
-
- # I test that the generated journal entry is attached to the PoS order
- self.assertTrue(
- self.pos_order_pos2.account_move,
- "Journal entry has not been attached to PoS order."
- )
-
# I test that the pickings are created as expected
# One picking attached and having all the positive move lines in the correct state
self.pos_order_pos2.create_picking()
@@ -294,6 +215,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'Move Lines should be in done state.'
)
+ untax1, atax1 = compute_tax(self.product3, 450, -2)
+ untax2, atax2 = compute_tax(self.product4, 300, 3)
self.pos_order_pos3 = self.PosOrder.create({
'company_id': self.company_id,
'pricelist_id': self.partner1.property_product_pricelist.id,
@@ -305,6 +228,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 0.0,
'qty': (-2.0),
'tax_ids': [(6, 0, self.product3.taxes_id.ids)],
+ 'price_subtotal': untax1,
+ 'price_subtotal_incl': untax1 + atax1,
}), (0, 0, {
'name': "OL/0006",
'product_id': self.product4.id,
@@ -312,7 +237,13 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 0.0,
'qty': 3.0,
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
- })]
+ 'price_subtotal': untax2,
+ 'price_subtotal_incl': untax2 + atax2,
+ })],
+ 'amount_tax': atax1 + atax2,
+ 'amount_total': untax1 + untax2 + atax1 + atax2,
+ 'amount_paid': 0,
+ 'amount_return': 0,
})
context_make_payment = {
@@ -320,7 +251,7 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
"active_id": self.pos_order_pos3.id
}
self.pos_make_payment_4 = self.PosMakePayment.with_context(context_make_payment).create({
- 'amount': 45,
+ 'amount': untax1 + untax2 + atax1 + atax2,
})
# I click on the validate button to register the payment.
@@ -334,18 +265,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'Order should be in paid state.'
)
- # I generate the journal entries
- self.pos_order_pos3._create_account_move_line()
-
- # I test that the generated journal entry is attached to the PoS order
- self.assertTrue(
- self.pos_order_pos3.account_move,
- "Journal entry has not been attached to PoS order."
- )
-
# I test that the pickings are created as expected
# One picking attached and having all the positive move lines in the correct state
- self.pos_order_pos3.create_picking()
self.assertEqual(
self.pos_order_pos3.picking_id.state,
'done',
@@ -356,9 +277,22 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
['done'],
'Move Lines should be in done state.'
)
+ # I close the session to generate the journal entries
+ self.pos_config.current_session_id.action_pos_session_closing_control()
+
def test_order_to_invoice(self):
+ def compute_tax(product, price, qty=1, taxes=None):
+ if taxes is None:
+ taxes = product.taxes_id.filtered(lambda t: t.company_id.id == self.env.user.id)
+ currency = self.pos_config.pricelist_id.currency_id
+ res = taxes.compute_all(price, currency, qty, product=product)
+ untax = res['total_excluded']
+ return untax, sum(tax.get('amount', 0.0) for tax in res['taxes'])
+
+ untax1, atax1 = compute_tax(self.product3, 450*0.95, 2)
+ untax2, atax2 = compute_tax(self.product4, 300*0.95, 3)
# I create a new PoS order with 2 units of PC1 at 450 EUR (Tax Incl) and 3 units of PCSC349 at 300 EUR. (Tax Excl)
self.pos_order_pos1 = self.PosOrder.create({
'company_id': self.company_id,
@@ -371,6 +305,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 5.0,
'qty': 2.0,
'tax_ids': [(6, 0, self.product3.taxes_id.ids)],
+ 'price_subtotal': untax1,
+ 'price_subtotal_incl': untax1 + atax1,
}), (0, 0, {
'name': "OL/0002",
'product_id': self.product4.id,
@@ -378,13 +314,19 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'discount': 5.0,
'qty': 3.0,
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
- })]
+ 'price_subtotal': untax2,
+ 'price_subtotal_incl': untax2 + atax2,
+ })],
+ 'amount_tax': atax1 + atax2,
+ 'amount_total': untax1 + untax2 + atax1 + atax2,
+ 'amount_paid': 0.0,
+ 'amount_return': 0.0,
})
# I click on the "Make Payment" wizard to pay the PoS order
context_make_payment = {"active_ids": [self.pos_order_pos1.id], "active_id": self.pos_order_pos1.id}
self.pos_make_payment = self.PosMakePayment.with_context(context_make_payment).create({
- 'amount': (450 * 2 + 300 * 3 * 1.05) * 0.95,
+ 'amount': untax1 + untax2 + atax1 + atax2,
})
# I click on the validate button to register the payment.
context_payment = {'active_id': self.pos_order_pos1.id}
@@ -401,8 +343,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
# I test that the total of the attached invoice is correct
invoice = self.env['account.invoice'].browse(res['res_id'])
- self.assertEqual(
- float_compare(invoice.amount_total, 1752.75, precision_digits=2), 0, "Invoice not correct")
+ self.assertAlmostEqual(
+ invoice.amount_total, self.pos_order_pos1.amount_total, places=2, msg="Invoice not correct")
"""In order to test the reports on Bank Statement defined in point_of_sale module, I create a bank statement line, confirm it and print the reports"""
@@ -456,15 +398,14 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
"""
Simulation of sales coming from the interface, even after closing the session
"""
- FROMPRODUCT = object()
- def compute_tax(product, price, taxes=FROMPRODUCT, qty=1):
- if taxes is FROMPRODUCT:
- taxes = product.taxes_id
+ def compute_tax(product, price, qty=1, taxes=None):
+ if not taxes:
+ taxes = product.taxes_id.filtered(lambda t: t.company_id.id == self.env.user.id)
currency = self.pos_config.pricelist_id.currency_id
- taxes = taxes.compute_all(price, currency, qty, product=product)['taxes']
- untax = price * qty
- return untax, sum(tax.get('amount', 0.0) for tax in taxes)
+ res = taxes.compute_all(price, currency, qty, product=product)
+ untax = res['total_excluded']
+ return untax, sum(tax.get('amount', 0.0) for tax in res['taxes'])
# I click on create a new session button
self.pos_config.open_session_cb()
@@ -478,7 +419,7 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'amount_return': 0,
'amount_tax': atax,
'amount_total': untax + atax,
- 'creation_date': fields.Datetime.now(),
+ 'creation_date': fields.Datetime.to_string(fields.Datetime.now()),
'fiscal_position_id': False,
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
'lines': [[0,
@@ -488,6 +429,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'pack_lot_ids': [],
'price_unit': 0.9,
'product_id': self.led_lamp.id,
+ 'price_subtotal': 0.9,
+ 'price_subtotal_incl': 1.04,
'qty': 1,
'tax_ids': [(6, 0, self.led_lamp.taxes_id.ids)]}]],
'name': 'Order 00042-003-0014',
@@ -512,7 +455,7 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'amount_return': 0,
'amount_tax': atax,
'amount_total': untax + atax,
- 'creation_date': fields.Datetime.now(),
+ 'creation_date': fields.Datetime.to_string(fields.Datetime.now()),
'fiscal_position_id': False,
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
'lines': [[0,
@@ -522,6 +465,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'pack_lot_ids': [],
'price_unit': 1.2,
'product_id': self.whiteboard_pen.id,
+ 'price_subtotal': 1.2,
+ 'price_subtotal_incl': 1.38,
'qty': 1,
'tax_ids': [(6, 0, self.whiteboard_pen.taxes_id.ids)]}]],
'name': 'Order 00043-003-0014',
@@ -546,7 +491,7 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'amount_return': 0,
'amount_tax': atax,
'amount_total': untax + atax,
- 'creation_date': fields.Datetime.now(),
+ 'creation_date': fields.Datetime.to_string(fields.Datetime.now()),
'fiscal_position_id': False,
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
'lines': [[0,
@@ -556,6 +501,8 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
'pack_lot_ids': [],
'price_unit': 1.28,
'product_id': self.newspaper_rack.id,
+ 'price_subtotal': 1.28,
+ 'price_subtotal_incl': 1.47,
'qty': 1,
'tax_ids': [[6, False, self.newspaper_rack.taxes_id.ids]]}]],
'name': 'Order 00044-003-0014',
diff --git a/addons/point_of_sale/views/pos_order_view.xml b/addons/point_of_sale/views/pos_order_view.xml
index eaf712483a1..d5c61ec4049 100644
--- a/addons/point_of_sale/views/pos_order_view.xml
+++ b/addons/point_of_sale/views/pos_order_view.xml
@@ -41,8 +41,8 @@
<field name="discount" widget="monetary"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tags" string="Taxes"/>
<field name="tax_ids" widget="many2many_tags" invisible="1"/>
- <field name="price_subtotal" widget="monetary"/>
- <field name="price_subtotal_incl" widget="monetary"/>
+ <field name="price_subtotal" widget="monetary" force_save="1"/>
+ <field name="price_subtotal_incl" widget="monetary" force_save="1"/>
</tree>
<form string="Order lines">
<group col="4">
@@ -50,8 +50,8 @@
<field name="qty"/>
<field name="discount" widget="monetary"/>
<field name="price_unit" widget="monetary"/>
- <field name="price_subtotal" invisible="1" widget="monetary"/>
- <field name="price_subtotal_incl" invisible="1" widget="monetary"/>
+ <field name="price_subtotal" invisible="1" widget="monetary" force_save="1"/>
+ <field name="price_subtotal_incl" invisible="1" widget="monetary" force_save="1"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tags" string="Taxes"/>
<field name="tax_ids" widget="many2many_tags" invisible="1"/>
<field name="notice"/>
@@ -59,13 +59,19 @@
</form>
</field>
<group class="oe_subtotal_footer oe_right" colspan="2" name="order_total">
- <field name="amount_tax" widget="monetary"/>
+ <field name="amount_tax"
+ force_save="1"
+ widget="monetary"/>
<div class="oe_subtotal_footer_separator oe_inline">
<label for="amount_total" />
<button name="button_dummy"
states="draft" string="(update)" class="oe_edit_only oe_link"/>
</div>
- <field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator" widget="monetary"/>
+ <field name="amount_total"
+ force_save="1"
+ nolabel="1"
+ class="oe_subtotal_footer_separator"
+ widget="monetary"/>
</group>
<div class="oe_clear"/>
</page>
diff --git a/addons/point_of_sale/wizard/__init__.py b/addons/point_of_sale/wizard/__init__.py
index 5801aa23b37..d85d8a81c86 100644
--- a/addons/point_of_sale/wizard/__init__.py
+++ b/addons/point_of_sale/wizard/__init__.py
@@ -3,6 +3,5 @@
from . import pos_box
from . import pos_details
-from . import pos_discount
from . import pos_open_statement
from . import pos_payment
diff --git a/addons/point_of_sale/wizard/pos_discount.py b/addons/point_of_sale/wizard/pos_discount.py
deleted file mode 100644
index d45f81055b8..00000000000
--- a/addons/point_of_sale/wizard/pos_discount.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models
-
-
-class PosDiscount(models.TransientModel):
- _name = 'pos.discount'
- _description = 'Add a Global Discount'
-
- discount = fields.Float(string='Discount (%)', required=True, digits=(16, 2), default=5)
-
- @api.multi
- def apply_discount(self):
- self.ensure_one()
- for order in self.env['pos.order'].browse(self.env.context.get('active_id', False)):
- order.lines.write({'discount': self.discount})
diff --git a/addons/point_of_sale/wizard/pos_discount.xml b/addons/point_of_sale/wizard/pos_discount.xml
deleted file mode 100644
index ff466c2dadc..00000000000
--- a/addons/point_of_sale/wizard/pos_discount.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<odoo>
- <record id="view_pos_discount" model="ir.ui.view">
- <field name="name">pos.discount.form</field>
- <field name="model">pos.discount</field>
- <field name="arch" type="xml">
- <form string="Apply Discount">
- <group>
- <field name="discount"/>
- </group>
- <footer>
- <button name="apply_discount" string="Apply Discount" type="object" class="btn-primary"/>
- <button string="Cancel" class="btn-secondary" special="cancel" />
- </footer>
- </form>
- </field>
- </record>
-
- <record id="action_pos_discount" model="ir.actions.act_window">
- <field name="name">Apply Discount</field>
- <field name="type">ir.actions.act_window</field>
- <field name="res_model">pos.discount</field>
- <field name="view_type">form</field>
- <field name="view_mode">form</field>
- <field name="target">new</field>
- </record>
-</odoo>