115 lines
5.7 KiB
Python
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
|