fix(query-tool): export button hover visibility, jobs tab hide columns and export with txn history

- Increase CSS specificity for .btn-export to prevent portal-shell override on hover
- Remove RESOURCEID and CONTAINERIDS from jobs tab display columns
- Add lot_jobs_with_txn.sql joining JOB with JOBTXNHISTORY for complete export
- Route lot_jobs export through get_lot_jobs_with_history() for full transaction data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-24 19:10:19 +08:00
parent 7fffa812a3
commit e37902861f
6 changed files with 729 additions and 598 deletions

View File

@@ -24,7 +24,6 @@ ensureMesApiAvailable();
const JOB_COLUMN_PRIORITY = Object.freeze([
'JOBID',
'RESOURCEID',
'RESOURCENAME',
'JOBSTATUS',
'JOBMODELNAME',
@@ -42,7 +41,6 @@ const JOB_COLUMN_PRIORITY = Object.freeze([
'PJ_SYMPTOMCODE2NAME',
'CREATE_EMPNAME',
'COMPLETE_EMPNAME',
'CONTAINERIDS',
'CONTAINERNAMES',
]);

View File

@@ -116,16 +116,17 @@ body {
cursor: not-allowed;
}
.btn-export {
.btn.btn-export {
background: #0f766e;
color: #fff;
}
.btn-export:hover {
.btn.btn-export:hover {
background: #0b5e59;
color: #fff;
}
.btn-export:disabled {
.btn.btn-export:disabled {
opacity: 0.6;
cursor: not-allowed;
}

View File

@@ -27,6 +27,7 @@ from mes_dashboard.services.query_tool_service import (
get_lot_holds,
get_lot_splits,
get_lot_jobs,
get_lot_jobs_with_history,
get_lot_associations_batch,
get_equipment_status_hours,
get_equipment_lots,
@@ -683,7 +684,7 @@ def export_csv():
filename = f'lot_splits_{container_id}.csv'
elif export_type == 'lot_jobs':
result = get_lot_jobs(
result = get_lot_jobs_with_history(
params.get('equipment_id'),
params.get('time_start'),
params.get('time_end')

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
-- LOT Related JOB Records with Transaction History Export
-- Joins JOB with JOBTXNHISTORY for complete CSV export
--
-- Parameters:
-- :equipment_id - Equipment ID (EQUIPMENTID = RESOURCEID)
-- :time_start - Start time of LOT processing
-- :time_end - End time of LOT processing
SELECT
j.RESOURCENAME,
j.JOBID,
j.JOBSTATUS AS JOB_FINAL_STATUS,
j.JOBMODELNAME,
j.JOBORDERNAME,
j.CREATEDATE AS JOB_CREATEDATE,
j.COMPLETEDATE AS JOB_COMPLETEDATE,
j.CAUSECODENAME AS JOB_CAUSECODENAME,
j.REPAIRCODENAME AS JOB_REPAIRCODENAME,
j.SYMPTOMCODENAME AS JOB_SYMPTOMCODENAME,
h.TXNDATE,
h.FROMJOBSTATUS,
h.JOBSTATUS AS TXN_JOBSTATUS,
h.STAGENAME,
h.CAUSECODENAME AS TXN_CAUSECODENAME,
h.REPAIRCODENAME AS TXN_REPAIRCODENAME,
h.SYMPTOMCODENAME AS TXN_SYMPTOMCODENAME,
h.USER_NAME,
h.EMP_NAME,
h.COMMENTS
FROM DWH.DW_MES_JOB j
JOIN DWH.DW_MES_JOBTXNHISTORY h ON j.JOBID = h.JOBID
WHERE j.RESOURCEID = :equipment_id
AND (
(j.CREATEDATE BETWEEN :time_start AND :time_end)
OR (j.COMPLETEDATE BETWEEN :time_start AND :time_end)
OR (j.CREATEDATE <= :time_start AND (j.COMPLETEDATE IS NULL OR j.COMPLETEDATE >= :time_end))
)
ORDER BY j.JOBID, h.TXNDATE

View File

@@ -1027,6 +1027,39 @@ class TestExportCsvBatchEndpoint:
data = response.get_json()
assert 'CONTAINERID' in data.get('error', '')
@patch('mes_dashboard.routes.query_tool_routes.get_lot_jobs_with_history')
def test_export_lot_jobs_calls_with_history(self, mock_jobs_hist, client):
"""lot_jobs export should call get_lot_jobs_with_history (includes txn)."""
mock_jobs_hist.return_value = {
'data': [
{
'RESOURCENAME': 'ASSY-01',
'JOBID': 'JOB-001',
'JOB_FINAL_STATUS': 'Complete',
'TXNDATE': '2026-01-15 10:00:00',
'TXN_JOBSTATUS': 'Complete',
'STAGENAME': 'Repair',
},
],
'total': 1,
}
response = client.post(
'/api/query-tool/export-csv',
json={
'export_type': 'lot_jobs',
'params': {
'equipment_id': 'EQ001',
'time_start': '2026-01-01 00:00:00',
'time_end': '2026-01-31 23:59:59',
},
},
)
assert response.status_code == 200
assert 'text/csv' in response.content_type
mock_jobs_hist.assert_called_once_with('EQ001', '2026-01-01 00:00:00', '2026-01-31 23:59:59')
class TestEquipmentListEndpoint:
"""Tests for /api/query-tool/equipment-list endpoint."""