import { string } from 'alga-js' import refreshTokenHelper from "../../utils/refreshTokenHelper" import errorHandlingHelper from "../../utils/errorHandlingHelper" /** * Lightweight endpoint that returns only the count of unpaid invoices * for the fulfillment customer linked to the current organization. */ const handleFunc = async (event: any, authToken: any = null) => { const config = useRuntimeConfig() const serviceToken = config.api.idempieretoken const organizationId = getCookie(event, 'logship_organization_id') if (!organizationId || !serviceToken) { return { count: 0 } } try { // Get the org's business partner ID const orgFilter = `AD_Org_ID eq ${organizationId}` const orgUrl = `${config.api.url}/models/ad_org?$filter=${string.urlEncode(orgFilter)}&$select=C_BPartner_ID` const orgRes: any = await $fetch(orgUrl, { method: 'GET', headers: { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: 'Bearer ' + serviceToken } }) const bpartnerId = orgRes?.records?.[0]?.C_BPartner_ID?.id if (!bpartnerId) { return { count: 0 } } // Fetch only unpaid invoices (IsPaid = N) with CO or CL status const bpartnerFilter = `C_BPartner_ID eq ${bpartnerId} and IsPaid eq 'N' and (DocStatus eq 'CO' or DocStatus eq 'CL')` const invoiceUrl = `${config.api.url}/models/C_Invoice?$filter=${string.urlEncode(bpartnerFilter)}&$select=C_Invoice_ID,IsPaid,GrandTotal&$orderby=C_Invoice_ID desc` const res: any = await $fetch(invoiceUrl, { method: 'GET', headers: { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: 'Bearer ' + serviceToken } }) const invoices = res?.records || [] if (invoices.length === 0) { return { count: 0 } } // Check allocations to exclude fully paid invoices (IsPaid might not be updated yet) const invoiceIds = invoices.map((inv: any) => inv.id) let allocationSums: Record = {} try { const allocUrl = `${config.api.url}/models/c_allocationline?$filter=${string.urlEncode(`C_Invoice_ID in (${invoiceIds.join(',')})`)}&$select=C_Invoice_ID,Amount,C_Payment_ID&$expand=C_Payment_ID($select=DocStatus)` const allocRes: any = await $fetch(allocUrl, { method: 'GET', headers: { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: 'Bearer ' + serviceToken } }) if (allocRes?.records?.length > 0) { for (const alloc of allocRes.records) { const invoiceId = alloc.C_Invoice_ID?.id const paymentDocStatus = alloc.C_Payment_ID?.DocStatus?.id || alloc.C_Payment_ID?.DocStatus || '' if (invoiceId && paymentDocStatus === 'CO') { allocationSums[invoiceId] = (allocationSums[invoiceId] || 0) + (alloc.Amount || 0) } } } } catch (err) { // If allocations fail, count all as unpaid } // Count invoices where paid amount < grand total (use abs for credit memos) let unpaidCount = 0 for (const invoice of invoices) { const paidAmt = Math.abs(allocationSums[invoice.id] || 0) const grandTotal = Math.abs(invoice.GrandTotal || 0) if (paidAmt < grandTotal) { unpaidCount++ } } return { count: unpaidCount } } catch (err) { console.warn('Could not fetch unpaid invoice count:', err) return { count: 0 } } } 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) { data = errorHandlingHelper(err?.data ?? err, error?.data ?? error) } } return data })