@accounter/server
Version:
Accounter GraphQL server
111 lines (106 loc) • 3.89 kB
text/typescript
import type {
CreditInvoiceResolvers,
InvoiceReceiptResolvers,
InvoiceResolvers,
Maybe,
ReceiptResolvers,
Resolver,
ResolversParentTypes,
ResolversTypes,
} from '../../../__generated__/types.js';
import { formatCurrency, formatFinancialAmount } from '../../../shared/helpers/index.js';
import type { DocumentSuggestionsProto } from '../../../shared/types/index.js';
import {
getChargeBusinesses,
getChargeDocumentsMeta,
getChargeTransactionsMeta,
} from '../../charges/helpers/common.helper.js';
import { ChargesProvider } from '../../charges/providers/charges.provider.js';
import { BusinessesProvider } from '../../financial-entities/providers/businesses.provider.js';
import { FinancialEntitiesProvider } from '../../financial-entities/providers/financial-entities.provider.js';
import type { DocumentsModule } from '../types.js';
type Suggestion = Awaited<ResolversTypes['DocumentSuggestions']>;
const missingInfoSuggestions: Resolver<
Maybe<Suggestion>,
ResolversParentTypes['FinancialDocument'],
GraphQLModules.Context
> = async (RawDocument, _, { injector }) => {
const response: DocumentSuggestionsProto = {};
if (RawDocument.charge_id) {
const [
charge,
{ transactionsAmount, transactionsCurrency },
{ documentsAmount, documentsCurrency },
{ mainBusinessId },
] = await Promise.all([
injector.get(ChargesProvider).getChargeByIdLoader.load(RawDocument.charge_id),
getChargeTransactionsMeta(RawDocument.charge_id, injector),
getChargeDocumentsMeta(RawDocument.charge_id, injector),
getChargeBusinesses(RawDocument.charge_id, injector),
]);
if (mainBusinessId) {
response.counterpartyId = mainBusinessId;
}
if (charge?.owner_id) {
response.ownerId = charge.owner_id;
}
if (transactionsAmount) {
response.isIncome = transactionsAmount > 0;
}
if (transactionsAmount && transactionsCurrency) {
// use transactions info, if exists
response.amount = {
amount: transactionsAmount,
currency: formatCurrency(transactionsCurrency),
};
} else if (documentsAmount && documentsCurrency) {
// Use parallel documents (if exists) as documentsAmount is based on invoices OR receipts
response.amount = {
amount: documentsAmount,
currency: documentsCurrency,
};
}
}
return response;
};
export const documentSuggestionsResolvers: DocumentsModule.Resolvers = {
Invoice: {
missingInfoSuggestions: missingInfoSuggestions as InvoiceResolvers['missingInfoSuggestions'],
},
Receipt: {
missingInfoSuggestions: missingInfoSuggestions as ReceiptResolvers['missingInfoSuggestions'],
},
InvoiceReceipt: {
missingInfoSuggestions:
missingInfoSuggestions as InvoiceReceiptResolvers['missingInfoSuggestions'],
},
CreditInvoice: {
missingInfoSuggestions:
missingInfoSuggestions as CreditInvoiceResolvers['missingInfoSuggestions'],
},
Proforma: {
missingInfoSuggestions:
missingInfoSuggestions as InvoiceReceiptResolvers['missingInfoSuggestions'],
},
DocumentSuggestions: {
counterparty: (suggestion, _, { injector }) =>
suggestion.counterpartyId
? injector
.get(FinancialEntitiesProvider)
.getFinancialEntityByIdLoader.load(suggestion.counterpartyId)
.then(res => res ?? null)
: null,
owner: (suggestion, _, { injector }) =>
suggestion.ownerId
? injector
.get(BusinessesProvider)
.getBusinessByIdLoader.load(suggestion.ownerId)
.then(res => res ?? null)
: null,
amount: suggestion =>
suggestion.amount
? formatFinancialAmount(suggestion.amount.amount, suggestion.amount.currency)
: null,
isIncome: suggestion => (suggestion.isIncome == null ? null : suggestion.isIncome),
},
};