ga_asset_management/models/stock_picking.py
2026-02-04 11:37:09 +07:00

115 lines
5.7 KiB
Python

from odoo import models, fields, api, _
from odoo.exceptions import UserError
import datetime
class StockPicking(models.Model):
_inherit = 'stock.picking'
def action_generate_asset_codes(self):
self.ensure_one()
for move in self.move_ids_without_package:
# Only generate if product creates asset (optional check, but good practice)
# However, user wants to manually decide, so we generate for all lines that look like assets?
# Let's assume user triggers this button for asset receipts.
# We can check if product has an asset model set in accounting?
# Or just blindly generate if missing?
# Re-using logic from account.asset.create:
if not move.asset_code and move.product_id:
sequence = self.env['ir.sequence'].next_by_code('ga.asset.code') or '00000'
year = datetime.datetime.now().year
# Logic from AccountAsset create: [Barcode or AST]/[Year]/[Sequence]
prefix = move.product_id.barcode or 'AST'
# Note: Sequence next_by_code returns '/0000X' as configured in XML
move.asset_code = f"{prefix}/{year}{sequence}"
has_asset_moves = fields.Boolean(compute='_compute_has_asset_moves', store=True)
@api.depends('move_ids.product_id', 'picking_type_code')
def _compute_has_asset_moves(self):
for pick in self:
has_asset = False
if pick.picking_type_code == 'incoming':
for move in pick.move_ids_without_package:
# Check if product is configured to create assets
# Logic: Check Product's Expense Account or Category's Expense Account
account = move.product_id.property_account_expense_id or move.product_id.categ_id.property_account_expense_categ_id
if account and account.create_asset != 'no':
has_asset = True
break
pick.has_asset_moves = has_asset
def button_validate(self):
# Validation Check
for pick in self:
if pick.has_asset_moves:
for move in pick.move_ids_without_package:
account = move.product_id.property_account_expense_id or move.product_id.categ_id.property_account_expense_categ_id
if account and account.create_asset != 'no' and not move.asset_code:
raise UserError(_(
"Asset Code is missing for product '%s'. \n"
"Please click 'Generate Asset Codes' before validating.",
move.product_id.name
))
return super(StockPicking, self).button_validate()
def _action_done(self):
res = super(StockPicking, self)._action_done()
# After validation, create assets for moves with asset_code
for pick in self:
for move in pick.move_ids_without_package:
if move.asset_code and not move.asset_id:
# Get Account to check configuration
account = move.product_id.property_account_expense_id or move.product_id.categ_id.property_account_expense_categ_id
# Prepare basic values
vals_base = {
'name': move.product_id.name,
'product_id': move.product_id.id,
'acquisition_date': fields.Date.today(),
'company_id': move.company_id.id,
'state': 'draft',
}
# Add Model if configured on Account
if account and account.asset_model:
vals_base['model_id'] = account.asset_model.id
qty = int(move.quantity)
# CASE 1: Multiple Assets per Line
if account and account.multiple_assets_per_line and qty > 1:
# 1st Asset uses the pre-generated code
vals = vals_base.copy()
vals['asset_code'] = move.asset_code
vals['original_value'] = move.price_unit # Per unit value
asset = self.env['account.asset'].create(vals)
move.asset_id = asset.id # Link first one to move
# Create remaining assets
for i in range(qty - 1):
vals_extra = vals_base.copy()
vals_extra['original_value'] = move.price_unit
# Generate new code for extra assets
sequence = self.env['ir.sequence'].next_by_code('ga.asset.code') or '00000'
year = datetime.datetime.now().year
prefix = move.product_id.barcode or 'AST'
vals_extra['asset_code'] = f"{prefix}/{year}{sequence}"
self.env['account.asset'].create(vals_extra)
# CASE 2: Single Assset (default)
else:
vals = vals_base.copy()
vals['asset_code'] = move.asset_code
vals['original_value'] = move.price_unit * move.quantity # Total Value
asset = self.env['account.asset'].create(vals)
move.asset_id = asset.id
return res