2018-01-16 06:58:15 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import time
|
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
import flectra
|
|
|
|
from flectra import fields
|
|
|
|
from flectra.tools import float_compare, mute_logger, test_reports
|
|
|
|
from flectra.addons.point_of_sale.tests.common import TestPointOfSaleCommon
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
@flectra.tests.common.at_install(False)
|
|
|
|
@flectra.tests.common.post_install(True)
|
2018-01-16 06:58:15 +01:00
|
|
|
class TestPointOfSaleFlow(TestPointOfSaleCommon):
|
|
|
|
|
|
|
|
def test_register_open(self):
|
|
|
|
"""
|
|
|
|
In order to test the Point of Sale module, I will open all cash registers through the wizard
|
|
|
|
"""
|
|
|
|
# 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({
|
|
|
|
'company_id': self.company_id,
|
|
|
|
'partner_id': self.partner1.id,
|
|
|
|
'pricelist_id': self.partner1.property_product_pricelist.id,
|
|
|
|
'lines': [(0, 0, {
|
|
|
|
'name': "OL/0001",
|
|
|
|
'product_id': self.product3.id,
|
|
|
|
'price_unit': 450,
|
|
|
|
'discount': 5.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': 5.0,
|
|
|
|
'qty': 3.0,
|
|
|
|
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
# I create a refund
|
|
|
|
refund_action = order.refund()
|
|
|
|
refund = self.PosOrder.browse(refund_action['res_id'])
|
|
|
|
|
|
|
|
self.assertEqual(order.amount_total, -1*refund.amount_total,
|
|
|
|
"The refund does not cancel the order (%s and %s)" % (order.amount_total, refund.amount_total))
|
|
|
|
|
|
|
|
payment_context = {"active_ids": refund.ids, "active_id": refund.id}
|
|
|
|
refund_payment = self.PosMakePayment.with_context(**payment_context).create({
|
|
|
|
'amount': refund.amount_total
|
|
|
|
})
|
|
|
|
|
|
|
|
# I click on the validate button to register the payment.
|
|
|
|
refund_payment.with_context(**payment_context).check()
|
|
|
|
|
|
|
|
self.assertEqual(refund.state, 'paid', "The refund is not marked as paid")
|
|
|
|
|
|
|
|
def test_order_to_picking(self):
|
|
|
|
"""
|
|
|
|
In order to test the Point of Sale in module, I will do three orders from the sale to the payment,
|
|
|
|
invoicing + picking, but will only check the picking consistency in the end.
|
|
|
|
|
|
|
|
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
|
|
|
|
"""
|
|
|
|
# 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.
|
|
|
|
self.pos_order_pos1 = 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)],
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
context_make_payment = {
|
|
|
|
"active_ids": [self.pos_order_pos1.id],
|
|
|
|
"active_id": self.pos_order_pos1.id
|
|
|
|
}
|
|
|
|
self.pos_make_payment_2 = self.PosMakePayment.with_context(context_make_payment).create({
|
|
|
|
'amount': 1845
|
|
|
|
})
|
|
|
|
|
|
|
|
# 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()
|
|
|
|
|
|
|
|
# I check that the order is marked as paid
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos1.state,
|
|
|
|
'paid',
|
|
|
|
'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
|
|
|
|
# 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',
|
|
|
|
'Picking should be in done state.'
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos1.picking_id.move_lines.mapped('state'),
|
|
|
|
['done', 'done'],
|
|
|
|
'Move Lines should be in done state.'
|
|
|
|
)
|
|
|
|
|
|
|
|
self.pos_order_pos2 = 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/0003",
|
|
|
|
'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/0004",
|
|
|
|
'product_id': self.product4.id,
|
|
|
|
'price_unit': 300,
|
|
|
|
'discount': 0.0,
|
|
|
|
'qty': (-3.0),
|
|
|
|
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
context_make_payment = {
|
|
|
|
"active_ids": [self.pos_order_pos2.id],
|
|
|
|
"active_id": self.pos_order_pos2.id
|
|
|
|
}
|
|
|
|
self.pos_make_payment_3 = self.PosMakePayment.with_context(context_make_payment).create({
|
|
|
|
'amount': (-1845)
|
|
|
|
})
|
|
|
|
|
|
|
|
# I click on the validate button to register the payment.
|
|
|
|
context_payment = {'active_id': self.pos_order_pos2.id}
|
|
|
|
self.pos_make_payment_3.with_context(context_payment).check()
|
|
|
|
|
|
|
|
# I check that the order is marked as paid
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos2.state,
|
|
|
|
'paid',
|
|
|
|
'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()
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos2.picking_id.state,
|
|
|
|
'done',
|
|
|
|
'Picking should be in done state.'
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos2.picking_id.move_lines.mapped('state'),
|
|
|
|
['done', 'done'],
|
|
|
|
'Move Lines should be in done state.'
|
|
|
|
)
|
|
|
|
|
|
|
|
self.pos_order_pos3 = 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/0005",
|
|
|
|
'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/0006",
|
|
|
|
'product_id': self.product4.id,
|
|
|
|
'price_unit': 300,
|
|
|
|
'discount': 0.0,
|
|
|
|
'qty': 3.0,
|
|
|
|
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
context_make_payment = {
|
|
|
|
"active_ids": [self.pos_order_pos3.id],
|
|
|
|
"active_id": self.pos_order_pos3.id
|
|
|
|
}
|
|
|
|
self.pos_make_payment_4 = self.PosMakePayment.with_context(context_make_payment).create({
|
|
|
|
'amount': 45,
|
|
|
|
})
|
|
|
|
|
|
|
|
# I click on the validate button to register the payment.
|
|
|
|
context_payment = {'active_id': self.pos_order_pos3.id}
|
|
|
|
self.pos_make_payment_4.with_context(context_payment).check()
|
|
|
|
|
|
|
|
# I check that the order is marked as paid
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos3.state,
|
|
|
|
'paid',
|
|
|
|
'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',
|
|
|
|
'Picking should be in done state.'
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
self.pos_order_pos3.picking_id.move_lines.mapped('state'),
|
|
|
|
['done'],
|
|
|
|
'Move Lines should be in done state.'
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_order_to_invoice(self):
|
|
|
|
|
|
|
|
# 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,
|
|
|
|
'partner_id': self.partner1.id,
|
|
|
|
'pricelist_id': self.partner1.property_product_pricelist.id,
|
|
|
|
'lines': [(0, 0, {
|
|
|
|
'name': "OL/0001",
|
|
|
|
'product_id': self.product3.id,
|
|
|
|
'price_unit': 450,
|
|
|
|
'discount': 5.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': 5.0,
|
|
|
|
'qty': 3.0,
|
|
|
|
'tax_ids': [(6, 0, self.product4.taxes_id.ids)],
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
# 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,
|
|
|
|
})
|
|
|
|
# I click on the validate button to register the payment.
|
|
|
|
context_payment = {'active_id': self.pos_order_pos1.id}
|
|
|
|
self.pos_make_payment.with_context(context_payment).check()
|
|
|
|
|
|
|
|
# I check that the order is marked as paid and there is no invoice
|
|
|
|
# attached to it
|
|
|
|
self.assertEqual(self.pos_order_pos1.state, 'paid', "Order should be in paid state.")
|
|
|
|
self.assertFalse(self.pos_order_pos1.invoice_id, 'Invoice should not be attached to order.')
|
|
|
|
|
|
|
|
# I generate an invoice from the order
|
|
|
|
res = self.pos_order_pos1.action_pos_order_invoice()
|
|
|
|
self.assertIn('res_id', res, "No invoice created")
|
|
|
|
|
|
|
|
# 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")
|
|
|
|
|
|
|
|
"""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"""
|
|
|
|
|
|
|
|
# I select the period and journal for the bank statement
|
|
|
|
|
|
|
|
context_journal = {'journal_type': 'bank'}
|
|
|
|
self.assertTrue(self.AccountBankStatement.with_context(
|
|
|
|
context_journal)._default_journal(), 'Journal has not been selected')
|
|
|
|
journal = self.env['account.journal'].create({
|
|
|
|
'name': 'Bank Test',
|
|
|
|
'code': 'BNKT',
|
|
|
|
'type': 'bank',
|
|
|
|
'company_id': self.company_id,
|
|
|
|
})
|
|
|
|
# I create a bank statement with Opening and Closing balance 0.
|
|
|
|
account_statement = self.AccountBankStatement.create({
|
|
|
|
'balance_start': 0.0,
|
|
|
|
'balance_end_real': 0.0,
|
|
|
|
'date': time.strftime('%Y-%m-%d'),
|
|
|
|
'journal_id': journal.id,
|
|
|
|
'company_id': self.company_id,
|
|
|
|
'name': 'pos session test',
|
|
|
|
})
|
|
|
|
# I create bank statement line
|
|
|
|
account_statement_line = self.AccountBankStatementLine.create({
|
|
|
|
'amount': 1000,
|
|
|
|
'partner_id': self.partner4.id,
|
|
|
|
'statement_id': account_statement.id,
|
|
|
|
'name': 'EXT001'
|
|
|
|
})
|
|
|
|
# I modify the bank statement and set the Closing Balance.
|
|
|
|
account_statement.write({
|
|
|
|
'balance_end_real': 1000.0,
|
|
|
|
})
|
|
|
|
|
|
|
|
# I reconcile the bank statement.
|
|
|
|
new_aml_dicts = [{
|
|
|
|
'account_id': self.partner4.property_account_receivable_id.id,
|
|
|
|
'name': "EXT001",
|
|
|
|
'credit': 1000.0,
|
|
|
|
'debit': 0.0,
|
|
|
|
}]
|
|
|
|
|
|
|
|
account_statement_line.process_reconciliations([{'new_aml_dicts': new_aml_dicts}])
|
|
|
|
|
|
|
|
# I confirm the bank statement using Confirm button
|
|
|
|
|
|
|
|
self.AccountBankStatement.button_confirm_bank()
|
|
|
|
|
|
|
|
def test_create_from_ui(self):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
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)
|
|
|
|
|
|
|
|
# I click on create a new session button
|
|
|
|
self.pos_config.open_session_cb()
|
|
|
|
|
|
|
|
current_session = self.pos_config.current_session_id
|
|
|
|
num_starting_orders = len(current_session.order_ids)
|
|
|
|
|
|
|
|
untax, atax = compute_tax(self.carotte, 0.9)
|
|
|
|
carrot_order = {'data':
|
|
|
|
{'amount_paid': untax + atax,
|
|
|
|
'amount_return': 0,
|
|
|
|
'amount_tax': atax,
|
|
|
|
'amount_total': untax + atax,
|
|
|
|
'creation_date': fields.Datetime.now(),
|
|
|
|
'fiscal_position_id': False,
|
|
|
|
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
|
|
|
|
'lines': [[0,
|
|
|
|
0,
|
|
|
|
{'discount': 0,
|
|
|
|
'id': 42,
|
|
|
|
'pack_lot_ids': [],
|
|
|
|
'price_unit': 0.9,
|
|
|
|
'product_id': self.carotte.id,
|
|
|
|
'qty': 1,
|
|
|
|
'tax_ids': [(6, 0, self.carotte.taxes_id.ids)]}]],
|
|
|
|
'name': 'Order 00042-003-0014',
|
|
|
|
'partner_id': False,
|
|
|
|
'pos_session_id': current_session.id,
|
|
|
|
'sequence_number': 2,
|
|
|
|
'statement_ids': [[0,
|
|
|
|
0,
|
|
|
|
{'account_id': self.env.user.partner_id.property_account_receivable_id.id,
|
|
|
|
'amount': untax + atax,
|
|
|
|
'journal_id': self.pos_config.journal_ids[0].id,
|
|
|
|
'name': fields.Datetime.now(),
|
|
|
|
'statement_id': current_session.statement_ids[0].id}]],
|
|
|
|
'uid': '00042-003-0014',
|
|
|
|
'user_id': self.env.uid},
|
|
|
|
'id': '00042-003-0014',
|
|
|
|
'to_invoice': False}
|
|
|
|
|
|
|
|
untax, atax = compute_tax(self.courgette, 1.2)
|
|
|
|
zucchini_order = {'data':
|
|
|
|
{'amount_paid': untax + atax,
|
|
|
|
'amount_return': 0,
|
|
|
|
'amount_tax': atax,
|
|
|
|
'amount_total': untax + atax,
|
|
|
|
'creation_date': fields.Datetime.now(),
|
|
|
|
'fiscal_position_id': False,
|
|
|
|
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
|
|
|
|
'lines': [[0,
|
|
|
|
0,
|
|
|
|
{'discount': 0,
|
|
|
|
'id': 3,
|
|
|
|
'pack_lot_ids': [],
|
|
|
|
'price_unit': 1.2,
|
|
|
|
'product_id': self.courgette.id,
|
|
|
|
'qty': 1,
|
|
|
|
'tax_ids': [(6, 0, self.courgette.taxes_id.ids)]}]],
|
|
|
|
'name': 'Order 00043-003-0014',
|
|
|
|
'partner_id': False,
|
|
|
|
'pos_session_id': current_session.id,
|
|
|
|
'sequence_number': self.pos_config.journal_id.id,
|
|
|
|
'statement_ids': [[0,
|
|
|
|
0,
|
|
|
|
{'account_id': self.env.user.partner_id.property_account_receivable_id.id,
|
|
|
|
'amount': untax + atax,
|
|
|
|
'journal_id': self.pos_config.journal_ids[0].id,
|
|
|
|
'name': fields.Datetime.now(),
|
|
|
|
'statement_id': current_session.statement_ids[0].id}]],
|
|
|
|
'uid': '00043-003-0014',
|
|
|
|
'user_id': self.env.uid},
|
|
|
|
'id': '00043-003-0014',
|
|
|
|
'to_invoice': False}
|
|
|
|
|
|
|
|
untax, atax = compute_tax(self.onions, 1.28)
|
|
|
|
onions_order = {'data':
|
|
|
|
{'amount_paid': untax + atax,
|
|
|
|
'amount_return': 0,
|
|
|
|
'amount_tax': atax,
|
|
|
|
'amount_total': untax + atax,
|
|
|
|
'creation_date': fields.Datetime.now(),
|
|
|
|
'fiscal_position_id': False,
|
|
|
|
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
|
|
|
|
'lines': [[0,
|
|
|
|
0,
|
|
|
|
{'discount': 0,
|
|
|
|
'id': 3,
|
|
|
|
'pack_lot_ids': [],
|
|
|
|
'price_unit': 1.28,
|
|
|
|
'product_id': self.onions.id,
|
|
|
|
'qty': 1,
|
|
|
|
'tax_ids': [[6, False, self.onions.taxes_id.ids]]}]],
|
|
|
|
'name': 'Order 00044-003-0014',
|
|
|
|
'partner_id': False,
|
|
|
|
'pos_session_id': current_session.id,
|
|
|
|
'sequence_number': self.pos_config.journal_id.id,
|
|
|
|
'statement_ids': [[0,
|
|
|
|
0,
|
|
|
|
{'account_id': self.env.user.partner_id.property_account_receivable_id.id,
|
|
|
|
'amount': untax + atax,
|
|
|
|
'journal_id': self.pos_config.journal_ids[0].id,
|
|
|
|
'name': fields.Datetime.now(),
|
|
|
|
'statement_id': current_session.statement_ids[0].id}]],
|
|
|
|
'uid': '00044-003-0014',
|
|
|
|
'user_id': self.env.uid},
|
|
|
|
'id': '00044-003-0014',
|
|
|
|
'to_invoice': False}
|
|
|
|
|
|
|
|
# I create an order on an open session
|
|
|
|
self.PosOrder.create_from_ui([carrot_order])
|
|
|
|
self.assertEqual(num_starting_orders + 1, len(current_session.order_ids), "Submitted order not encoded")
|
|
|
|
|
|
|
|
# I resubmit the same order
|
|
|
|
self.PosOrder.create_from_ui([carrot_order])
|
|
|
|
self.assertEqual(num_starting_orders + 1, len(current_session.order_ids), "Resubmitted order was not skipped")
|
|
|
|
|
|
|
|
# I close the session
|
|
|
|
current_session.action_pos_session_closing_control()
|
|
|
|
self.assertEqual(current_session.state, 'closed', "Session was not properly closed")
|
|
|
|
self.assertFalse(self.pos_config.current_session_id, "Current session not properly recomputed")
|
|
|
|
|
|
|
|
# I keep selling after the session is closed
|
2018-01-16 11:34:37 +01:00
|
|
|
with mute_logger('flectra.addons.point_of_sale.models.pos_order'):
|
2018-01-16 06:58:15 +01:00
|
|
|
self.PosOrder.create_from_ui([zucchini_order, onions_order])
|
|
|
|
rescue_session = self.PosSession.search([
|
|
|
|
('config_id', '=', self.pos_config.id),
|
|
|
|
('state', '=', 'opened'),
|
|
|
|
('rescue', '=', True)
|
|
|
|
])
|
|
|
|
self.assertEqual(len(rescue_session), 1, "One (and only one) rescue session should be created for orphan orders")
|
|
|
|
self.assertIn("(RESCUE FOR %s)" % current_session.name, rescue_session.name, "Rescue session is not linked to the previous one")
|
|
|
|
self.assertEqual(len(rescue_session.order_ids), 2, "Rescue session does not contain both orders")
|
|
|
|
|
|
|
|
# I close the rescue session
|
|
|
|
rescue_session.action_pos_session_closing_control()
|
|
|
|
self.assertEqual(rescue_session.state, 'closed', "Rescue session was not properly closed")
|