[ADD]:Added Upstream Patch for sale_stock
This commit is contained in:
parent
227710041f
commit
fea006c468
@ -25,9 +25,7 @@ class AccountInvoiceLine(models.Model):
|
|||||||
qty_done = sum([x.uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
|
qty_done = sum([x.uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
|
||||||
quantity = self.uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
|
quantity = self.uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
|
||||||
# Put moves in fixed order by date executed
|
# Put moves in fixed order by date executed
|
||||||
moves = self.env['stock.move']
|
moves = s_line.move_ids.sorted(lambda x: x.date)
|
||||||
moves |= s_line.move_ids
|
|
||||||
moves.sorted(lambda x: x.date)
|
|
||||||
# Go through all the moves and do nothing until you get to qty_done
|
# Go through all the moves and do nothing until you get to qty_done
|
||||||
# Beyond qty_done we need to calculate the average of the price_unit
|
# Beyond qty_done we need to calculate the average of the price_unit
|
||||||
# on the moves we encounter.
|
# on the moves we encounter.
|
||||||
@ -37,23 +35,4 @@ class AccountInvoiceLine(models.Model):
|
|||||||
return price_unit
|
return price_unit
|
||||||
|
|
||||||
def _compute_average_price(self, qty_done, quantity, moves):
|
def _compute_average_price(self, qty_done, quantity, moves):
|
||||||
average_price_unit = 0
|
return self.env['product.product']._compute_average_price(qty_done, quantity, moves)
|
||||||
qty_delivered = 0
|
|
||||||
invoiced_qty = 0
|
|
||||||
for move in moves:
|
|
||||||
if move.state != 'done':
|
|
||||||
continue
|
|
||||||
invoiced_qty += move.product_qty
|
|
||||||
if invoiced_qty <= qty_done:
|
|
||||||
continue
|
|
||||||
qty_to_consider = move.product_qty
|
|
||||||
if invoiced_qty - move.product_qty < qty_done:
|
|
||||||
qty_to_consider = invoiced_qty - qty_done
|
|
||||||
qty_to_consider = min(qty_to_consider, quantity - qty_delivered)
|
|
||||||
qty_delivered += qty_to_consider
|
|
||||||
# `move.price_unit` is negative if the move is out and positive if the move is
|
|
||||||
# dropshipped. Use its absolute value to compute the average price unit.
|
|
||||||
average_price_unit = (average_price_unit * (qty_delivered - qty_to_consider) + abs(move.price_unit) * qty_to_consider) / qty_delivered
|
|
||||||
if qty_delivered == quantity:
|
|
||||||
break
|
|
||||||
return average_price_unit
|
|
||||||
|
@ -137,13 +137,9 @@ class SaleOrderLine(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
@api.depends('product_id')
|
@api.depends('product_id')
|
||||||
def _compute_qty_delivered_updateable(self):
|
def _compute_qty_delivered_updateable(self):
|
||||||
# prefetch field before filtering
|
for line in self:
|
||||||
self.mapped('product_id')
|
if line.product_id.type not in ('consu', 'product'):
|
||||||
# on consumable or stockable products, qty_delivered_updateable defaults
|
super(SaleOrderLine, line)._compute_qty_delivered_updateable()
|
||||||
# to False; on other lines use the original computation
|
|
||||||
lines = self.filtered(lambda line: line.product_id.type not in ('consu', 'product'))
|
|
||||||
lines = lines.with_prefetch(self._prefetch)
|
|
||||||
super(SaleOrderLine, lines)._compute_qty_delivered_updateable()
|
|
||||||
|
|
||||||
@api.onchange('product_id')
|
@api.onchange('product_id')
|
||||||
def _onchange_product_id_set_customer_lead(self):
|
def _onchange_product_id_set_customer_lead(self):
|
||||||
@ -343,8 +339,8 @@ class SaleOrderLine(models.Model):
|
|||||||
raise UserError('You cannot decrease the ordered quantity below the delivered quantity.\n'
|
raise UserError('You cannot decrease the ordered quantity below the delivered quantity.\n'
|
||||||
'Create a return first.')
|
'Create a return first.')
|
||||||
for line in self:
|
for line in self:
|
||||||
pickings = self.order_id.picking_ids.filtered(lambda p: p.state not in ('done', 'cancel'))
|
pickings = line.order_id.picking_ids.filtered(lambda p: p.state not in ('done', 'cancel'))
|
||||||
for picking in pickings:
|
for picking in pickings:
|
||||||
picking.message_post("The quantity of %s has been updated from %d to %d in %s" %
|
picking.message_post("The quantity of %s has been updated from %d to %d in %s" %
|
||||||
(line.product_id.name, line.product_uom_qty, values['product_uom_qty'], self.order_id.name))
|
(line.product_id.display_name, line.product_uom_qty, values['product_uom_qty'], line.order_id.name))
|
||||||
super(SaleOrderLine, self)._update_line_quantity(values)
|
super(SaleOrderLine, self)._update_line_quantity(values)
|
||||||
|
@ -28,7 +28,7 @@ class StockMove(models.Model):
|
|||||||
|
|
||||||
def _action_done(self):
|
def _action_done(self):
|
||||||
result = super(StockMove, self)._action_done()
|
result = super(StockMove, self)._action_done()
|
||||||
for line in result.mapped('sale_line_id'):
|
for line in result.mapped('sale_line_id').sudo():
|
||||||
line.qty_delivered = line._get_delivered_qty()
|
line.qty_delivered = line._get_delivered_qty()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class StockMove(models.Model):
|
|||||||
for move in self:
|
for move in self:
|
||||||
if move.state == 'done':
|
if move.state == 'done':
|
||||||
sale_order_lines = self.filtered(lambda move: move.sale_line_id and move.product_id.expense_policy == 'no').mapped('sale_line_id')
|
sale_order_lines = self.filtered(lambda move: move.sale_line_id and move.product_id.expense_policy == 'no').mapped('sale_line_id')
|
||||||
for line in sale_order_lines:
|
for line in sale_order_lines.sudo():
|
||||||
line.qty_delivered = line._get_delivered_qty()
|
line.qty_delivered = line._get_delivered_qty()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@ -64,15 +64,3 @@ class StockPicking(models.Model):
|
|||||||
_inherit = 'stock.picking'
|
_inherit = 'stock.picking'
|
||||||
|
|
||||||
sale_id = fields.Many2one(related="group_id.sale_id", string="Sales Order", store=True)
|
sale_id = fields.Many2one(related="group_id.sale_id", string="Sales Order", store=True)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _create_backorder(self, backorder_moves=[]):
|
|
||||||
res = super(StockPicking, self)._create_backorder(backorder_moves)
|
|
||||||
for picking in self.filtered(lambda pick: pick.picking_type_id.code == 'outgoing'):
|
|
||||||
backorder = picking.search([('backorder_id', '=', picking.id)])
|
|
||||||
if backorder.sale_id:
|
|
||||||
backorder.message_post_with_view(
|
|
||||||
'mail.message_origin_link',
|
|
||||||
values={'self': backorder, 'origin': backorder.sale_id},
|
|
||||||
subtype_id=self.env.ref('mail.mt_note').id)
|
|
||||||
return res
|
|
||||||
|
@ -52,7 +52,7 @@ class TestSaleStock(TestSale):
|
|||||||
pick_2 = self.so.picking_ids[0]
|
pick_2 = self.so.picking_ids[0]
|
||||||
pick_2.force_assign()
|
pick_2.force_assign()
|
||||||
pick_2.move_lines.write({'quantity_done': 1})
|
pick_2.move_lines.write({'quantity_done': 1})
|
||||||
self.assertIsNone(pick_2.button_validate(), 'Sale Stock: second picking should be final without need for a backorder')
|
self.assertTrue(pick_2.button_validate(), 'Sale Stock: second picking should be final without need for a backorder')
|
||||||
self.assertEqual(self.so.invoice_status, 'to invoice', 'Sale Stock: so invoice_status should be "to invoice" after complete delivery')
|
self.assertEqual(self.so.invoice_status, 'to invoice', 'Sale Stock: so invoice_status should be "to invoice" after complete delivery')
|
||||||
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
||||||
del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line]
|
del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line]
|
||||||
@ -104,7 +104,7 @@ class TestSaleStock(TestSale):
|
|||||||
pick = self.so.picking_ids
|
pick = self.so.picking_ids
|
||||||
pick.force_assign()
|
pick.force_assign()
|
||||||
pick.move_lines.write({'quantity_done': 2})
|
pick.move_lines.write({'quantity_done': 2})
|
||||||
self.assertIsNone(pick.button_validate(), 'Sale Stock: complete delivery should not need a backorder')
|
self.assertTrue(pick.button_validate(), 'Sale Stock: complete delivery should not need a backorder')
|
||||||
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
||||||
del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line]
|
del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line]
|
||||||
self.assertEqual(del_qties, del_qties_truth, 'Sale Stock: delivered quantities are wrong after partial delivery')
|
self.assertEqual(del_qties, del_qties_truth, 'Sale Stock: delivered quantities are wrong after partial delivery')
|
||||||
|
Loading…
Reference in New Issue
Block a user