Support global discounts in supplier invoices

This commit is contained in:
Guillem Barba 2016-04-19 12:10:24 +02:00
parent 2f3187c689
commit e4d92c56b2
15 changed files with 599 additions and 71 deletions

View File

@ -1 +1,4 @@
* Support global discounts in supplier invoices
Version 3.4.0 - 2016-02-17
* Initial release

View File

@ -4,11 +4,13 @@ from trytond.pool import Pool
from .invoice import *
from .party import *
def register():
Pool.register(
Party,
Configuration,
Invoice,
InvoiceLine,
Purchase,
Sale,
module='account_invoice_discount_global', type_='model')

View File

@ -1,10 +1,13 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from decimal import Decimal
from trytond.config import config
from trytond.model import ModelView, Workflow, fields
from trytond.pool import PoolMeta, Pool
from trytond.config import config
from trytond.pyson import Eval
__all__ = ['Configuration', 'Invoice', 'InvoiceLine', 'Sale']
__all__ = ['Configuration', 'Invoice', 'InvoiceLine', 'Sale', 'Purchase']
DISCOUNT_DIGITS = int(config.get('digits', 'discount_digits', 4))
@ -36,10 +39,13 @@ class Invoice:
def default_invoice_discount():
return Decimal(0)
@fields.depends('party')
@fields.depends('party', 'type')
def on_change_with_invoice_discount(self):
if self.party:
return self.party.invoice_discount
if self.type in ('in_invoice', 'in_credit_note'):
return self.party.supplier_invoice_discount
else:
return self.party.customer_invoice_discount
@classmethod
@ModelView.button
@ -47,35 +53,39 @@ class Invoice:
pool = Pool()
Line = pool.get('account.invoice.line')
Config = Pool().get('account.configuration')
config = Config(1)
product = config.discount_product
lines = []
for invoice in invoices:
if not invoice.invoice_discount:
continue
lines.extend(invoice._get_discount_line(invoice, product))
lines.extend(invoice._get_discount_line(product))
if lines:
Line.create([x._save_values for x in lines])
cls.update_taxes(invoices)
def _get_discount_line(self, invoice, product):
def _get_discount_line(self, product):
Line = Pool().get('account.invoice.line')
amount = -1 * invoice.untaxed_amount * invoice.invoice_discount
amount = -1 * self.untaxed_amount * self.invoice_discount
lines = []
if amount and invoice.lines:
if amount and self.lines:
if not product:
self.raise_user_error('missing_discount_product',
invoice.rec_name)
self.rec_name)
line = Line()
line.invoice = self
line.type = 'line'
line.product = product
line.account = product.account_revenue_used
if self.type in ('in_invoice', 'in_credit_note'):
line.account = product.account_expense_used
else:
line.account = product.account_revenue_used
line.description = product.rec_name
line.quantity = 1
line.unit = product.default_uom
line.unit_price = amount
line._update_taxes()
line._update_taxes(self.type, self.party)
lines.append(line)
return lines
@ -132,23 +142,36 @@ class InvoiceLine:
__name__ = 'account.invoice.line'
__metaclass__ = PoolMeta
def _update_taxes(self):
def _update_taxes(self, invoice_type, party):
Tax = Pool().get('account.tax')
taxes = []
party = self.invoice.party
pattern = self._get_tax_rule_pattern()
for tax in self.product.customer_taxes_used:
if party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(tax, pattern)
if invoice_type in ('in_invoice', 'in_credit_note'):
for tax in self.product.supplier_taxes_used:
if party.supplier_tax_rule:
tax_ids = party.supplier_tax_rule.apply(tax, pattern)
if tax_ids:
taxes.extend(tax_ids)
continue
taxes.append(tax.id)
if party.supplier_tax_rule:
tax_ids = party.supplier_tax_rule.apply(None, pattern)
if tax_ids:
taxes.extend(tax_ids)
continue
taxes.append(tax.id)
if party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(None, pattern)
if tax_ids:
taxes.extend(tax_ids)
self.taxes = Tax.browse(taxes)
else:
for tax in self.product.customer_taxes_used:
if party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(tax, pattern)
if tax_ids:
taxes.extend(tax_ids)
continue
taxes.append(tax.id)
if party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(None, pattern)
if tax_ids:
taxes.extend(tax_ids)
if taxes:
self.taxes = Tax.browse(taxes)
class Sale:
@ -158,5 +181,18 @@ class Sale:
def _get_invoice_sale(self, invoice_type):
invoice = super(Sale, self)._get_invoice_sale(invoice_type)
if invoice:
invoice.invoice_discount = invoice.on_change_with_invoice_discount()
invoice.invoice_discount = (
invoice.on_change_with_invoice_discount())
return invoice
class Purchase:
__name__ = 'purchase.purchase'
__metaclass__ = PoolMeta
def _get_invoice_purchase(self, invoice_type):
invoice = super(Purchase, self)._get_invoice_purchase(invoice_type)
if invoice:
invoice.invoice_discount = (
invoice.on_change_with_invoice_discount())
return invoice

View File

@ -1,3 +1,6 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="configuration_view_form">
@ -6,6 +9,7 @@
<field name="inherit" ref="account.configuration_view_form"/>
<field name="name">configuration_form</field>
</record>
<record model="ir.ui.view" id="invoice_view_form">
<field name="model">account.invoice</field>
<field name="type">form</field>

View File

@ -1,8 +1,7 @@
#
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
#, fuzzy
msgctxt "error:account.invoice:"
msgid "Invoice \"%s\" has a discount but no discount product is configured."
msgstr ""
@ -17,9 +16,13 @@ msgctxt "field:account.invoice,invoice_discount:"
msgid "Invoice Discount"
msgstr "Descompte en factura"
msgctxt "field:party.party,invoice_discount:"
msgid "Invoice Discount"
msgstr "Descompte en factura"
msgctxt "field:party.party,customer_invoice_discount:"
msgid "Customer Invoice Discount"
msgstr "Descompte en factura de client"
msgctxt "field:party.party,supplier_invoice_discount:"
msgid "Supplier Invoice Discount"
msgstr "Descompte en factura de proveïdor"
msgctxt "view:account.invoice:"
msgid "%"
@ -28,3 +31,7 @@ msgstr "%"
msgctxt "view:party.party:"
msgid "%"
msgstr "%"
msgctxt "view:party.party:"
msgid "Invoice Discount"
msgstr "Descompte en factura"

View File

@ -1,4 +1,4 @@
#
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
@ -16,9 +16,13 @@ msgctxt "field:account.invoice,invoice_discount:"
msgid "Invoice Discount"
msgstr "Descuento en factura"
msgctxt "field:party.party,invoice_discount:"
msgid "Invoice Discount"
msgstr "Descuento en factura"
msgctxt "field:party.party,customer_invoice_discount:"
msgid "Customer Invoice Discount"
msgstr "Descuento en factura de cliente"
msgctxt "field:party.party,supplier_invoice_discount:"
msgid "Supplier Invoice Discount"
msgstr "Descuento en factura de proveedor"
msgctxt "view:account.invoice:"
msgid "%"
@ -27,3 +31,7 @@ msgstr "%"
msgctxt "view:party.party:"
msgid "%"
msgstr "%"
msgctxt "view:party.party:"
msgid "Invoice Discount"
msgstr "Descuento en factura"

View File

@ -1,6 +1,13 @@
from trytond.model import fields
from trytond.pool import PoolMeta
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from sql import Null
from trytond import backend
from trytond.config import config
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
from trytond.transaction import Transaction
__all__ = ['Party']
@ -10,5 +17,32 @@ DISCOUNT_DIGITS = int(config.get('digits', 'discount_digits', 4))
class Party:
__name__ = 'party.party'
__metaclass__ = PoolMeta
invoice_discount = fields.Numeric('Invoice Discount',
digits=(16, DISCOUNT_DIGITS))
customer_invoice_discount = fields.Property(fields.Numeric(
'Customer Invoice Discount', digits=(16, DISCOUNT_DIGITS), states={
'invisible': ~Eval('context', {}).get('company'),
}))
supplier_invoice_discount = fields.Property(fields.Numeric(
'Supplier Invoice Discount', digits=(16, DISCOUNT_DIGITS), states={
'invisible': ~Eval('context', {}).get('company'),
}))
@classmethod
def __register__(cls, module_name):
pool = Pool()
Property = pool.get('ir.property')
TableHandler = backend.get('TableHandler')
super(Party, cls).__register__(module_name)
cursor = Transaction().cursor
handler = TableHandler(cursor, cls, module_name)
table = cls.__table__()
# Migration from 3.4.0: moved invoice_discount to property
# customer_invoice_discount
if handler.column_exist('invoice_discount'):
cursor.execute(*table.select(table.id, table.invoice_discount,
where=table.invoice_discount != Null))
for party_id, invoice_discount in cursor.fetchall():
Property.set('customer_invoice_discount', cls._name, party_id,
invoice_discount)
handler.drop_column('invoice_discount', exception=True)

View File

@ -1,3 +1,6 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="party_view_form">

View File

@ -1,8 +1,9 @@
================
Invoice Scenario
================
================================
Invoice Discount Global Scenario
================================
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
@ -15,7 +16,7 @@ Create database::
>>> config = config.set_trytond()
>>> config.pool.test = True
Install account_invoice::
Install account_invoice_discount_global::
>>> Module = Model.get('ir.module.module')
>>> account_invoice_module, = Module.find(
@ -137,10 +138,12 @@ Create tax::
>>> tax.credit_note_tax_code = credit_note_tax_code
>>> tax.save()
Create party::
Create party with customer invoice discount of 5% and supplier discount of 3%::
>>> Party = Model.get('party.party')
>>> party = Party(name='Party')
>>> party.customer_invoice_discount = Decimal('0.05')
>>> party.supplier_invoice_discount = Decimal('0.03')
>>> party.save()
Create product::
@ -148,8 +151,6 @@ Create product::
>>> ProductUom = Model.get('product.uom')
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> ProductTemplate = Model.get('product.template')
>>> Product = Model.get('product.product')
>>> product = Product()
>>> template = ProductTemplate()
>>> template.name = 'product'
>>> template.default_uom = unit
@ -159,17 +160,12 @@ Create product::
>>> template.account_expense = expense
>>> template.account_revenue = revenue
>>> template.customer_taxes.append(tax)
>>> template.supplier_taxes.append(Tax(tax.id))
>>> template.save()
>>> product.template = template
>>> product.save()
>>> product, = template.products
Create discount product::
>>> ProductUom = Model.get('product.uom')
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> ProductTemplate = Model.get('product.template')
>>> Product = Model.get('product.product')
>>> discount_product = Product()
>>> template = ProductTemplate()
>>> template.name = 'product'
>>> template.default_uom = unit
@ -179,13 +175,12 @@ Create discount product::
>>> template.account_expense = expense
>>> template.account_revenue = revenue
>>> template.save()
>>> discount_product.template = template
>>> discount_product.save()
>>> discount_product, = template.products
Configure discount product::
>>> Configuration = Model.get('account.configuration')
>>> configuration = Configuration.find([])[0]
>>> configuration = Configuration(1)
>>> configuration.discount_product = discount_product
>>> configuration.save()
@ -201,13 +196,14 @@ Create payment term::
>>> payment_term.lines.append(payment_term_line)
>>> payment_term.save()
Create invoice::
Create customer invoice::
>>> Invoice = Model.get('account.invoice')
>>> InvoiceLine = Model.get('account.invoice.line')
>>> invoice = Invoice()
>>> invoice.party = party
>>> invoice.payment_term = payment_term
>>> invoice.invoice_date = today
>>> line = InvoiceLine()
>>> invoice.lines.append(line)
>>> line.product = product
@ -224,17 +220,82 @@ Create invoice::
Decimal('20.00')
>>> invoice.total_amount
Decimal('240.00')
>>> invoice.invoice_discount = Decimal('0.1')
>>> invoice.save()
Check invoice discount is parties customer invoice discount::
>>> invoice.invoice_discount
Decimal('0.05')
Change invoice discount::
>>> invoice.invoice_discount = Decimal('0.1')
>>> invoice.untaxed_amount
Decimal('220.00')
>>> invoice.save()
Post invoice and check discount is applied::
>>> Invoice.post([invoice.id], config.context)
>>> invoice.reload()
>>> invoice.state
u'posted'
>>> invoice.invoice_discount
Decimal('0.1')
>>> discount_line, = [l for l in invoice.lines
... if l.product == discount_product]
>>> discount_line.quantity
1.0
>>> discount_line.amount
Decimal('-22.00')
>>> invoice.untaxed_amount
Decimal('198.00')
>>> invoice.tax_amount
Decimal('20.00')
>>> invoice.total_amount
Decimal('218.00')
Create supplier invoice::
>>> invoice = Invoice()
>>> invoice.type = 'in_invoice'
>>> invoice.party = party
>>> invoice.payment_term = payment_term
>>> invoice.invoice_date = today
>>> line = InvoiceLine()
>>> invoice.lines.append(line)
>>> line.product = product
>>> line.quantity = 10
>>> invoice.untaxed_amount
Decimal('250.00')
>>> invoice.tax_amount
Decimal('25.00')
>>> invoice.total_amount
Decimal('275.00')
>>> invoice.save()
Check invoice discount is parties supplier invoice discount::
>>> invoice.invoice_discount
Decimal('0.03')
Post invoice and check discount is applied::
>>> Invoice.post([invoice.id], config.context)
>>> invoice.reload()
>>> invoice.state
u'posted'
>>> invoice.invoice_discount
Decimal('0.03')
>>> discount_line, = [l for l in invoice.lines
... if l.product == discount_product]
>>> discount_line.quantity
1.0
>>> discount_line.amount
Decimal('-7.50')
>>> invoice.untaxed_amount
Decimal('242.50')
>>> invoice.tax_amount
Decimal('25.00')
>>> invoice.total_amount
Decimal('267.50')

View File

@ -0,0 +1,344 @@
=======================================================
Invoice Discount Global from Sale and Purchase Scenario
=======================================================
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
>>> from operator import attrgetter
>>> from proteus import config, Model, Wizard
>>> today = datetime.date.today()
Create database::
>>> config = config.set_trytond()
>>> config.pool.test = True
Install account_invoice_discount_global, sale and purchase::
>>> Module = Model.get('ir.module.module')
>>> account_invoice_module, = Module.find(
... [('name', '=', 'account_invoice_discount_global')])
>>> sale_module, = Module.find([('name', '=', 'sale')])
>>> purchase_module, = Module.find([('name', '=', 'purchase')])
>>> Module.install([
... account_invoice_module.id,
... sale_module.id,
... purchase_module.id,
... ], config.context)
>>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
Create company::
>>> Currency = Model.get('currency.currency')
>>> CurrencyRate = Model.get('currency.currency.rate')
>>> currencies = Currency.find([('code', '=', 'USD')])
>>> if not currencies:
... currency = Currency(name='U.S. Dollar', symbol='$', code='USD',
... rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
... mon_decimal_point='.', mon_thousands_sep=',')
... currency.save()
... CurrencyRate(date=today + relativedelta(month=1, day=1),
... rate=Decimal('1.0'), currency=currency).save()
... else:
... currency, = currencies
>>> Company = Model.get('company.company')
>>> Party = Model.get('party.party')
>>> company_config = Wizard('company.company.config')
>>> company_config.execute('company')
>>> company = company_config.form
>>> party = Party(name='Dunder Mifflin')
>>> party.save()
>>> company.party = party
>>> company.currency = currency
>>> company_config.execute('add')
>>> company, = Company.find([])
Reload the context::
>>> User = Model.get('res.user')
>>> Group = Model.get('res.group')
>>> config._context = User.get_preferences(True, config.context)
Create sale user::
>>> sale_user = User()
>>> sale_user.name = 'Sale'
>>> sale_user.login = 'sale'
>>> sale_user.main_company = company
>>> sale_group, = Group.find([('name', '=', 'Sales')])
>>> sale_user.groups.append(sale_group)
>>> sale_user.save()
Create stock user::
>>> stock_user = User()
>>> stock_user.name = 'Stock'
>>> stock_user.login = 'stock'
>>> stock_user.main_company = company
>>> stock_group, = Group.find([('name', '=', 'Stock')])
>>> stock_user.groups.append(stock_group)
>>> stock_user.save()
Create account user::
>>> account_user = User()
>>> account_user.name = 'Account'
>>> account_user.login = 'account'
>>> account_user.main_company = company
>>> account_group, = Group.find([('name', '=', 'Account')])
>>> account_user.groups.append(account_group)
>>> account_user.save()
Create fiscal year::
>>> FiscalYear = Model.get('account.fiscalyear')
>>> Sequence = Model.get('ir.sequence')
>>> SequenceStrict = Model.get('ir.sequence.strict')
>>> fiscalyear = FiscalYear(name=str(today.year))
>>> fiscalyear.start_date = today + relativedelta(month=1, day=1)
>>> fiscalyear.end_date = today + relativedelta(month=12, day=31)
>>> fiscalyear.company = company
>>> post_move_seq = Sequence(name=str(today.year), code='account.move',
... company=company)
>>> post_move_seq.save()
>>> fiscalyear.post_move_sequence = post_move_seq
>>> invoice_seq = SequenceStrict(name=str(today.year),
... code='account.invoice', company=company)
>>> invoice_seq.save()
>>> fiscalyear.out_invoice_sequence = invoice_seq
>>> fiscalyear.in_invoice_sequence = invoice_seq
>>> fiscalyear.out_credit_note_sequence = invoice_seq
>>> fiscalyear.in_credit_note_sequence = invoice_seq
>>> fiscalyear.save()
>>> FiscalYear.create_period([fiscalyear.id], config.context)
Create chart of accounts::
>>> AccountTemplate = Model.get('account.account.template')
>>> Account = Model.get('account.account')
>>> Journal = Model.get('account.journal')
>>> account_template, = AccountTemplate.find([('parent', '=', None)])
>>> create_chart = Wizard('account.create_chart')
>>> create_chart.execute('account')
>>> create_chart.form.account_template = account_template
>>> create_chart.form.company = company
>>> create_chart.execute('create_account')
>>> receivable, = Account.find([
... ('kind', '=', 'receivable'),
... ('company', '=', company.id),
... ])
>>> payable, = Account.find([
... ('kind', '=', 'payable'),
... ('company', '=', company.id),
... ])
>>> revenue, = Account.find([
... ('kind', '=', 'revenue'),
... ('company', '=', company.id),
... ])
>>> expense, = Account.find([
... ('kind', '=', 'expense'),
... ('company', '=', company.id),
... ])
>>> account_tax, = Account.find([
... ('kind', '=', 'other'),
... ('company', '=', company.id),
... ('name', '=', 'Main Tax'),
... ])
>>> create_chart.form.account_receivable = receivable
>>> create_chart.form.account_payable = payable
>>> create_chart.execute('create_properties')
Create tax::
>>> TaxCode = Model.get('account.tax.code')
>>> Tax = Model.get('account.tax')
>>> tax = Tax()
>>> tax.name = 'Tax'
>>> tax.description = 'Tax'
>>> tax.type = 'percentage'
>>> tax.rate = Decimal('.10')
>>> tax.invoice_account = account_tax
>>> tax.credit_note_account = account_tax
>>> invoice_base_code = TaxCode(name='invoice base')
>>> invoice_base_code.save()
>>> tax.invoice_base_code = invoice_base_code
>>> invoice_tax_code = TaxCode(name='invoice tax')
>>> invoice_tax_code.save()
>>> tax.invoice_tax_code = invoice_tax_code
>>> credit_note_base_code = TaxCode(name='credit note base')
>>> credit_note_base_code.save()
>>> tax.credit_note_base_code = credit_note_base_code
>>> credit_note_tax_code = TaxCode(name='credit note tax')
>>> credit_note_tax_code.save()
>>> tax.credit_note_tax_code = credit_note_tax_code
>>> tax.save()
Create parties::
>>> Party = Model.get('party.party')
>>> supplier = Party(name='Supplier')
>>> supplier.supplier_invoice_discount = Decimal('0.03')
>>> supplier.save()
>>> customer = Party(name='Customer')
>>> customer.customer_invoice_discount = Decimal('0.05')
>>> customer.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 = 'service'
>>> template.purchasable = True
>>> template.salable = True
>>> template.list_price = Decimal('40')
>>> template.cost_price = Decimal('25')
>>> template.account_expense = expense
>>> template.account_revenue = revenue
>>> template.customer_taxes.append(tax)
>>> template.supplier_taxes.append(Tax(tax.id))
>>> template.save()
>>> product, = template.products
Create discount product::
>>> template = ProductTemplate()
>>> template.name = 'product'
>>> template.default_uom = unit
>>> template.type = 'service'
>>> template.list_price = Decimal('0')
>>> template.cost_price = Decimal('0')
>>> template.account_expense = expense
>>> template.account_revenue = revenue
>>> template.save()
>>> discount_product, = template.products
Configure discount product::
>>> Configuration = Model.get('account.configuration')
>>> configuration = Configuration(1)
>>> configuration.discount_product = discount_product
>>> configuration.save()
Create payment term::
>>> PaymentTerm = Model.get('account.invoice.payment_term')
>>> PaymentTermLine = Model.get('account.invoice.payment_term.line')
>>> payment_term = PaymentTerm(name='Direct')
>>> payment_term_line = PaymentTermLine(type='remainder', days=0)
>>> payment_term.lines.append(payment_term_line)
>>> payment_term.save()
Sale 5 services::
>>> 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 = 5.0
>>> sale.save()
>>> Sale.quote([sale.id], config.context)
>>> Sale.confirm([sale.id], config.context)
>>> Sale.process([sale.id], config.context)
>>> sale.state
u'processing'
>>> sale.reload()
>>> sale.untaxed_amount
Decimal('200.00')
>>> sale.tax_amount
Decimal('20.00')
>>> sale.total_amount
Decimal('220.00')
>>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
(0, 0, 1)
>>> invoice, = sale.invoices
>>> invoice.origins == sale.rec_name
True
Created invoice has customer's invoice discount::
>>> invoice.invoice_discount
Decimal('0.05')
Post invoice and check discount is applied::
>>> Invoice = Model.get('account.invoice')
>>> Invoice.post([i.id for i in sale.invoices], config.context)
>>> invoice.reload()
>>> discount_line, = [l for l in invoice.lines
... if l.product == discount_product]
>>> discount_line.quantity
1.0
>>> discount_line.amount
Decimal('-10.00')
>>> invoice.untaxed_amount
Decimal('190.00')
>>> invoice.tax_amount
Decimal('20.00')
>>> invoice.total_amount
Decimal('210.00')
Purchase 3 services::
>>> Purchase = Model.get('purchase.purchase')
>>> PurchaseLine = Model.get('purchase.line')
>>> purchase = Purchase()
>>> purchase.party = supplier
>>> purchase.payment_term = payment_term
>>> purchase.invoice_method = 'order'
>>> purchase_line = PurchaseLine()
>>> purchase.lines.append(purchase_line)
>>> purchase_line.product = product
>>> purchase_line.quantity = 3.0
>>> purchase.click('quote')
>>> purchase.click('confirm')
>>> purchase.click('process')
>>> purchase.state
u'processing'
>>> purchase.reload()
>>> purchase.untaxed_amount
Decimal('75.00')
>>> purchase.tax_amount
Decimal('7.50')
>>> purchase.total_amount
Decimal('82.50')
>>> len(purchase.moves), len(purchase.shipment_returns), len(purchase.invoices)
(0, 0, 1)
>>> invoice, = purchase.invoices
>>> invoice.origins == purchase.rec_name
True
Created invoice has supplier's invoice discount::
>>> invoice.invoice_discount
Decimal('0.03')
Post invoice and check discount is applied::
>>> invoice.invoice_date = today
>>> invoice.save()
>>> Invoice.post([invoice.id], config.context)
>>> invoice.reload()
>>> discount_line, = [l for l in invoice.lines
... if l.product == discount_product]
>>> discount_line.quantity
1.0
>>> discount_line.amount
Decimal('-2.25')
>>> invoice.untaxed_amount
Decimal('72.75')
>>> invoice.tax_amount
Decimal('7.50')
>>> invoice.total_amount
Decimal('80.25')

View File

@ -1,14 +1,15 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
import unittest
import doctest
import unittest
import trytond.tests.test_tryton
from trytond.tests.test_tryton import test_view, test_depends
from trytond.tests.test_tryton import doctest_setup, doctest_teardown
class TestCase(unittest.TestCase):
'Test module'
'Test account_invoice_discount_global module'
def setUp(self):
trytond.tests.test_tryton.install_module(
@ -29,4 +30,7 @@ def suite():
suite.addTests(doctest.DocFileSuite('scenario_invoice.rst',
setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite('scenario_invoice_sale_purchase.rst',
setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite

View File

@ -1,8 +1,10 @@
[tryton]
version=3.4.0
version=3.4.1
depends:
account_invoice
extras_depend:
sale
purchase
xml:
invoice.xml
party.xml

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<data>
<xpath expr="/form/field[@name='default_account_payable']" position="after">
<label name="discount_product"/>

View File

@ -1,9 +1,15 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook/page[@id='invoice']/field[@name='currency']" position="after">
<xpath expr="/form/notebook/page[@id='invoice']/field[@name='currency']"
position="after">
<label name="invoice_discount"/>
<group id="discount" col="2" xexpand="0">
<field name="invoice_discount" factor="100" xalign="1.0" xexpand="0"/>
<label name="invoice_discount" string="%" xalign="0.0" xexpand="1" xfill="1"/>
<field name="invoice_discount" factor="100"
xalign="1.0" xexpand="0"/>
<label name="invoice_discount" string="%"
xalign="0.0" xexpand="1" xfill="1"/>
</group>
</xpath>
</data>
</data>

View File

@ -1,9 +1,23 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook/page[@id='sale']" position="inside">
<label name="invoice_discount"/>
<group id="discount" col="2" xexpand="0">
<field name="invoice_discount" factor="100" xalign="1.0" xexpand="0"/>
<label name="invoice_discount" string="%" xalign="0.0" xexpand="1" xfill="1"/>
<xpath expr="/form/notebook/page[@id='accounting']/field[@name='vat_number']"
position="after">
<separator string="Invoice Discount" colspan="4" id="invoice_discount"/>
<label name="customer_invoice_discount"/>
<group id="customer_invoice_discount" col="2" xexpand="0">
<field name="customer_invoice_discount" factor="100"
xalign="1.0" xexpand="0"/>
<label name="customer_invoice_discount" string="%"
xalign="0.0" xexpand="1" xfill="1"/>
</group>
<label name="supplier_invoice_discount"/>
<group id="supplier_invoice_discount" col="2" xexpand="0">
<field name="supplier_invoice_discount" factor="100"
xalign="1.0" xexpand="0"/>
<label name="supplier_invoice_discount" string="%"
xalign="0.0" xexpand="1" xfill="1"/>
</group>
</xpath>
</data>
</data>