UNPKG

@memberjunction/actions-bizapps-accounting

Version:

Accounting system integration actions for MemberJunction

346 lines 13.8 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { RegisterClass } from '@memberjunction/global'; import { BusinessCentralBaseAction } from '../business-central-base.action.js'; import { BaseAction } from '@memberjunction/actions'; /** * Action to retrieve sales invoices from Microsoft Dynamics 365 Business Central */ let GetBusinessCentralSalesInvoicesAction = class GetBusinessCentralSalesInvoicesAction extends BusinessCentralBaseAction { /** * Description of the action */ get Description() { return 'Retrieves sales invoices from Microsoft Dynamics 365 Business Central with comprehensive filtering options'; } /** * Main execution method */ async InternalRunAction(params) { try { const contextUser = params.ContextUser; if (!contextUser) { return { Success: false, ResultCode: 'ERROR', Message: 'Context user is required for Business Central API calls' }; } // Store params for base class methods this.params = params.Params; // Build filters based on parameters const filters = []; // Customer filter const customerNumber = this.getParamValue(params.Params, 'CustomerNumber'); if (customerNumber) { filters.push(`customerNumber eq '${customerNumber}'`); } // Status filter const status = this.getParamValue(params.Params, 'Status'); if (status) { filters.push(`status eq '${status}'`); } // Date range filters const startDate = this.getParamValue(params.Params, 'StartDate'); if (startDate) { filters.push(`invoiceDate ge ${this.formatBCDate(new Date(startDate))}`); } const endDate = this.getParamValue(params.Params, 'EndDate'); if (endDate) { filters.push(`invoiceDate le ${this.formatBCDate(new Date(endDate))}`); } // Due date filters const dueStartDate = this.getParamValue(params.Params, 'DueStartDate'); if (dueStartDate) { filters.push(`dueDate ge ${this.formatBCDate(new Date(dueStartDate))}`); } const dueEndDate = this.getParamValue(params.Params, 'DueEndDate'); if (dueEndDate) { filters.push(`dueDate le ${this.formatBCDate(new Date(dueEndDate))}`); } // Amount filters const minAmount = this.getParamValue(params.Params, 'MinAmount'); if (minAmount !== undefined) { filters.push(`totalAmountIncludingTax ge ${minAmount}`); } const maxAmount = this.getParamValue(params.Params, 'MaxAmount'); if (maxAmount !== undefined) { filters.push(`totalAmountIncludingTax le ${maxAmount}`); } // Only unpaid filter const onlyUnpaid = this.getParamValue(params.Params, 'OnlyUnpaid'); if (onlyUnpaid) { filters.push('remainingAmount gt 0'); } // Select fields to retrieve const select = [ 'id', 'number', 'invoiceDate', 'dueDate', 'customerNumber', 'customerName', 'customerId', 'status', 'totalAmountExcludingTax', 'totalTaxAmount', 'totalAmountIncludingTax', 'remainingAmount', 'currencyCode', 'paymentTermsId', 'shipmentMethodId', 'billToName', 'billToCustomerId', 'shipToName', 'shipToContact', 'sellToAddressLine1', 'sellToAddressLine2', 'sellToCity', 'sellToState', 'sellToCountry', 'sellToPostCode', 'externalDocumentNumber', 'lastModifiedDateTime' ]; // Expand lines if requested const expand = []; const includeLines = this.getParamValue(params.Params, 'IncludeLines'); if (includeLines) { expand.push('salesInvoiceLines'); } // Order by const orderBy = 'invoiceDate desc,number desc'; // Max results const maxResults = this.getParamValue(params.Params, 'MaxResults') || 100; // Execute the query const response = await this.queryBC('salesInvoices', filters, select, expand, orderBy, maxResults, contextUser); const bcInvoices = response.value || []; const invoices = bcInvoices.map(invoice => this.mapBCSalesInvoice(invoice)); // Calculate summary const summary = this.calculateInvoiceSummary(invoices); // Create output parameters if (!params.Params.find(p => p.Name === 'Invoices')) { params.Params.push({ Name: 'Invoices', Type: 'Output', Value: invoices }); } else { params.Params.find(p => p.Name === 'Invoices').Value = invoices; } if (!params.Params.find(p => p.Name === 'TotalCount')) { params.Params.push({ Name: 'TotalCount', Type: 'Output', Value: invoices.length }); } else { params.Params.find(p => p.Name === 'TotalCount').Value = invoices.length; } if (!params.Params.find(p => p.Name === 'Summary')) { params.Params.push({ Name: 'Summary', Type: 'Output', Value: summary }); } else { params.Params.find(p => p.Name === 'Summary').Value = summary; } return { Success: true, ResultCode: 'SUCCESS', Message: `Successfully retrieved ${invoices.length} sales invoices from Business Central` }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { Success: false, ResultCode: 'ERROR', Message: errorMessage }; } } /** * Map Business Central sales invoice to standard format */ mapBCSalesInvoice(bcInvoice) { return { id: bcInvoice.id, number: bcInvoice.number, invoiceDate: this.parseBCDate(bcInvoice.invoiceDate), dueDate: this.parseBCDate(bcInvoice.dueDate), customerNumber: bcInvoice.customerNumber, customerName: bcInvoice.customerName, customerId: bcInvoice.customerId, status: bcInvoice.status, totalAmountExcludingTax: bcInvoice.totalAmountExcludingTax || 0, totalTaxAmount: bcInvoice.totalTaxAmount || 0, totalAmountIncludingTax: bcInvoice.totalAmountIncludingTax || 0, remainingAmount: bcInvoice.remainingAmount || 0, currencyCode: bcInvoice.currencyCode || 'USD', paymentTermsId: bcInvoice.paymentTermsId, shipmentMethodId: bcInvoice.shipmentMethodId, billToName: bcInvoice.billToName, billToCustomerId: bcInvoice.billToCustomerId, shipToName: bcInvoice.shipToName, shipToContact: bcInvoice.shipToContact, sellToAddressLine1: bcInvoice.sellToAddressLine1, sellToAddressLine2: bcInvoice.sellToAddressLine2, sellToCity: bcInvoice.sellToCity, sellToState: bcInvoice.sellToState, sellToCountry: bcInvoice.sellToCountry, sellToPostCode: bcInvoice.sellToPostCode, externalDocumentNumber: bcInvoice.externalDocumentNumber, lastModifiedDateTime: this.parseBCDate(bcInvoice.lastModifiedDateTime), lines: bcInvoice.salesInvoiceLines ? this.mapInvoiceLines(bcInvoice.salesInvoiceLines) : undefined }; } /** * Map invoice lines */ mapInvoiceLines(lines) { return lines.map(line => ({ id: line.id, lineNumber: line.lineNumber || line.sequence, lineType: line.lineType, itemId: line.itemId, accountId: line.accountId, description: line.description || '', quantity: line.quantity || 0, unitPrice: line.unitPrice || 0, discountAmount: line.discountAmount || 0, discountPercent: line.discountPercent || 0, netAmount: line.netAmount || 0, taxCode: line.taxCode, amountExcludingTax: line.amountExcludingTax || 0, taxPercent: line.taxPercent || 0, totalTaxAmount: line.totalTaxAmount || 0, amountIncludingTax: line.amountIncludingTax || 0 })); } /** * Calculate invoice summary statistics */ calculateInvoiceSummary(invoices) { const summary = { totalInvoices: invoices.length, totalAmountExcludingTax: 0, totalTaxAmount: 0, totalAmountIncludingTax: 0, totalRemainingAmount: 0, totalPaidAmount: 0, averageInvoiceAmount: 0, invoicesByStatus: {}, overdueInvoices: 0, overdueAmount: 0, oldestUnpaidDate: null, largestUnpaidAmount: 0 }; const today = new Date(); invoices.forEach(invoice => { // Sum totals summary.totalAmountExcludingTax += invoice.totalAmountExcludingTax; summary.totalTaxAmount += invoice.totalTaxAmount; summary.totalAmountIncludingTax += invoice.totalAmountIncludingTax; summary.totalRemainingAmount += invoice.remainingAmount; summary.totalPaidAmount += (invoice.totalAmountIncludingTax - invoice.remainingAmount); // Count by status summary.invoicesByStatus[invoice.status] = (summary.invoicesByStatus[invoice.status] || 0) + 1; // Track overdue if (invoice.remainingAmount > 0 && invoice.dueDate < today) { summary.overdueInvoices++; summary.overdueAmount += invoice.remainingAmount; } // Track oldest unpaid if (invoice.remainingAmount > 0) { if (!summary.oldestUnpaidDate || invoice.invoiceDate < summary.oldestUnpaidDate) { summary.oldestUnpaidDate = invoice.invoiceDate; } if (invoice.remainingAmount > summary.largestUnpaidAmount) { summary.largestUnpaidAmount = invoice.remainingAmount; } } }); summary.averageInvoiceAmount = invoices.length > 0 ? summary.totalAmountIncludingTax / invoices.length : 0; return summary; } /** * Define the parameters for this action */ get Params() { const baseParams = this.getCommonAccountingParams(); const specificParams = [ { Name: 'CustomerNumber', Type: 'Input', Value: null }, { Name: 'Status', Type: 'Input', Value: null }, { Name: 'StartDate', Type: 'Input', Value: null }, { Name: 'EndDate', Type: 'Input', Value: null }, { Name: 'DueStartDate', Type: 'Input', Value: null }, { Name: 'DueEndDate', Type: 'Input', Value: null }, { Name: 'MinAmount', Type: 'Input', Value: null }, { Name: 'MaxAmount', Type: 'Input', Value: null }, { Name: 'OnlyUnpaid', Type: 'Input', Value: false }, { Name: 'IncludeLines', Type: 'Input', Value: true }, { Name: 'MaxResults', Type: 'Input', Value: 100 } ]; return [...baseParams, ...specificParams]; } }; GetBusinessCentralSalesInvoicesAction = __decorate([ RegisterClass(BaseAction, 'GetBusinessCentralSalesInvoicesAction') ], GetBusinessCentralSalesInvoicesAction); export { GetBusinessCentralSalesInvoicesAction }; //# sourceMappingURL=get-sales-invoices.action.js.map