diff --git a/models/__pycache__/account_move_line.cpython-312.pyc b/models/__pycache__/account_move_line.cpython-312.pyc index d044f39..81c9cf5 100644 Binary files a/models/__pycache__/account_move_line.cpython-312.pyc and b/models/__pycache__/account_move_line.cpython-312.pyc differ diff --git a/models/account_move_line.py b/models/account_move_line.py index 55ef4f9..f3789b1 100755 --- a/models/account_move_line.py +++ b/models/account_move_line.py @@ -3,6 +3,8 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError +from odoo.tools import float_compare +from datetime import timedelta class AccountMoveLine(models.Model): @@ -157,6 +159,111 @@ class AccountMoveLine(models.Model): if was_locked: po.button_done() + + # --------------------------------------------------------- + # INVENTORY VALUATION UPDATE (AVCO/FIFO FIX) + # --------------------------------------------------------- + # If PO is received, updating price should update Stock Value + if po_line.state in ['purchase', 'done'] and po_line.product_id.type == 'product': + for stock_move in po_line.move_ids.filtered(lambda m: m.state == 'done'): + # Calculate Diff based on NEW Price (updated above) + new_val = price_unit * stock_move.quantity + # Current Value from SVLs + current_val = sum(stock_move.stock_valuation_layer_ids.mapped('value')) + diff = new_val - current_val + + currency = stock_move.company_id.currency_id + if not currency.is_zero(diff): + # 1. Create Correction SVL + svl_vals = { + 'company_id': stock_move.company_id.id, + 'product_id': stock_move.product_id.id, + 'description': _("Valuation correction from Vendor Bill %s") % line.move_id.name, + 'value': diff, + 'quantity': 0, + 'stock_move_id': stock_move.id, + } + svl = self.env['stock.valuation.layer'].create(svl_vals) + + # Backdate SVL + if stock_move.date: + new_date = stock_move.date + timedelta(seconds=1) + self.env.cr.execute("UPDATE stock_valuation_layer SET create_date = %s WHERE id = %s", (new_date, svl.id)) + + # 2. AVCO/FIFO Logic: Update Standard Price and Distribute Value + product = stock_move.product_id + if product.categ_id.property_cost_method in ['average', 'fifo'] and product.quantity_svl > 0: + new_std_price = product.standard_price + (diff / product.quantity_svl) + product.with_context(disable_auto_svl=True).sudo().write({'standard_price': new_std_price}) + + remaining_svls = self.env['stock.valuation.layer'].search([ + ('product_id', '=', product.id), + ('remaining_qty', '>', 0), + ('company_id', '=', stock_move.company_id.id), + ]) + + if remaining_svls: + remaining_qty_total = sum(remaining_svls.mapped('remaining_qty')) + if remaining_qty_total > 0: + remaining_value_to_distribute = diff + remaining_value_unit_cost = remaining_value_to_distribute / remaining_qty_total + + for layer in remaining_svls: + if float_compare(layer.remaining_qty, remaining_qty_total, precision_rounding=product.uom_id.rounding) >= 0: + taken_remaining_value = remaining_value_to_distribute + else: + taken_remaining_value = remaining_value_unit_cost * layer.remaining_qty + + taken_remaining_value = stock_move.company_id.currency_id.round(taken_remaining_value) + layer.sudo().write({'remaining_value': layer.remaining_value + taken_remaining_value}) + + remaining_value_to_distribute -= taken_remaining_value + remaining_qty_total -= layer.remaining_qty + + # 3. Create Accounting Entry + if stock_move.product_id.categ_id.property_valuation == 'real_time': + accounts = stock_move.product_id.product_tmpl_id.get_product_accounts() + acc_expense = accounts.get('expense') + acc_valuation = accounts.get('stock_valuation') + + if acc_expense and acc_valuation: + if diff > 0: + debit_acc = acc_valuation.id + credit_acc = acc_expense.id + amount = diff + else: + debit_acc = acc_expense.id + credit_acc = acc_valuation.id + amount = abs(diff) + + acc_date = stock_move.date.date() if stock_move.date else fields.Date.today() + + move_vals = { + 'journal_id': accounts['stock_journal'].id, + 'company_id': stock_move.company_id.id, + 'ref': _("Revaluation for %s from Bill Edit") % stock_move.product_id.name, + 'date': acc_date, + 'move_type': 'entry', + 'stock_valuation_layer_ids': [(6, 0, [svl.id])], + 'line_ids': [ + (0, 0, { + 'name': _("Valuation Correction - %s") % stock_move.product_id.name, + 'account_id': debit_acc, + 'debit': amount, + 'credit': 0, + 'product_id': stock_move.product_id.id, + }), + (0, 0, { + 'name': _("Valuation Correction - %s") % stock_move.product_id.name, + 'account_id': credit_acc, + 'debit': 0, + 'credit': amount, + 'product_id': stock_move.product_id.id, + }) + ] + } + am = self.env['account.move'].create(move_vals) + am._post() return res