[tryton-debian-vcs] tryton-modules-purchase branch debian updated. debian/3.0.0-3-4-g047f168

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Tue Apr 22 13:09:34 UTC 2014


The following commit has been merged in the debian branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/tryton-modules-purchase.git;a=commitdiff;h=debian/3.0.0-3-4-g047f168

commit 047f168f830e2d78847c18bf110ab97593ded48b
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Tue Apr 22 15:00:09 2014 +0200

    Bumping minimal required Python version to 2.7.

diff --git a/debian/control b/debian/control
index a516d50..ef2c380 100644
--- a/debian/control
+++ b/debian/control
@@ -9,7 +9,7 @@ Standards-Version: 3.9.5
 Homepage: http://www.tryton.org/
 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=tryton/tryton-modules-purchase.git
 Vcs-Git: git://anonscm.debian.org/tryton/tryton-modules-purchase.git
-X-Python-Version: >= 2.6
+X-Python-Version: >= 2.7
 
 Package: tryton-modules-purchase
 Architecture: all
commit a27bdb3036d9bf2205a6d164a8960a168084f434
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Tue Apr 22 14:46:36 2014 +0200

    Updating copyright.

diff --git a/debian/copyright b/debian/copyright
index fdd8122..75eceed 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,9 +1,9 @@
 Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 
 Files: *
-Copyright: 2008-2013 Cédric Krier
+Copyright: 2008-2014 Cédric Krier
            2008-2013 Bertrand Chenal
-           2008-2013 B2CK SPRL
+           2008-2014 B2CK SPRL
            2004-2008 Tiny SPRL
 License: GPL-3+
 
commit b1a554a2b5c2bbe3cc0aedb66b5ff7424ae7878b
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Tue Apr 22 14:23:03 2014 +0200

    Merging upstream version 3.2.0.

diff --git a/CHANGELOG b/CHANGELOG
index 91a5c28..47d1e58 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+* Add link between stock moves and invoice lines
+* Add warning for supplier moves without origin
+
 Version 3.0.0 - 2013-10-21
 * Bug fixes (see mercurial logs for details)
 * Replace reference copying by relate
diff --git a/COPYRIGHT b/COPYRIGHT
index 5d422e0..77715d8 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,6 +1,6 @@
-Copyright (C) 2008-2013 Cédric Krier.
+Copyright (C) 2008-2014 Cédric Krier.
 Copyright (C) 2008-2013 Bertrand Chenal.
-Copyright (C) 2008-2013 B2CK SPRL.
+Copyright (C) 2008-2014 B2CK SPRL.
 Copyright (C) 2004-2008 Tiny SPRL.
 
 This program is free software: you can redistribute it and/or modify
diff --git a/INSTALL b/INSTALL
index dea2f76..f07f4fa 100644
--- a/INSTALL
+++ b/INSTALL
@@ -4,7 +4,7 @@ Installing trytond_purchase
 Prerequisites
 -------------
 
- * Python 2.6 or later (http://www.python.org/)
+ * Python 2.7 or later (http://www.python.org/)
  * trytond (http://www.tryton.org/)
  * python-sql (http://code.google.com/p/python-sql/)
  * trytond_company (http://www.tryton.org/)
diff --git a/MANIFEST.in b/MANIFEST.in
index fc0b03e..05c3f79 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,5 @@
 include INSTALL
 include README
-include TODO
 include COPYRIGHT
 include CHANGELOG
 include LICENSE
diff --git a/PKG-INFO b/PKG-INFO
index d117bd0..f525b62 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: trytond_purchase
-Version: 3.0.0
+Version: 3.2.0
 Summary: Tryton module for purchase
 Home-page: http://www.tryton.org/
 Author: Tryton
-Author-email: UNKNOWN
+Author-email: issue_tracker at tryton.org
 License: GPL-3
-Download-URL: http://downloads.tryton.org/3.0/
+Download-URL: http://downloads.tryton.org/3.2/
 Description: trytond_purchase
         ================
         
@@ -43,6 +43,7 @@ Description: trytond_purchase
         
           http://www.tryton.org/
         
+Keywords: tryton purchase
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Plugins
@@ -62,7 +63,6 @@ Classifier: Natural Language :: Russian
 Classifier: Natural Language :: Slovenian
 Classifier: Natural Language :: Spanish
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Topic :: Office/Business
 Classifier: Topic :: Office/Business :: Financial :: Accounting
diff --git a/__init__.py b/__init__.py
index 810de6c..3811cbf 100644
--- a/__init__.py
+++ b/__init__.py
@@ -13,7 +13,6 @@ def register():
     Pool.register(
         Move,
         Purchase,
-        PurchaseInvoice,
         PurchaseIgnoredInvoice,
         PurchaseRecreadtedInvoice,
         PurchaseLine,
diff --git a/invoice.py b/invoice.py
index 5650f2a..55cf40f 100644
--- a/invoice.py
+++ b/invoice.py
@@ -17,10 +17,11 @@ def process_purchase(func):
     def wrapper(cls, invoices):
         pool = Pool()
         Purchase = pool.get('purchase.purchase')
+        with Transaction().set_user(0, set_context=True):
+            purchases = [p for i in cls.browse(invoices) for p in i.purchases]
         func(cls, invoices)
         with Transaction().set_user(0, set_context=True):
-            Purchase.process([p for i in cls.browse(invoices)
-                    for p in i.purchases])
+            Purchase.process(purchases)
     return wrapper
 
 
@@ -31,15 +32,13 @@ class Invoice:
         ('ignored', 'Ignored'),
         ('recreated', 'Recreated'),
         ], 'Exception State'), 'get_purchase_exception_state')
-    purchases = fields.Many2Many('purchase.purchase-account.invoice',
-            'invoice', 'purchase', 'Purchases', readonly=True)
+    purchases = fields.Function(fields.One2Many('purchase.purchase', None,
+            'Purchases'), 'get_purchases', searcher='search_purchases')
 
     @classmethod
     def __setup__(cls):
         super(Invoice, cls).__setup__()
         cls._error_messages.update({
-                'delete_purchase_invoice': ('You can not delete invoices '
-                    'that come from a purchase.'),
                 'reset_invoice_purchase': ('You cannot reset to draft '
                     'an invoice generated by a purchase.'),
                 })
@@ -65,18 +64,23 @@ class Invoice:
                 res[invoice.id] = ''
         return res
 
+    def get_purchases(self, name):
+        pool = Pool()
+        PurchaseLine = pool.get('purchase.line')
+        purchases = set()
+        for line in self.lines:
+            if isinstance(line.origin, PurchaseLine):
+                purchases.add(line.origin.purchase.id)
+        return list(purchases)
+
     @classmethod
+    def search_purchases(cls, name, clause):
+        return [('lines.origin.purchase.id',) + tuple(clause[1:])
+            + ('purchase.line',)]
+
+    @classmethod
+    @process_purchase
     def delete(cls, invoices):
-        pool = Pool()
-        Purchase_Invoice = pool.get('purchase.purchase-account.invoice')
-        purchase_invoice = Purchase_Invoice.__table__()
-        cursor = Transaction().cursor
-        if invoices:
-            cursor.execute(*purchase_invoice.select(purchase_invoice.id,
-                    where=purchase_invoice.invoice.in_(
-                        [i.id for i in invoices])))
-            if cursor.fetchone():
-                cls.raise_user_error('delete_purchase_invoice')
         super(Invoice, cls).delete(invoices)
 
     @classmethod
diff --git a/locale/bg_BG.po b/locale/bg_BG.po
index 6d5eff1..c71e95e 100644
--- a/locale/bg_BG.po
+++ b/locale/bg_BG.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr ""
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr "Не може да прехвърляте в проект фактура генерирана при покупка."
 
@@ -31,11 +27,11 @@ msgid "Purchase \"%(purchase)s\" misses the supplier location for line \"%(line)
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
@@ -582,38 +578,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Променено от"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Създадено на"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Създадено от"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Фактура"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Покупка"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Име"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Променено на"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Променено от"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Създадено на"
@@ -874,10 +838,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Покупка"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Покупка - Фактура"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Покупка - Игнорирана фактура"
diff --git a/locale/ca_ES.po b/locale/ca_ES.po
index a0868ad..f7bc172 100644
--- a/locale/ca_ES.po
+++ b/locale/ca_ES.po
@@ -3,17 +3,14 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "No podeu esborrar factures generades des d'una compra."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr "No podeu restaurar a esborrany una factura generada per una compra."
 
 msgctxt "error:product.template:"
 msgid ""
 "Purchase prices are based on the purchase uom, are you sure to change it?"
-msgstr "Els preus de compra estan basats en la UdM de compra. Vol canviar-ho?"
+msgstr ""
+"Els preus de compra estan basats en la UdM de compra. Voleu canviar-ho?"
 
 msgctxt "error:purchase.line:"
 msgid ""
@@ -35,12 +32,13 @@ msgstr ""
 " \"%(purchase)s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "S'ha de definir un magatzem pel pressupost de la venda \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "S'ha de definir un magatzem pel pressupost de la compta \"%s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
-msgstr "S'ha de definir una adreça de facturació pel pressupost de venda \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
+msgstr ""
+"S'ha de definir una adreça de facturació pel pressupost de la compta \"%s\"."
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
@@ -536,11 +534,11 @@ msgstr "Albarans de devolució"
 
 msgctxt "field:purchase.purchase,shipment_state:"
 msgid "Shipment State"
-msgstr "Estat d'enviament"
+msgstr "Estat enviament"
 
 msgctxt "field:purchase.purchase,shipments:"
 msgid "Shipments"
-msgstr "Enviaments"
+msgstr "Albarans"
 
 msgctxt "field:purchase.purchase,state:"
 msgid "State"
@@ -556,7 +554,7 @@ msgstr "Impost"
 
 msgctxt "field:purchase.purchase,tax_amount_cache:"
 msgid "Tax Cache"
-msgstr "Impostos precalculado"
+msgstr "Impostos precalculats"
 
 msgctxt "field:purchase.purchase,total_amount:"
 msgid "Total"
@@ -564,11 +562,11 @@ msgstr "Total"
 
 msgctxt "field:purchase.purchase,total_amount_cache:"
 msgid "Total Cache"
-msgstr "Total precalculado"
+msgstr "Total precalculat"
 
 msgctxt "field:purchase.purchase,untaxed_amount:"
 msgid "Untaxed"
-msgstr "Sense impost"
+msgstr "Base imposable"
 
 msgctxt "field:purchase.purchase,untaxed_amount_cache:"
 msgid "Untaxed Cache"
@@ -586,38 +584,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Usuari modificació"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Data creació"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Usuari creació"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Factura"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Compra"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Nom"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Data modificació"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Usuari modificació"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Data creació"
@@ -729,11 +695,11 @@ msgstr "Els moviments seleccionats es refaran. Els altres s'ignoraran."
 
 msgctxt "help:purchase.product_supplier,delivery_time:"
 msgid "In number of days"
-msgstr "En nombre de dies"
+msgstr "En nombre de dies."
 
 msgctxt "help:purchase.product_supplier.price,quantity:"
 msgid "Minimal quantity"
-msgstr "Quantitat mínima"
+msgstr "Quantitat mínima."
 
 msgctxt "model:ir.action,name:act_invoice_form"
 msgid "Invoices"
@@ -765,7 +731,7 @@ msgstr "Retorna"
 
 msgctxt "model:ir.action,name:act_shipment_form"
 msgid "Shipments"
-msgstr "Enviaments"
+msgstr "Albarans"
 
 msgctxt "model:ir.action,name:report_purchase"
 msgid "Purchase"
@@ -777,7 +743,7 @@ msgstr "Gestionar excepció de factura"
 
 msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
 msgid "Handle Shipment Exception"
-msgstr "Gestionar excepció d'enviament"
+msgstr "Gestiona excepció d'enviament"
 
 msgctxt "model:ir.action.act_window.domain,name:act_purchase_form_domain_all"
 msgid "All"
@@ -870,10 +836,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Compra"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Compra - Factura"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Compra - Factura ignorada"
@@ -888,7 +850,7 @@ msgstr "Compra"
 
 msgctxt "model:res.group,name:group_purchase_admin"
 msgid "Purchase Administrator"
-msgstr "Administrador de compra"
+msgstr "Administració de compres"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Amount"
@@ -920,7 +882,7 @@ msgstr "Telèfon:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Purchase Order N°:"
-msgstr "Comanda de compra Nº:"
+msgstr "Comanda de compra Núm.:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Quantity"
@@ -928,7 +890,7 @@ msgstr "Quantitat"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Request for Quotation N°:"
-msgstr "Sol·licitud de pressupost Nº:"
+msgstr "Sol·licitud de pressupost Núm.:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Taxes"
@@ -968,7 +930,7 @@ msgstr "Ignorat"
 
 msgctxt "selection:account.invoice,purchase_exception_state:"
 msgid "Recreated"
-msgstr "Refet"
+msgstr "Recreada"
 
 msgctxt "selection:purchase.configuration,purchase_invoice_method:"
 msgid "Based On Order"
@@ -1020,7 +982,7 @@ msgstr "Cap"
 
 msgctxt "selection:purchase.purchase,invoice_state:"
 msgid "Paid"
-msgstr "Pagat"
+msgstr "Pagada"
 
 msgctxt "selection:purchase.purchase,invoice_state:"
 msgid "Waiting"
@@ -1036,7 +998,7 @@ msgstr "Cap"
 
 msgctxt "selection:purchase.purchase,shipment_state:"
 msgid "Received"
-msgstr "Rebut"
+msgstr "Rebuda"
 
 msgctxt "selection:purchase.purchase,shipment_state:"
 msgid "Waiting"
@@ -1044,15 +1006,15 @@ msgstr "En espera"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Canceled"
-msgstr "Cancel·lat"
+msgstr "Cancel·lada"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Confirmed"
-msgstr "Confirmat"
+msgstr "Confirmada"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Done"
-msgstr "Finalitzat"
+msgstr "Finalitzada"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Draft"
@@ -1072,7 +1034,7 @@ msgstr "Ignorat"
 
 msgctxt "selection:stock.move,purchase_exception_state:"
 msgid "Recreated"
-msgstr "Refet"
+msgstr "Recreat"
 
 msgctxt "view:product.product:"
 msgid "Products"
@@ -1100,7 +1062,7 @@ msgstr "Esculli un moviment a refer"
 
 msgctxt "view:purchase.handle.shipment.exception.ask:"
 msgid "Handle shipment Exception"
-msgstr "Gestiona excepcions d'enviament"
+msgstr "Gestiona excepció d'enviament"
 
 msgctxt "view:purchase.line:"
 msgid "General"
@@ -1180,7 +1142,7 @@ msgstr "Pressupost"
 
 msgctxt "view:purchase.purchase:"
 msgid "Shipments"
-msgstr "Enviaments"
+msgstr "Albarans"
 
 msgctxt "view:stock.move:"
 msgid "Moves"
diff --git a/locale/cs_CZ.po b/locale/cs_CZ.po
index 20c0770..87e92e3 100644
--- a/locale/cs_CZ.po
+++ b/locale/cs_CZ.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr ""
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr ""
 
@@ -29,11 +25,11 @@ msgid "Purchase \"%(purchase)s\" misses the supplier location for line \"%(line)
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
@@ -578,38 +574,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr ""
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr ""
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr ""
@@ -862,10 +826,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr ""
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr ""
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index ce5d0a1..6162c66 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -3,13 +3,9 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "Aus einem Einkauf stammende Rechnungen können nicht gelöscht werden."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr ""
-"Eine durch einen Einkauf generierte Bewegung kann nicht auf Entwurf "
+"Eine durch einen Einkauf generierte Rechnung kann nicht auf Entwurf "
 "zurückgesetzt werden."
 
 msgctxt "error:product.template:"
@@ -35,18 +31,16 @@ msgstr ""
 msgctxt "error:purchase.line:"
 msgid "Purchase \"%(purchase)s\" misses the supplier location for line \"%(line)s\"."
 msgstr ""
-"Für Einkauf \"%(purchase)s\" Position \"%(line)s\" ist kein Lagerort "
-"Lieferant eingetragen."
+"Für Einkaufsposition \"%(line)s\" von Einkauf \"%(purchase)s\" ist kein "
+"Lagerort Lieferant eingetragen."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Für Angebot von Verkauf \"%s\" muss ein Warenlager angegeben werden."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "Für Angebotsanfrage \"%s\" muss ein Warenlager angegeben werden."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
-msgstr ""
-"Rechnungsadresse muss angegeben werden für Angebotsanfrage von Einkauf "
-"\"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
+msgstr "Für Angebotsanfrage \"%s\" muss eine Rechnungsadresse angegeben werden."
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
@@ -59,7 +53,7 @@ msgstr "Einkauf \"%s\" muss annulliert werden, bevor er gelöscht werden kann."
 msgctxt "error:stock.shipment.in.return:"
 msgid "You cannot reset to draft a move generated by a purchase."
 msgstr ""
-"Eine durch einen Einkauf generierte Bewegung kann nicht auf Entwurf "
+"Eine durch einen Einkauf generierte Lagerbewegung kann nicht auf Entwurf "
 "zurückgesetzt werden."
 
 msgctxt "error:stock.shipment.in:"
@@ -88,7 +82,7 @@ msgstr "Käuflich"
 
 msgctxt "field:product.template,purchase_uom:"
 msgid "Purchase UOM"
-msgstr "Einheit Einkauf"
+msgstr "Maßeinheit Einkauf"
 
 msgctxt "field:purchase.configuration,create_date:"
 msgid "Create Date"
@@ -132,7 +126,7 @@ msgstr "ID"
 
 msgctxt "field:purchase.handle.invoice.exception.ask,recreate_invoices:"
 msgid "Recreate Invoices"
-msgstr "Rechnungen nachbilden"
+msgstr "Rechnungen neu erstellen"
 
 msgctxt "field:purchase.handle.shipment.exception.ask,domain_moves:"
 msgid "Domain Moves"
@@ -144,7 +138,7 @@ msgstr "ID"
 
 msgctxt "field:purchase.handle.shipment.exception.ask,recreate_moves:"
 msgid "Recreate Moves"
-msgstr "Bewegungen nachbilden"
+msgstr "Lagerbewegungen neu erstellen"
 
 msgctxt "field:purchase.line,amount:"
 msgid "Amount"
@@ -164,7 +158,7 @@ msgstr "Lieferdatum"
 
 msgctxt "field:purchase.line,description:"
 msgid "Description"
-msgstr "Bezeichnung"
+msgstr "Beschreibung"
 
 msgctxt "field:purchase.line,from_location:"
 msgid "From Location"
@@ -196,7 +190,7 @@ msgstr "Ignorierte Bewegungen"
 
 msgctxt "field:purchase.line,moves_recreated:"
 msgid "Recreated Moves"
-msgstr "Nachgebildete Bewegungen"
+msgstr "Neu erstellte Lagerbewegungen"
 
 msgctxt "field:purchase.line,note:"
 msgid "Note"
@@ -244,7 +238,7 @@ msgstr "Einheit"
 
 msgctxt "field:purchase.line,unit_digits:"
 msgid "Unit Digits"
-msgstr "Anzahl Stellen"
+msgstr "Nachkommastellen"
 
 msgctxt "field:purchase.line,unit_price:"
 msgid "Unit Price"
@@ -272,7 +266,7 @@ msgstr "ID"
 
 msgctxt "field:purchase.line-account.tax,line:"
 msgid "Purchase Line"
-msgstr "Position Einkauf"
+msgstr "Einkaufsposition"
 
 msgctxt "field:purchase.line-account.tax,rec_name:"
 msgid "Name"
@@ -308,7 +302,7 @@ msgstr "Bewegung"
 
 msgctxt "field:purchase.line-ignored-stock.move,purchase_line:"
 msgid "Purchase Line"
-msgstr "Position Einkauf"
+msgstr "Einkaufsposition"
 
 msgctxt "field:purchase.line-ignored-stock.move,rec_name:"
 msgid "Name"
@@ -340,7 +334,7 @@ msgstr "Bewegung"
 
 msgctxt "field:purchase.line-recreated-stock.move,purchase_line:"
 msgid "Purchase Line"
-msgstr "Position Einkauf"
+msgstr "Einkaufsposition"
 
 msgctxt "field:purchase.line-recreated-stock.move,rec_name:"
 msgid "Name"
@@ -472,7 +466,7 @@ msgstr "Währung"
 
 msgctxt "field:purchase.purchase,currency_digits:"
 msgid "Currency Digits"
-msgstr "Währung (signifikante Stellen)"
+msgstr "Nachkommastellen Währung"
 
 msgctxt "field:purchase.purchase,description:"
 msgid "Description"
@@ -504,7 +498,7 @@ msgstr "Ignorierte Rechnungen"
 
 msgctxt "field:purchase.purchase,invoices_recreated:"
 msgid "Recreated Invoices"
-msgstr "Nachgebildete Rechnungen"
+msgstr "Neu erstellte Rechnungen"
 
 msgctxt "field:purchase.purchase,lines:"
 msgid "Lines"
@@ -594,38 +588,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Letzte Änderung durch"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Erstellungsdatum"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Erstellt durch"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Rechnung"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Einkauf"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Name"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Zuletzt geändert"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Letzte Änderung durch"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Erstellungsdatum"
@@ -708,11 +670,11 @@ msgstr "Anzahl Einkauf"
 
 msgctxt "field:stock.move,purchase_unit:"
 msgid "Purchase Unit"
-msgstr "Einheit Einkauf"
+msgstr "Einkaufseinheit"
 
 msgctxt "field:stock.move,purchase_unit_digits:"
 msgid "Purchase Unit Digits"
-msgstr "Anzahl Stellen Einkauf"
+msgstr "Nachkommastellen Einkauf"
 
 msgctxt "field:stock.move,purchase_unit_price:"
 msgid "Purchase Unit Price"
@@ -730,13 +692,13 @@ msgctxt "help:purchase.handle.invoice.exception.ask,recreate_invoices:"
 msgid ""
 "The selected invoices will be recreated. The other ones will be ignored."
 msgstr ""
-"Die ausgewählten Rechnungen werden nachgebildet. Alle anderen werden "
+"Die ausgewählten Rechnungen werden neu erstellt. Alle anderen werden "
 "ignoriert."
 
 msgctxt "help:purchase.handle.shipment.exception.ask,recreate_moves:"
 msgid "The selected moves will be recreated. The other ones will be ignored."
 msgstr ""
-"Die ausgewählten Bewegungen werden nachgebildet. Alle anderen werden "
+"Die ausgewählten Lagerbewegungen werden neu erstellt. Alle anderen werden "
 "ignoriert."
 
 msgctxt "help:purchase.product_supplier,delivery_time:"
@@ -856,19 +818,19 @@ msgstr "Nachfrage Liefervorbehalt"
 
 msgctxt "model:purchase.line,name:"
 msgid "Purchase Line"
-msgstr "Einkauf Position"
+msgstr "Einkaufsposition"
 
 msgctxt "model:purchase.line-account.tax,name:"
 msgid "Purchase Line - Tax"
-msgstr "Position Einkauf - Steuer"
+msgstr "Einkaufsposition - Steuer"
 
 msgctxt "model:purchase.line-ignored-stock.move,name:"
 msgid "Purchase Line - Ignored Move"
-msgstr "Position Einkauf - Bewegung Ignoriert"
+msgstr "Einkaufsposition - Bewegung Ignoriert"
 
 msgctxt "model:purchase.line-recreated-stock.move,name:"
 msgid "Purchase Line - Ignored Move"
-msgstr "Position Einkauf - Bewegung Nachgebildet"
+msgstr "Einkaufsposition - Ignorierte Lagerbewegung"
 
 msgctxt "model:purchase.product_supplier,name:"
 msgid "Product Supplier"
@@ -876,23 +838,19 @@ msgstr "Artikel Lieferant"
 
 msgctxt "model:purchase.product_supplier.price,name:"
 msgid "Product Supplier Price"
-msgstr "Artikel Einkaufspreis"
+msgstr "Einkaufspreis"
 
 msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Einkauf"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Einkauf - Rechnung"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Einkauf - Rechnung Ignoriert"
 
 msgctxt "model:purchase.purchase-recreated-account.invoice,name:"
 msgid "Purchase - Recreated Invoice"
-msgstr "Einkauf - Rechnung Nachgebildet"
+msgstr "Einkauf - Neu erstellte Rechnung"
 
 msgctxt "model:res.group,name:group_purchase"
 msgid "Purchase"
@@ -912,11 +870,11 @@ msgstr "Datum:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Description"
-msgstr "Bezeichnung"
+msgstr "Beschreibung"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Description:"
-msgstr "Bezeichnung:"
+msgstr "Beschreibung:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Draft Purchase Order"
@@ -932,7 +890,7 @@ msgstr "Telefon:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Purchase Order N°:"
-msgstr "Auftrag Nr. "
+msgstr "Auftrag Nr.:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Quantity"
@@ -948,15 +906,15 @@ msgstr "Steuern"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Taxes:"
-msgstr "Steuern:"
+msgstr "Steuern"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Total (excl. taxes):"
-msgstr "Netto:"
+msgstr "Netto"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Total:"
-msgstr "Gesamt:"
+msgstr "Gesamt"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Unit Price"
@@ -968,7 +926,7 @@ msgstr "USt-ID-Nr.:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "VAT:"
-msgstr "USt.:"
+msgstr "USt-ID-Nr:"
 
 msgctxt "selection:account.invoice,purchase_exception_state:"
 msgid ""
@@ -980,7 +938,7 @@ msgstr "Ignoriert"
 
 msgctxt "selection:account.invoice,purchase_exception_state:"
 msgid "Recreated"
-msgstr "Nachgebildet"
+msgstr "Neu erstellt"
 
 msgctxt "selection:purchase.configuration,purchase_invoice_method:"
 msgid "Based On Order"
@@ -1084,7 +1042,7 @@ msgstr "Ignoriert"
 
 msgctxt "selection:stock.move,purchase_exception_state:"
 msgid "Recreated"
-msgstr "Nachgebildet"
+msgstr "Neu erstellt"
 
 msgctxt "view:product.product:"
 msgid "Products"
@@ -1100,7 +1058,7 @@ msgstr "Einstellungen Einkauf"
 
 msgctxt "view:purchase.handle.invoice.exception.ask:"
 msgid "Choose invoices to recreate"
-msgstr "Rechnungen zum Nachbilden auswählen"
+msgstr "Rechnungen zur Neuerstellung auswählen"
 
 msgctxt "view:purchase.handle.invoice.exception.ask:"
 msgid "Handle Invoice Exception"
@@ -1108,7 +1066,7 @@ msgstr "Rechnungsvorbehalt bearbeiten"
 
 msgctxt "view:purchase.handle.shipment.exception.ask:"
 msgid "Choose move to recreate"
-msgstr "Bewegungen zum Nachbilden auswählen"
+msgstr "Lagerbewegungen zur Neuerstellung auswählen"
 
 msgctxt "view:purchase.handle.shipment.exception.ask:"
 msgid "Handle shipment Exception"
@@ -1128,11 +1086,11 @@ msgstr "Notizen"
 
 msgctxt "view:purchase.line:"
 msgid "Purchase Line"
-msgstr "Position Einkauf"
+msgstr "Einkaufsposition"
 
 msgctxt "view:purchase.line:"
 msgid "Purchase Lines"
-msgstr "Positionen Einkauf"
+msgstr "Einkaufspositionen"
 
 msgctxt "view:purchase.product_supplier.price:"
 msgid "Product Supplier Price"
diff --git a/locale/es_AR.po b/locale/es_AR.po
index e96b3a4..3171cd0 100644
--- a/locale/es_AR.po
+++ b/locale/es_AR.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "No puede eliminar facturas generadas por compras."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr "No puede restablecer a borrador una factura generada por una compra."
 
@@ -35,14 +31,14 @@ msgstr ""
 "«%(purchase)s»."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Se debe definir un almacén para el presupuesto de venta «%s»."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "Se debe definir un almacén para el presupuesto de la compra «%s»."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
 msgstr ""
-"Se debe definir una dirección de facturación para el presupuesto de venta "
-"«%s»."
+"Se debe definir la dirección de facturación para el presupuesto de la compra"
+" «%s»."
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
@@ -107,7 +103,7 @@ msgstr "Secuencia de referencia de compra"
 
 msgctxt "field:purchase.configuration,rec_name:"
 msgid "Name"
-msgstr "Nombre campo"
+msgstr "Nombre"
 
 msgctxt "field:purchase.configuration,write_date:"
 msgid "Write Date"
@@ -589,38 +585,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Usuario modificación"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Fecha creación"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Usuario creación"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Factura"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Compra"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Nombre"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Fecha modificación"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Usuario modificación"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Fecha creación"
@@ -875,10 +839,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Compra"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Compra - Factura"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Compra - Factura ignorada"
diff --git a/locale/es_CO.po b/locale/es_CO.po
index dd98df9..fa5eaee 100644
--- a/locale/es_CO.po
+++ b/locale/es_CO.po
@@ -3,12 +3,8 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "No puede eliminar facturas generadas por una compra."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
-msgstr "No puede restablecer a borrador una factura generada por una compra."
+msgstr "No puede devolver a borrador una factura generada por una compra."
 
 msgctxt "error:product.template:"
 msgid ""
@@ -36,13 +32,13 @@ msgstr ""
 "\"%(line)s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Un depósito de estar definido en la cotización de venta \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "Debe definir una bodega para la cotización de compra \"%s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
 msgstr ""
-"La dirección de facturación deben definirse en la cotización de la venta "
+"La dirección de la factura debe definirse en la cotización de la compra "
 "\"%s\"."
 
 msgctxt "error:purchase.purchase:"
@@ -55,20 +51,19 @@ msgstr "La compra \"%s\" debe ser cancelada antes de ser eliminada."
 
 msgctxt "error:stock.shipment.in.return:"
 msgid "You cannot reset to draft a move generated by a purchase."
-msgstr ""
-"No puede restablecer a borrador un movimiento generado por una compra."
+msgstr "No puede devolver a borrador un movimiento generado por una compra."
 
 msgctxt "error:stock.shipment.in:"
 msgid ""
 "You cannot reset to draft move \"%s\" because it was generated by a "
 "purchase."
 msgstr ""
-"No puede restablecer a borrador el movimiento \"%s\" porque fue generado por"
-" una compra."
+"No puede devolver a borrador el movimiento \"%s\" porque fue generado por "
+"una compra."
 
 msgctxt "field:account.invoice,purchase_exception_state:"
 msgid "Exception State"
-msgstr "Estado excepción"
+msgstr "Estado Excepción"
 
 msgctxt "field:account.invoice,purchases:"
 msgid "Purchases"
@@ -240,7 +235,7 @@ msgstr "Unidad"
 
 msgctxt "field:purchase.line,unit_digits:"
 msgid "Unit Digits"
-msgstr "Dígitos de Unidad"
+msgstr "Decimales de Unidad"
 
 msgctxt "field:purchase.line,unit_price:"
 msgid "Unit Price"
@@ -468,7 +463,7 @@ msgstr "Moneda"
 
 msgctxt "field:purchase.purchase,currency_digits:"
 msgid "Currency Digits"
-msgstr "Decimales de la Moneda"
+msgstr "Decimales de Moneda"
 
 msgctxt "field:purchase.purchase,description:"
 msgid "Description"
@@ -568,15 +563,15 @@ msgstr "Total"
 
 msgctxt "field:purchase.purchase,total_amount_cache:"
 msgid "Total Cache"
-msgstr "Total Precalculado"
+msgstr "Cache del Total"
 
 msgctxt "field:purchase.purchase,untaxed_amount:"
 msgid "Untaxed"
-msgstr "Base Sin Impuesto"
+msgstr "Base"
 
 msgctxt "field:purchase.purchase,untaxed_amount_cache:"
 msgid "Untaxed Cache"
-msgstr "Base Sin Impuesto Precalculado"
+msgstr "Cache de Base Sin Impuesto"
 
 msgctxt "field:purchase.purchase,warehouse:"
 msgid "Warehouse"
@@ -590,38 +585,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Modificado por Usuario"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Fecha de Creación"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Creado por Usuario"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Factura"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Compra"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Nombre"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Fecha de Modificación"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Modificado por Usuario"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Fecha de Creación"
@@ -696,7 +659,7 @@ msgstr "Moneda de Compra"
 
 msgctxt "field:stock.move,purchase_exception_state:"
 msgid "Exception State"
-msgstr "Estado excepción"
+msgstr "Estado Excepción"
 
 msgctxt "field:stock.move,purchase_quantity:"
 msgid "Purchase Quantity"
@@ -876,10 +839,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Compra"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Compra - Factura"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Compra - Factura Ignorada"
@@ -946,7 +905,7 @@ msgstr "Impuestos:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Total (excl. taxes):"
-msgstr "Base (Sin Impuesto):"
+msgstr "Base (sin Impuestos):"
 
 msgctxt "odt:purchase.purchase:"
 msgid "Total:"
@@ -958,7 +917,7 @@ msgstr "Precio Unitario"
 
 msgctxt "odt:purchase.purchase:"
 msgid "VAT Number:"
-msgstr "NIT:"
+msgstr "Número Identificación:"
 
 msgctxt "odt:purchase.purchase:"
 msgid "VAT:"
@@ -1050,7 +1009,7 @@ msgstr "En Espera"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Canceled"
-msgstr "Cancelada"
+msgstr "Anulada"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Confirmed"
@@ -1094,7 +1053,7 @@ msgstr "Configuración de Compras"
 
 msgctxt "view:purchase.handle.invoice.exception.ask:"
 msgid "Choose invoices to recreate"
-msgstr "Seleccione facturas a recrear"
+msgstr "Seleccione facturas a rehacer"
 
 msgctxt "view:purchase.handle.invoice.exception.ask:"
 msgid "Handle Invoice Exception"
@@ -1102,7 +1061,7 @@ msgstr "Excepción Manual de Factura"
 
 msgctxt "view:purchase.handle.shipment.exception.ask:"
 msgid "Choose move to recreate"
-msgstr "Seleccione movimientos a recrear"
+msgstr "Seleccione movimientos a rehacer"
 
 msgctxt "view:purchase.handle.shipment.exception.ask:"
 msgid "Handle shipment Exception"
diff --git a/locale/es_ES.po b/locale/es_ES.po
index 0f42e29..1baefde 100644
--- a/locale/es_ES.po
+++ b/locale/es_ES.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "No puede borrar facturas generadas por compras."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr "No puede restaurar a borrador una factura generada por una compra."
 
@@ -36,14 +32,14 @@ msgstr ""
 "\"%(purchase)s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Se debe definir un almacén para el presupuesto de venta \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "Se debe definir un almacén para el presupuesto de la compra \"%s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
 msgstr ""
-"Se debe definir una dirección de facturación para el presupuesto de venta "
-"\"%s\"."
+"Se debe definir una dirección de facturación para el presupuesto de la "
+"compra \"%s\"."
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
@@ -179,7 +175,7 @@ msgstr "Movimientos realizados"
 
 msgctxt "field:purchase.line,move_exception:"
 msgid "Moves Exception"
-msgstr "Exepción de movimientos"
+msgstr "Excepción de movimientos"
 
 msgctxt "field:purchase.line,moves:"
 msgid "Moves"
@@ -575,7 +571,7 @@ msgstr "Base imponible"
 
 msgctxt "field:purchase.purchase,untaxed_amount_cache:"
 msgid "Untaxed Cache"
-msgstr "Base imponible precalculado"
+msgstr "Base imponible precalculada"
 
 msgctxt "field:purchase.purchase,warehouse:"
 msgid "Warehouse"
@@ -589,38 +585,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Usuario modificación"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Fecha creación"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Usuario creación"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Factura"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Compra"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Nombre"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Fecha modificación"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Usuario modificación"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Fecha creación"
@@ -770,7 +734,7 @@ msgstr "Devolver"
 
 msgctxt "model:ir.action,name:act_shipment_form"
 msgid "Shipments"
-msgstr "Envíos"
+msgstr "Albaranes"
 
 msgctxt "model:ir.action,name:report_purchase"
 msgid "Purchase"
@@ -875,10 +839,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Compra"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Compra - Factura"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Compra - Factura ignorada"
diff --git a/locale/fr_FR.po b/locale/fr_FR.po
index 4929bc8..2f343b1 100644
--- a/locale/fr_FR.po
+++ b/locale/fr_FR.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "Vous ne pouvez supprimer une facture qui provient d'un achat."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr "Vous ne pouvez pas réinitialiser une facture générée par un achat."
 
@@ -37,12 +33,13 @@ msgstr ""
 " \"%(purchase)s\""
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Un entrepôt doit être défini pour le devis \"%s\""
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "Un entrepôt doit être défini pour le devis de l'achat \"%s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
-msgstr "L'adresse de facturation doit être définie pour le devis \"%s\". "
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
+msgstr ""
+"L'adresse de facturation doit être défini pour le devis de l'achat \"%s\"."
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
@@ -50,7 +47,7 @@ msgstr "Le compte à payer est manquant sur le tiers \"%s\"."
 
 msgctxt "error:purchase.purchase:"
 msgid "Purchase \"%s\" must be cancelled before deletion."
-msgstr "La commande \"%s\" doit être annulée avant sa suppression"
+msgstr "La commande \"%s\" doit être annulée avant suppression."
 
 msgctxt "error:stock.shipment.in.return:"
 msgid "You cannot reset to draft a move generated by a purchase."
@@ -170,7 +167,7 @@ msgstr "ID"
 
 msgctxt "field:purchase.line,invoice_lines:"
 msgid "Invoice Lines"
-msgstr "Lignes de factures"
+msgstr "Lignes de facture"
 
 msgctxt "field:purchase.line,move_done:"
 msgid "Moves Done"
@@ -588,38 +585,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Mis à jour par"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Date de création"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Créé par"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Facture"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Achat"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Nom"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Date de mise à jour"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Mis à jour par"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Date de création"
@@ -874,10 +839,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Achat"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Achat - Facture"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Achat - Facture ignorée"
diff --git a/locale/nl_NL.po b/locale/nl_NL.po
index 4c9c7c2..c7da2eb 100644
--- a/locale/nl_NL.po
+++ b/locale/nl_NL.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr ""
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr ""
 
@@ -29,11 +25,11 @@ msgid "Purchase \"%(purchase)s\" misses the supplier location for line \"%(line)
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
 msgstr ""
 
 msgctxt "error:purchase.purchase:"
@@ -646,40 +642,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr ""
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr ""
-
-#, fuzzy
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Verkoopfactuur"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr ""
-
-#, fuzzy
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Naam bijlage"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr ""
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr ""
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr ""
@@ -952,10 +914,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr ""
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr ""
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr ""
diff --git a/locale/ru_RU.po b/locale/ru_RU.po
index 5291128..46df167 100644
--- a/locale/ru_RU.po
+++ b/locale/ru_RU.po
@@ -3,10 +3,6 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "Вы не можете удалить инвойсы созданный из покупки."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr "Вы не можете сбросить в черновик инвойс созданный из покупки."
 
@@ -34,12 +30,12 @@ msgstr ""
 "\"%(line)s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Должен быть указан склад для котировки продажи \"%s\"."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr ""
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
-msgstr "Должен быть указан адрес инвойса для котировки продажи \"%s\"."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
+msgstr ""
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
@@ -585,38 +581,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Изменено пользователем"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Дата создания"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Создано пользователем"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Инвойс"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Покупки"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Наименование"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Дата изменения"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Изменено пользователем"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Дата создания"
@@ -872,10 +836,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Покупки"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Покупки - Инвойсы"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Покупки - Игнорированные инвойсы"
diff --git a/locale/sl_SI.po b/locale/sl_SI.po
index ea0b3f1..14a54dd 100644
--- a/locale/sl_SI.po
+++ b/locale/sl_SI.po
@@ -3,14 +3,10 @@ msgid ""
 msgstr "Content-Type: text/plain; charset=utf-8\n"
 
 msgctxt "error:account.invoice:"
-msgid "You can not delete invoices that come from a purchase."
-msgstr "Računov, izhajajočih iz nabavnih nalogov, ni možno brisati."
-
-msgctxt "error:account.invoice:"
 msgid "You cannot reset to draft an invoice generated by a purchase."
 msgstr ""
 "Računa, ustvarjenega iz nabavnega naloga, ni možno prestaviti v stanje "
-"osnutka."
+"priprave."
 
 msgctxt "error:product.template:"
 msgid ""
@@ -38,16 +34,16 @@ msgstr ""
 "dobaviteljeva lokacija."
 
 msgctxt "error:purchase.purchase:"
-msgid "A warehouse must be defined for quotation of sale \"%s\"."
-msgstr "Za ponudbo \"%s\" mora biti določeno skladišče."
+msgid "A warehouse must be defined for quotation of purchase \"%s\"."
+msgstr "Skladišče mora biti navedeno za nabavno ponudbo \"%s\"."
 
 msgctxt "error:purchase.purchase:"
-msgid "Invoice address must be defined for quotation of sale \"%s\"."
-msgstr "Za ponudbo \"%s\" mora biti določen plačnik."
+msgid "Invoice address must be defined for quotation of purchase \"%s\"."
+msgstr "Naslov plačnika mora biti naveden za nabavno ponudbo \"%s\"."
 
 msgctxt "error:purchase.purchase:"
 msgid "Missing \"Account Payable\" on party \"%s\"."
-msgstr "Za stranko \"%s\" manjka terjatveni konto."
+msgstr "Partnerju \"%s\" manjka terjatveni konto."
 
 msgctxt "error:purchase.purchase:"
 msgid "Purchase \"%s\" must be cancelled before deletion."
@@ -57,7 +53,7 @@ msgctxt "error:stock.shipment.in.return:"
 msgid "You cannot reset to draft a move generated by a purchase."
 msgstr ""
 "Prometa, ustvarjenega iz nabavnega naloga, ni možno prestaviti v stanje "
-"osnutka."
+"priprave."
 
 msgctxt "error:stock.shipment.in:"
 msgid ""
@@ -65,7 +61,7 @@ msgid ""
 "purchase."
 msgstr ""
 "Prometa \"%s\", ustvarjenega iz nabavnega naloga, ni možno prestaviti v "
-"stanje osnutka."
+"stanje priprave."
 
 msgctxt "field:account.invoice,purchase_exception_state:"
 msgid "Exception State"
@@ -357,7 +353,7 @@ msgstr "Šifra"
 
 msgctxt "field:purchase.product_supplier,company:"
 msgid "Company"
-msgstr "Podjetje"
+msgstr "Družba"
 
 msgctxt "field:purchase.product_supplier,create_date:"
 msgid "Create Date"
@@ -453,7 +449,7 @@ msgstr "Opomba"
 
 msgctxt "field:purchase.purchase,company:"
 msgid "Company"
-msgstr "Podjetje"
+msgstr "Družba"
 
 msgctxt "field:purchase.purchase,create_date:"
 msgid "Create Date"
@@ -513,11 +509,11 @@ msgstr "Promet"
 
 msgctxt "field:purchase.purchase,party:"
 msgid "Party"
-msgstr "Stranka"
+msgstr "Partner"
 
 msgctxt "field:purchase.purchase,party_lang:"
 msgid "Party Language"
-msgstr "Jezik stranke"
+msgstr "Jezik partnerja"
 
 msgctxt "field:purchase.purchase,payment_term:"
 msgid "Payment Term"
@@ -591,38 +587,6 @@ msgctxt "field:purchase.purchase,write_uid:"
 msgid "Write User"
 msgstr "Zapisal"
 
-msgctxt "field:purchase.purchase-account.invoice,create_date:"
-msgid "Create Date"
-msgstr "Ustvarjeno"
-
-msgctxt "field:purchase.purchase-account.invoice,create_uid:"
-msgid "Create User"
-msgstr "Ustvaril"
-
-msgctxt "field:purchase.purchase-account.invoice,id:"
-msgid "ID"
-msgstr "ID"
-
-msgctxt "field:purchase.purchase-account.invoice,invoice:"
-msgid "Invoice"
-msgstr "Račun"
-
-msgctxt "field:purchase.purchase-account.invoice,purchase:"
-msgid "Purchase"
-msgstr "Nabavni nalog"
-
-msgctxt "field:purchase.purchase-account.invoice,rec_name:"
-msgid "Name"
-msgstr "Ime"
-
-msgctxt "field:purchase.purchase-account.invoice,write_date:"
-msgid "Write Date"
-msgstr "Zapisano"
-
-msgctxt "field:purchase.purchase-account.invoice,write_uid:"
-msgid "Write User"
-msgstr "Zapisal"
-
 msgctxt "field:purchase.purchase-ignored-account.invoice,create_date:"
 msgid "Create Date"
 msgstr "Ustvarjeno"
@@ -746,7 +710,7 @@ msgstr "Računi"
 
 msgctxt "model:ir.action,name:act_open_supplier"
 msgid "Parties associated to Purchases"
-msgstr "Stranke pri nabavi"
+msgstr "Partnerji, povezani z nabavo"
 
 msgctxt "model:ir.action,name:act_purchase_configuration_form"
 msgid "Purchase Configuration"
@@ -796,7 +760,7 @@ msgstr "Potrjeno"
 msgctxt ""
 "model:ir.action.act_window.domain,name:act_purchase_form_domain_draft"
 msgid "Draft"
-msgstr "Osnutek"
+msgstr "Priprava"
 
 msgctxt ""
 "model:ir.action.act_window.domain,name:act_purchase_form_domain_quotation"
@@ -833,7 +797,7 @@ msgstr "Poročila"
 
 msgctxt "model:ir.ui.menu,name:menu_supplier"
 msgid "Parties associated to Purchases"
-msgstr "Stranke pri nabavi"
+msgstr "Partnerji pri nabavi"
 
 msgctxt "model:purchase.configuration,name:"
 msgid "Purchase Configuration"
@@ -875,10 +839,6 @@ msgctxt "model:purchase.purchase,name:"
 msgid "Purchase"
 msgstr "Nabavni nalog"
 
-msgctxt "model:purchase.purchase-account.invoice,name:"
-msgid "Purchase - Invoice"
-msgstr "Nabavni nalog - Račun"
-
 msgctxt "model:purchase.purchase-ignored-account.invoice,name:"
 msgid "Purchase - Ignored Invoice"
 msgstr "Nabavni nalog - Prezrt račun"
@@ -1061,7 +1021,7 @@ msgstr "Zaključeno"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Draft"
-msgstr "Osnutek"
+msgstr "V pripravi"
 
 msgctxt "selection:purchase.purchase,state:"
 msgid "Quotation"
@@ -1153,7 +1113,7 @@ msgstr "Potrditev"
 
 msgctxt "view:purchase.purchase:"
 msgid "Draft"
-msgstr "Osnutek"
+msgstr "Priprava"
 
 msgctxt "view:purchase.purchase:"
 msgid "Handle Invoice Exception"
diff --git a/party.xml b/party.xml
index 4f70ba5..d342535 100644
--- a/party.xml
+++ b/party.xml
@@ -6,7 +6,7 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window" id="act_purchase_form2">
             <field name="name">Purchases</field>
             <field name="res_model">purchase.purchase</field>
-            <field name="domain">[("party", "=", Eval('active_id'))]</field>
+            <field name="domain">[('party', 'in', Eval('active_ids'))]</field>
         </record>
         <record model="ir.action.keyword"
                 id="act_open_purchase_keyword1">
diff --git a/product.py b/product.py
index d4164ba..a0b7af5 100644
--- a/product.py
+++ b/product.py
@@ -31,7 +31,6 @@ class Template:
             'required': Eval('purchasable', False),
             },
         domain=[('category', '=', Eval('default_uom_category'))],
-        on_change_with=['default_uom', 'purchase_uom', 'purchasable'],
         depends=['active', 'purchasable', 'default_uom_category'])
 
     @classmethod
@@ -52,6 +51,7 @@ class Template:
         if 'purchasable' not in cls.account_expense.depends:
             cls.account_expense.depends.append('purchasable')
 
+    @fields.depends('default_uom', 'purchase_uom', 'purchasable')
     def on_change_with_purchase_uom(self):
         if self.default_uom:
             if self.purchase_uom:
@@ -63,12 +63,15 @@ class Template:
                 return self.default_uom.id
 
     @classmethod
-    def write(cls, templates, vals):
-        if vals.get("purchase_uom"):
+    def write(cls, *args):
+        actions = iter(args)
+        for templates, values in zip(actions, actions):
+            if not values.get("purchase_uom"):
+                continue
             for template in templates:
                 if not template.purchase_uom:
                     continue
-                if template.purchase_uom.id == vals["purchase_uom"]:
+                if template.purchase_uom.id == values["purchase_uom"]:
                     continue
                 for product in template.products:
                     if not product.product_suppliers:
@@ -76,7 +79,7 @@ class Template:
                     cls.raise_user_warning(
                             '%s at product_template' % template.id,
                             'change_purchase_uom')
-        super(Template, cls).write(templates, vals)
+        super(Template, cls).write(*args)
 
 
 class Product:
@@ -145,7 +148,7 @@ class ProductSupplier(ModelSQL, ModelView):
     product = fields.Many2One('product.template', 'Product', required=True,
             ondelete='CASCADE', select=True)
     party = fields.Many2One('party.party', 'Supplier', required=True,
-            ondelete='CASCADE', select=True, on_change=['party'])
+        ondelete='CASCADE', select=True)
     name = fields.Char('Name', size=None, translate=True, select=True)
     code = fields.Char('Code', size=None, select=True)
     sequence = fields.Integer('Sequence')
@@ -219,6 +222,7 @@ class ProductSupplier(ModelSQL, ModelView):
             company = Company(Transaction().context['company'])
             return company.currency.id
 
+    @fields.depends('party')
     def on_change_party(self):
         cursor = Transaction().cursor
         changes = {
diff --git a/purchase.py b/purchase.py
index 1abdd58..4766924 100644
--- a/purchase.py
+++ b/purchase.py
@@ -16,7 +16,7 @@ from trytond.pyson import Eval, Bool, If, PYSONEncoder, Id
 from trytond.transaction import Transaction
 from trytond.pool import Pool, PoolMeta
 
-__all__ = ['Purchase', 'PurchaseInvoice', 'PurchaseIgnoredInvoice',
+__all__ = ['Purchase', 'PurchaseIgnoredInvoice',
     'PurchaseRecreadtedInvoice', 'PurchaseLine', 'PurchaseLineTax',
     'PurchaseLineIgnoredMove', 'PurchaseLineRecreatedMove', 'PurchaseReport',
     'OpenSupplier', 'HandleShipmentExceptionAsk', 'HandleShipmentException',
@@ -62,13 +62,16 @@ class Purchase(Workflow, ModelSQL, ModelView):
         depends=['state'])
     payment_term = fields.Many2One('account.invoice.payment_term',
         'Payment Term', required=True, states=_STATES, depends=_DEPENDS)
-    party = fields.Many2One('party.party', 'Party',
-            required=True, states=_STATES, on_change=['party', 'payment_term'],
-            select=True, depends=_DEPENDS)
-    party_lang = fields.Function(fields.Char('Party Language',
-            on_change_with=['party']), 'on_change_with_party_lang')
+    party = fields.Many2One('party.party', 'Party', required=True,
+        states=_STATES, select=True, depends=_DEPENDS)
+    party_lang = fields.Function(fields.Char('Party Language'),
+        'on_change_with_party_lang')
     invoice_address = fields.Many2One('party.address', 'Invoice Address',
-        domain=[('party', '=', Eval('party'))], states=_STATES,
+        domain=[('party', '=', Eval('party'))],
+        states={
+            'readonly': Eval('state') != 'draft',
+            'required': ~Eval('state').in_(['draft', 'quotation', 'cancel']),
+            },
         depends=['state', 'party'])
     warehouse = fields.Many2One('stock.location', 'Warehouse',
         domain=[('type', '=', 'warehouse')], states=_STATES,
@@ -79,11 +82,10 @@ class Purchase(Workflow, ModelSQL, ModelView):
                 | (Eval('lines', [0]) & Eval('currency'))),
             },
         depends=['state'])
-    currency_digits = fields.Function(fields.Integer('Currency Digits',
-            on_change_with=['currency']), 'on_change_with_currency_digits')
+    currency_digits = fields.Function(fields.Integer('Currency Digits'),
+        'on_change_with_currency_digits')
     lines = fields.One2Many('purchase.line', 'purchase', 'Lines',
-        states=_STATES, on_change=['lines', 'currency', 'party'],
-        depends=_DEPENDS)
+        states=_STATES, depends=_DEPENDS)
     comment = fields.Text('Comment')
     untaxed_amount = fields.Function(fields.Numeric('Untaxed',
             digits=(16, Eval('currency_digits', 2)),
@@ -115,8 +117,8 @@ class Purchase(Workflow, ModelSQL, ModelView):
             ('paid', 'Paid'),
             ('exception', 'Exception'),
             ], 'Invoice State', readonly=True, required=True)
-    invoices = fields.Many2Many('purchase.purchase-account.invoice',
-            'purchase', 'invoice', 'Invoices', readonly=True)
+    invoices = fields.Function(fields.One2Many('account.invoice', None,
+            'Invoices'), 'get_invoices', searcher='search_invoices')
     invoices_ignored = fields.Many2Many(
             'purchase.purchase-ignored-account.invoice',
             'purchase', 'invoice', 'Ignored Invoices', readonly=True)
@@ -144,9 +146,9 @@ class Purchase(Workflow, ModelSQL, ModelView):
         cls._order.insert(1, ('id', 'DESC'))
         cls._error_messages.update({
                 'invoice_address_required': ('Invoice address must be '
-                    'defined for quotation of sale "%s".'),
+                    'defined for quotation of purchase "%s".'),
                 'warehouse_required': ('A warehouse must be defined for '
-                    'quotation of sale "%s".'),
+                    'quotation of purchase "%s".'),
                 'missing_account_payable': ('Missing "Account Payable" on '
                     'party "%s".'),
                 'delete_cancel': ('Purchase "%s" must be cancelled before '
@@ -156,6 +158,7 @@ class Purchase(Workflow, ModelSQL, ModelView):
                 ('draft', 'quotation'),
                 ('quotation', 'confirmed'),
                 ('confirmed', 'confirmed'),
+                ('done', 'confirmed'),
                 ('draft', 'cancel'),
                 ('quotation', 'cancel'),
                 ('quotation', 'draft'),
@@ -299,6 +302,7 @@ class Purchase(Workflow, ModelSQL, ModelView):
     def default_shipment_state():
         return 'none'
 
+    @fields.depends('party', 'payment_term')
     def on_change_party(self):
         pool = Pool()
         PaymentTerm = pool.get('account.invoice.payment_term')
@@ -347,11 +351,13 @@ class Purchase(Workflow, ModelSQL, ModelView):
                     changes['payment_term']).rec_name
         return changes
 
+    @fields.depends('currency')
     def on_change_with_currency_digits(self, name=None):
         if self.currency:
             return self.currency.digits
         return 2
 
+    @fields.depends('party')
     def on_change_with_party_lang(self, name=None):
         Config = Pool().get('ir.configuration')
         if self.party:
@@ -365,6 +371,7 @@ class Purchase(Workflow, ModelSQL, ModelView):
             context['language'] = self.party.lang.code
         return context
 
+    @fields.depends('lines', 'currency', 'party')
     def on_change_lines(self):
         pool = Pool()
         Tax = pool.get('account.tax')
@@ -381,12 +388,13 @@ class Purchase(Workflow, ModelSQL, ModelView):
             for line in self.lines:
                 if getattr(line, 'type', 'line') != 'line':
                     continue
-                changes['untaxed_amount'] += line.amount or Decimal(0)
+                changes['untaxed_amount'] += (getattr(line, 'amount', None)
+                    or Decimal(0))
 
                 with Transaction().set_context(context):
                     tax_list = Tax.compute(getattr(line, 'taxes', []),
-                        line.unit_price or Decimal('0.0'),
-                        line.quantity or 0.0)
+                        getattr(line, 'unit_price', None) or Decimal('0.0'),
+                        getattr(line, 'quantity', None) or 0.0)
                 for tax in tax_list:
                     key, val = Invoice._compute_tax(tax, 'in_invoice')
                     if not key in taxes:
@@ -435,21 +443,31 @@ class Purchase(Workflow, ModelSQL, ModelView):
         tax_amount = {}
         total_amount = {}
 
+        if {'tax_amount', 'total_amount'} & set(names):
+            compute_taxes = True
+        else:
+            compute_taxes = False
+        # Sort cached first and re-instanciate to optimize cache management
+        purchases = sorted(purchases,
+            key=lambda p: p.state in cls._states_cached, reverse=True)
+        purchases = cls.browse(purchases)
         for purchase in purchases:
             if (purchase.state in cls._states_cached
                     and purchase.untaxed_amount_cache is not None
                     and purchase.tax_amount_cache is not None
                     and purchase.total_amount_cache is not None):
                 untaxed_amount[purchase.id] = purchase.untaxed_amount_cache
-                tax_amount[purchase.id] = purchase.tax_amount_cache
-                total_amount[purchase.id] = purchase.total_amount_cache
+                if compute_taxes:
+                    tax_amount[purchase.id] = purchase.tax_amount_cache
+                    total_amount[purchase.id] = purchase.total_amount_cache
             else:
                 untaxed_amount[purchase.id] = sum(
                     (line.amount for line in purchase.lines
                         if line.type == 'line'), _ZERO)
-                tax_amount[purchase.id] = purchase.get_tax_amount()
-                total_amount[purchase.id] = (
-                    untaxed_amount[purchase.id] + tax_amount[purchase.id])
+                if compute_taxes:
+                    tax_amount[purchase.id] = purchase.get_tax_amount()
+                    total_amount[purchase.id] = (
+                        untaxed_amount[purchase.id] + tax_amount[purchase.id])
 
         result = {
             'untaxed_amount': untaxed_amount,
@@ -461,6 +479,18 @@ class Purchase(Workflow, ModelSQL, ModelView):
                 del result[key]
         return result
 
+    def get_invoices(self, name):
+        invoices = set()
+        for line in self.lines:
+            for invoice_line in line.invoice_lines:
+                if invoice_line.invoice:
+                    invoices.add(invoice_line.invoice.id)
+        return list(invoices)
+
+    @classmethod
+    def search_invoices(cls, name, clause):
+        return [('lines.invoice_lines.invoice.id',) + tuple(clause[1:])]
+
     def get_invoice_state(self):
         '''
         Return the invoice state for the purchase.
@@ -534,15 +564,15 @@ class Purchase(Workflow, ModelSQL, ModelView):
 
     @classmethod
     def search_rec_name(cls, name, clause):
-        names = clause[2].split(' - ', 1)
-        purchases = cls.search(['OR',
-                ('reference', clause[1], names[0]),
-                ('supplier_reference', clause[1], names[0]),
-                ], order=[])
-        res = [('id', 'in', [p.id for p in purchases])]
+        _, operator, value = clause
+        names = value.split(' - ', 1)
+        domain = ['OR',
+            ('reference', operator, names[0]),
+            ('supplier_reference', operator, names[0]),
+            ]
         if len(names) != 1 and names[1]:
-            res.append(('party', clause[1], names[1]))
-        return res
+            domain = [domain, ('party', operator, names[1])]
+        return domain
 
     @classmethod
     def copy(cls, purchases, default=None):
@@ -552,7 +582,6 @@ class Purchase(Workflow, ModelSQL, ModelView):
         default['state'] = 'draft'
         default['reference'] = None
         default['invoice_state'] = 'none'
-        default['invoices'] = None
         default['invoices_ignored'] = None
         default['shipment_state'] = 'none'
         default.setdefault('purchase_date', None)
@@ -666,10 +695,6 @@ class Purchase(Workflow, ModelSQL, ModelView):
 
         with Transaction().set_user(0, set_context=True):
             Invoice.update_taxes([invoice])
-
-        self.write([self], {
-                'invoices': [('add', [invoice.id])],
-                })
         return invoice
 
     def create_move(self, move_type):
@@ -708,8 +733,11 @@ class Purchase(Workflow, ModelSQL, ModelView):
 
     def is_done(self):
         return ((self.invoice_state == 'paid'
-                or self.invoice_method == 'manual')
-            and self.shipment_state == 'received')
+                or self.invoice_state == 'none')
+            and (self.shipment_state == 'received'
+                or self.shipment_state == 'none'
+                or all(l.product.type == 'service'
+                    for l in self.lines if l.product)))
 
     @classmethod
     def delete(cls, purchases):
@@ -762,8 +790,6 @@ class Purchase(Workflow, ModelSQL, ModelView):
     def process(cls, purchases):
         done = []
         for purchase in purchases:
-            if purchase.state in ('done', 'cancel'):
-                continue
             purchase.create_invoice('in_invoice')
             purchase.create_invoice('in_credit_note')
             purchase.set_invoice_state()
@@ -780,16 +806,6 @@ class Purchase(Workflow, ModelSQL, ModelView):
                     })
 
 
-class PurchaseInvoice(ModelSQL):
-    'Purchase - Invoice'
-    __name__ = 'purchase.purchase-account.invoice'
-    _table = 'purchase_invoices_rel'
-    purchase = fields.Many2One('purchase.purchase', 'Purchase',
-            ondelete='CASCADE', select=True, required=True)
-    invoice = fields.Many2One('account.invoice', 'Invoice',
-            ondelete='RESTRICT', select=True, required=True)
-
-
 class PurchaseIgnoredInvoice(ModelSQL):
     'Purchase - Ignored Invoice'
     __name__ = 'purchase.purchase-ignored-account.invoice'
@@ -829,9 +845,7 @@ class PurchaseLine(ModelSQL, ModelView):
             'invisible': Eval('type') != 'line',
             'required': Eval('type') == 'line',
             'readonly': ~Eval('_parent_purchase'),
-            }, on_change=['product', 'quantity', 'unit',
-            '_parent_purchase.currency', '_parent_purchase.party',
-            '_parent_purchase.purchase_date'],
+            },
         depends=['unit_digits', 'type'])
     unit = fields.Many2One('product.uom', 'Unit',
         states={
@@ -844,19 +858,15 @@ class PurchaseLine(ModelSQL, ModelView):
                 ('category', '=', Eval('product_uom_category')),
                 ('category', '!=', -1)),
             ],
-        on_change=['product', 'quantity', 'unit', '_parent_purchase.currency',
-            '_parent_purchase.party'],
         depends=['product', 'type', 'product_uom_category'])
-    unit_digits = fields.Function(fields.Integer('Unit Digits',
-            on_change_with=['unit']), 'on_change_with_unit_digits')
+    unit_digits = fields.Function(fields.Integer('Unit Digits'),
+        'on_change_with_unit_digits')
     product = fields.Many2One('product.product', 'Product',
         domain=[('purchasable', '=', True)],
         states={
             'invisible': Eval('type') != 'line',
             'readonly': ~Eval('_parent_purchase'),
-            }, on_change=['product', 'unit', 'quantity', 'description',
-            '_parent_purchase.party', '_parent_purchase.currency',
-            '_parent_purchase.purchase_date'],
+            },
         context={
             'locations': If(Bool(Eval('_parent_purchase', {}).get(
                         'warehouse')),
@@ -867,8 +877,7 @@ class PurchaseLine(ModelSQL, ModelView):
             'stock_skip_warehouse': True,
             }, depends=['type'])
     product_uom_category = fields.Function(
-        fields.Many2One('product.uom.category', 'Product Uom Category',
-            on_change_with=['product']),
+        fields.Many2One('product.uom.category', 'Product Uom Category'),
         'on_change_with_product_uom_category')
     unit_price = fields.Numeric('Unit Price', digits=(16, 4),
         states={
@@ -881,8 +890,7 @@ class PurchaseLine(ModelSQL, ModelView):
             states={
                 'invisible': ~Eval('type').in_(['line', 'subtotal']),
                 'readonly': ~Eval('_parent_purchase'),
-                }, on_change_with=['type', 'quantity', 'unit_price', 'unit',
-                '_parent_purchase.currency'],
+                },
             depends=['type']), 'get_amount')
     description = fields.Text('Description', size=None, required=True)
     note = fields.Text('Note')
@@ -910,8 +918,6 @@ class PurchaseLine(ModelSQL, ModelView):
     to_location = fields.Function(fields.Many2One('stock.location',
             'To Location'), 'get_to_location')
     delivery_date = fields.Function(fields.Date('Delivery Date',
-            on_change_with=['product', 'quantity',
-                '_parent_purchase.purchase_date', '_parent_purchase.party'],
             states={
                 'invisible': ((Eval('type') != 'line')
                     | (If(Bool(Eval('quantity')), Eval('quantity', 0), 0)
@@ -990,6 +996,7 @@ class PurchaseLine(ModelSQL, ModelView):
                 return True
         return False
 
+    @fields.depends('unit')
     def on_change_with_unit_digits(self, name=None):
         if self.unit:
             return self.unit.digits
@@ -1016,6 +1023,9 @@ class PurchaseLine(ModelSQL, ModelView):
             self.product.purchase_uom.id
         return context
 
+    @fields.depends('product', 'unit', 'quantity', 'description',
+        '_parent_purchase.party', '_parent_purchase.currency',
+        '_parent_purchase.purchase_date')
     def on_change_product(self):
         Product = Pool().get('product.product')
 
@@ -1066,10 +1076,14 @@ class PurchaseLine(ModelSQL, ModelView):
         res['amount'] = self.on_change_with_amount()
         return res
 
+    @fields.depends('product')
     def on_change_with_product_uom_category(self, name=None):
         if self.product:
             return self.product.default_uom_category.id
 
+    @fields.depends('product', 'quantity', 'unit',
+        '_parent_purchase.currency', '_parent_purchase.party',
+        '_parent_purchase.purchase_date')
     def on_change_quantity(self):
         Product = Pool().get('product.product')
 
@@ -1085,9 +1099,13 @@ class PurchaseLine(ModelSQL, ModelView):
                     Decimal(1) / 10 ** self.__class__.unit_price.digits[1])
         return res
 
+    @fields.depends('product', 'quantity', 'unit',
+        '_parent_purchase.currency', '_parent_purchase.party')
     def on_change_unit(self):
         return self.on_change_quantity()
 
+    @fields.depends('type', 'quantity', 'unit_price', 'unit',
+        '_parent_purchase.currency')
     def on_change_with_amount(self):
         if self.type == 'line':
             currency = self.purchase.currency if self.purchase else None
@@ -1128,6 +1146,8 @@ class PurchaseLine(ModelSQL, ModelView):
         else:
             return self.purchase.party.supplier_location.id
 
+    @fields.depends('product', 'quantity',
+        '_parent_purchase.purchase_date', '_parent_purchase.party')
     def on_change_with_delivery_date(self, name=None):
         if (self.product
                 and self.quantity > 0
@@ -1172,16 +1192,21 @@ class PurchaseLine(ModelSQL, ModelView):
         if (invoice_type == 'in_invoice') != (self.quantity >= 0):
             return []
 
+        stock_moves = []
         if (self.purchase.invoice_method == 'order'
                 or not self.product
                 or self.product.type == 'service'):
             quantity = abs(self.quantity)
+            stock_moves = self.moves
         else:
             quantity = 0.0
             for move in self.moves:
                 if move.state == 'done':
                     quantity += Uom.compute_qty(move.uom, move.quantity,
                         self.unit)
+                    if move.invoiced_quantity < move.quantity:
+                        stock_moves.append(move)
+        invoice_line.stock_moves = stock_moves
 
         skip_ids = set(l.id for i in self.purchase.invoices_recreated
             for l in i.lines)
@@ -1205,7 +1230,7 @@ class PurchaseLine(ModelSQL, ModelView):
             if not invoice_line.account:
                 self.raise_user_error('missing_account_expense', {
                         'product': invoice_line.product.rec_name,
-                        'purchase': invoice_line.purchase.rec_name,
+                        'purchase': self.purchase.rec_name,
                         })
         else:
             for model in ('product.template', 'product.category'):
@@ -1214,7 +1239,7 @@ class PurchaseLine(ModelSQL, ModelView):
                     break
             if not invoice_line.account:
                 self.raise_user_error('missing_account_expense_property',
-                    (invoice_line.purchase.rec_name,))
+                    {'purchase': self.purchase.rec_name})
         return [invoice_line]
 
     @classmethod
@@ -1267,6 +1292,8 @@ class PurchaseLine(ModelSQL, ModelView):
         move.unit_price = self.unit_price
         move.currency = self.purchase.currency
         move.planned_date = self.delivery_date
+        move.invoice_lines = [l for l in self.invoice_lines
+            if not l.stock_moves]
         move.origin = self
         return move
 
@@ -1395,7 +1422,7 @@ class HandleShipmentException(Wizard):
                 if move.state == 'cancel' and move not in skip:
                     moves.append(move.id)
         return {
-            'to_recreate': moves,
+            'recreate_moves': moves,
             'domain_moves': moves,
             }
 
@@ -1465,7 +1492,7 @@ class HandleInvoiceException(Wizard):
             if invoice.state == 'cancel' and invoice not in skip:
                 invoices.append(invoice.id)
         return {
-            'to_recreate': invoices,
+            'recreate_invoices': invoices,
             'domain_invoices': invoices,
             }
 
diff --git a/purchase.xml b/purchase.xml
index a0427d8..58eee04 100644
--- a/purchase.xml
+++ b/purchase.xml
@@ -69,7 +69,7 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window" id="act_shipment_form">
             <field name="name">Shipments</field>
             <field name="res_model">stock.shipment.in</field>
-            <field name="domain">[("id", "in", Eval('shipments'))]</field>
+            <field name="domain">[('moves.purchase', 'in', Eval('active_ids'))]</field>
         </record>
         <record model="ir.action.keyword"
                 id="act_open_shipment_keyword1">
@@ -80,7 +80,7 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window" id="act_return_form">
             <field name="name">Returns</field>
             <field name="res_model">stock.shipment.in.return</field>
-            <field name="domain">[("id", "in", Eval('shipment_returns'))]</field>
+            <field name="domain">[('moves.purchase', 'in', Eval('active_ids'))]</field>
         </record>
         <record model="ir.action.keyword"
             id="act_open_shipment_return_keyword1">
@@ -91,8 +91,7 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window" id="act_invoice_form">
             <field name="name">Invoices</field>
             <field name="res_model">account.invoice</field>
-            <field name="domain">[("id", "in", Eval('invoices'))]</field>
-            <field name="context">{'type': 'in_invoice'}</field>
+            <field name="domain">[('lines.origin.purchase.id', 'in', Eval('active_ids'), 'purchase.line')]</field>
         </record>
         <record model="ir.action.keyword"
                 id="act_open_invoice_keyword1">
@@ -166,7 +165,7 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window" id="act_purchase_invoice_relate">
             <field name="name">Purchases</field>
             <field name="res_model">purchase.purchase</field>
-            <field name="domain">[('invoices', 'in', [Eval('id')])]</field>
+            <field name="domain">[('invoices', 'in', Eval('active_ids'))]</field>
         </record>
         <record model="ir.action.act_window.view"
             id="act_purchase_invoice_relate_view1">
@@ -205,6 +204,14 @@ this repository contains the full copyright notices and license terms. -->
             <field name="perm_create" eval="True"/>
             <field name="perm_delete" eval="True"/>
         </record>
+        <record model="ir.model.access" id="access_purchase_account">
+            <field name="model" search="[('model', '=', 'purchase.purchase')]"/>
+            <field name="group" ref="account.group_account"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
 
         <record model="ir.model.button" id="purchase_cancel_button">
             <field name="name">cancel</field>
@@ -318,6 +325,14 @@ this repository contains the full copyright notices and license terms. -->
             <field name="perm_create" eval="True"/>
             <field name="perm_delete" eval="True"/>
         </record>
+        <record model="ir.model.access" id="access_purchase_line_account">
+            <field name="model" search="[('model', '=', 'purchase.line')]"/>
+            <field name="group" ref="account.group_account"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
 
         <record model="ir.ui.view" id="product_supplier_view_form">
             <field name="model">purchase.product_supplier</field>
diff --git a/setup.py b/setup.py
index 4ecd41d..ac8919c 100644
--- a/setup.py
+++ b/setup.py
@@ -11,33 +11,51 @@ import ConfigParser
 def read(fname):
     return open(os.path.join(os.path.dirname(__file__), fname)).read()
 
+
+def get_require_version(name):
+    if minor_version % 2:
+        require = '%s >= %s.%s.dev0, < %s.%s'
+    else:
+        require = '%s >= %s.%s, < %s.%s'
+    require %= (name, major_version, minor_version,
+        major_version, minor_version + 1)
+    return require
+
 config = ConfigParser.ConfigParser()
 config.readfp(open('tryton.cfg'))
 info = dict(config.items('tryton'))
 for key in ('depends', 'extras_depend', 'xml'):
     if key in info:
         info[key] = info[key].strip().splitlines()
-major_version, minor_version, _ = info.get('version', '0.0.1').split('.', 2)
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
 major_version = int(major_version)
 minor_version = int(minor_version)
+name = 'trytond_purchase'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+    major_version, minor_version)
+if minor_version % 2:
+    version = '%s.%s.dev0' % (major_version, minor_version)
+    download_url = (
+        'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+            name[8:], name, version))
 
 requires = ['python-sql']
 for dep in info.get('depends', []):
     if not re.match(r'(ir|res|webdav)(\W|$)', dep):
-        requires.append('trytond_%s >= %s.%s, < %s.%s' %
-            (dep, major_version, minor_version, major_version,
-                minor_version + 1))
-requires.append('trytond >= %s.%s, < %s.%s' %
-    (major_version, minor_version, major_version, minor_version + 1))
+        requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
 
-setup(name='trytond_purchase',
-    version=info.get('version', '0.0.1'),
+setup(name=name,
+    version=version,
     description='Tryton module for purchase',
     long_description=read('README'),
     author='Tryton',
+    author_email='issue_tracker at tryton.org',
     url='http://www.tryton.org/',
-    download_url=("http://downloads.tryton.org/" +
-        info.get('version', '0.0.1').rsplit('.', 1)[0] + '/'),
+    download_url=download_url,
+    keywords='tryton purchase',
     package_dir={'trytond.modules.purchase': '.'},
     packages=[
         'trytond.modules.purchase',
@@ -67,7 +85,6 @@ setup(name='trytond_purchase',
         'Natural Language :: Slovenian',
         'Natural Language :: Spanish',
         'Operating System :: OS Independent',
-        'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
         'Topic :: Office/Business',
         'Topic :: Office/Business :: Financial :: Accounting',
diff --git a/stock.py b/stock.py
index b01801a..fed0e5d 100644
--- a/stock.py
+++ b/stock.py
@@ -41,14 +41,17 @@ class ShipmentIn:
                 })
 
     @classmethod
-    def write(cls, shipments, vals):
+    def write(cls, *args):
         pool = Pool()
         Purchase = pool.get('purchase.purchase')
         PurchaseLine = pool.get('purchase.line')
 
-        super(ShipmentIn, cls).write(shipments, vals)
+        super(ShipmentIn, cls).write(*args)
 
-        if 'state' in vals and vals['state'] in ('received', 'cancel'):
+        actions = iter(args)
+        for shipments, values in zip(actions, actions):
+            if values.get('state') not in ('received', 'cancel'):
+                continue
             purchases = []
             move_ids = []
             for shipment in shipments:
@@ -92,14 +95,17 @@ class ShipmentInReturn:
                 })
 
     @classmethod
-    def write(cls, shipments, vals):
+    def write(cls, *args):
         pool = Pool()
         Purchase = pool.get('purchase.purchase')
         PurchaseLine = pool.get('purchase.line')
 
-        super(ShipmentInReturn, cls).write(shipments, vals)
+        super(ShipmentInReturn, cls).write(*args)
 
-        if 'state' in vals and vals['state'] == 'done':
+        actions = iter(args)
+        for shipments, values in zip(actions, actions):
+            if values.get('state') != 'done':
+                continue
             move_ids = []
             for shipment in shipments:
                 move_ids.extend([x.id for x in shipment.moves])
@@ -159,8 +165,8 @@ class Move:
             'Purchase Currency', states={
                 'invisible': ~Eval('purchase_visible', False),
                 }, depends=['purchase_visible']), 'get_purchase_fields')
-    purchase_visible = fields.Function(fields.Boolean('Purchase Visible',
-        on_change_with=['from_location']), 'on_change_with_purchase_visible')
+    purchase_visible = fields.Function(fields.Boolean('Purchase Visible'),
+        'on_change_with_purchase_visible')
     supplier = fields.Function(fields.Many2One('party.party', 'Supplier'),
         'get_supplier', searcher='search_supplier')
     purchase_exception_state = fields.Function(fields.Selection([
@@ -193,6 +199,12 @@ class Move:
         models.append('purchase.line')
         return models
 
+    @classmethod
+    def check_origin_types(cls):
+        types = super(Move, cls).check_origin_types()
+        types.add('supplier')
+        return types
+
     def get_purchase(self, name):
         PurchaseLine = Pool().get('purchase.line')
         if isinstance(self.origin, PurchaseLine):
@@ -226,6 +238,7 @@ class Move:
             elif name[9:] == 'unit_digits':
                 return 2
 
+    @fields.depends('from_location')
     def on_change_with_purchase_visible(self, name=None):
         if self.from_location:
             if self.from_location.type == 'supplier':
diff --git a/tests/scenario_purchase.rst b/tests/scenario_purchase.rst
index 51472dc..2f70843 100644
--- a/tests/scenario_purchase.rst
+++ b/tests/scenario_purchase.rst
@@ -27,11 +27,11 @@ Create company::
 
     >>> Currency = Model.get('currency.currency')
     >>> CurrencyRate = Model.get('currency.currency.rate')
-    >>> currencies = Currency.find([('code', '=', 'EUR')])
+    >>> currencies = Currency.find([('code', '=', 'USD')])
     >>> if not currencies:
-    ...     currency = Currency(name='Euro', symbol=u'€', code='EUR',
+    ...     currency = Currency(name='U.S. Dollar', symbol='$', code='USD',
     ...         rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
-    ...         mon_decimal_point=',')
+    ...         mon_decimal_point='.', mon_thousands_sep=',')
     ...     currency.save()
     ...     CurrencyRate(date=today + relativedelta(month=1, day=1),
     ...         rate=Decimal('1.0'), currency=currency).save()
@@ -42,7 +42,7 @@ Create company::
     >>> company_config = Wizard('company.company.config')
     >>> company_config.execute('company')
     >>> company = company_config.form
-    >>> party = Party(name='B2CK')
+    >>> party = Party(name='Dunder Mifflin')
     >>> party.save()
     >>> company.party = party
     >>> company.currency = currency
@@ -112,6 +112,7 @@ 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')
@@ -137,6 +138,15 @@ Create chart of accounts::
     >>> create_chart.form.account_receivable = receivable
     >>> create_chart.form.account_payable = payable
     >>> create_chart.execute('create_properties')
+    >>> cash, = Account.find([
+    ...         ('kind', '=', 'other'),
+    ...         ('name', '=', 'Main Cash'),
+    ...         ('company', '=', company.id),
+    ...         ])
+    >>> cash_journal, = Journal.find([('type', '=', 'cash')])
+    >>> cash_journal.credit_account = cash
+    >>> cash_journal.debit_account = cash
+    >>> cash_journal.save()
 
 Create parties::
 
@@ -168,6 +178,21 @@ Create product::
     >>> product.template = template
     >>> product.save()
 
+    >>> service = Product()
+    >>> template = ProductTemplate()
+    >>> template.name = 'service'
+    >>> template.default_uom = unit
+    >>> template.type = 'service'
+    >>> template.purchasable = True
+    >>> template.list_price = Decimal('10')
+    >>> template.cost_price = Decimal('10')
+    >>> template.cost_price_method = 'fixed'
+    >>> template.account_expense = expense
+    >>> template.account_revenue = revenue
+    >>> template.save()
+    >>> service.template = template
+    >>> service.save()
+
 Create payment term::
 
     >>> PaymentTerm = Model.get('account.invoice.payment_term')
@@ -231,13 +256,28 @@ Purchase 5 products::
     >>> invoice.origins == purchase.rec_name
     True
 
+Invoice line must be linked to stock move::
+
+    >>> _, invoice_line1, invoice_line2 = sorted(invoice.lines,
+    ...     key=lambda l: l.quantity)
+    >>> stock_move1, stock_move2 = sorted(purchase.moves,
+    ...     key=lambda m: m.quantity)
+    >>> invoice_line1.stock_moves == [stock_move1]
+    True
+    >>> stock_move1.invoice_lines == [invoice_line1]
+    True
+    >>> invoice_line2.stock_moves == [stock_move2]
+    True
+    >>> stock_move2.invoice_lines == [invoice_line2]
+    True
+
 Post invoice and check no new invoices::
 
     >>> config.user = account_user.id
     >>> Invoice = Model.get('account.invoice')
-    >>> purchase.invoices[0].invoice_date = today
-    >>> purchase.invoices[0].save()
-    >>> Invoice.post([i.id for i in purchase.invoices], config.context)
+    >>> invoice = Invoice(purchase.invoices[0].id)
+    >>> invoice.invoice_date = today
+    >>> invoice.click('post')
     >>> config.user = purchase_user.id
     >>> purchase.reload()
     >>> len(purchase.moves), len(purchase.shipment_returns), len(purchase.invoices)
@@ -271,6 +311,15 @@ Purchase 5 products with an invoice method 'on shipment'::
     >>> len(purchase.moves), len(purchase.shipment_returns), len(purchase.invoices)
     (2, 0, 0)
 
+Not yet linked to invoice lines::
+
+    >>> stock_move1, stock_move2 = sorted(purchase.moves,
+    ...     key=lambda m: m.quantity)
+    >>> len(stock_move1.invoice_lines)
+    0
+    >>> len(stock_move2.invoice_lines)
+    0
+
 Validate Shipments::
 
     >>> config.user = stock_user.id
@@ -292,13 +341,14 @@ Validate Shipments::
 
 Open supplier invoice::
 
-    >>> Invoice = Model.get('account.invoice')
+    >>> config.user = purchase_user.id
     >>> invoice, = purchase.invoices
     >>> config.user = account_user.id
+    >>> invoice = Invoice(invoice.id)
     >>> invoice.type
     u'in_invoice'
-    >>> len(invoice.lines)
-    2
+    >>> invoice_line1, invoice_line2 = sorted(invoice.lines,
+    ...     key=lambda l: l.quantity)
     >>> for line in invoice.lines:
     ...     line.quantity = 1
     ...     line.save()
@@ -306,6 +356,13 @@ Open supplier invoice::
     >>> invoice.save()
     >>> Invoice.post([invoice.id], config.context)
 
+Invoice lines must be linked to each stock moves::
+
+    >>> invoice_line1.stock_moves == [stock_move1]
+    True
+    >>> invoice_line2.stock_moves == [stock_move2]
+    True
+
 Check second invoices::
 
     >>> config.user = purchase_user.id
@@ -362,8 +419,10 @@ Check Return Shipments::
 
 Open supplier credit note::
 
+    >>> config.user = purchase_user.id
     >>> credit_note, = return_.invoices
     >>> config.user = account_user.id
+    >>> credit_note = Invoice(credit_note.id)
     >>> credit_note.type
     u'in_credit_note'
     >>> len(credit_note.lines)
@@ -437,6 +496,8 @@ Checking the invoice::
     >>> mix_invoice, mix_credit_note = sorted(mix.invoices,
     ...     key=attrgetter('type'), reverse=True)
     >>> config.user = account_user.id
+    >>> mix_invoice = Invoice(mix_invoice.id)
+    >>> mix_credit_note = Invoice(mix_credit_note.id)
     >>> mix_invoice.type, mix_credit_note.type
     (u'in_invoice', u'in_credit_note')
     >>> len(mix_invoice.lines), len(mix_credit_note.lines)
@@ -507,3 +568,43 @@ Checking Shipments::
     u'product'
     >>> move_return.quantity
     3.0
+
+Purchase services::
+
+    >>> config.user = purchase_user.id
+    >>> service_purchase = Purchase()
+    >>> service_purchase.party = supplier
+    >>> service_purchase.payment_term = payment_term
+    >>> purchase_line = service_purchase.lines.new()
+    >>> purchase_line.product = service
+    >>> purchase_line.quantity = 1
+    >>> service_purchase.save()
+    >>> service_purchase.click('quote')
+    >>> service_purchase.click('confirm')
+    >>> service_purchase.state
+    u'confirmed'
+    >>> service_invoice, = service_purchase.invoices
+
+Pay the service invoice::
+
+    >>> config.user = account_user.id
+    >>> service_invoice.invoice_date = today
+    >>> service_invoice.click('post')
+    >>> pay = Wizard('account.invoice.pay', [service_invoice])
+    >>> pay.form.journal = cash_journal
+    >>> pay.form.amount = service_invoice.total_amount
+    >>> pay.execute('choice')
+    >>> service_invoice.reload()
+    >>> service_invoice.state
+    u'paid'
+
+Check service purchase states::
+
+    >>> config.user = purchase_user.id
+    >>> service_purchase.reload()
+    >>> service_purchase.invoice_state
+    u'paid'
+    >>> service_purchase.shipment_state
+    u'none'
+    >>> service_purchase.state
+    u'done'
diff --git a/tests/test_purchase.py b/tests/test_purchase.py
index a672a91..b40c8c7 100644
--- a/tests/test_purchase.py
+++ b/tests/test_purchase.py
@@ -1,52 +1,26 @@
-#!/usr/bin/env python
 #This file is part of Tryton.  The COPYRIGHT file at the top level of
 #this repository contains the full copyright notices and license terms.
-
-import sys
-import os
-DIR = os.path.abspath(os.path.normpath(os.path.join(__file__,
-    '..', '..', '..', '..', '..', 'trytond')))
-if os.path.isdir(DIR):
-    sys.path.insert(0, os.path.dirname(DIR))
-
 import unittest
 import doctest
 import trytond.tests.test_tryton
-from trytond.tests.test_tryton import test_view, test_depends
-from trytond.backend.sqlite.database import Database as SQLiteDatabase
+from trytond.tests.test_tryton import test_view, test_depends, doctest_dropdb
 
 
 class PurchaseTestCase(unittest.TestCase):
-    '''
-    Test Purchase module.
-    '''
+    'Test Purchase module'
 
     def setUp(self):
         trytond.tests.test_tryton.install_module('purchase')
 
     def test0005views(self):
-        '''
-        Test views.
-        '''
+        'Test views'
         test_view('purchase')
 
     def test0006depends(self):
-        '''
-        Test depends.
-        '''
+        'Test depends'
         test_depends()
 
 
-def doctest_dropdb(test):
-    database = SQLiteDatabase().connect()
-    cursor = database.cursor(autocommit=True)
-    try:
-        database.drop(cursor, ':memory:')
-        cursor.commit()
-    finally:
-        cursor.close()
-
-
 def suite():
     suite = trytond.tests.test_tryton.suite()
     suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
@@ -55,6 +29,3 @@ def suite():
             setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='UTF-8',
             optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
     return suite
-
-if __name__ == '__main__':
-    unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/tryton.cfg b/tryton.cfg
index d730807..1b20ea5 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -1,8 +1,9 @@
 [tryton]
-version=3.0.0
+version=3.2.0
 depends:
     account
     account_invoice
+    account_invoice_stock
     account_product
     company
     currency
diff --git a/trytond_purchase.egg-info/PKG-INFO b/trytond_purchase.egg-info/PKG-INFO
index 9b4ba9e..41f7726 100644
--- a/trytond_purchase.egg-info/PKG-INFO
+++ b/trytond_purchase.egg-info/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: trytond-purchase
-Version: 3.0.0
+Version: 3.2.0
 Summary: Tryton module for purchase
 Home-page: http://www.tryton.org/
 Author: Tryton
-Author-email: UNKNOWN
+Author-email: issue_tracker at tryton.org
 License: GPL-3
-Download-URL: http://downloads.tryton.org/3.0/
+Download-URL: http://downloads.tryton.org/3.2/
 Description: trytond_purchase
         ================
         
@@ -43,6 +43,7 @@ Description: trytond_purchase
         
           http://www.tryton.org/
         
+Keywords: tryton purchase
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Plugins
@@ -62,7 +63,6 @@ Classifier: Natural Language :: Russian
 Classifier: Natural Language :: Slovenian
 Classifier: Natural Language :: Spanish
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Topic :: Office/Business
 Classifier: Topic :: Office/Business :: Financial :: Accounting
diff --git a/trytond_purchase.egg-info/requires.txt b/trytond_purchase.egg-info/requires.txt
index bc38aef..4fa7d4c 100644
--- a/trytond_purchase.egg-info/requires.txt
+++ b/trytond_purchase.egg-info/requires.txt
@@ -1,10 +1,11 @@
 python-sql
-trytond_account >= 3.0, < 3.1
-trytond_account_invoice >= 3.0, < 3.1
-trytond_account_product >= 3.0, < 3.1
-trytond_company >= 3.0, < 3.1
-trytond_currency >= 3.0, < 3.1
-trytond_party >= 3.0, < 3.1
-trytond_product >= 3.0, < 3.1
-trytond_stock >= 3.0, < 3.1
-trytond >= 3.0, < 3.1
\ No newline at end of file
+trytond_account >= 3.2, < 3.3
+trytond_account_invoice >= 3.2, < 3.3
+trytond_account_invoice_stock >= 3.2, < 3.3
+trytond_account_product >= 3.2, < 3.3
+trytond_company >= 3.2, < 3.3
+trytond_currency >= 3.2, < 3.3
+trytond_party >= 3.2, < 3.3
+trytond_product >= 3.2, < 3.3
+trytond_stock >= 3.2, < 3.3
+trytond >= 3.2, < 3.3
\ No newline at end of file
diff --git a/view/purchase_tree.xml b/view/purchase_tree.xml
index 4f16d6c..6e62f52 100644
--- a/view/purchase_tree.xml
+++ b/view/purchase_tree.xml
@@ -9,7 +9,6 @@ this repository contains the full copyright notices and license terms. -->
     <field name="warehouse"/>
     <field name="currency"/>
     <field name="untaxed_amount"/>
-    <field name="total_amount"/>
     <field name="state"/>
     <field name="invoice_state"/>
     <field name="shipment_state"/>
-- 
tryton-modules-purchase



More information about the tryton-debian-vcs mailing list