diff --git a/MANIFEST.in b/MANIFEST.in
index 1489ca2..4c6b589 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -9,4 +9,4 @@ include view/*.xml
include locale/*.po
include doc/*
include tests/*.rst
-include *.odt
+include *.fodt
diff --git a/__init__.py b/__init__.py
index 497aecd..713e62f 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,10 +1,10 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from trytond.pool import Pool
-from .invoice import *
+from . import invoice
def register():
Pool.register(
- InvoiceLine,
+ invoice.InvoiceLine,
module='account_invoice_discount', type_='model')
diff --git a/invoice.fodt b/invoice.fodt
new file mode 100644
index 0000000..2e6bfec
--- /dev/null
+++ b/invoice.fodt
@@ -0,0 +1,1157 @@
+
+
+
+ LibreOffice/5.4.2.2.0$Linux_X86_64 LibreOffice_project/40m0$Build-22012-11-15T15:00:351P0D
+
+
+ 55541
+ 0
+ 25049
+ 21408
+ true
+ false
+
+
+ view2
+ 3729
+ 79347
+ 0
+ 55541
+ 25047
+ 76948
+ 0
+ 1
+ false
+ 100
+ false
+ false
+
+
+
+
+ false
+ true
+ true
+ true
+ 0
+ true
+ true
+
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ false
+
+ false
+ false
+ false
+ true
+ false
+ false
+
+ false
+ false
+ false
+ false
+ true
+ 2578396
+ false
+ true
+ false
+ false
+ true
+ true
+ false
+ true
+ 0
+ false
+ true
+ high-resolution
+ false
+ false
+ false
+ true
+ true
+ true
+
+ true
+ false
+ false
+ true
+ false
+ false
+ false
+
+ false
+ false
+ 882034
+ false
+ 1
+ true
+ false
+ false
+ 0
+ false
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <if test="invoice.company.header">
+ <for each="line in invoice.company.header.split('\n')">
+ <line>
+ </for>
+ </if>
+ <invoice.company.rec_name>
+
+
+ <if test="invoice.company.footer">
+ <for each="line in invoice.company.footer.split('\n')">
+ <line>
+ </for>
+ </if>
+
+
+
+
+
+
+
+
+
+
+
+
+ <replace text:p="set_lang(invoice.party.lang and invoice.party.lang.code or 'en')">
+ <replace text:p="invoice.set_lang(invoice.party.lang and invoice.party.lang.code or 'en')">
+ <for each="line in invoice.invoice_address.full_address.split('\n')">
+ <line>
+ </for>
+ <if test="invoice.party_tax_identifier">
+ <invoice.party_tax_identifier.type_string>: <invoice.party_tax_identifier.code>
+ </if>
+ <if test="invoice.type == 'in'">
+ Supplier Invoice N°:<invoice.number and ' ' + invoice.number or ''>
+ </if>
+ <if test="invoice.type == 'out'">
+ <choose test="">
+ <when test="invoice.state == 'draft'">
+ Draft Invoice
+ </when>
+ <when test="invoice.state == 'validated'">
+ Pro forma Invoice
+ </when>
+ <otherwise test="">
+ Invoice N°:<invoice.number and ' ' + invoice.number or ''>
+ </otherwise>
+ </choose>
+ </if>
+ Description: <invoice.description or ''>
+ Reference: <invoice.origins or ''><', ' if (invoice.reference and invoice.origins) else ''><invoice.reference or ''>
+ <if test="invoice.invoice_date">
+ Date: <format_date(invoice.invoice_date, invoice.party.lang)>
+ </if>
+ <if test="invoice.tax_identifier">
+ <invoice.tax_identifier.type_string>: <invoice.tax_identifier.code>
+ </if>
+
+
+
+
+
+
+
+
+
+
+
+
+ Description
+
+
+ Quantity
+
+
+
+ Unit Price
+
+
+ Discount
+
+
+ Taxes
+
+
+ Amount
+
+
+
+
+
+ <for each="line in invoice.lines">
+
+
+
+
+
+
+
+
+
+
+
+
+ <choose test="">
+
+
+
+
+
+
+
+
+
+
+
+
+ <when test="line.type == 'line'">
+
+
+
+
+
+
+
+
+
+
+
+
+ <for each="line in line.description.split('\n')">
+ <line>
+ </for>
+
+
+ <(format_number(line.quantity, invoice.party.lang, digits=line.unit_digits) + (line.unit and (' ' + line.unit.symbol) or '')) or ''>
+
+
+
+ <format_currency(line.unit_price, invoice.party.lang, invoice.currency)>
+
+
+ <format_number(line.discount * 100, invoice.party.lang)>%
+
+
+ <','.join('[' + str(x.sequence_number) + ']' for x in line.invoice_taxes)>
+
+
+ <format_currency(line.amount, invoice.party.lang, invoice.currency)>
+
+
+
+
+
+
+
+
+
+ </when>
+
+
+
+
+
+
+
+
+ <when test="line.type == 'subtotal'">
+
+
+
+
+
+
+
+
+
+
+
+
+ <for each="line in line.description.split('\n')">
+ <line>
+ </for>
+
+
+
+
+
+
+
+
+
+ <format_currency(line.amount, invoice.party.lang, invoice.currency)>
+
+
+
+
+ </when>
+
+
+
+
+
+
+
+
+
+
+
+
+ <when test="line.type == 'title'">
+
+
+
+
+
+
+
+
+
+
+
+
+ <for each="line in line.description.split('\n')">
+ <line>
+ </for>
+
+
+
+
+
+
+
+
+
+
+
+
+ </when>
+
+
+
+
+
+
+
+
+
+
+
+
+ <otherwise test="">
+
+
+
+
+
+
+
+
+
+
+
+
+ <for each="line in line.description.split('\n')">
+ <line>
+ </for>
+
+
+
+
+
+
+
+
+
+
+
+
+ </otherwise>
+
+
+
+
+
+
+
+
+
+
+
+
+ </choose>
+
+
+
+
+
+
+
+
+
+
+
+
+ </for>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tax
+
+
+ Base
+
+
+ Amount
+
+
+
+
+
+ <for each="tax in invoice.taxes">
+
+
+
+
+
+
+ <'[' + '%s' % tax.sequence_number + ']'><tax.description or ''>
+
+
+ <format_currency(tax.base, invoice.party.lang, invoice.currency)>
+
+
+ <format_currency(tax.amount, invoice.party.lang, invoice.currency)>
+
+
+
+
+ <if test="tax.legal_notice">
+
+
+
+
+
+
+ <for each="line in tax.legal_notice.split('\n')">
+ <line>
+ </for>
+
+
+
+
+
+
+ </if>
+
+
+
+
+
+
+ </for>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total (excl. taxes):
+
+
+ <format_currency(invoice.untaxed_amount, invoice.party.lang, invoice.currency)>
+
+
+
+
+ Taxes:
+
+
+ <format_currency(invoice.tax_amount, invoice.party.lang, invoice.currency)>
+
+
+
+
+ Total:
+
+
+ <format_currency(invoice.total_amount, invoice.party.lang, invoice.currency)>
+
+
+
+
+
+
+
+ <if test="invoice.lines_to_pay">
+
+
+
+
+
+
+
+ Payment Term
+ <if test="invoice.payment_term and invoice.payment_term.description">
+ <for each="description in (invoice.payment_term.description or '').split('\n')">
+ <description>
+ </for>
+ </if>
+
+
+
+
+
+ Date
+
+
+ Amount
+
+
+
+
+
+ <for each="line in invoice.lines_to_pay">
+
+
+
+
+
+ <format_date(line.maturity_date, invoice.party.lang)>
+
+
+ <line.amount_second_currency and format_currency(line.amount_second_currency, invoice.party.lang, invoice.currency) or format_currency(line.debit - line.credit, invoice.party.lang, invoice.currency)>
+
+
+
+
+ </for>
+
+
+
+
+ </if>
+ <for each="comment in (invoice.comment or '').split('\n')">
+ <comment>
+ </for>
+
+
+
\ No newline at end of file
diff --git a/invoice.odt b/invoice.odt
deleted file mode 100644
index b2a8457..0000000
Binary files a/invoice.odt and /dev/null differ
diff --git a/invoice.py b/invoice.py
index 578bf28..06a8e73 100644
--- a/invoice.py
+++ b/invoice.py
@@ -33,13 +33,9 @@ class InvoiceLine:
super(InvoiceLine, cls).__setup__()
cls.unit_price.states['readonly'] = True
cls.unit_price.digits = (20, price_digits[1] + discount_digits[1])
- if 'discount' not in cls.amount.on_change_with:
- cls.amount.on_change_with.add('discount')
- if 'gross_unit_price' not in cls.amount.on_change_with:
- cls.amount.on_change_with.add('gross_unit_price')
- @staticmethod
- def default_discount():
+ @classmethod
+ def default_discount(cls):
return Decimal(0)
def update_prices(self):
@@ -78,6 +74,10 @@ class InvoiceLine:
def on_change_discount(self):
return self.update_prices()
+ @fields.depends('discount', 'gross_unit_price')
+ def on_change_with_amount(self):
+ return super(InvoiceLine, self).on_change_with_amount()
+
@fields.depends('gross_unit_price', 'unit_price', 'discount')
def on_change_product(self):
super(InvoiceLine, self).on_change_product()
diff --git a/invoice.xml b/invoice.xml
index 0a2a606..cbd1269 100644
--- a/invoice.xml
+++ b/invoice.xml
@@ -15,10 +15,20 @@
+
+
+
+
Invoice
account.invoice
account.invoice
- account_invoice_discount/invoice.odt
+ account_invoice_discount/invoice.fodt
+
+
+
+ form_print
+ account.invoice,-1
+
diff --git a/setup.py b/setup.py
index 1688a51..3c5c1ca 100644
--- a/setup.py
+++ b/setup.py
@@ -73,7 +73,7 @@ setup(name=name,
],
package_data={
'trytond.modules.account_invoice_discount': (info.get('xml', [])
- + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.odt',
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
'icons/*.svg', 'tests/*.rst']),
},
classifiers=[
diff --git a/tests/scenario_invoice.rst b/tests/scenario_invoice.rst
index 86c616b..67e067b 100644
--- a/tests/scenario_invoice.rst
+++ b/tests/scenario_invoice.rst
@@ -63,20 +63,16 @@ 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
>>> template.type = 'service'
>>> template.list_price = Decimal('20')
- >>> template.cost_price = Decimal('12')
>>> template.account_expense = expense
>>> template.account_revenue = revenue
>>> template.customer_taxes.append(tax)
>>> template.save()
- >>> product.template = template
- >>> product.save()
+ >>> product, = template.products
Create payment term::
@@ -179,7 +175,7 @@ Post invoice and check again invoice totals and taxes::
>>> credit_note_tax_code.sum
Decimal('0.00')
-Discounts are copyied when crediting the invoice::
+Discounts are copied when crediting the invoice::
>>> credit = Wizard('account.invoice.credit', [invoice])
>>> credit.form.with_refund = True
diff --git a/tox.ini b/tox.ini
index 08e43cf..527d859 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,10 @@
[tox]
-envlist = {py27,py33,py34,py35}-{sqlite,postgresql,mysql},pypy-{sqlite,postgresql}
+envlist = {py27,py34,py35,py36}-{sqlite,postgresql,mysql},pypy-{sqlite,postgresql}
[testenv]
commands = {envpython} setup.py test
deps =
- {py27,py33,py34,py35}-postgresql: psycopg2 >= 2.5
+ {py27,py34,py35,py36}-postgresql: psycopg2 >= 2.5
pypy-postgresql: psycopg2cffi >= 2.5
mysql: MySQL-python
sqlite: sqlitebck
diff --git a/tryton.cfg b/tryton.cfg
index b044ae0..9f91b73 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -1,5 +1,5 @@
[tryton]
-version=4.3.0
+version=4.7.0
depends:
ir
account_invoice