You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

100 lines
5.5 KiB

# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Ammu Raj (odoo@cybrosys.com)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
################################################################################
from odoo import models
class StockMoveLine(models.Model):
""" Class to inherit the model stock.move.line to override the create
function """
_inherit = 'stock.move.line'
def write(self, vals):
""" When editing a done stock.move.line, we impact the valuation.
Users may increase or decrease the `qty_done` field. There are three
cost method available: standard, average and fifo. We implement the
logic in a similar way for standard and average: increase or decrease
the original value with the standard or average price of today. In
fifo, we have a different logic whether the move is incoming or
outgoing. If the move is incoming, we update the value and
remaining_value/qty with the unit price of the move. If the move is
outgoing and the user increases qty_done, we call _run_fifo, and it'll
consume layer(s) in the stack the same way a new outgoing move would
have done. If the move is outgoing and the user decreases qty_done, we
either increase the last receipt candidate if one is found or we
decrease the value with the last fifo price.
"""
if 'qty_done' in vals:
moves_to_update = {}
for move_line in self.filtered(
lambda ml: ml.state == 'done' and (
ml.move_id._is_in() or ml.move_id._is_out())):
moves_to_update[move_line.move_id] = (
vals['qty_done'] - move_line.qty_done)
for move_id, qty_difference in moves_to_update.items():
move_vals = {}
if move_id.product_id.cost_method in ['standard', 'average',
'last']:
correction_value = (qty_difference *
move_id.product_id.standard_price)
if move_id._is_in():
move_vals['value'] = move_id.value + correction_value
elif move_id._is_out():
move_vals['value'] = move_id.value - correction_value
else:
if move_id._is_in():
correction_value = qty_difference * move_id.price_unit
move_vals['value'] = move_id.value + correction_value
move_vals['remaining_qty'] = (move_id.remaining_qty +
qty_difference)
move_vals['remaining_value'] = (move_id.remaining_value
+ correction_value)
elif move_id._is_out() and qty_difference > 0:
correction_value = self.env['stock.move']._run_fifo(
move_id, quantity=qty_difference)
# No need to adapt `remaining_qty` and
# `remaining_value` as `_run_fifo` took care of it
move_vals['value'] = move_id.value - correction_value
elif move_id._is_out() and qty_difference < 0:
candidates_receipt = self.env['stock.move'].search(
move_id._get_in_domain(), order='date, id desc',
limit=1)
if candidates_receipt:
candidates_receipt.write({
'remaining_qty': candidates_receipt.remaining_qty + -qty_difference,
'remaining_value': candidates_receipt.remaining_value + (
-qty_difference * candidates_receipt.price_unit),
})
correction_value = (qty_difference *
candidates_receipt.price_unit)
else:
correction_value = (qty_difference *
move_id.product_id.standard_price)
move_vals['value'] = move_id.value - correction_value
move_id.write(move_vals)
if move_id.product_id.valuation == 'real_time':
move_id.with_context(
force_valuation_amount=correction_value,
forced_quantity=qty_difference)._account_entry_move()
if qty_difference > 0:
move_id.product_price_update_before_done(
forced_qty=qty_difference)
return super().write(vals)