Skip to content

Commit

Permalink
feat(invoices): accounting export fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvdbrug committed Nov 12, 2024
1 parent acca189 commit e4e0653
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 11 deletions.
6 changes: 6 additions & 0 deletions packages/vendure-plugin-invoices/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 4.1.1 (2024-11-12)

- Better error message extraction from Xero API response
- Limit search term for looking up contacts in Xero by max 50 characters, to prevent Xero API errors
- Log unknown errors on invoice with timestamp when accounting export fails

# 4.1.0 (2024-08-30)

- Exporting credit invoices via accounting strategies now have their own method interface
Expand Down
2 changes: 1 addition & 1 deletion packages/vendure-plugin-invoices/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vendure-hub/pinelab-invoice-plugin",
"version": "4.1.0",
"version": "4.1.1",
"description": "Vendure plugin for PDF invoice generation",
"author": "Martijn van de Brug <[email protected]>",
"homepage": "https://pinelab-plugins.com/",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ export class AccountingService implements OnModuleInit {
} catch (e) {
await invoiceRepository.update(invoice.id, {
accountingReference: {
errorMessage: (e as Error)?.message,
errorMessage:
(e as Error)?.message ||
`Unknown error occured at ${new Date().toISOString()}`,
},
});
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {
order,
invoice,
isCreditInvoiceFor.invoiceNumber
) || `Credit note for ${isCreditInvoiceFor}`;
) || `Credit note for ${isCreditInvoiceFor.invoiceNumber}`;
const creditNote: import('xero-node').CreditNote = {
creditNoteNumber: `${invoice.invoiceNumber} (CN)`,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -268,7 +268,7 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {
): Promise<import('xero-node').Contact> {
await this.tokenCache.value(); // Always get a token before making a request
// Find by contact name first
const contacName = this.getNormalizedContactName(customer, companyName);
const contactName = this.getNormalizedContactName(customer, companyName);
let contacts = await this.xero.accountingApi.getContacts(
this.tenantId,
undefined,
Expand All @@ -278,7 +278,7 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {
undefined,
undefined,
undefined,
this.getNormalizedContactName(customer, companyName)
contactName
);
if (!contacts.body.contacts?.length) {
// If no contacts, try to find by email
Expand Down Expand Up @@ -321,7 +321,7 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {
);
const createdContact = createdContacts.body.contacts?.[0];
Logger.info(
`No contact found with name '${contacName}' or email '${customer.emailAddress}'. Created new contact with email "${createdContact?.emailAddress}" (${createdContact?.contactID})`,
`No contact found with name '${contactName}' or email '${customer.emailAddress}'. Created new contact with email "${createdContact?.emailAddress}" (${createdContact?.contactID})`,
loggerCtx
);
return createdContacts.body.contacts![0];
Expand All @@ -345,10 +345,14 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {
/**
* Get the readable error message from the Xero response
*/
private getErrorMessage(err: any): string {
private getErrorMessage(err: string): string {
const errorObj = JSON.parse(err);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return (
JSON.parse(err)?.response?.body?.Elements?.[0]?.ValidationErrors?.[0]
?.Message || JSON.parse(err)?.response?.body?.Message
errorObj?.response?.body?.Elements?.[0]?.ValidationErrors?.[0]?.Message ||
errorObj?.response?.body?.Message ||
errorObj?.response?.body ||
errorObj?.body
);
}

Expand Down Expand Up @@ -426,7 +430,8 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {

/**
* Get the normalized contact name. Uses company or other wise customers full name.
* Trims and replaces duplicate spaces/tabs/newlines
* Trims and replaces duplicate spaces/tabs/newlines.
* Shortens to max 50 characters, because that is the max allowed for the Xero API
*/
private getNormalizedContactName(
customer: Customer,
Expand All @@ -435,7 +440,7 @@ export class XeroUKExportStrategy implements AccountingExportStrategy {
const contactName =
companyName ||
[customer.firstName, customer.lastName].filter(Boolean).join(' ');
return contactName.trim().replace(/\s\s+/g, ' ');
return contactName.trim().replace(/\s\s+/g, ' ').substring(0, 50);
}

private getTaxType(
Expand Down

0 comments on commit e4e0653

Please sign in to comment.