fix(query-tool): finalize raw-material tab/export and resolve ORA-00918

This commit is contained in:
egg
2026-02-22 17:59:27 +08:00
parent 9890586191
commit 97872cca97
11 changed files with 238 additions and 54 deletions

View File

@@ -89,3 +89,26 @@ def test_fetch_events_history_branch_replaces_container_filter(
assert "h.CONTAINERID = :container_id" not in sql
assert "{{ WORKCENTER_FILTER }}" not in sql
assert params == {"p0": "CID-1"}
@patch("mes_dashboard.services.event_fetcher.cache_set")
@patch("mes_dashboard.services.event_fetcher.cache_get", return_value=None)
@patch("mes_dashboard.services.event_fetcher.read_sql_df")
@patch("mes_dashboard.services.event_fetcher.SQLLoader.load")
def test_fetch_events_materials_branch_replaces_aliased_container_filter(
mock_sql_load,
mock_read_sql_df,
_mock_cache_get,
_mock_cache_set,
):
mock_sql_load.return_value = (
"SELECT * FROM t m WHERE m.CONTAINERID = :container_id ORDER BY TXNDATE"
)
mock_read_sql_df.return_value = pd.DataFrame([])
EventFetcher.fetch_events(["CID-1", "CID-2"], "materials")
sql, params = mock_read_sql_df.call_args.args
assert "m.CONTAINERID = :container_id" not in sql
assert "IN" in sql.upper()
assert params == {"p0": "CID-1", "p1": "CID-2"}

View File

@@ -123,5 +123,5 @@ def test_resource_history_export_uses_contract_headers(
chunks = list(export_resource_history_csv('2024-01-01', '2024-01-10'))
assert chunks
header_row = next(csv.reader(io.StringIO(chunks[0])))
header_row = next(csv.reader(io.StringIO(chunks[0].lstrip('\ufeff'))))
assert header_row == export_headers

View File

@@ -690,10 +690,10 @@ class TestExportCsvEndpoint:
assert '不支援' in data['error'] or 'type' in data['error'].lower()
@patch('mes_dashboard.routes.query_tool_routes.get_lot_history')
def test_export_lot_history_success(self, mock_get_history, client):
"""Should return CSV for lot history."""
mock_get_history.return_value = {
'data': [
def test_export_lot_history_success(self, mock_get_history, client):
"""Should return CSV for lot history."""
mock_get_history.return_value = {
'data': [
{
'EQUIPMENTNAME': 'ASSY-01',
'SPECNAME': 'SPEC-001',
@@ -709,9 +709,46 @@ class TestExportCsvEndpoint:
'export_type': 'lot_history',
'params': {'container_id': '488103800029578b'}
}
)
assert response.status_code == 200
assert 'text/csv' in response.content_type
)
assert response.status_code == 200
assert 'text/csv' in response.content_type
@patch('mes_dashboard.routes.query_tool_routes.get_lot_materials')
def test_export_lot_materials_uses_container_name_as_lot_id(
self,
mock_get_materials,
client,
):
mock_get_materials.return_value = {
'data': [
{
'CONTAINERID': '488103800029578b',
'CONTAINERNAME': 'GA25010001-A01',
'MATERIALPARTNAME': 'M-001',
'MATERIALLOTNAME': 'LOT-MAT-01',
'QTYCONSUMED': 10,
'WORKCENTERNAME': 'DB',
'SPECNAME': 'SPEC-DB',
'EQUIPMENTNAME': 'EQ-01',
'TXNDATE': '2026-02-22 10:00:00',
}
],
'total': 1,
}
response = client.post(
'/api/query-tool/export-csv',
json={
'export_type': 'lot_materials',
'params': {'container_id': '488103800029578b'}
}
)
assert response.status_code == 200
assert 'lot_raw_materials_488103800029578b.csv' in response.headers.get('Content-Disposition', '')
decoded = response.data.decode('utf-8-sig')
assert 'LOT ID' in decoded
assert 'GA25010001-A01' in decoded
class TestEquipmentListEndpoint: