Picklist / invoice et al: sort order of items

Hello everybody,
yet another dummy question: I could never find out how Tryton sorts entries of a purchase list in next processing steps. Meaning:

  • I create a sale, items are created in a certain order
  • I create a picklist from that sale - order of items may have changed
  • I create an invoice (I’m using collective invoices :heart:) - again there can be another sort order of items.

What I’d like to have is straight chronological in the line of input in sales - but certainly in the process I’m doing strange things which mess up the order. Neither in sales nor in invoices I can find a control for the sort order - but that may be my proverbial blindness…

Hints would be greatly appreciated.

Cheers,
Wolf

On the shipment we do not really care about that but depending on the Python version (if dict keys keep insert order) and the kind of grouping used, the outgoing moves may be in the same order.

Indeed the order should be kept if the invoice method is on order otherwise it will depend on when the stock moves are done.

Allright. That’s not really critical.

Hm. My invoicing method is “on delivery”. But it’s not so much about different orders - they usually are kept in the order they are delivered. My issue is the order of items within a sale. It’s really painful to search for mistakes if order of items in sale and in invoice are different. Is there a way to make sure they are?

Well. AFAIU, in this case it’s not my fault, but Tryton may change the order of items on the way from sale (maybe purchase) to delivery, picklist and invoice. True?

In case, I’d vote for a moderate effort to keep order of items the same any case. Else can cause serious trouble. Ticket?

Cheers,
Wolf

Being new to Tryton programming I’ve the following thoughts on Wolf’s issue, and I’d be happy for comments on my approach:

The module sale-invoice-grouping generates items in account.invoice.line without setting the field sequence. So the sort order is set by python itself, it looks as it’s often more or less driven by random.

Because I do not (yet) understand how the module sale-invoice-grouping works and how it can be adjusted to set the sort order, I would suggest to set the field account.invoice.line.sequence for all lines belonging to the invoice before printing.

With the help of the field account.invoice.line.origin it’s possible to get the record in sale.line and with the field sale.line.sale it’s possible to get the record in sale.sale. The fields sale.sale.sale_date and sale.sale.shipping_date are containing the necessary informations for the sorting order.

By collecting all these dates for all invoice lines it should be possible to set sorting order as requested.

Is it true this could be implemented as a new action for the module account-invoice? And if so, where can I find more info on how to add a new action?

Without the knowledge of adding a new action I’d implement it as a proteus script.

Thanks in advance, Michael

Since Python 3.7 the dictionary keeps the insertion order. So it is no more random.

Copying the sequence field would create more trouble when the invoice is grouped because you will mix different sets of sequence.

This can be of course implemented as key for sorting lines but only on report because in the view the ordering must always be done by SQL expression.

For the record the actual issue was not really about the order (it was a possible solution) but about Display stock moves and invoice lines on sale and purchase line form (#12003) · Issues · Tryton / Tryton · GitLab

Here is my code for the proposal, I posted above. It shows how to collect the shipping dates of every article starting from invoice.line, when using the module sale_invoice_grouping.

import re
from proteus import config, Model 

config = config.set_trytond(database_uri)

mInvoice = Model.get('account.invoice')
mInvoiceLine = Model.get('account.invoice.line')
mSaleLine = Model.get('sale.line')

invoice, = mInvoice.find(['id','=',id2find])
for invoiceline in invoice.lines:
    origin = str(invoiceline.origin)
    if not invoiceline.type == "line":
        continue
    result = re.match("sale\.line\,[0-9]+", origin)
    if not result:
        continue
    table, record = origin.split(",")
    saleline, = mSaleLine.find(['id','=',record])
    sale = saleline.sale
	# save the necessary items in a dictionary
	# or object to sort and set the field sequence
	# in the the object invoiceline in a further step
	# - invoiceline
	# - sale.sale_date
	# - saleline.shipping_date

After sorting the items, the field sequence can be set and saved.

i = 1
for invoiceline in listWithInvoiceLines:
	invoiceline.sequence = i
	invoiceline.save()
	i = i + 1

After reloading the view of the invoice in the client, the invoice lines are shown in the new order.

When using the module sale_shippment_costs besides, an issue occurs: The field sale.line.shipping_date in the automatically generated carrier products is always set to the actual date (datetime.date.today()). @herrdeh has open new thread for this issue.