import { apiRequest, getPath } from './client.js'; const DEFAULT_LIST_PAGE_LIMIT = 100; function unwrapEntryPayload(payload) { return payload?.data || payload?.entry || payload?.item || payload; } function unwrapListPayload(payload) { if (Array.isArray(payload)) { return payload; } return payload?.data || payload?.entries || payload?.items || payload?.groups || []; } function hasExplicitPagination(filters = {}) { return ( (filters.limit !== undefined && filters.limit !== null) || (filters.offset !== undefined && filters.offset !== null) ); } async function fetchAllListPages(store, path, baseQuery = {}) { const items = []; let offset = 0; while (true) { const payload = await apiRequest(store, path, { query: { ...baseQuery, limit: DEFAULT_LIST_PAGE_LIMIT, offset, }, }); const pageItems = unwrapListPayload(payload); items.push(...pageItems); if (pageItems.length < DEFAULT_LIST_PAGE_LIMIT) { break; } offset += DEFAULT_LIST_PAGE_LIMIT; } return items; } export async function searchItemDefinitions(store, query) { if (query.trim().length <= 2) { return []; } const payload = await apiRequest(store, `${getPath('items')}/grouped`, { query: { search_name: query, expanded: 0 }, }); if (Array.isArray(payload)) { return payload; } return payload?.data || payload?.items || []; } export async function listStockEntries(store, filters = {}) { const baseQuery = {}; const searchName = filters.searchName || filters.search_name; if (searchName) { baseQuery.search_name = searchName; } if (hasExplicitPagination(filters)) { const query = { ...baseQuery }; if (filters.limit !== undefined && filters.limit !== null) { query.limit = filters.limit; } if (filters.offset !== undefined && filters.offset !== null) { query.offset = filters.offset; } const payload = await apiRequest(store, getPath('items'), { query, }); return unwrapListPayload(payload); } return fetchAllListPages(store, getPath('items'), baseQuery); } export async function listGroupedStockEntries(store, options = {}) { const baseQuery = {}; const expanded = options.expanded ?? 1; baseQuery.expanded = expanded; const searchName = options.searchName || options.search_name; if (searchName) { baseQuery.search_name = searchName; } if (hasExplicitPagination(options)) { const query = { ...baseQuery }; if (options.limit !== undefined && options.limit !== null) { query.limit = options.limit; } if (options.offset !== undefined && options.offset !== null) { query.offset = options.offset; } const payload = await apiRequest(store, `${getPath('items')}/grouped`, { query, }); return unwrapListPayload(payload); } return fetchAllListPages(store, `${getPath('items')}/grouped`, baseQuery); } export async function getStockEntry(store, stockId) { const payload = await apiRequest(store, `${getPath('items')}/${stockId}`); return unwrapEntryPayload(payload); } export async function createStockEntry(store, body) { const payload = await apiRequest(store, getPath('items'), { method: 'POST', body, query: { label: 1, print: 1 }, }); return unwrapEntryPayload(payload); } function normalizeUpsertResponse(payload) { return { status: payload?.status || null, mode: payload?.mode || null, operation: payload?.operation || null, matchType: payload?.match_type || null, matchedItem: payload?.matched_item || null, item: payload?.item || null, payload: payload?.payload || null, }; } function normalizeIdentifierLookupResponse(payload) { return { status: payload?.status || null, source: payload?.source || null, cacheHit: Boolean(payload?.cache_hit), identifierCode: payload?.identifier_code || null, identifierType: payload?.identifier_type || null, item: payload?.item || null, payloadFetchedAt: payload?.payload_fetched_at || null, retryAfterSeconds: Number.isInteger(payload?.retry_after_seconds) ? payload.retry_after_seconds : null, staleCache: Boolean(payload?.stale_cache), }; } function normalizeItemLookupResponse(payload) { return { status: payload?.status || null, found: Boolean(payload?.found), update: Boolean(payload?.update), identifierCode: payload?.identifier_code || null, identifierType: payload?.identifier_type || null, preview: payload?.preview || null, updatedFields: Array.isArray(payload?.updated_fields) ? payload.updated_fields : [], offPayloadFetchedAt: payload?.off_payload_fetched_at || null, retryAfterSeconds: Number.isInteger(payload?.retry_after_seconds) ? payload.retry_after_seconds : null, staleCache: Boolean(payload?.stale_cache), item: payload?.item || null, }; } export async function previewItemUpsert(store, body) { const payload = await apiRequest(store, `${getPath('items')}/upsert`, { method: 'POST', body, query: { mode: 'preview' }, }); return normalizeUpsertResponse(payload); } export async function applyItemUpsert(store, body) { const payload = await apiRequest(store, `${getPath('items')}/upsert`, { method: 'POST', body, query: { mode: 'apply' }, }); return normalizeUpsertResponse(payload); } export async function lookupItemByIdentifier(store, identifierCode) { const payload = await apiRequest(store, `${getPath('items')}/lookup`, { method: 'POST', body: { identifier_code: String(identifierCode || '').trim(), }, }); return normalizeIdentifierLookupResponse(payload); } export async function lookupItemDetails(store, uuidB64, { update = false } = {}) { const payload = await apiRequest(store, `${getPath('items')}/${uuidB64}/lookup`, { method: 'POST', query: { update: update ? 1 : 0 }, }); return normalizeItemLookupResponse(payload); } export async function patchStockItem(store, uuidB64, body) { const payload = await apiRequest(store, `${getPath('items')}/${uuidB64}`, { method: 'PATCH', body, }); return unwrapEntryPayload(payload); } export async function updateStockItem(store, uuidB64, body) { await apiRequest(store, `${getPath('items')}/${uuidB64}/stock`, { method: 'POST', body, }); return getStockEntry(store, uuidB64); } export async function deleteStockItem(store, uuidB64) { const payload = await apiRequest(store, `${getPath('items')}/${uuidB64}`, { method: 'DELETE', }); return unwrapEntryPayload(payload); } export async function useStockItem(store, uuidB64) { try { await apiRequest(store, `${getPath('items')}/${uuidB64}/use`, { method: 'POST', }); return { status: 'used' }; } catch (error) { const status = error?.status || error?.cause?.status; if (status === 409 || status === 404) { return { status: 'already_gone' }; } throw error; } } export async function adjustStockEntry(store, stockId, body) { await apiRequest(store, `${getPath('items')}/${stockId}/stock`, { method: 'POST', body, }); return getStockEntry(store, stockId); } export async function listKitchenChanges(store, { since, limit = 10 } = {}) { const payload = await apiRequest(store, getPath('changes'), { query: { since, limit, }, }); return { since: payload?.since || null, nextCursor: payload?.next_cursor || null, changes: Array.isArray(payload?.changes) ? payload.changes : [], }; }