diff --git a/CHANGELOG b/CHANGELOG index b0e7cfa676..a7e9735eb7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add actual quantity on line * Add return wizard * Add employee on purchases for some states * Add contact and invoice party on purchase diff --git a/purchase.py b/purchase.py index 77aed90d60..5f3d071945 100644 --- a/purchase.py +++ b/purchase.py @@ -909,6 +909,9 @@ class Purchase( @classmethod @ModelView.button def process(cls, purchases): + pool = Pool() + Line = pool.get('purchase.line') + lines = [] process, done = [], [] cls.lock(purchases) for purchase in purchases: @@ -921,6 +924,11 @@ class Purchase( if return_moves: purchase.create_return_shipment(return_moves) purchase.set_shipment_state() + + for line in purchase.lines: + line.set_actual_quantity() + lines.append(line) + if purchase.is_done(): if purchase.state != 'done': if purchase.state == 'confirmed': @@ -928,6 +936,7 @@ class Purchase( done.append(purchase) elif purchase.state != 'processing': process.append(purchase) + Line.save(lines) if process: cls.proceed(process) if done: @@ -987,6 +996,12 @@ class Line(sequence_ordered(), ModelSQL, ModelView): 'readonly': Eval('purchase_state') != 'draft', }, depends=['unit_digits', 'type', 'purchase_state']) + actual_quantity = fields.Float( + "Actual Quantity", digits=(16, Eval('unit_digits', 2)), readonly=True, + states={ + 'invisible': Eval('type') != 'line', + }, + depends=['unit_digits', 'type']) unit = fields.Many2One('product.uom', 'Unit', ondelete='RESTRICT', states={ @@ -1600,6 +1615,26 @@ class Line(sequence_ordered(), ModelSQL, ModelView): else: return [l for l in self.invoice_lines if not l.stock_moves] + def set_actual_quantity(self): + pool = Pool() + Uom = pool.get('product.uom') + if self.type != 'line': + return + moved_quantity = 0 + for move in self.moves: + if move.state != 'cancel': + moved_quantity += Uom.compute_qty( + move.uom, move.quantity, self.unit) + if self.quantity < 0: + moved_quantity *= -1 + invoiced_quantity = 0 + for invoice_line in self.invoice_lines: + if (not invoice_line.invoice + or invoice_line.invoice.state != 'cancel'): + invoiced_quantity += Uom.compute_qty( + invoice_line.unit, invoice_line.quantity, self.unit) + self.actual_quantity = max(moved_quantity, invoiced_quantity, key=abs) + def get_rec_name(self, name): pool = Pool() Lang = pool.get('ir.lang') diff --git a/tests/scenario_purchase.rst b/tests/scenario_purchase.rst index 576d326181..66921cf43a 100644 --- a/tests/scenario_purchase.rst +++ b/tests/scenario_purchase.rst @@ -204,6 +204,11 @@ Invoice line must be linked to stock move:: >>> stock_move2.invoice_lines == [invoice_line2] True +Check actual quantity:: + + >>> all(l.quantity == l.actual_quantity for l in purchase.lines) + True + Post invoice and check no new invoices:: >>> invoice.invoice_date = today