|
|
|
@ -534,6 +534,7 @@ class SparepartManager:
|
|
|
|
sparepart_id = requirement.sparepart_id
|
|
|
|
sparepart_id = requirement.sparepart_id
|
|
|
|
needed_quantity = requirement.quantity_required
|
|
|
|
needed_quantity = requirement.quantity_required
|
|
|
|
sparepart_name = requirement.sparepart_name
|
|
|
|
sparepart_name = requirement.sparepart_name
|
|
|
|
|
|
|
|
sparepart_remark= requirement.remark
|
|
|
|
unit_cost = requirement.avg_cost if requirement.avg_cost > 0 else requirement.unit_cost
|
|
|
|
unit_cost = requirement.avg_cost if requirement.avg_cost > 0 else requirement.unit_cost
|
|
|
|
|
|
|
|
|
|
|
|
current_stock = adjusted_stocks.get(sparepart_id, 0)
|
|
|
|
current_stock = adjusted_stocks.get(sparepart_id, 0)
|
|
|
|
@ -562,7 +563,8 @@ class SparepartManager:
|
|
|
|
'status': order.status.value,
|
|
|
|
'status': order.status.value,
|
|
|
|
'months_until_delivery': self._calculate_months_until_delivery(order.expected_delivery_date, target_month),
|
|
|
|
'months_until_delivery': self._calculate_months_until_delivery(order.expected_delivery_date, target_month),
|
|
|
|
'is_on_time': self._is_delivery_on_time(order.expected_delivery_date, target_month),
|
|
|
|
'is_on_time': self._is_delivery_on_time(order.expected_delivery_date, target_month),
|
|
|
|
'usage': 'covers_requirement'
|
|
|
|
'usage': 'covers_requirement',
|
|
|
|
|
|
|
|
'remark': sparepart_remark
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pr_po_summary['existing_orders'].append(order_info)
|
|
|
|
pr_po_summary['existing_orders'].append(order_info)
|
|
|
|
pr_po_summary['total_existing_value'] += order.total_cost
|
|
|
|
pr_po_summary['total_existing_value'] += order.total_cost
|
|
|
|
@ -574,6 +576,7 @@ class SparepartManager:
|
|
|
|
missing_parts.append({
|
|
|
|
missing_parts.append({
|
|
|
|
'sparepart_id': sparepart_id,
|
|
|
|
'sparepart_id': sparepart_id,
|
|
|
|
'sparepart_name': sparepart_name,
|
|
|
|
'sparepart_name': sparepart_name,
|
|
|
|
|
|
|
|
'remark': sparepart_remark,
|
|
|
|
'required': needed_quantity,
|
|
|
|
'required': needed_quantity,
|
|
|
|
'current_stock': current_stock,
|
|
|
|
'current_stock': current_stock,
|
|
|
|
'ordered_quantity': total_ordered_quantity,
|
|
|
|
'ordered_quantity': total_ordered_quantity,
|
|
|
|
@ -605,6 +608,7 @@ class SparepartManager:
|
|
|
|
new_order = {
|
|
|
|
new_order = {
|
|
|
|
'sparepart_id': sparepart_id,
|
|
|
|
'sparepart_id': sparepart_id,
|
|
|
|
'sparepart_name': sparepart_name,
|
|
|
|
'sparepart_name': sparepart_name,
|
|
|
|
|
|
|
|
'remark': sparepart_remark,
|
|
|
|
'quantity_needed': shortage,
|
|
|
|
'quantity_needed': shortage,
|
|
|
|
'unit_cost': unit_cost,
|
|
|
|
'unit_cost': unit_cost,
|
|
|
|
'total_cost': procurement_cost,
|
|
|
|
'total_cost': procurement_cost,
|
|
|
|
@ -911,7 +915,7 @@ class SparepartManager:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Integration functions for database operations
|
|
|
|
# Integration functions for database operations
|
|
|
|
async def load_sparepart_data_from_db(scope, prev_oh_scope, db_session, analysis_window_months = None) -> SparepartManager:
|
|
|
|
async def load_sparepart_data_from_db(scope, prev_oh_scope, db_session, app_db_session, analysis_window_months = None) -> SparepartManager:
|
|
|
|
"""Load sparepart data from database"""
|
|
|
|
"""Load sparepart data from database"""
|
|
|
|
# You'll need to implement these queries based on your database schema
|
|
|
|
# You'll need to implement these queries based on your database schema
|
|
|
|
# Get scope dates for analysis window
|
|
|
|
# Get scope dates for analysis window
|
|
|
|
@ -934,7 +938,7 @@ async def load_sparepart_data_from_db(scope, prev_oh_scope, db_session, analysis
|
|
|
|
MAX(wm.inv_curbaltotal) AS curbaltotal,
|
|
|
|
MAX(wm.inv_curbaltotal) AS curbaltotal,
|
|
|
|
AVG(wm.inv_avgcost) AS avgcost,
|
|
|
|
AVG(wm.inv_avgcost) AS avgcost,
|
|
|
|
COALESCE(mspl.description, 'No description available') AS description
|
|
|
|
COALESCE(mspl.description, 'No description available') AS description
|
|
|
|
FROM public.wo_maxim_material wm
|
|
|
|
FROM public.wo_maximo_material wm
|
|
|
|
LEFT JOIN public.maximo_sparepart_pr_po_line mspl
|
|
|
|
LEFT JOIN public.maximo_sparepart_pr_po_line mspl
|
|
|
|
ON wm.inv_itemnum = mspl.item_num
|
|
|
|
ON wm.inv_itemnum = mspl.item_num
|
|
|
|
WHERE wm.inv_itemnum IS NOT NULL
|
|
|
|
WHERE wm.inv_itemnum IS NOT NULL
|
|
|
|
@ -943,9 +947,16 @@ async def load_sparepart_data_from_db(scope, prev_oh_scope, db_session, analysis
|
|
|
|
log.info("Fetch sparepart")
|
|
|
|
log.info("Fetch sparepart")
|
|
|
|
sparepart_stocks_query = await db_session.execute(query)
|
|
|
|
sparepart_stocks_query = await db_session.execute(query)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sparepart_remark = (await app_db_session.execute(
|
|
|
|
|
|
|
|
select(SparepartRemark)
|
|
|
|
|
|
|
|
)).scalars().all()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sparepart_remark_dict = {item.itemnum: item.remark for item in sparepart_remark}
|
|
|
|
|
|
|
|
|
|
|
|
for stock_record in sparepart_stocks_query:
|
|
|
|
for stock_record in sparepart_stocks_query:
|
|
|
|
stock = SparepartStock(
|
|
|
|
stock = SparepartStock(
|
|
|
|
sparepart_id=stock_record.itemnum,
|
|
|
|
sparepart_id=stock_record.itemnum,
|
|
|
|
|
|
|
|
remark=sparepart_remark.get(stock_record.itemnum),
|
|
|
|
sparepart_name=stock_record.description,
|
|
|
|
sparepart_name=stock_record.description,
|
|
|
|
current_stock=stock_record.curbaltotal,
|
|
|
|
current_stock=stock_record.curbaltotal,
|
|
|
|
unit_cost=stock_record.avgcost,
|
|
|
|
unit_cost=stock_record.avgcost,
|
|
|
|
@ -1110,13 +1121,18 @@ async def load_sparepart_data_from_db(scope, prev_oh_scope, db_session, analysis
|
|
|
|
# Load equipment sparepart requirements
|
|
|
|
# Load equipment sparepart requirements
|
|
|
|
# You'll need to create this table/relationship
|
|
|
|
# You'll need to create this table/relationship
|
|
|
|
query = text("""WITH oh_workorders AS (
|
|
|
|
query = text("""WITH oh_workorders AS (
|
|
|
|
-- First, get all OH work orders
|
|
|
|
-- First, get all OH work orders
|
|
|
|
SELECT DISTINCT
|
|
|
|
SELECT DISTINCT
|
|
|
|
wonum,
|
|
|
|
wonum,
|
|
|
|
asset_location
|
|
|
|
asset_location
|
|
|
|
FROM public.wo_staging_maximo_2
|
|
|
|
FROM public.wo_maximo ma
|
|
|
|
WHERE worktype = 'OH' AND asset_location IS NOT NULL and asset_unit IN ('3', '00') AND EXTRACT(YEAR FROM reportdate) >= 2019
|
|
|
|
WHERE worktype = 'OH' AND asset_location IS NOT NULL and asset_unit IN ('3', '00') AND EXTRACT(YEAR FROM reportdate) >= 2019
|
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
current_oh as (
|
|
|
|
|
|
|
|
SELECT DISTINCT wonum, asset_location, asset_unit
|
|
|
|
|
|
|
|
FROM public.wo_maximo ma
|
|
|
|
|
|
|
|
WHERE ma.xx_parent IN ('155026', '155027', '155029', '155030')
|
|
|
|
|
|
|
|
),
|
|
|
|
sparepart_usage AS (
|
|
|
|
sparepart_usage AS (
|
|
|
|
SELECT
|
|
|
|
SELECT
|
|
|
|
oh.asset_location,
|
|
|
|
oh.asset_location,
|
|
|
|
@ -1124,8 +1140,8 @@ async def load_sparepart_data_from_db(scope, prev_oh_scope, db_session, analysis
|
|
|
|
mwm.itemqty,
|
|
|
|
mwm.itemqty,
|
|
|
|
mwm.wonum,
|
|
|
|
mwm.wonum,
|
|
|
|
mwm.inv_avgcost
|
|
|
|
mwm.inv_avgcost
|
|
|
|
FROM oh_workorders oh
|
|
|
|
FROM current_oh oh
|
|
|
|
INNER JOIN public.wo_maxim_material mwm
|
|
|
|
INNER JOIN public.wo_maximo_material mwm
|
|
|
|
ON oh.wonum = mwm.wonum
|
|
|
|
ON oh.wonum = mwm.wonum
|
|
|
|
),
|
|
|
|
),
|
|
|
|
location_sparepart_stats AS (
|
|
|
|
location_sparepart_stats AS (
|
|
|
|
@ -1262,7 +1278,8 @@ ORDER BY lss.asset_location, lss.itemnum;""")
|
|
|
|
lead_time=float(req_record.avg_leadtime_months),
|
|
|
|
lead_time=float(req_record.avg_leadtime_months),
|
|
|
|
sparepart_name=req_record.item_description,
|
|
|
|
sparepart_name=req_record.item_description,
|
|
|
|
unit_cost=float(req_record.avg_unit_cost),
|
|
|
|
unit_cost=float(req_record.avg_unit_cost),
|
|
|
|
avg_cost=float(req_record.avgcost or 0)
|
|
|
|
avg_cost=float(req_record.avgcost or 0),
|
|
|
|
|
|
|
|
remark=sparepart_remark.get(req_record.itemnum, "")
|
|
|
|
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
equipment_requirements[req_record.asset_location].append(requirement)
|
|
|
|
equipment_requirements[req_record.asset_location].append(requirement)
|
|
|
|
@ -1306,12 +1323,12 @@ po_with_pr_date AS (
|
|
|
|
ON pr.num = po.po_number
|
|
|
|
ON pr.num = po.po_number
|
|
|
|
AND pr.type = 'PR'
|
|
|
|
AND pr.type = 'PR'
|
|
|
|
),
|
|
|
|
),
|
|
|
|
WITH item_inventory AS (
|
|
|
|
item_inventory AS (
|
|
|
|
SELECT
|
|
|
|
SELECT
|
|
|
|
itemnum,
|
|
|
|
itemnum,
|
|
|
|
MAX(inv_curbaltotal) AS current_balance_total,
|
|
|
|
MAX(inv_curbaltotal) AS current_balance_total,
|
|
|
|
AVG(inv_avgcost) AS avg_cost
|
|
|
|
AVG(inv_avgcost) AS avg_cost
|
|
|
|
FROM public.wo_maxim_material
|
|
|
|
FROM public.wo_maximo_material
|
|
|
|
WHERE inv_itemnum IS NOT NULL
|
|
|
|
WHERE inv_itemnum IS NOT NULL
|
|
|
|
GROUP BY itemnum
|
|
|
|
GROUP BY itemnum
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|