first commit
This commit is contained in:
2
modules/sale/tests/__init__.py
Normal file
2
modules/sale/tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
BIN
modules/sale/tests/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
modules/sale/tests/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/sale/tests/__pycache__/test_module.cpython-311.pyc
Normal file
BIN
modules/sale/tests/__pycache__/test_module.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/sale/tests/__pycache__/test_scenario.cpython-311.pyc
Normal file
BIN
modules/sale/tests/__pycache__/test_scenario.cpython-311.pyc
Normal file
Binary file not shown.
703
modules/sale/tests/scenario_sale.rst
Normal file
703
modules/sale/tests/scenario_sale.rst
Normal file
@@ -0,0 +1,703 @@
|
||||
=============
|
||||
Sale Scenario
|
||||
=============
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report, Wizard
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, create_tax, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... create_payment_term, set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual, set_user
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Employee = Model.get('company.employee')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> User = Model.get('res.user')
|
||||
|
||||
Set employee::
|
||||
|
||||
>>> employee_party = Party(name="Employee")
|
||||
>>> employee_party.save()
|
||||
>>> employee = Employee(party=employee_party)
|
||||
>>> employee.save()
|
||||
>>> user = User(config.user)
|
||||
>>> user.employees.append(employee)
|
||||
>>> user.employee = employee
|
||||
>>> user.save()
|
||||
>>> set_user(user.id)
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(create_fiscalyear())
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
>>> revenue = accounts['revenue']
|
||||
>>> expense = accounts['expense']
|
||||
>>> cash = accounts['cash']
|
||||
|
||||
>>> Journal = Model.get('account.journal')
|
||||
>>> PaymentMethod = Model.get('account.invoice.payment.method')
|
||||
>>> cash_journal, = Journal.find([('type', '=', 'cash')])
|
||||
>>> cash_journal.save()
|
||||
>>> payment_method = PaymentMethod()
|
||||
>>> payment_method.name = 'Cash'
|
||||
>>> payment_method.journal = cash_journal
|
||||
>>> payment_method.credit_account = cash
|
||||
>>> payment_method.debit_account = cash
|
||||
>>> payment_method.save()
|
||||
|
||||
Create tax::
|
||||
|
||||
>>> tax = create_tax(Decimal('.10'))
|
||||
>>> tax.save()
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create account categories::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = expense
|
||||
>>> account_category.account_revenue = revenue
|
||||
>>> account_category.save()
|
||||
|
||||
>>> account_category_tax, = account_category.duplicate()
|
||||
>>> account_category_tax.customer_taxes.append(tax)
|
||||
>>> account_category_tax.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category_tax
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'service'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'service'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('30')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> service, = template.products
|
||||
|
||||
Create payment term::
|
||||
|
||||
>>> payment_term = create_payment_term()
|
||||
>>> payment_term.save()
|
||||
|
||||
Create an Inventory::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> storage, = Location.find([
|
||||
... ('code', '=', 'STO'),
|
||||
... ])
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage
|
||||
>>> inventory_line = inventory.lines.new(product=product)
|
||||
>>> inventory_line.quantity = 100.0
|
||||
>>> inventory_line.expected_quantity = 0.0
|
||||
>>> inventory.click('confirm')
|
||||
>>> inventory.state
|
||||
'done'
|
||||
|
||||
Sale 5 products::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> SaleLine = Model.get('sale.line')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale.invoice_method = 'order'
|
||||
>>> sale_line = SaleLine()
|
||||
>>> sale.lines.append(sale_line)
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 2.0
|
||||
>>> sale_line = SaleLine()
|
||||
>>> sale.lines.append(sale_line)
|
||||
>>> sale_line.type = 'comment'
|
||||
>>> sale_line.description = 'Comment'
|
||||
>>> sale_line = SaleLine()
|
||||
>>> sale.lines.append(sale_line)
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 3.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
|
||||
(Decimal('50.00'), Decimal('5.00'), Decimal('55.00'))
|
||||
>>> assertEqual(sale.quoted_by, employee)
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
|
||||
(Decimal('50.00'), Decimal('5.00'), Decimal('55.00'))
|
||||
>>> assertEqual(sale.confirmed_by, employee)
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'waiting'
|
||||
>>> sale.invoice_state
|
||||
'pending'
|
||||
>>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
|
||||
(1, 0, 1)
|
||||
>>> invoice, = sale.invoices
|
||||
>>> assertEqual(invoice.origins, sale.rec_name)
|
||||
>>> shipment, = sale.shipments
|
||||
>>> assertEqual(shipment.origins, sale.rec_name)
|
||||
|
||||
Invoice line must be linked to stock move::
|
||||
|
||||
>>> invoice_line1, invoice_line2 = sorted(
|
||||
... invoice.lines, key=lambda l: l.quantity or 0)
|
||||
>>> stock_move1, stock_move2 = sorted(shipment.outgoing_moves,
|
||||
... key=lambda m: m.quantity or 0)
|
||||
>>> assertEqual(invoice_line1.stock_moves, [stock_move1])
|
||||
>>> assertEqual(stock_move1.invoice_lines, [invoice_line1])
|
||||
>>> assertEqual(invoice_line2.stock_moves, [stock_move2])
|
||||
>>> assertEqual(stock_move2.invoice_lines, [invoice_line2])
|
||||
|
||||
Check actual quantity::
|
||||
|
||||
>>> for line in sale.lines:
|
||||
... assertEqual(line.quantity, line.actual_quantity)
|
||||
|
||||
Post invoice and check no new invoices::
|
||||
|
||||
|
||||
>>> for invoice in sale.invoices:
|
||||
... invoice.click('post')
|
||||
>>> sale.reload()
|
||||
>>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
|
||||
(1, 0, 1)
|
||||
>>> sale.invoice_state
|
||||
'awaiting payment'
|
||||
|
||||
Testing the report::
|
||||
|
||||
>>> sale_report = Report('sale.sale')
|
||||
>>> ext, _, _, name = sale_report.execute([sale], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Sale-1'
|
||||
|
||||
Sale 5 products with an invoice method 'on shipment'::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> SaleLine = Model.get('sale.line')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale.invoice_method = 'shipment'
|
||||
>>> sale_line = SaleLine()
|
||||
>>> sale.lines.append(sale_line)
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 2.0
|
||||
>>> sale_line = SaleLine()
|
||||
>>> sale.lines.append(sale_line)
|
||||
>>> sale_line.type = 'comment'
|
||||
>>> sale_line.description = 'Comment'
|
||||
>>> sale_line = SaleLine()
|
||||
>>> sale.lines.append(sale_line)
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 3.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'waiting'
|
||||
>>> sale.invoice_state
|
||||
'none'
|
||||
>>> sale.reload()
|
||||
>>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
|
||||
(1, 0, 0)
|
||||
|
||||
Not yet linked to invoice lines::
|
||||
|
||||
>>> shipment, = sale.shipments
|
||||
>>> stock_move1, stock_move2 = sorted(shipment.outgoing_moves,
|
||||
... key=lambda m: m.quantity or 0)
|
||||
>>> len(stock_move1.invoice_lines)
|
||||
0
|
||||
>>> len(stock_move2.invoice_lines)
|
||||
0
|
||||
|
||||
Validate Shipments::
|
||||
|
||||
>>> shipment.click('assign_try')
|
||||
>>> shipment.click('pick')
|
||||
>>> shipment.click('pack')
|
||||
>>> shipment.click('do')
|
||||
|
||||
Open customer invoice::
|
||||
|
||||
>>> sale.reload()
|
||||
>>> sale.invoice_state
|
||||
'pending'
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice.type
|
||||
'out'
|
||||
>>> invoice_line1, invoice_line2 = sorted(invoice.lines,
|
||||
... key=lambda l: l.quantity or 0)
|
||||
>>> for line in invoice.lines:
|
||||
... line.quantity = 1
|
||||
... line.save()
|
||||
>>> invoice.click('post')
|
||||
|
||||
Invoice lines must be linked to each stock moves::
|
||||
|
||||
>>> assertEqual(invoice_line1.stock_moves, [stock_move1])
|
||||
>>> assertEqual(invoice_line2.stock_moves, [stock_move2])
|
||||
|
||||
Check second invoices::
|
||||
|
||||
>>> sale.reload()
|
||||
>>> len(sale.invoices)
|
||||
2
|
||||
>>> sum(l.quantity for i in sale.invoices for l in i.lines)
|
||||
5.0
|
||||
|
||||
Sale 5 products with shipment method 'on invoice'::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale.shipment_method = 'invoice'
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 5.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
>>> sale.invoice_state
|
||||
'pending'
|
||||
>>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
|
||||
(0, 0, 1)
|
||||
|
||||
Not yet linked to stock moves::
|
||||
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> len(invoice_line.stock_moves)
|
||||
0
|
||||
|
||||
Post and Pay Invoice for 4 products::
|
||||
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> invoice_line.quantity
|
||||
5.0
|
||||
>>> invoice_line.quantity = 4.0
|
||||
>>> invoice.click('post')
|
||||
>>> pay = invoice.click('pay')
|
||||
>>> pay.form.payment_method = payment_method
|
||||
>>> pay.execute('choice')
|
||||
>>> invoice.reload()
|
||||
>>> invoice.state
|
||||
'paid'
|
||||
|
||||
Invoice lines linked to 1 move::
|
||||
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> len(invoice_line.stock_moves)
|
||||
1
|
||||
|
||||
Stock moves must be linked to invoice line::
|
||||
|
||||
>>> sale.reload()
|
||||
>>> shipment, = sale.shipments
|
||||
>>> shipment.reload()
|
||||
>>> stock_move, = shipment.outgoing_moves
|
||||
>>> stock_move.quantity
|
||||
4.0
|
||||
>>> assertEqual(stock_move.invoice_lines, [invoice_line])
|
||||
|
||||
Ship 3 products::
|
||||
|
||||
>>> stock_inventory_move, = shipment.inventory_moves
|
||||
>>> stock_inventory_move.quantity
|
||||
4.0
|
||||
>>> stock_inventory_move.quantity = 3.0
|
||||
>>> shipment.click('assign_try')
|
||||
>>> shipment.click('pick')
|
||||
>>> shipment.click('pack')
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
|
||||
New shipments created::
|
||||
|
||||
>>> sale.reload()
|
||||
>>> len(sale.shipments)
|
||||
2
|
||||
|
||||
Invoice lines linked to new moves::
|
||||
|
||||
>>> invoice.reload()
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> len(invoice_line.stock_moves)
|
||||
2
|
||||
|
||||
Create a Return::
|
||||
|
||||
>>> return_ = Sale()
|
||||
>>> return_.party = customer
|
||||
>>> return_.payment_term = payment_term
|
||||
>>> return_.invoice_method = 'shipment'
|
||||
>>> return_line = SaleLine()
|
||||
>>> return_.lines.append(return_line)
|
||||
>>> return_line.product = product
|
||||
>>> return_line.quantity = -4.
|
||||
>>> return_line = SaleLine()
|
||||
>>> return_.lines.append(return_line)
|
||||
>>> return_line.type = 'comment'
|
||||
>>> return_line.description = 'Comment'
|
||||
>>> return_.click('quote')
|
||||
>>> return_.click('confirm')
|
||||
>>> return_.state
|
||||
'processing'
|
||||
>>> return_.shipment_state
|
||||
'waiting'
|
||||
>>> return_.invoice_state
|
||||
'none'
|
||||
>>> (len(return_.shipments), len(return_.shipment_returns),
|
||||
... len(return_.invoices))
|
||||
(0, 1, 0)
|
||||
|
||||
Receive Return Shipment for 3 products::
|
||||
|
||||
>>> ship_return, = return_.shipment_returns
|
||||
>>> move_return, = ship_return.incoming_moves
|
||||
>>> move_return.product.rec_name
|
||||
'product'
|
||||
>>> move_return.quantity
|
||||
4.0
|
||||
>>> move_return.quantity = 3
|
||||
>>> ship_return.click('receive')
|
||||
|
||||
Check Return::
|
||||
|
||||
>>> return_.reload()
|
||||
>>> return_.shipment_state
|
||||
'partially shipped'
|
||||
>>> return_.invoice_state
|
||||
'pending'
|
||||
>>> (len(return_.shipments), len(return_.shipment_returns),
|
||||
... len(return_.invoices))
|
||||
(0, 2, 1)
|
||||
|
||||
Open customer credit note::
|
||||
|
||||
>>> credit_note, = return_.invoices
|
||||
>>> credit_note.type
|
||||
'out'
|
||||
>>> len(credit_note.lines)
|
||||
1
|
||||
>>> sum(l.quantity for l in credit_note.lines)
|
||||
-3.0
|
||||
>>> credit_note.click('post')
|
||||
|
||||
Receive Remaining Return Shipment::
|
||||
|
||||
>>> return_.reload()
|
||||
>>> _, ship_return = return_.shipment_returns
|
||||
>>> move_return, = ship_return.incoming_moves
|
||||
>>> move_return.product.rec_name
|
||||
'product'
|
||||
>>> move_return.quantity
|
||||
1.0
|
||||
>>> ship_return.click('receive')
|
||||
|
||||
Check Return::
|
||||
|
||||
>>> return_.reload()
|
||||
>>> return_.shipment_state
|
||||
'sent'
|
||||
>>> return_.invoice_state
|
||||
'awaiting payment'
|
||||
>>> (len(return_.shipments), len(return_.shipment_returns),
|
||||
... len(return_.invoices))
|
||||
(0, 2, 2)
|
||||
|
||||
Mixing return and sale::
|
||||
|
||||
>>> mix = Sale()
|
||||
>>> mix.party = customer
|
||||
>>> mix.payment_term = payment_term
|
||||
>>> mix.invoice_method = 'order'
|
||||
>>> mixline = SaleLine()
|
||||
>>> mix.lines.append(mixline)
|
||||
>>> mixline.product = product
|
||||
>>> mixline.quantity = 7.
|
||||
>>> mixline_comment = SaleLine()
|
||||
>>> mix.lines.append(mixline_comment)
|
||||
>>> mixline_comment.type = 'comment'
|
||||
>>> mixline_comment.description = 'Comment'
|
||||
>>> mixline2 = SaleLine()
|
||||
>>> mix.lines.append(mixline2)
|
||||
>>> mixline2.product = product
|
||||
>>> mixline2.quantity = -2.
|
||||
>>> mix.click('quote')
|
||||
>>> mix.click('confirm')
|
||||
>>> mix.state
|
||||
'processing'
|
||||
>>> mix.shipment_state
|
||||
'waiting'
|
||||
>>> mix.invoice_state
|
||||
'pending'
|
||||
>>> len(mix.shipments), len(mix.shipment_returns), len(mix.invoices)
|
||||
(1, 1, 1)
|
||||
|
||||
Checking Shipments::
|
||||
|
||||
>>> mix_return, = mix.shipment_returns
|
||||
>>> mix_shipment, = mix.shipments
|
||||
>>> mix_return.click('receive')
|
||||
>>> move_return, = mix_return.incoming_moves
|
||||
>>> move_return.product.rec_name
|
||||
'product'
|
||||
>>> move_return.quantity
|
||||
2.0
|
||||
>>> mix_shipment.click('assign_try')
|
||||
>>> mix_shipment.click('pick')
|
||||
>>> mix_shipment.click('pack')
|
||||
>>> mix_shipment.click('do')
|
||||
>>> move_shipment, = mix_shipment.outgoing_moves
|
||||
>>> move_shipment.product.rec_name
|
||||
'product'
|
||||
>>> move_shipment.quantity
|
||||
7.0
|
||||
|
||||
Checking the invoice::
|
||||
|
||||
>>> mix.reload()
|
||||
>>> mix_invoice, = mix.invoices
|
||||
>>> mix_invoice.type
|
||||
'out'
|
||||
>>> len(mix_invoice.lines)
|
||||
2
|
||||
>>> sorted(l.quantity for l in mix_invoice.lines)
|
||||
[-2.0, 7.0]
|
||||
>>> mix_invoice.click('post')
|
||||
|
||||
Mixing stuff with an invoice method 'on shipment'::
|
||||
|
||||
>>> mix = Sale()
|
||||
>>> mix.party = customer
|
||||
>>> mix.payment_term = payment_term
|
||||
>>> mix.invoice_method = 'shipment'
|
||||
>>> mixline = SaleLine()
|
||||
>>> mix.lines.append(mixline)
|
||||
>>> mixline.product = product
|
||||
>>> mixline.quantity = 6.
|
||||
>>> mixline_comment = SaleLine()
|
||||
>>> mix.lines.append(mixline_comment)
|
||||
>>> mixline_comment.type = 'comment'
|
||||
>>> mixline_comment.description = 'Comment'
|
||||
>>> mixline2 = SaleLine()
|
||||
>>> mix.lines.append(mixline2)
|
||||
>>> mixline2.product = product
|
||||
>>> mixline2.quantity = -3.
|
||||
>>> mix.click('quote')
|
||||
>>> mix.click('confirm')
|
||||
>>> mix.state
|
||||
'processing'
|
||||
>>> mix.shipment_state
|
||||
'waiting'
|
||||
>>> mix.invoice_state
|
||||
'none'
|
||||
>>> len(mix.shipments), len(mix.shipment_returns), len(mix.invoices)
|
||||
(1, 1, 0)
|
||||
|
||||
Checking Shipments::
|
||||
|
||||
>>> mix_return, = mix.shipment_returns
|
||||
>>> mix_shipment, = mix.shipments
|
||||
>>> mix_return.click('receive')
|
||||
>>> move_return, = mix_return.incoming_moves
|
||||
>>> move_return.product.rec_name
|
||||
'product'
|
||||
>>> move_return.quantity
|
||||
3.0
|
||||
>>> mix_shipment.click('assign_try')
|
||||
>>> mix_shipment.click('pick')
|
||||
>>> mix_shipment.click('pack')
|
||||
>>> move_shipment, = mix_shipment.outgoing_moves
|
||||
>>> move_shipment.product.rec_name
|
||||
'product'
|
||||
>>> move_shipment.quantity
|
||||
6.0
|
||||
|
||||
Sale services::
|
||||
|
||||
>>> service_sale = Sale()
|
||||
>>> service_sale.party = customer
|
||||
>>> service_sale.payment_term = payment_term
|
||||
>>> sale_line = service_sale.lines.new()
|
||||
>>> sale_line.product = service
|
||||
>>> sale_line.quantity = 1
|
||||
>>> service_sale.save()
|
||||
>>> service_sale.click('quote')
|
||||
>>> service_sale.click('confirm')
|
||||
>>> service_sale.state
|
||||
'processing'
|
||||
>>> service_sale.shipment_state
|
||||
'none'
|
||||
>>> service_sale.invoice_state
|
||||
'pending'
|
||||
>>> service_invoice, = service_sale.invoices
|
||||
|
||||
Pay the service invoice::
|
||||
|
||||
>>> service_invoice.click('post')
|
||||
>>> pay = service_invoice.click('pay')
|
||||
>>> pay.form.payment_method = payment_method
|
||||
>>> pay.execute('choice')
|
||||
>>> service_invoice.reload()
|
||||
>>> service_invoice.state
|
||||
'paid'
|
||||
|
||||
Check service sale states::
|
||||
|
||||
>>> service_sale.reload()
|
||||
>>> service_sale.invoice_state
|
||||
'paid'
|
||||
>>> service_sale.shipment_state
|
||||
'none'
|
||||
>>> service_sale.state
|
||||
'done'
|
||||
|
||||
Return sales using the wizard::
|
||||
|
||||
>>> sale_to_return = Sale()
|
||||
>>> sale_to_return.party = customer
|
||||
>>> sale_to_return.payment_term = payment_term
|
||||
>>> sale_line = sale_to_return.lines.new()
|
||||
>>> sale_line.product = service
|
||||
>>> sale_line.quantity = 1
|
||||
>>> sale_line = sale_to_return.lines.new()
|
||||
>>> sale_line.type = 'comment'
|
||||
>>> sale_line.description = 'Test comment'
|
||||
>>> sale_to_return.click('quote')
|
||||
>>> sale_to_return.click('confirm')
|
||||
>>> sale_to_return.state
|
||||
'processing'
|
||||
>>> return_sale = Wizard('sale.return_sale', [sale_to_return])
|
||||
>>> return_sale.execute('return_')
|
||||
>>> returned_sale, = Sale.find([
|
||||
... ('state', '=', 'draft'),
|
||||
... ])
|
||||
>>> assertEqual(returned_sale.origin, sale_to_return)
|
||||
>>> sorted([x.quantity or 0 for x in returned_sale.lines])
|
||||
[-1.0, 0]
|
||||
|
||||
Create a sale to be invoiced on shipment partialy and check correctly linked
|
||||
to invoices::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale.invoice_method = 'shipment'
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 10.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> shipment, = sale.shipments
|
||||
>>> for move in shipment.inventory_moves:
|
||||
... move.quantity = 5.0
|
||||
>>> shipment.click('assign_try')
|
||||
>>> shipment.click('pick')
|
||||
>>> shipment.click('pack')
|
||||
>>> shipment.click('do')
|
||||
>>> sale.reload()
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> invoice_line.quantity
|
||||
5.0
|
||||
>>> stock_move, = invoice_line.stock_moves
|
||||
>>> stock_move.quantity
|
||||
5.0
|
||||
>>> stock_move.state
|
||||
'done'
|
||||
|
||||
Create a sale to be sent on invoice partially and check correctly linked to
|
||||
invoices::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale.shipment_method = 'invoice'
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 10.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> assertEqual(invoice_line.stock_moves, [])
|
||||
>>> invoice_line.quantity = 5.0
|
||||
>>> invoice.click('post')
|
||||
>>> pay = invoice.click('pay')
|
||||
>>> pay.form.payment_method = payment_method
|
||||
>>> pay.execute('choice')
|
||||
>>> invoice.reload()
|
||||
>>> invoice.state
|
||||
'paid'
|
||||
>>> sale.reload()
|
||||
>>> sale.invoice_state
|
||||
'partially paid'
|
||||
>>> invoice_line.reload()
|
||||
>>> stock_move, = invoice_line.stock_moves
|
||||
>>> stock_move.quantity
|
||||
5.0
|
||||
>>> stock_move.state
|
||||
'draft'
|
||||
|
||||
Deleting a line from a invoice should recreate it::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 10.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice_line, = invoice.lines
|
||||
>>> invoice.lines.remove(invoice_line)
|
||||
>>> invoice.click('post')
|
||||
>>> sale.reload()
|
||||
>>> new_invoice, = sale.invoices
|
||||
>>> new_invoice.number
|
||||
>>> len(new_invoice.lines)
|
||||
1
|
||||
31
modules/sale/tests/scenario_sale_default_methods.rst
Normal file
31
modules/sale/tests/scenario_sale_default_methods.rst
Normal file
@@ -0,0 +1,31 @@
|
||||
=============================
|
||||
Sale Default Methods Scenario
|
||||
=============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company)
|
||||
|
||||
Create a party and set their default methods::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.sale_shipment_method = 'invoice'
|
||||
>>> customer.sale_invoice_method = 'shipment'
|
||||
>>> customer.save()
|
||||
|
||||
Create a sale to to check default methods::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.shipment_method
|
||||
'invoice'
|
||||
>>> sale.invoice_method
|
||||
'shipment'
|
||||
59
modules/sale/tests/scenario_sale_default_taxes.rst
Normal file
59
modules/sale/tests/scenario_sale_default_taxes.rst
Normal file
@@ -0,0 +1,59 @@
|
||||
=======================
|
||||
Sale with Default Taxes
|
||||
=======================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_tax, get_accounts)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> Tax = Model.get('account.tax')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create tax::
|
||||
|
||||
>>> tax = create_tax(Decimal('.10'))
|
||||
>>> tax.save()
|
||||
>>> accounts['revenue'].taxes.append(Tax(tax.id))
|
||||
>>> accounts['revenue'].save()
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create a sale without product::
|
||||
|
||||
>>> sale = Sale(party=customer)
|
||||
>>> line = sale.lines.new()
|
||||
>>> assertEqual(line.taxes, [tax])
|
||||
>>> line.quantity = 1
|
||||
>>> line.unit_price = Decimal('100.0000')
|
||||
>>> sale.click('quote')
|
||||
>>> sale.total_amount
|
||||
Decimal('110.00')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
|
||||
Check invoice::
|
||||
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice.total_amount
|
||||
Decimal('110.00')
|
||||
>>> line, = invoice.lines
|
||||
>>> assertEqual(line.account, accounts['revenue'])
|
||||
48
modules/sale/tests/scenario_sale_empty.rst
Normal file
48
modules/sale/tests/scenario_sale_empty.rst
Normal file
@@ -0,0 +1,48 @@
|
||||
===================
|
||||
Sale Empty Scenario
|
||||
===================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import create_chart
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create empty sale::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.click('quote')
|
||||
>>> sale.state
|
||||
'quotation'
|
||||
>>> sale.untaxed_amount
|
||||
Decimal('0')
|
||||
>>> sale.tax_amount
|
||||
Decimal('0')
|
||||
>>> sale.total_amount
|
||||
Decimal('0')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'done'
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
>>> len(sale.shipments)
|
||||
0
|
||||
>>> len(sale.shipment_returns)
|
||||
0
|
||||
>>> sale.invoice_state
|
||||
'none'
|
||||
>>> len(sale.invoices)
|
||||
0
|
||||
103
modules/sale/tests/scenario_sale_line_cancelled.rst
Normal file
103
modules/sale/tests/scenario_sale_line_cancelled.rst
Normal file
@@ -0,0 +1,103 @@
|
||||
============================
|
||||
Sale Line Cancelled Scenario
|
||||
============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import create_chart, get_accounts
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create party::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
>>> template = ProductTemplate(name="Product")
|
||||
>>> template.default_uom, = ProductUom.find([('name', '=', "Unit")])
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10.0000')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Sale product::
|
||||
|
||||
>>> sale = Sale(party=customer)
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 1
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'waiting'
|
||||
>>> sale.invoice_state
|
||||
'pending'
|
||||
|
||||
Cancel shipment and invoice::
|
||||
|
||||
>>> shipment, = sale.shipments
|
||||
>>> shipment.click('cancel')
|
||||
>>> shipment.state
|
||||
'cancelled'
|
||||
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice.click('cancel')
|
||||
>>> invoice.state
|
||||
'cancelled'
|
||||
|
||||
>>> sale.reload()
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'exception'
|
||||
>>> sale.invoice_state
|
||||
'exception'
|
||||
|
||||
Ignore exceptions::
|
||||
|
||||
>>> invoice_handle_exception = sale.click('handle_invoice_exception')
|
||||
>>> invoice_handle_exception.form.ignore_invoices.extend(
|
||||
... invoice_handle_exception.form.ignore_invoices.find())
|
||||
>>> invoice_handle_exception.execute('handle')
|
||||
|
||||
>>> sale.invoice_state
|
||||
'none'
|
||||
|
||||
>>> shipment_handle_exception = sale.click('handle_shipment_exception')
|
||||
>>> shipment_handle_exception.form.ignore_moves.extend(
|
||||
... shipment_handle_exception.form.ignore_moves.find())
|
||||
>>> shipment_handle_exception.execute('handle')
|
||||
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
|
||||
>>> sale.state
|
||||
'done'
|
||||
@@ -0,0 +1,91 @@
|
||||
=======================================
|
||||
Sale Line Cancelled On Invoice Scenario
|
||||
=======================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import create_chart, get_accounts
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create party::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
>>> template = ProductTemplate(name="Product")
|
||||
>>> template.default_uom, = ProductUom.find([('name', '=', "Unit")])
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10.0000')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Sale product::
|
||||
|
||||
>>> sale = Sale(party=customer)
|
||||
>>> sale.shipment_method = 'invoice'
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 1
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
>>> sale.invoice_state
|
||||
'pending'
|
||||
|
||||
Cancel invoice::
|
||||
|
||||
>>> invoice, = sale.invoices
|
||||
>>> invoice.click('cancel')
|
||||
>>> invoice.state
|
||||
'cancelled'
|
||||
|
||||
>>> sale.reload()
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
>>> sale.invoice_state
|
||||
'exception'
|
||||
|
||||
Ignore exception::
|
||||
|
||||
>>> invoice_handle_exception = sale.click('handle_invoice_exception')
|
||||
>>> invoice_handle_exception.form.ignore_invoices.extend(
|
||||
... invoice_handle_exception.form.ignore_invoices.find())
|
||||
>>> invoice_handle_exception.execute('handle')
|
||||
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
|
||||
>>> sale.state
|
||||
'done'
|
||||
@@ -0,0 +1,91 @@
|
||||
========================================
|
||||
Sale Line Cancelled On Shipment Scenario
|
||||
========================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import create_chart, get_accounts
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create party::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
>>> template = ProductTemplate(name="Product")
|
||||
>>> template.default_uom, = ProductUom.find([('name', '=', "Unit")])
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10.0000')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Sale product::
|
||||
|
||||
>>> sale = Sale(party=customer)
|
||||
>>> sale.invoice_method = 'shipment'
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 1
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'waiting'
|
||||
>>> sale.invoice_state
|
||||
'none'
|
||||
|
||||
Cancel shipment::
|
||||
|
||||
>>> shipment, = sale.shipments
|
||||
>>> shipment.click('cancel')
|
||||
>>> shipment.state
|
||||
'cancelled'
|
||||
|
||||
>>> sale.reload()
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'exception'
|
||||
>>> sale.invoice_state
|
||||
'none'
|
||||
|
||||
Ignore exception::
|
||||
|
||||
>>> shipment_handle_exception = sale.click('handle_shipment_exception')
|
||||
>>> shipment_handle_exception.form.ignore_moves.extend(
|
||||
... shipment_handle_exception.form.ignore_moves.find())
|
||||
>>> shipment_handle_exception.execute('handle')
|
||||
|
||||
>>> sale.shipment_state
|
||||
'none'
|
||||
|
||||
>>> sale.state
|
||||
'done'
|
||||
90
modules/sale/tests/scenario_sale_manual_invoice.rst
Normal file
90
modules/sale/tests/scenario_sale_manual_invoice.rst
Normal file
@@ -0,0 +1,90 @@
|
||||
============================
|
||||
Sale Manual Invoice Scenario
|
||||
============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import create_chart, get_accounts
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create party::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create account category::
|
||||
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'service'
|
||||
>>> template.salable = True
|
||||
>>> template.account_category = account_category
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Sale with manual invoice method::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.invoice_method = 'manual'
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 10
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.invoice_state
|
||||
'none'
|
||||
>>> len(sale.invoices)
|
||||
0
|
||||
|
||||
Manually create an invoice::
|
||||
|
||||
>>> sale.click('manual_invoice')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.invoice_state
|
||||
'pending'
|
||||
|
||||
Change quantity on invoice and create a new invoice::
|
||||
|
||||
>>> invoice, = sale.invoices
|
||||
>>> line, = invoice.lines
|
||||
>>> line.quantity = 5
|
||||
>>> invoice.save()
|
||||
|
||||
>>> len(sale.invoices)
|
||||
1
|
||||
>>> sale.click('manual_invoice')
|
||||
>>> len(sale.invoices)
|
||||
2
|
||||
76
modules/sale/tests/scenario_sale_manual_shipment.rst
Normal file
76
modules/sale/tests/scenario_sale_manual_shipment.rst
Normal file
@@ -0,0 +1,76 @@
|
||||
=============================
|
||||
Sale Manual Shipment Scenario
|
||||
=============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
|
||||
Create party::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Sale with manual shipment method::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.shipment_method = 'manual'
|
||||
>>> sale.invoice_method = 'manual' # no need for accounting
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 10
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> len(sale.shipments)
|
||||
0
|
||||
|
||||
Manually create a shipment::
|
||||
|
||||
>>> sale.click('manual_shipment')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> sale.shipment_state
|
||||
'waiting'
|
||||
|
||||
Change quantity on shipment and create a new shipment::
|
||||
|
||||
>>> shipment, = sale.shipments
|
||||
>>> move, = shipment.outgoing_moves
|
||||
>>> move.quantity = 5
|
||||
>>> shipment.save()
|
||||
|
||||
>>> len(sale.shipments)
|
||||
1
|
||||
>>> sale.click('manual_shipment')
|
||||
>>> len(sale.shipments)
|
||||
2
|
||||
94
modules/sale/tests/scenario_sale_modify_header.rst
Normal file
94
modules/sale/tests/scenario_sale_modify_header.rst
Normal file
@@ -0,0 +1,94 @@
|
||||
===========================
|
||||
Sale Modify Header Scenario
|
||||
===========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_tax, get_accounts)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
>>> revenue = accounts['revenue']
|
||||
|
||||
Create tax and tax rule::
|
||||
|
||||
>>> tax = create_tax(Decimal('.10'))
|
||||
>>> tax.save()
|
||||
>>> other_tax = create_tax(Decimal('.05'))
|
||||
>>> other_tax.save()
|
||||
|
||||
>>> TaxRule = Model.get('account.tax.rule')
|
||||
>>> foreign = TaxRule(name='Foreign Customers')
|
||||
>>> foreign_tax = foreign.lines.new()
|
||||
>>> foreign_tax.origin_tax = tax
|
||||
>>> foreign_tax.tax = other_tax
|
||||
>>> foreign.save()
|
||||
|
||||
Create account categories::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = revenue
|
||||
>>> account_category.customer_taxes.append(tax)
|
||||
>>> account_category.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
>>> another = Party(name='Another Customer', customer_tax_rule=foreign)
|
||||
>>> another.save()
|
||||
|
||||
Create a sale with a line::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 3
|
||||
>>> sale_line_comment = sale.lines.new(type='comment')
|
||||
>>> sale.save()
|
||||
>>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
|
||||
(Decimal('30.00'), Decimal('3.00'), Decimal('33.00'))
|
||||
|
||||
Change the party::
|
||||
|
||||
>>> modify_header = sale.click('modify_header')
|
||||
>>> assertEqual(modify_header.form.party, customer)
|
||||
>>> modify_header.form.party = another
|
||||
>>> modify_header.execute('modify')
|
||||
|
||||
>>> sale.party.name
|
||||
'Another Customer'
|
||||
>>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
|
||||
(Decimal('30.00'), Decimal('1.50'), Decimal('31.50'))
|
||||
57
modules/sale/tests/scenario_sale_quotation.rst
Normal file
57
modules/sale/tests/scenario_sale_quotation.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
=======================
|
||||
Sale Quotation Scenario
|
||||
=======================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import create_chart
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> SaleConfiguration = Model.get('sale.configuration')
|
||||
>>> Party = Model.get('party.party')
|
||||
|
||||
Set quotation validity to 1 week::
|
||||
|
||||
>>> sale_configuration = SaleConfiguration(1)
|
||||
>>> sale_configuration.sale_quotation_validity = dt.timedelta(weeks=1)
|
||||
>>> sale_configuration.save()
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Create a quotation::
|
||||
|
||||
>>> sale = Sale(party=customer)
|
||||
>>> sale.click('quote')
|
||||
>>> sale.state
|
||||
'quotation'
|
||||
>>> assertEqual(sale.quotation_date, today)
|
||||
>>> assertEqual(sale.quotation_validity, dt.timedelta(weeks=1))
|
||||
>>> assertEqual(sale.quotation_expire, today + dt.timedelta(weeks=1))
|
||||
|
||||
Expire quotation::
|
||||
|
||||
>>> sale.quotation_date = today - dt.timedelta(weeks=2)
|
||||
>>> sale.save()
|
||||
|
||||
>>> cron, = Cron.find(
|
||||
... [('method', '=', 'sale.sale|cancel_expired_quotation')], limit=1)
|
||||
>>> cron.click('run_once')
|
||||
|
||||
>>> sale.reload()
|
||||
>>> sale.state
|
||||
'cancelled'
|
||||
315
modules/sale/tests/scenario_sale_reporting.rst
Normal file
315
modules/sale/tests/scenario_sale_reporting.rst
Normal file
@@ -0,0 +1,315 @@
|
||||
=======================
|
||||
Sale Reporting Scenario
|
||||
=======================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from dateutil.relativedelta import relativedelta
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('sale', create_company, create_chart)
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(create_fiscalyear())
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
>>> revenue = accounts['revenue']
|
||||
>>> expense = accounts['expense']
|
||||
|
||||
Create countries::
|
||||
|
||||
>>> Region = Model.get('country.region')
|
||||
>>> Country = Model.get('country.country')
|
||||
>>> Subdivision = Model.get('country.subdivision')
|
||||
>>> north_america, = Region.find([('code_numeric', '=', '021')])
|
||||
>>> country_us = Country(name="United States", region=north_america)
|
||||
>>> country_us.save()
|
||||
>>> california = Subdivision(
|
||||
... name="California", type='state', country=country_us)
|
||||
>>> california.save()
|
||||
>>> new_york = Subdivision(
|
||||
... name="New York", type='state', country=country_us)
|
||||
>>> new_york.save()
|
||||
|
||||
Create party categories::
|
||||
|
||||
>>> PartyCategory = Model.get('party.category')
|
||||
>>> party_category_root1 = PartyCategory(name="Root1")
|
||||
>>> party_category_root1.save()
|
||||
>>> party_category_child1 = PartyCategory(
|
||||
... name="Child1", parent=party_category_root1)
|
||||
>>> party_category_child1.save()
|
||||
>>> party_category_child2 = PartyCategory(
|
||||
... name="Child2", parent=party_category_root1)
|
||||
>>> party_category_child2.save()
|
||||
>>> party_category_root2 = PartyCategory(name="Root2")
|
||||
>>> party_category_root2.save()
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer1 = Party(name='Customer1')
|
||||
>>> customer1.categories.append(PartyCategory(party_category_child1.id))
|
||||
>>> customer1.categories.append(PartyCategory(party_category_root2.id))
|
||||
>>> address, = customer1.addresses
|
||||
>>> address.country = country_us
|
||||
>>> address.subdivision = california
|
||||
>>> customer1.save()
|
||||
>>> customer2 = Party(name='Customer2')
|
||||
>>> customer2.categories.append(PartyCategory(party_category_child2.id))
|
||||
>>> address, = customer2.addresses
|
||||
>>> address.country = country_us
|
||||
>>> address.subdivision = new_york
|
||||
>>> customer2.save()
|
||||
|
||||
Create account categories::
|
||||
|
||||
>>> Category = Model.get('product.category')
|
||||
>>> account_category = Category(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = revenue
|
||||
>>> account_category.save()
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> template1 = ProductTemplate()
|
||||
>>> template1.name = "Product1"
|
||||
>>> template1.default_uom = unit
|
||||
>>> template1.type = 'service'
|
||||
>>> template1.salable = True
|
||||
>>> template1.list_price = Decimal('10')
|
||||
>>> template1.account_category = account_category
|
||||
>>> template1.save()
|
||||
>>> product1, = template1.products
|
||||
|
||||
>>> template2, = template1.duplicate(default={'name': "Product2"})
|
||||
>>> template2.account_category = account_category
|
||||
>>> template2.save()
|
||||
>>> product2, = template2.products
|
||||
|
||||
>>> category_root1 = Category(name="Root1")
|
||||
>>> category_root1.save()
|
||||
>>> category_child1 = Category(name="Child1", parent=category_root1)
|
||||
>>> category_child1.save()
|
||||
>>> category_child2 = Category(name="Child2", parent=category_root1)
|
||||
>>> category_child2.save()
|
||||
>>> category_root2 = Category(name="Root2")
|
||||
>>> category_root2.save()
|
||||
|
||||
>>> template1.categories.append(Category(category_child1.id))
|
||||
>>> template1.categories.append(Category(category_root2.id))
|
||||
>>> template1.save()
|
||||
>>> template2.categories.append(Category(category_child2.id))
|
||||
>>> template2.save()
|
||||
|
||||
Create sales::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
|
||||
>>> sale1 = Sale()
|
||||
>>> sale1.party = customer1
|
||||
>>> sale1.sale_date = fiscalyear.start_date
|
||||
>>> line = sale1.lines.new()
|
||||
>>> line.product = product1
|
||||
>>> line.quantity = 2
|
||||
>>> line = sale1.lines.new()
|
||||
>>> line.product = product2
|
||||
>>> line.quantity = 1
|
||||
>>> sale1.click('quote')
|
||||
>>> sale1.click('confirm')
|
||||
|
||||
>>> sale2 = Sale()
|
||||
>>> sale2.party = customer2
|
||||
>>> sale2.sale_date = fiscalyear.start_date + relativedelta(months=1)
|
||||
>>> line = sale2.lines.new()
|
||||
>>> line.product = product1
|
||||
>>> line.quantity = 1
|
||||
>>> sale2.click('quote')
|
||||
>>> sale2.click('confirm')
|
||||
|
||||
Check sale reporting per customer::
|
||||
|
||||
>>> Customer = Model.get('sale.reporting.customer')
|
||||
>>> CustomerTimeseries = Model.get('sale.reporting.customer.time_series')
|
||||
>>> context = dict(
|
||||
... from_date=fiscalyear.start_date,
|
||||
... to_date=fiscalyear.end_date,
|
||||
... period='month')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = Customer.find([])
|
||||
... time_series = CustomerTimeseries.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.customer.id, r.number, r.revenue) for r in reports},
|
||||
... {(customer1.id, 1, Decimal('30')),
|
||||
... (customer2.id, 1, Decimal('10'))})
|
||||
>>> len(time_series)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.customer.id, r.date, r.number, r.revenue)
|
||||
... for r in time_series},
|
||||
... {(customer1.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
|
||||
... (customer2.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))})
|
||||
|
||||
Check sale reporting per customer categories::
|
||||
|
||||
>>> CustomerCategory = Model.get('sale.reporting.customer.category')
|
||||
>>> CustomerCategoryTimeseries = Model.get(
|
||||
... 'sale.reporting.customer.category.time_series')
|
||||
>>> CustomerCategoryTree = Model.get('sale.reporting.customer.category.tree')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = CustomerCategory.find([])
|
||||
... time_series = CustomerCategoryTimeseries.find([])
|
||||
... tree = CustomerCategoryTree.find([])
|
||||
>>> len(reports)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.category.id, r.number, r.revenue) for r in reports},
|
||||
... {(party_category_child1.id, 1, Decimal('30')),
|
||||
... (party_category_root2.id, 1, Decimal('30')),
|
||||
... (party_category_child2.id, 1, Decimal('10'))})
|
||||
>>> len(time_series)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({
|
||||
... (r.category.id, r.date, r.number, r.revenue)
|
||||
... for r in time_series},
|
||||
... {
|
||||
... (party_category_child1.id, sale1.sale_date.replace(day=1),
|
||||
... 1, Decimal('30')),
|
||||
... (party_category_root2.id, sale1.sale_date.replace(day=1),
|
||||
... 1, Decimal('30')),
|
||||
... (party_category_child2.id, sale2.sale_date.replace(day=1),
|
||||
... 1, Decimal('10'))})
|
||||
>>> len(tree)
|
||||
4
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.name, r.revenue) for r in tree},
|
||||
... {('Root1', Decimal('40')),
|
||||
... ('Child1', Decimal('30')),
|
||||
... ('Child2', Decimal('10')),
|
||||
... ('Root2', Decimal('30'))})
|
||||
>>> child1, = CustomerCategoryTree.find([('rec_name', '=', 'Child1')])
|
||||
>>> child1.rec_name
|
||||
'Child1'
|
||||
|
||||
Check sale reporting per product::
|
||||
|
||||
>>> Product = Model.get('sale.reporting.product')
|
||||
>>> ProductTimeseries = Model.get('sale.reporting.product.time_series')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = Product.find([])
|
||||
... time_series = ProductTimeseries.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.product.id, r.number, r.revenue) for r in reports},
|
||||
... {(product1.id, 2, Decimal('30')),
|
||||
... (product2.id, 1, Decimal('10'))})
|
||||
>>> len(time_series)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.product.id, r.date, r.number, r.revenue)
|
||||
... for r in time_series},
|
||||
... {(product1.id, sale1.sale_date.replace(day=1), 1, Decimal('20')),
|
||||
... (product2.id, sale1.sale_date.replace(day=1), 1, Decimal('10')),
|
||||
... (product1.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))})
|
||||
|
||||
Check sale reporting per product categories::
|
||||
|
||||
>>> ProductCategory = Model.get('sale.reporting.product.category')
|
||||
>>> ProductCategoryTimeseries = Model.get(
|
||||
... 'sale.reporting.product.category.time_series')
|
||||
>>> ProductCategoryTree = Model.get('sale.reporting.product.category.tree')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = ProductCategory.find([])
|
||||
... time_series = ProductCategoryTimeseries.find([])
|
||||
... tree = ProductCategoryTree.find([])
|
||||
>>> len(reports)
|
||||
4
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.category.id, r.number, r.revenue) for r in reports},
|
||||
... {(category_child1.id, 2, Decimal('30')),
|
||||
... (category_root2.id, 2, Decimal('30')),
|
||||
... (category_child2.id, 1, Decimal('10')),
|
||||
... (account_category.id, 2, Decimal('40'))})
|
||||
>>> len(time_series)
|
||||
7
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.category.id, r.date, r.number, r.revenue)
|
||||
... for r in time_series},
|
||||
... {(category_child1.id, sale1.sale_date.replace(day=1), 1, Decimal('20')),
|
||||
... (category_root2.id, sale1.sale_date.replace(day=1), 1, Decimal('20')),
|
||||
... (category_child2.id, sale1.sale_date.replace(day=1), 1, Decimal('10')),
|
||||
... (category_child1.id, sale2.sale_date.replace(day=1), 1, Decimal('10')),
|
||||
... (category_root2.id, sale2.sale_date.replace(day=1), 1, Decimal('10')),
|
||||
... (account_category.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
|
||||
... (account_category.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))})
|
||||
>>> len(tree)
|
||||
5
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.name, r.revenue) for r in tree},
|
||||
... {('Root1', Decimal('40')),
|
||||
... ('Child1', Decimal('30')),
|
||||
... ('Child2', Decimal('10')),
|
||||
... ('Root2', Decimal('30')),
|
||||
... ('Account Category', Decimal('40'))})
|
||||
>>> child1, = ProductCategoryTree.find([('rec_name', '=', 'Child1')])
|
||||
>>> child1.rec_name
|
||||
'Child1'
|
||||
|
||||
Check sale reporting per countries::
|
||||
|
||||
>>> RegionTree = Model.get('sale.reporting.region.tree')
|
||||
>>> CountryTree = Model.get('sale.reporting.country.tree')
|
||||
>>> CountryTimeseries = Model.get('sale.reporting.country.time_series')
|
||||
>>> SubdivisionTimeseries = Model.get(
|
||||
... 'sale.reporting.country.subdivision.time_series')
|
||||
>>> with config.set_context(context=context):
|
||||
... region = RegionTree(north_america.id)
|
||||
... countries = CountryTree.find([])
|
||||
... country_time_series = CountryTimeseries.find([])
|
||||
... subdivision_time_series = SubdivisionTimeseries.find([])
|
||||
>>> region.revenue
|
||||
Decimal('40.00')
|
||||
>>> region.parent.revenue
|
||||
Decimal('40.00')
|
||||
>>> len(countries)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... sorted((c.region, c.number, c.revenue) for c in countries)
|
||||
[('California', 1, Decimal('30.00')), ('New York', 1, Decimal('10.00')), ('United States', 2, Decimal('40.00'))]
|
||||
>>> len(country_time_series)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.country.id, r.date, r.number, r.revenue)
|
||||
... for r in country_time_series},
|
||||
... {(country_us.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
|
||||
... (country_us.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))})
|
||||
>>> len(subdivision_time_series)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.subdivision.id, r.date, r.number, r.revenue)
|
||||
... for r in subdivision_time_series},
|
||||
... {(california.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
|
||||
... (new_york.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))})
|
||||
71
modules/sale/tests/test_module.py
Normal file
71
modules/sale/tests/test_module.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
|
||||
from trytond.modules.account.tests import create_chart
|
||||
from trytond.modules.company.tests import (
|
||||
CompanyTestMixin, PartyCompanyCheckEraseMixin, create_company, set_company)
|
||||
from trytond.modules.party.tests import PartyCheckReplaceMixin
|
||||
from trytond.pool import Pool
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class SaleTestCase(
|
||||
PartyCompanyCheckEraseMixin, PartyCheckReplaceMixin, CompanyTestMixin,
|
||||
ModuleTestCase):
|
||||
'Test Sale module'
|
||||
module = 'sale'
|
||||
|
||||
@with_transaction()
|
||||
def test_sale_price(self):
|
||||
"Test sale price"
|
||||
pool = Pool()
|
||||
Account = pool.get('account.account')
|
||||
Template = pool.get('product.template')
|
||||
Product = pool.get('product.product')
|
||||
Uom = pool.get('product.uom')
|
||||
|
||||
company = create_company()
|
||||
with set_company(company):
|
||||
create_chart(company)
|
||||
|
||||
receivable, = Account.search([
|
||||
('closed', '!=', True),
|
||||
('type.receivable', '=', True),
|
||||
('party_required', '=', True),
|
||||
('company', '=', company.id),
|
||||
], limit=1)
|
||||
payable, = Account.search([
|
||||
('closed', '!=', True),
|
||||
('type.payable', '=', True),
|
||||
('party_required', '=', True),
|
||||
('company', '=', company.id),
|
||||
], limit=1)
|
||||
|
||||
kg, = Uom.search([('name', '=', 'Kilogram')])
|
||||
g, = Uom.search([('name', '=', 'Gram')])
|
||||
pound, = Uom.search([('name', '=', 'Pound')])
|
||||
|
||||
template, = Template.create([{
|
||||
'name': 'Product',
|
||||
'default_uom': g.id,
|
||||
'sale_uom': kg.id,
|
||||
'list_price': Decimal(5),
|
||||
'products': [('create', [{}])],
|
||||
}])
|
||||
product, = template.products
|
||||
|
||||
prices = Product.get_sale_price([product], quantity=100)
|
||||
self.assertEqual(prices, {product.id: Decimal(5000)})
|
||||
prices = Product.get_sale_price([product], quantity=1500)
|
||||
self.assertEqual(prices, {product.id: Decimal(5000)})
|
||||
|
||||
with Transaction().set_context(uom=pound.id):
|
||||
prices = Product.get_sale_price([product], quantity=0.5)
|
||||
self.assertEqual(prices, {product.id: Decimal('2267.9618')})
|
||||
prices = Product.get_sale_price([product], quantity=1.5)
|
||||
self.assertEqual(prices, {product.id: Decimal('2267.9618')})
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
8
modules/sale/tests/test_scenario.py
Normal file
8
modules/sale/tests/test_scenario.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.tests.test_tryton import load_doc_tests
|
||||
|
||||
|
||||
def load_tests(*args, **kwargs):
|
||||
return load_doc_tests(__name__, __file__, *args, **kwargs)
|
||||
Reference in New Issue
Block a user