import { string } from 'alga-js' import refreshTokenHelper from "../../utils/refreshTokenHelper" import getTokenHelper from "../../utils/getTokenHelper" import errorHandlingHelper from "../../utils/errorHandlingHelper" import fetchHelper from "../../utils/fetchHelper" /** * GET /api/commission/open-tickets?orderId=&inoutId= * * OPEN tickets (r_request) linked to a scanned shipment — matched via the * shipment itself (M_InOut_ID) OR its order (C_Order_ID). Called by the * commissioning page as a dedicated async request right after a shipment is * loaded, so the scan flow itself is never slowed down (no $expand on the * main shipment query). * * Open/closed semantics mirror server/api/orders/[id]/requests.get.ts: * closed = r_status.IsClosed of the ticket's status (small lookup table, one * extra call instead of an N+1) OR the request's Processed flag OR the app's * own "completed" flag (custom column R_Request.IsComplete — set by the * complete/reopen toggles in MyTicketDetail.vue / requests/[id]/edit.vue). * Only open tickets are returned — the caller just shows what it gets. */ const handleFunc = async (event: any, authToken: any = null) => { const token = authToken ?? await getTokenHelper(event) const query = getQuery(event) const orderId = parseInt(String(query.orderId ?? '')) const inoutId = parseInt(String(query.inoutId ?? '')) const linkFilters: string[] = [] if (Number.isFinite(orderId) && orderId > 0) linkFilters.push('C_Order_ID eq ' + orderId) if (Number.isFinite(inoutId) && inoutId > 0) linkFilters.push('M_InOut_ID eq ' + inoutId) if (!linkFilters.length) { return { status: 200, 'row-count': 0, records: [] } } const filter = '(' + linkFilters.join(' OR ') + ') AND IsActive eq true' const res: any = await fetchHelper(event, `models/r_request?$filter=${string.urlEncode(filter)}&$orderby=${string.urlEncode('Created desc')}`, 'GET', token, null) const statusClosed: Record = {} try { const stRes: any = await fetchHelper(event, 'models/r_status?$top=200', 'GET', token, null) for (const st of (stRes?.records || [])) { statusClosed[st.id] = st.IsClosed === true } } catch {} // non-fatal — open/closed then relies on Processed alone const records = (res?.records || []) .filter((item: any) => { const closedByStatus = item.R_Status_ID?.id != null && statusClosed[item.R_Status_ID.id] === true // Custom Yes-No column — accept both casings + 'Y' (iDempiere REST casing varies by model). const completed = item.IsComplete ?? item.isComplete const isCompleted = completed === true || completed === 'Y' return !closedByStatus && !isCompleted && item.Processed !== true }) .map((item: any) => ({ id: item.id, documentNo: item.DocumentNo || '', summary: item.Summary || '', created: item.Created || '', status: item.R_Status_ID?.identifier || '', requestType: item.R_RequestType_ID?.identifier || '', salesRep: item.SalesRep_ID?.identifier || '', organization: item.AD_Org_ID?.identifier || '', linkedVia: item.M_InOut_ID?.id ? 'shipment' : 'order' })) return { status: 200, 'row-count': records.length, records } } export default defineEventHandler(async (event) => { let data: any = {} try { data = await handleFunc(event) } catch(err: any) { try { let authToken: any = await refreshTokenHelper(event) data = await handleFunc(event, authToken) } catch(error: any) { data = errorHandlingHelper(err?.data ?? err, error?.data ?? error) } } return data })