diff --git a/BACKEND/app/services/line_connection.ts b/BACKEND/app/services/line_connection.ts index 8f32213..0d09fae 100644 --- a/BACKEND/app/services/line_connection.ts +++ b/BACKEND/app/services/line_connection.ts @@ -11,6 +11,7 @@ import { detectConfigRamByModel, detectScenarioByModel, escapeHtml, + getIncomingInfoBySN, isRamSufficient, isValidJson, LogStreamBuffer, @@ -1933,6 +1934,14 @@ Ports Missing/Down: ${missing.length}\n\n` const totalPoE = testedPoE.length + missingPoE.length const totalSFP = testedSFP.length + missingSFP.length + const dataIncomingBySN = await getIncomingInfoBySN(config?.inventory?.sn) + const serialInfo = dataIncomingBySN?.serialNumbersInfo?.find( + (s: any) => s.serialNumberA === config?.inventory?.sn + ) + const listImages = dataIncomingBySN?.packagePo?.listFiles?.filter( + (s: any) => s.kind === 'other' + ) + const showVersion = config?.data?.find( (d) => d.command?.trim()?.includes('show ver') || d.command?.trim()?.includes('sh ver') ) @@ -2077,13 +2086,20 @@ Ports Missing/Down: ${missing.length}\n\n` // Physical Check checklist const checklistItems: Array<[string, string]> = [ - ['ok', 'Packaging intact — no damage to box or foam'], - ['ok', 'No physical damage — chassis, fans, PSU'], - ['ok', `S/N matches label — ${productSN} verified`], - ['ok', 'All 48 GigE + 4 SFP+ ports clean'], - ['ok', 'Accessories — power cable, rack ears, console cable'], - ['warn', 'Minor scratch on top chassis (2cm) — cosmetic only'], + [ + serialInfo?.optionVisualInspection?.statusChassis ? 'ok' : 'warn', + serialInfo?.optionVisualInspection?.statusChassis + ? 'Overall hardware status is normal' + : 'Hardware issue detected on chassis/system', + ], + [ + serialInfo?.optionVisualInspection?.statusPortsPOE ? 'ok' : 'warn', + serialInfo?.optionVisualInspection?.statusPortsPOE + ? 'All ports and PoE functions are operating normally' + : 'Port or PoE issue detected', + ], ] + const checklistRowsHtml = checklistItems .map(([k, t]) => k === 'ok' @@ -2096,6 +2112,30 @@ Ports Missing/Down: ${missing.length}\n\n` const photoCellHtml = (label: string) => `
${label}
` + // Photo cell with actual image + const imageCellHtml = (url: string, label: string) => + `
` + + // Prepare image grid: get first 4 images from listImages if available + const imageList = listImages && Array.isArray(listImages) ? listImages.slice(0, 4) : [] + const imageLabels = ['Front', 'Rear', 'S/N Label', 'Package'] + const getPhotoCell = (idx: number) => { + const image = imageList[idx] + const label = imageLabels[idx] + return image && image.url + ? imageCellHtml(process.env.ERP_URL + image.url, label) + : photoCellHtml(label) + } + const photoGridRowsHtml = ` + + ${getPhotoCell(0)} + ${getPhotoCell(1)} + + + ${getPhotoCell(2)} + ${getPhotoCell(3)} + ` + // Helper function to highlight SNs from listInventory in outputTestLog const highlightSnInConsoleOutput = (text: string, listInventory: any[] | undefined) => { if (!text || !listInventory || listInventory.length === 0) { @@ -2184,8 +2224,8 @@ Ports Missing/Down: ${missing.length}\n\n` P/N${productPN} S/N${productSN} MAC${macAddress || '-'} - Cond.${'-'} - Supplier${'-'} + Cond.${serialInfo?.condition || '-'} + Supplier${serialInfo?.supplier?.name || '-'} @@ -2240,9 +2280,10 @@ Ports Missing/Down: ${missing.length}\n\n`
Receiving & Inspection Notes
⚠ Warning from Warehouse
-

Box arrived with slight indentation on the left corner. Internal foam was still intact. Serial number on box was partially obscured by shipping label but verified upon unboxing.

-

Not Available

-
+

${dataIncomingBySN?.packagePo?.notes || ''}

+

${serialInfo?.notes || ''}

+ ${!dataIncomingBySN?.packagePo?.notes && !serialInfo?.notes ? '

No notes available.

' : ''} +
Accessory Checklist
@@ -2287,10 +2328,10 @@ Ports Missing/Down: ${missing.length}\n\n` Received
- Not Available + ${dataIncomingBySN?.packagePo?.receivedBy?.fullName || 'Unknown'}
- ${momentTZ().tz(timeZone).format('DD MMM')} + ${dataIncomingBySN?.packagePo?.receivedDate ? momentTZ(dataIncomingBySN?.packagePo?.receivedDate).tz(timeZone).format('DD MMM, HH:mm') : ''}
@@ -2303,10 +2344,10 @@ Ports Missing/Down: ${missing.length}\n\n` Visual Check
- Not Available + ${dataIncomingBySN?.packagePo?.receivedBy?.fullName || 'Unknown'}
- ${momentTZ().tz(timeZone).format('DD MMM')} + ${dataIncomingBySN?.packagePo?.receivedDate ? momentTZ(dataIncomingBySN?.packagePo?.receivedDate).tz(timeZone).format('DD MMM, HH:mm') : ''}
@@ -2318,7 +2359,7 @@ Ports Missing/Down: ${missing.length}\n\n` Software Test
- ${this?.userTest?.dpelp?.name || ''} + ${this?.userTest?.dpelp?.name || 'Unknown'}
${momentTZ(this?.userTest?.dpelp?.time).tz(timeZone).format('DD MMM, HH:mm')} @@ -2351,29 +2392,19 @@ Ports Missing/Down: ${missing.length}\n\n` Visual Check -
- +
${this?.userTest?.physical?.name || ''} · ${momentTZ(this?.userTest?.physical?.time).tz(timeZone).format('DD MMM, HH:mm')}Not Available${dataIncomingBySN?.packagePo?.receivedBy?.fullName || 'Unknown'} · ${dataIncomingBySN?.packagePo?.receivedDate ? momentTZ(dataIncomingBySN?.packagePo?.receivedDate).tz(timeZone).format('DD MMM, HH:mm') : ''}
- - -
- - - - - - - - + ${photoGridRowsHtml}
${photoCellHtml('Front')}${photoCellHtml('Rear')}
${photoCellHtml('S/N Label')}${photoCellHtml('Package')}
+ ${checklistRowsHtml} Not Available
diff --git a/BACKEND/app/ultils/helper.ts b/BACKEND/app/ultils/helper.ts index 39bbfe3..2374ac8 100644 --- a/BACKEND/app/ultils/helper.ts +++ b/BACKEND/app/ultils/helper.ts @@ -1437,3 +1437,35 @@ export function canInputCommand(buffer: string): boolean { return false } + +export async function getIncomingInfoBySN(sn: string) { + try { + if (!sn) return + const remoteUrl = process.env.ERP_URL || 'https://stage.nswteam.net' + const header = { + Authorization: 'Bearer ' + process.env.ERP_TOKEN, + } + const responseDataSN = await axios.post( + remoteUrl + '/api/transferGetData', + { + urlAPI: '/api/package-po/get-incoming-by-sn', + filter: { + where: { + serialNumber: sn, + }, + }, + }, + { + headers: header, + } + ) + + if (!responseDataSN?.data?.data) { + return + } + + return responseDataSN?.data?.data + } catch (error) { + console.log('getIncomingInfoBySN', error) + } +} diff --git a/BACKEND/providers/socket_io_provider.ts b/BACKEND/providers/socket_io_provider.ts index f8a3df5..aef7d6c 100644 --- a/BACKEND/providers/socket_io_provider.ts +++ b/BACKEND/providers/socket_io_provider.ts @@ -1447,8 +1447,8 @@ export class WebSocketIo { */ generateZulipMessage(results: any[]) { let msg = `` - msg += `| Line | PID | SN | MAC | IOS | License | Summary | Issues |\n` - msg += `| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n` + msg += `| Line | PID | SN | MAC | IOS | License | Issues |\n` + msg += `| ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n` for (const item of results) { if (!item) continue @@ -1464,7 +1464,7 @@ export class WebSocketIo { // Format issues const issuesMd = item.issues?.length - ? item.issues.map((i: string) => `• ${i}`).join(' --') + ? item.issues.map((i: string) => `• ${i.replace('|', '')}`).join(' --') : '- No issues detected.' msg += @@ -1474,7 +1474,6 @@ export class WebSocketIo { ` | ${item.mac || ''}` + ` | ${item.ios || ''}` + ` | ${licenseMd}` + - ` | ${item.summary || ''}` + ` | ${issuesMd}` + ` |\n` }