diff --git a/frontend/src/hold-detail/App.vue b/frontend/src/hold-detail/App.vue
index 5e7d920..84e5239 100644
--- a/frontend/src/hold-detail/App.vue
+++ b/frontend/src/hold-detail/App.vue
@@ -36,7 +36,9 @@ const refreshing = ref(false);
const lotsLoading = ref(false);
const lotsError = ref('');
const loadError = ref('');
-const lastUpdate = ref('');
+const lastUpdate = computed(() => {
+ return summary.value?.dataUpdateDate ? `Last Update: ${summary.value.dataUpdateDate}` : '';
+});
function unwrapApiResult(result, fallbackMessage) {
if (result?.success) {
@@ -216,7 +218,6 @@ async function loadAllData(showOverlay = true) {
totalPages: Number(lotsData?.pagination?.totalPages || 1),
};
- lastUpdate.value = `Last Update: ${new Date().toLocaleString('zh-TW')}`;
} catch (error) {
if (error?.name === 'AbortError') {
return;
diff --git a/frontend/src/resource-status/components/FloatingTooltip.vue b/frontend/src/resource-status/components/FloatingTooltip.vue
index f3fbea8..9902ed4 100644
--- a/frontend/src/resource-status/components/FloatingTooltip.vue
+++ b/frontend/src/resource-status/components/FloatingTooltip.vue
@@ -275,10 +275,18 @@ onBeforeUnmount(() => {
Wafer P/N
{{ lotDetailValue(getLotDetail(lot.RUNCARDLOTID), 'waferPn') }}
+
+ Wafer Description
+ {{ lotDetailValue(getLotDetail(lot.RUNCARDLOTID), 'waferDesc') }}
+
Leadframe
{{ lotDetailValue(getLotDetail(lot.RUNCARDLOTID), 'leadframeName') }}
+
+ LF Description
+ {{ lotDetailValue(getLotDetail(lot.RUNCARDLOTID), 'leadframeDesc') }}
+
Compound
{{ lotDetailValue(getLotDetail(lot.RUNCARDLOTID), 'compoundName') }}
diff --git a/frontend/src/wip-detail/components/LotDetailPanel.vue b/frontend/src/wip-detail/components/LotDetailPanel.vue
index 5e02649..8883d56 100644
--- a/frontend/src/wip-detail/components/LotDetailPanel.vue
+++ b/frontend/src/wip-detail/components/LotDetailPanel.vue
@@ -103,7 +103,7 @@ function hasHoldSection() {
const basicFields = ['lotId', 'workorder', 'wipStatus', 'status', 'qty', 'qty2', 'ageByDays', 'priority'];
const productFields = ['product', 'productLine', 'packageLef', 'pjType', 'pjFunction', 'bop', 'dateCode', 'produceRegion'];
const processFields = ['workcenterGroup', 'workcenter', 'spec', 'specSequence', 'workflow', 'equipment', 'equipmentCount', 'location'];
-const materialFields = ['waferLotId', 'waferPn', 'waferLotPrefix', 'leadframeName', 'leadframeOption', 'compoundName', 'dieConsumption', 'uts'];
+const materialFields = ['waferLotId', 'waferPn', 'waferLotPrefix', 'waferDesc', 'leadframeName', 'leadframeOption', 'leadframeDesc', 'compoundName', 'dieConsumption', 'uts'];
const holdFields = ['holdReason', 'holdCount', 'holdEmp', 'holdDept', 'holdComment', 'releaseTime', 'releaseEmp', 'releaseComment'];
const ncrFields = ['ncrId', 'ncrDate'];
const commentFields = ['comment', 'commentDate', 'commentEmp', 'futureHoldComment'];
diff --git a/src/mes_dashboard/services/wip_service.py b/src/mes_dashboard/services/wip_service.py
index 4d4dbff..c75a84c 100644
--- a/src/mes_dashboard/services/wip_service.py
+++ b/src/mes_dashboard/services/wip_service.py
@@ -3036,6 +3036,8 @@ LOT_DETAIL_FIELD_LABELS = {
'priority': 'Work Order Priority',
'tmttRemaining': 'TMTT Remaining',
'dieConsumption': 'Die Consumption Qty',
+ 'leadframeDesc': 'LF Description',
+ 'waferDesc': 'Wafer Description',
'wipStatus': 'WIP Status',
'dataUpdateDate': 'Data Update Date'
}
@@ -3062,6 +3064,12 @@ def get_lot_detail(lotid: str) -> Optional[Dict[str, Any]]:
return None
row = df.iloc[0]
+ if len(df) > 1:
+ row = row.copy()
+ for col in ('LEADFRAMEDESC', 'WAFERDESC'):
+ if col in df.columns:
+ vals = df[col].dropna().unique()
+ row[col] = ', '.join(str(v) for v in vals) if len(vals) > 0 else None
return _build_lot_detail_response(row)
except (DatabasePoolExhaustedError, DatabaseCircuitOpenError):
raise
@@ -3127,7 +3135,9 @@ def _get_lot_detail_from_oracle(lotid: str) -> Optional[Dict[str, Any]]:
PRIORITYCODENAME,
TMTT_R,
WAFER_FACTOR,
- SYS_DATE
+ SYS_DATE,
+ LEADFRAMEDESC,
+ WAFERDESC
FROM {WIP_VIEW}
WHERE LOTID = :lotid
"""
@@ -3137,6 +3147,12 @@ def _get_lot_detail_from_oracle(lotid: str) -> Optional[Dict[str, Any]]:
return None
row = df.iloc[0]
+ if len(df) > 1:
+ row = row.copy()
+ for col in ('LEADFRAMEDESC', 'WAFERDESC'):
+ if col in df.columns:
+ vals = df[col].dropna().unique()
+ row[col] = ', '.join(str(v) for v in vals) if len(vals) > 0 else None
return _build_lot_detail_response(row)
except (DatabasePoolExhaustedError, DatabaseCircuitOpenError):
raise
@@ -3233,7 +3249,9 @@ def _build_lot_detail_response(row) -> Dict[str, Any]:
'dateCode': _safe_value(safe_get('DATECODE')),
'leadframeName': _safe_value(safe_get('LEADFRAMENAME')),
'leadframeOption': _safe_value(safe_get('LEADFRAMEOPTION')),
+ 'leadframeDesc': _safe_value(safe_get('LEADFRAMEDESC')),
'compoundName': _safe_value(safe_get('COMNAME')),
+ 'waferDesc': _safe_value(safe_get('WAFERDESC')),
'location': _safe_value(safe_get('LOCATIONNAME')),
'ncrId': _safe_value(safe_get('EVENTNAME')),
'ncrDate': format_date('OCCURRENCEDATE'),