import refreshTokenHelper from "../../../utils/refreshTokenHelper" import forceLogoutHelper from "../../../utils/forceLogoutHelper" import errorHandlingHelper from "../../../utils/errorHandlingHelper" import { resolveOrderSourceAmazonConnection, getMerchantListingsReport } from "../../../utils/amazonSpApi" import { matchListingsToProducts } from "../../../utils/sisMatching" // SIS (Sales Information System) — the full, matched listings table for one // Amazon order source. Pulls Amazon's bulk merchant-listings report (cached // ~30 min server-side), joins it to local products (SKU/ASIN match tiers, // internal price + qty-on-hand), and returns the whole set — the frontend // paginates/filters client-side, same convention as the Shopify stock page. const handleFunc = async (event: any, authToken: any = null) => { const token = authToken ?? await getTokenHelper(event) const query = getQuery(event) const orderSourceId = Number(query.orderSourceId) const forceRefresh = String(query.refresh || '') === '1' if (!orderSourceId) { return { status: 400, message: 'orderSourceId is required' } } const { orgId, sellerId, marketplaceId, accessToken } = await resolveOrderSourceAmazonConnection(event, token, orderSourceId) const { rows: listingRows, fromCache, generatedAt } = await getMerchantListingsReport( accessToken, orderSourceId, marketplaceId, { forceRefresh } ) const config = useRuntimeConfig(event) const priceListId = config.public?.pricelistid || '101' const rows = await matchListingsToProducts(event, token, orgId, listingRows, priceListId) return { status: 200, orderSourceId, sellerId, marketplaceId, fromCache, generatedAt, total: rows.length, matchedCount: rows.filter(r => r.productId).length, unmatchedCount: rows.filter(r => !r.productId).length, rows } } export default defineEventHandler(async (event) => { let data: any = {} try { data = await handleFunc(event) } catch (err: any) { // An Amazon-side failure (report timeout, 429, ...) is not an auth // problem — retrying the whole handler would re-run the report // creation + up to 45s of polling + the matching pass a second time, // which is what made this page occasionally hang well past a minute. // Fail straight to the client instead, same philosophy as the // lastIdempiereError guard in refreshTokenHelper, extended to Amazon. if (err?.isAmazonError) { data = errorHandlingHelper(err?.data ?? err, err?.data ?? err) return data } try { let authToken: any = await refreshTokenHelper(event) data = await handleFunc(event, authToken) } catch (error: any) { data = errorHandlingHelper(err?.data ?? err, error?.data ?? error) forceLogoutHelper(event, data) } } return data })