Padding report

This commit is contained in:
2026-04-27 20:09:36 +02:00
parent 308252215f
commit 384c1285b1
6 changed files with 234 additions and 1 deletions

View File

@@ -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
`<tree>` 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 `<tree>`:
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`.

View File

@@ -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,

View File

@@ -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'

View File

@@ -36,5 +36,31 @@
<field name="model">account.invoice,-1</field>
<field name="action" ref="report_payment_order"/>
</record>
<record model="ir.ui.view" id="invoice_padding_context_view_form">
<field name="model">invoice.padding.context</field>
<field name="type">form</field>
<field name="name">invoice_padding_context_form</field>
</record>
<record model="ir.ui.view" id="invoice_padding_report_view_list">
<field name="model">invoice.padding.report</field>
<field name="type">tree</field>
<field name="name">invoice_padding_report_list</field>
</record>
<record model="ir.action.act_window" id="act_invoice_padding_report_form">
<field name="name">Invoice with padding</field>
<field name="res_model">invoice.padding.report</field>
<field name="context_model">invoice.padding.context</field>
</record>
<record model="ir.action.act_window.view" id="act_invoice_padding_report_form_view">
<field name="sequence" eval="70"/>
<field name="view" ref="invoice_padding_report_view_list"/>
<field name="act_window" ref="act_invoice_padding_report_form"/>
</record>
<menuitem
parent="purchase_trade.menu_global_reporting"
sequence="101"
action="act_invoice_padding_report_form"
id="menu_invoice_padding_report_form"/>
</data>
</tryton>

View File

@@ -0,0 +1,16 @@
<form>
<label name="from_date"/>
<field name="from_date"/>
<label name="to_date"/>
<field name="to_date"/>
<label name="party"/>
<field name="party"/>
<label name="currency"/>
<field name="currency"/>
<label name="status"/>
<field name="status"/>
<label name="sale"/>
<field name="sale"/>
<label name="lot"/>
<field name="lot"/>
</form>

View File

@@ -0,0 +1,19 @@
<tree>
<field name="party" width="140"/>
<field name="currency" width="60"/>
<field name="sale" width="100"/>
<field name="sale_line" width="100"/>
<field name="lot" width="120"/>
<field name="product" width="140"/>
<field name="padding_status" width="80"/>
<field name="padding_quantity" width="110" sum="1"/>
<field name="unit" width="60"/>
<field name="unit_price" width="90"/>
<field name="padding_amount" width="110" sum="1"/>
<field name="provisional_invoice" width="130"/>
<field name="provisional_date" width="90"/>
<field name="provisional_state" width="90"/>
<field name="final_invoice" width="130"/>
<field name="final_date" width="90"/>
<field name="final_state" width="90"/>
</tree>