UNPKG

@accounter/server

Version:
207 lines • 10.1 kB
import { GraphQLError } from 'graphql'; import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js'; import { GreenInvoiceClientProvider } from '../../app-providers/green-invoice-client.js'; import { ScopeProvider } from '../../auth/providers/scope.provider.js'; import { IssuedDocumentsProvider } from '../../documents/providers/issued-documents.provider.js'; import { validateClientIntegrations } from '../../financial-entities/helpers/clients.helper.js'; import { ClientsProvider } from '../../financial-entities/providers/clients.provider.js'; import { convertGreenInvoiceDocumentToDocumentDraft, getGreenInvoiceDocuments, getLinkedDocuments, greenInvoiceCountryToCountryCode, greenInvoiceToDocumentStatus, insertNewDocumentFromGreenInvoice, } from '../helpers/green-invoice.helper.js'; export const greenInvoiceResolvers = { Query: { greenInvoiceClient: async (_, { clientId }, { injector }) => { try { const client = await injector.get(ClientsProvider).getClientByIdLoader.load(clientId); if (!client) { throw new GraphQLError(`Client not found for ID="${clientId}"`); } const greenInvoiceId = validateClientIntegrations(client.integrations)?.greenInvoiceId; if (!greenInvoiceId) { throw new GraphQLError(`Client ID="${clientId}" is missing Green Invoice integration`); } return greenInvoiceId; } catch (error) { const message = 'Failed to fetch Green Invoice client'; console.error(message, error); throw new GraphQLError(message); } }, }, Mutation: { syncGreenInvoiceDocuments: async (_, { ownerId: inputOwnerId, singlePageLimit = true }, { injector }) => { // Sync targets a single business: validate an explicit target against // membership; otherwise (incl. blank input) default to the primary business. const trimmedOwnerId = inputOwnerId?.trim(); const ownerId = trimmedOwnerId ? await injector.get(ScopeProvider).resolveWriteTarget(trimmedOwnerId) : (await injector.get(AdminContextProvider).getVerifiedAdminContext()).ownerId; const greenInvoiceDocuments = await getGreenInvoiceDocuments(injector, !singlePageLimit); const issuedDocuments = await injector.get(IssuedDocumentsProvider).getAllIssuedDocuments(); // check for new or updated documents const newDocuments = []; const documentToUpdate = []; await Promise.all(greenInvoiceDocuments.map(async (item) => { const existingDocs = issuedDocuments.filter(doc => doc.external_id === item.id); // Throw an error if more than one document found with the same external ID if (existingDocs.length > 1) { throw new GraphQLError(`Found multiple issued documents with the same external ID: ${item.id}`); } // If no existing document found, add it to the new documents list if (existingDocs.length === 0) { newDocuments.push(item); return; } // For existing document => check for updates const existingDoc = existingDocs[0]; documentToUpdate.push({ localDoc: existingDoc, externalDoc: item, }); })); const addedDocs = []; // run insertions first, to avoid broken linked documents await Promise.all(newDocuments.map(async (greenInvoiceDoc) => { const newDocument = await insertNewDocumentFromGreenInvoice(injector, greenInvoiceDoc, ownerId); if (newDocument) { addedDocs.push(newDocument); } })); // Check for updates await Promise.all(documentToUpdate.map(async ({ localDoc, externalDoc }) => { const docToUpdate = {}; // check if the document status has changed const latestStatus = greenInvoiceToDocumentStatus(externalDoc.status); if (latestStatus !== localDoc.status) { docToUpdate.status = latestStatus; } // check if the linked documents have changed const linkedDocuments = await getLinkedDocuments(injector, externalDoc.id).catch(e => { console.error('Failed to fetch linked documents', e); return null; }); if (linkedDocuments?.length && (!localDoc.linked_document_ids || localDoc.linked_document_ids.length !== linkedDocuments.length || localDoc.linked_document_ids?.some(id => !linkedDocuments.includes(id)))) { docToUpdate.linkedDocumentIds = linkedDocuments; } // if has attributes to update, add to the update list if (Object.keys(docToUpdate).length > 0) { await injector .get(IssuedDocumentsProvider) .updateIssuedDocument({ documentId: localDoc.id, ...docToUpdate, }) .catch(e => { console.error('Failed to update issued document linked documents', e); throw new GraphQLError(`Failed to update issued document linked documents for Green Invoice ID: ${docToUpdate.documentId}`); }); } })); return addedDocs; }, }, IssuedDocumentInfo: { originalDocument: async (info, _, { injector }) => { if (!info?.externalId) { throw new GraphQLError('External ID is required to fetch original document'); } try { const document = await injector .get(GreenInvoiceClientProvider) .documentLoader.load(info.externalId); if (!document) { throw new GraphQLError('Original document not found'); } return await convertGreenInvoiceDocumentToDocumentDraft(document, injector); } catch (error) { console.error('Error fetching original document:', error); throw new GraphQLError('Error fetching original document'); } }, }, ClientIntegrations: { greenInvoiceInfo: business => validateClientIntegrations(business.integrations).greenInvoiceId ?? null, }, GreenInvoiceClient: { greenInvoiceId: clientId => clientId, businessId: async (clientId, _, { injector }) => { const client = await injector .get(ClientsProvider) .getClientByGreenInvoiceIdLoader.load(clientId); if (!client) { throw new GraphQLError(`Client not found for Green Invoice ID="${clientId}"`); } return client.business_id; }, country: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => { if (client?.country) { return greenInvoiceCountryToCountryCode(client.country); } return null; }); }, emails: async (clientId, _, { injector }) => { const emails = await injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.emails); return [...(emails?.filter(Boolean) ?? []), 'ap@the-guild.dev']; // TODO: remove hardcoded email }, name: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.name ?? null); }, phone: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.phone ?? null); }, taxId: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.taxId ?? null); }, address: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.address ?? null); }, city: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.city ?? null); }, zip: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.zip ?? null); }, fax: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.fax ?? null); }, mobile: async (clientId, _, { injector }) => { return injector .get(GreenInvoiceClientProvider) .clientLoader.load(clientId) .then(client => client?.mobile ?? null); }, }, }; //# sourceMappingURL=green-invoice.resolvers.js.map