@ -301,11 +301,19 @@ async def get_master_by_assetnum(
None ,
)
# Historical data query
# Historical data query - filter to only one reference (prioritize oldest acquisition year)
oldest_ref_subquery = (
Select ( EquipmentHistoricalTransactionRecords . acquisition_year_ref )
. filter ( EquipmentHistoricalTransactionRecords . assetnum == assetnum )
. order_by ( EquipmentHistoricalTransactionRecords . acquisition_year_ref . asc ( ) )
. limit ( 1 )
. scalar_subquery ( )
)
historical_query = (
Select ( EquipmentHistoricalTransactionRecords )
. join ( EquipmentHistoricalTransactionRecords . equipment )
. filter ( Equipment . assetnum == assetnum )
. filter( EquipmentHistoricalTransactionRecords . assetnum == assetnum )
. filter ( Equipment HistoricalTransactionRecords. acquisition_year_ref == oldest_ref_subquery )
. order_by ( EquipmentHistoricalTransactionRecords . tahun . asc ( ) )
)
historical_result = await db_session . execute ( historical_query )
@ -672,7 +680,7 @@ async def check_and_update_acquisition_data(db_session: DbSession, assetnum: str
if conn :
try :
cursor = conn . cursor ( )
# Query the first year from wo_maximo
# Query the oldest year from wo_maximo to detect the original acquisition
query = """
select DATE_PART ( ' year ' , a . reportdate ) AS year , a . asset_replacecost AS cost
from wo_maximo a
@ -720,89 +728,96 @@ async def check_and_update_acquisition_data(db_session: DbSession, assetnum: str
change_year = ( eq . acquisition_year != first_year )
change_cost = ( first_cost is not None and eq . acquisition_cost != first_cost )
if change_year or change_cost :
print ( f " Acquisition change detected for { assetnum } : Year { current_acq } -> { first_year } , Cost { current_acq_cost } -> { first_cost } . Archiving history. " )
# We only archive transaction history if the acquisition year itself changed.
# This prevents redundant history entries for cost-only updates.
if change_year :
print ( f " Acquisition year change detected for { assetnum } : { current_acq } -> { first_year } . Archiving history. " )
acq_year_ref = f " { current_acq } _ { current_target } "
# --- ARCHIVE HISTORICAL DATA ---
# 1. Copy old equipment master data to history
history_ms_query = text ( """
INSERT INTO lcc_ms_equipment_historical_data (
id , assetnum , acquisition_year , acquisition_cost , capital_cost_record_time , design_life ,
forecasting_start_year , forecasting_target_year , manhours_rate , created_at , created_by ,
updated_at , updated_by , min_eac_info , harga_saat_ini , minimum_eac_seq , minimum_eac_year ,
minimum_eac , minimum_npv , minimum_pmt , minimum_pmt_aq_cost , minimum_is_actual ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours , category_no , proportion ,
acquisition_year_ref
)
SELECT
uuid_generate_v4 ( ) , assetnum , acquisition_year , acquisition_cost , capital_cost_record_time , design_life ,
forecasting_start_year , forecasting_target_year , manhours_rate , created_at , created_by ,
updated_at , updated_by , min_eac_info , harga_saat_ini , minimum_eac_seq , minimum_eac_year ,
minimum_eac , minimum_npv , minimum_pmt , minimum_pmt_aq_cost , minimum_is_actual ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours , category_no , proportion ,
: acq_year_ref
FROM lcc_ms_equipment_data
WHERE assetnum = : assetnum
""" )
await db_session . execute ( history_ms_query , { " acq_year_ref " : acq_year_ref , " assetnum " : assetnum } )
# 2. Copy old transaction data to lcc_equipment_historical_tr_data
# Format: {acquisition_year}_{forecasting_target_year}
# Check for existing identical archive to prevent duplicates (after calculation failures/retries)
check_hist_query = text ( " SELECT 1 FROM lcc_ms_equipment_historical_data WHERE assetnum = :assetnum AND acquisition_year_ref = :acq_year_ref LIMIT 1 " )
hist_exists = ( await db_session . execute ( check_hist_query , { " assetnum " : assetnum , " acq_year_ref " : acq_year_ref } ) ) . fetchone ( )
history_tr_query = text ( """
INSERT INTO lcc_equipment_historical_tr_data (
id , assetnum , tahun , seq , is_actual ,
raw_cm_interval , raw_cm_material_cost , raw_cm_labor_time , raw_cm_labor_human ,
raw_pm_interval , raw_pm_material_cost , raw_pm_labor_time , raw_pm_labor_human ,
raw_oh_interval , raw_oh_material_cost , raw_oh_labor_time , raw_oh_labor_human ,
raw_predictive_interval , raw_predictive_material_cost , raw_predictive_labor_time , raw_predictive_labor_human ,
raw_project_task_material_cost , " raw_loss_output_MW " , raw_loss_output_price ,
raw_operational_cost , raw_maintenance_cost ,
rc_cm_material_cost , rc_cm_labor_cost ,
rc_pm_material_cost , rc_pm_labor_cost ,
rc_oh_material_cost , rc_oh_labor_cost ,
rc_predictive_labor_cost ,
rc_project_material_cost , rc_lost_cost , rc_operation_cost , rc_maintenance_cost ,
rc_total_cost ,
eac_npv , eac_annual_mnt_cost , eac_annual_acq_cost , eac_disposal_cost , eac_eac ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours ,
created_by , created_at , acquisition_year_ref
)
SELECT
uuid_generate_v4 ( ) , assetnum , tahun , seq , is_actual ,
raw_cm_interval , raw_cm_material_cost , raw_cm_labor_time , raw_cm_labor_human ,
raw_pm_interval , raw_pm_material_cost , raw_pm_labor_time , raw_pm_labor_human ,
raw_oh_interval , raw_oh_material_cost , raw_oh_labor_time , raw_oh_labor_human ,
raw_predictive_interval , raw_predictive_material_cost , raw_predictive_labor_time , raw_predictive_labor_human ,
raw_project_task_material_cost , " raw_loss_output_MW " , raw_loss_output_price ,
raw_operational_cost , raw_maintenance_cost ,
rc_cm_material_cost , rc_cm_labor_cost ,
rc_pm_material_cost , rc_pm_labor_cost ,
rc_oh_material_cost , rc_oh_labor_cost ,
rc_predictive_labor_cost ,
rc_project_material_cost , rc_lost_cost , rc_operation_cost , rc_maintenance_cost ,
rc_total_cost ,
eac_npv , eac_annual_mnt_cost , eac_annual_acq_cost , eac_disposal_cost , eac_eac ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours ,
created_by , NOW ( ) , : acq_year_ref
FROM lcc_equipment_tr_data
WHERE assetnum = : assetnum
""" )
await db_session . execute ( history_tr_query , { " acq_year_ref " : acq_year_ref , " assetnum " : assetnum } )
if not hist_exists :
# 1. Copy old equipment master data to history
history_ms_query = text ( """
INSERT INTO lcc_ms_equipment_historical_data (
id , assetnum , acquisition_year , acquisition_cost , capital_cost_record_time , design_life ,
forecasting_start_year , forecasting_target_year , manhours_rate , created_at , created_by ,
updated_at , updated_by , min_eac_info , harga_saat_ini , minimum_eac_seq , minimum_eac_year ,
minimum_eac , minimum_npv , minimum_pmt , minimum_pmt_aq_cost , minimum_is_actual ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours , category_no , proportion ,
acquisition_year_ref
)
SELECT
uuid_generate_v4 ( ) , assetnum , acquisition_year , acquisition_cost , capital_cost_record_time , design_life ,
forecasting_start_year , forecasting_target_year , manhours_rate , created_at , created_by ,
updated_at , updated_by , min_eac_info , harga_saat_ini , minimum_eac_seq , minimum_eac_year ,
minimum_eac , minimum_npv , minimum_pmt , minimum_pmt_aq_cost , minimum_is_actual ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours , category_no , proportion ,
: acq_year_ref
FROM lcc_ms_equipment_data
WHERE assetnum = : assetnum
""" )
await db_session . execute ( history_ms_query , { " acq_year_ref " : acq_year_ref , " assetnum " : assetnum } )
# 2. Copy old transaction data to lcc_equipment_historical_tr_data
history_tr_query = text ( """
INSERT INTO lcc_equipment_historical_tr_data (
id , assetnum , tahun , seq , is_actual ,
raw_cm_interval , raw_cm_material_cost , raw_cm_labor_time , raw_cm_labor_human ,
raw_pm_interval , raw_pm_material_cost , raw_pm_labor_time , raw_pm_labor_human ,
raw_oh_interval , raw_oh_material_cost , raw_oh_labor_time , raw_oh_labor_human ,
raw_predictive_interval , raw_predictive_material_cost , raw_predictive_labor_time , raw_predictive_labor_human ,
raw_project_task_material_cost , " raw_loss_output_MW " , raw_loss_output_price ,
raw_operational_cost , raw_maintenance_cost ,
rc_cm_material_cost , rc_cm_labor_cost ,
rc_pm_material_cost , rc_pm_labor_cost ,
rc_oh_material_cost , rc_oh_labor_cost ,
rc_predictive_labor_cost ,
rc_project_material_cost , rc_lost_cost , rc_operation_cost , rc_maintenance_cost ,
rc_total_cost ,
eac_npv , eac_annual_mnt_cost , eac_annual_acq_cost , eac_disposal_cost , eac_eac ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours ,
created_by , created_at , acquisition_year_ref
)
SELECT
uuid_generate_v4 ( ) , assetnum , tahun , seq , is_actual ,
raw_cm_interval , raw_cm_material_cost , raw_cm_labor_time , raw_cm_labor_human ,
raw_pm_interval , raw_pm_material_cost , raw_pm_labor_time , raw_pm_labor_human ,
raw_oh_interval , raw_oh_material_cost , raw_oh_labor_time , raw_oh_labor_human ,
raw_predictive_interval , raw_predictive_material_cost , raw_predictive_labor_time , raw_predictive_labor_human ,
raw_project_task_material_cost , " raw_loss_output_MW " , raw_loss_output_price ,
raw_operational_cost , raw_maintenance_cost ,
rc_cm_material_cost , rc_cm_labor_cost ,
rc_pm_material_cost , rc_pm_labor_cost ,
rc_oh_material_cost , rc_oh_labor_cost ,
rc_predictive_labor_cost ,
rc_project_material_cost , rc_lost_cost , rc_operation_cost , rc_maintenance_cost ,
rc_total_cost ,
eac_npv , eac_annual_mnt_cost , eac_annual_acq_cost , eac_disposal_cost , eac_eac ,
efdh_equivalent_forced_derated_hours , foh_forced_outage_hours ,
created_by , NOW ( ) , : acq_year_ref
FROM lcc_equipment_tr_data
WHERE assetnum = : assetnum
""" )
await db_session . execute ( history_tr_query , { " acq_year_ref " : acq_year_ref , " assetnum " : assetnum } )
# 3. Delete old data
del_query = text ( " DELETE FROM lcc_equipment_tr_data WHERE assetnum = :assetnum " )
await db_session . execute ( del_query , { " assetnum " : assetnum } )
# Update Equipment Master
# Update Equipment Master regardless of if archive was needed/skipped
if change_year or change_cost :
if first_cost is not None and eq . acquisition_cost != first_cost :
eq . acquisition_cost = first_cost
if eq . acquisition_year != first_year :
eq . acquisition_year = first_year
eq . forecasting_start_year = first_year # Align start with acquisition
if is_valid_default and current_life :
eq . forecasting_target_year = first_year + current_life