diff --git a/modules/purchase_trade/AGENTS.md b/modules/purchase_trade/AGENTS.md index 35933b6..6ee3094 100644 --- a/modules/purchase_trade/AGENTS.md +++ b/modules/purchase_trade/AGENTS.md @@ -165,7 +165,9 @@ de negoce physique: `docs/template-rules.md`. 6. Pour les vues XML Tryton de ce module, utiliser `editable="1"` sur les `` editables; ne pas utiliser `editable="bottom"`. -7. Si une regle de texte par defaut durable est demandee sur achat/vente, +7. Ne pas ajouter `keyword_open` / `open_keyword` sur les vues ``: + ces attributs ne sont pas supportes par Tryton. +8. Si une regle de texte par defaut durable est demandee sur achat/vente, preferer un singleton de configuration expose dans un menu fonctionnel existant plutot qu'un menu technique `purchase_trade`. diff --git a/modules/purchase_trade/__init__.py b/modules/purchase_trade/__init__.py index 9924bf2..e092b88 100755 --- a/modules/purchase_trade/__init__.py +++ b/modules/purchase_trade/__init__.py @@ -196,6 +196,8 @@ def register(): Pool.register( configuration.AccountConfiguration, configuration.AccountConfigurationDefaultAccount, + invoice.InvoicePaddingReport, + invoice.InvoicePaddingContext, module='purchase_trade', type_='model') Pool.register( invoice.Invoice, diff --git a/modules/purchase_trade/invoice.py b/modules/purchase_trade/invoice.py index d625d6f..a2b4159 100644 --- a/modules/purchase_trade/invoice.py +++ b/modules/purchase_trade/invoice.py @@ -1,6 +1,11 @@ from decimal import Decimal, ROUND_HALF_UP from datetime import date as dt_date +from sql import Literal +from sql.conditionals import Case +from sql.functions import CurrentTimestamp + +from trytond.model import ModelSQL, ModelView, fields from trytond.pool import Pool, PoolMeta from trytond.modules.purchase_trade.numbers_to_words import amount_to_currency_words from trytond.exceptions import UserError @@ -123,6 +128,7 @@ class Invoice(metaclass=PoolMeta): for move_line in (sale_line, accrual_line): move_line.lot = lot move_line.origin = invoice_line + move_line.description = 'Padding' if not reversal: sale_line.account = sale_account @@ -187,6 +193,7 @@ class Invoice(metaclass=PoolMeta): self.additional_moves = tuple(self.additional_moves or ()) + (move,) return [move] + @staticmethod def _format_report_number(value, digits='0.0000', keep_trailing_decimal=False, strip_trailing_zeros=True): @@ -1261,6 +1268,167 @@ class Invoice(metaclass=PoolMeta): return 'USD' +class InvoicePaddingReport(ModelSQL, ModelView): + "Invoice with padding" + __name__ = 'invoice.padding.report' + + party = fields.Many2One('party.party', "Party") + sale = fields.Many2One('sale.sale', "Sale") + sale_line = fields.Many2One('sale.line', "Sale Line") + lot = fields.Many2One('lot.lot', "Lot") + product = fields.Many2One('product.product', "Product") + currency = fields.Many2One('currency.currency', "Currency") + unit = fields.Many2One('product.uom', "Unit") + padding_quantity = fields.Numeric("Padding Quantity", digits='unit') + unit_price = fields.Numeric("Unit Price", digits=(16, 6)) + padding_amount = fields.Numeric("Padding Amount", digits=(16, 2)) + provisional_invoice = fields.Many2One( + 'account.invoice', "Provisional Invoice") + provisional_date = fields.Date("Provisional Date") + provisional_state = fields.Selection([ + ('draft', "Draft"), + ('validated', "Validated"), + ('posted', "Posted"), + ('paid', "Paid"), + ('cancelled', "Cancelled"), + ], "Provisional State") + final_invoice = fields.Many2One('account.invoice', "Final Invoice") + final_date = fields.Date("Final Date") + final_state = fields.Selection([ + (None, ''), + ('draft', "Draft"), + ('validated', "Validated"), + ('posted', "Posted"), + ('paid', "Paid"), + ('cancelled', "Cancelled"), + ], "Final State") + padding_status = fields.Selection([ + ('active', "Active"), + ('reversed', "Reversed"), + ], "Padding Status") + + @classmethod + def table_query(cls): + pool = Pool() + Lot = pool.get('lot.lot') + SaleLine = pool.get('sale.line') + Sale = pool.get('sale.sale') + InvoiceLine = pool.get('account.invoice.line') + Invoice = pool.get('account.invoice') + + lot = Lot.__table__() + sale_line = SaleLine.__table__() + sale = Sale.__table__() + prov_line = InvoiceLine.__table__() + prov_invoice = Invoice.__table__() + final_line = InvoiceLine.__table__() + final_invoice = Invoice.__table__() + + context = Transaction().context + party = context.get('party') + currency = context.get('currency') + status_filter = context.get('status') + from_date = context.get('from_date') + to_date = context.get('to_date') + sale_filter = context.get('sale') + lot_filter = context.get('lot') + + reversed_condition = ( + (final_invoice.id > 0) + & ~final_invoice.state.in_(['draft', 'cancelled'])) + padding_status = Case( + (reversed_condition, 'reversed'), + else_='active') + + where = Literal(True) + where &= lot.sale_invoice_padding > 0 + where &= prov_invoice.id > 0 + if party: + where &= prov_invoice.party == party + if currency: + where &= prov_invoice.currency == currency + if status_filter and status_filter != 'all': + where &= padding_status == status_filter + if from_date: + where &= prov_invoice.invoice_date >= from_date + if to_date: + where &= prov_invoice.invoice_date <= to_date + if sale_filter: + where &= sale.id == sale_filter + if lot_filter: + where &= lot.id == lot_filter + + return ( + lot + .join(sale_line, 'LEFT', condition=lot.sale_line == sale_line.id) + .join(sale, 'LEFT', condition=sale_line.sale == sale.id) + .join(prov_line, 'LEFT', + condition=lot.sale_invoice_line_prov == prov_line.id) + .join(prov_invoice, 'LEFT', + condition=prov_line.invoice == prov_invoice.id) + .join(final_line, 'LEFT', + condition=lot.sale_invoice_line == final_line.id) + .join(final_invoice, 'LEFT', + condition=final_line.invoice == final_invoice.id) + .select( + Literal(0).as_('create_uid'), + CurrentTimestamp().as_('create_date'), + Literal(0).as_('write_uid'), + Literal(None).as_('write_date'), + lot.id.as_('id'), + prov_invoice.party.as_('party'), + sale.id.as_('sale'), + sale_line.id.as_('sale_line'), + lot.id.as_('lot'), + prov_line.product.as_('product'), + prov_invoice.currency.as_('currency'), + prov_line.unit.as_('unit'), + lot.sale_invoice_padding.as_('padding_quantity'), + prov_line.unit_price.as_('unit_price'), + (lot.sale_invoice_padding * prov_line.unit_price).as_( + 'padding_amount'), + prov_invoice.id.as_('provisional_invoice'), + prov_invoice.invoice_date.as_('provisional_date'), + prov_invoice.state.as_('provisional_state'), + final_invoice.id.as_('final_invoice'), + final_invoice.invoice_date.as_('final_date'), + final_invoice.state.as_('final_state'), + padding_status.as_('padding_status'), + where=where, + )) + + +class InvoicePaddingContext(ModelView): + "Invoice with padding context" + __name__ = 'invoice.padding.context' + + from_date = fields.Date("From") + to_date = fields.Date("To") + party = fields.Many2One('party.party', "Party") + currency = fields.Many2One('currency.currency', "Currency") + status = fields.Selection([ + ('all', "All"), + ('active', "Active"), + ('reversed', "Reversed"), + ], "Status") + sale = fields.Many2One('sale.sale', "Sale") + lot = fields.Many2One('lot.lot', "Lot") + + @classmethod + def default_from_date(cls): + Date = Pool().get('ir.date') + return Date.today().replace(day=1, month=1, year=1999) + + @classmethod + def default_to_date(cls): + Date = Pool().get('ir.date') + return Date.today() + + @classmethod + def default_status(cls): + return 'active' + + class InvoiceLine(metaclass=PoolMeta): __name__ = 'account.invoice.line' diff --git a/modules/purchase_trade/invoice.xml b/modules/purchase_trade/invoice.xml index ca8a2b8..72a8b7e 100644 --- a/modules/purchase_trade/invoice.xml +++ b/modules/purchase_trade/invoice.xml @@ -36,5 +36,31 @@ account.invoice,-1 + + + invoice.padding.context + form + invoice_padding_context_form + + + invoice.padding.report + tree + invoice_padding_report_list + + + Invoice with padding + invoice.padding.report + invoice.padding.context + + + + + + + diff --git a/modules/purchase_trade/view/invoice_padding_context_form.xml b/modules/purchase_trade/view/invoice_padding_context_form.xml new file mode 100644 index 0000000..631312e --- /dev/null +++ b/modules/purchase_trade/view/invoice_padding_context_form.xml @@ -0,0 +1,16 @@ +
+