@accounter/server
Version:
Accounter GraphQL server
126 lines (118 loc) • 5.12 kB
text/typescript
import { GraphQLError } from 'graphql';
import { degradeChargesAccountantApproval } from '../../accountant-approval/helpers/degrade-charges.helper.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { mergeChargesExecutor } from '../../charges/helpers/merge-charges.helper.js';
import { ChargesProvider } from '../../charges/providers/charges.provider.js';
import type { IGetChargesByIdsResult } from '../../charges/types.js';
import { buildMergeChargesByTransactionReferencePlan } from '../helpers/merge-charges-by-reference.helper.js';
import { CronJobsProvider } from '../providers/cron-jobs.provider.js';
import type { CronJobsModule } from '../types.js';
export const cronJobsResolvers: CronJobsModule.Resolvers = {
Mutation: {
mergeChargesByTransactionReference: async (_, { dryRun = true }, { injector }) => {
try {
const { ownerId } = await injector.get(AdminContextProvider).getVerifiedAdminContext();
const candidates = await injector.get(CronJobsProvider).getReferenceMergeCandidates({
ownerId,
});
const chargeIds = new Set<string>(candidates.map(candidate => candidate.charge_id));
const charges = await injector
.get(ChargesProvider)
.getChargeByIdLoader.loadMany(Array.from(chargeIds))
.then(
res =>
res.filter(
charge => charge && !(charge instanceof Error),
) as IGetChargesByIdsResult[],
);
const chargeById = new Map(charges.map(charge => [charge.id, charge]));
const { plans, errors: planningErrors } = buildMergeChargesByTransactionReferencePlan({
candidates,
chargeById,
});
const plannedMerges = plans.map(({ reference, baseChargeId, chargeIdsToMerge }) => ({
reference,
baseChargeId,
chargeIdsToMerge,
}));
const plannedBaseChargeIds = new Set(plans.map(plan => plan.baseChargeId));
if (dryRun) {
return {
success: planningErrors.length === 0,
charges: Array.from(plannedBaseChargeIds)
.map(id => chargeById.get(id))
.filter(charge => charge) as IGetChargesByIdsResult[],
plannedMerges,
errors: planningErrors.length > 0 ? planningErrors : undefined,
};
}
const executionErrors = [...planningErrors];
const mergedBaseChargeIds = new Set<string>();
for (const { reference, baseChargeId, chargeIdsToMerge } of plans) {
try {
await mergeChargesExecutor(chargeIdsToMerge, baseChargeId, injector);
const degradedCharges = await degradeChargesAccountantApproval(injector, [
baseChargeId,
]);
const degradedBaseCharge = degradedCharges.get(baseChargeId);
if (degradedBaseCharge) {
// keep the returned charge in sync with its fresh (PENDING) state
chargeById.set(baseChargeId, degradedBaseCharge);
}
mergedBaseChargeIds.add(baseChargeId);
} catch (error) {
const message =
error instanceof GraphQLError
? error.message
: ((error as Error)?.message ?? 'Unknown error');
executionErrors.push(
`Failed to merge reference "${reference}" into charge ID=${baseChargeId}: ${message}`,
);
}
}
return {
success: executionErrors.length === 0,
charges: Array.from(mergedBaseChargeIds)
.map(id => chargeById.get(id))
.filter(charge => charge) as IGetChargesByIdsResult[],
plannedMerges,
errors: executionErrors.length > 0 ? executionErrors : undefined,
};
} catch (e) {
if (e instanceof GraphQLError) {
throw e;
}
return {
success: false,
errors: [(e as Error)?.message ?? 'Unknown error'],
};
}
},
flagForeignFeeTransactions: async (_, __, { injector }) => {
try {
const { ownerId } = await injector.get(AdminContextProvider).getVerifiedAdminContext();
const res = await injector.get(CronJobsProvider).flagForeignFeeTransactions({ ownerId });
const updatedTransactionsIds = res.map(({ id }) => id);
return {
success: true,
transactions: updatedTransactionsIds,
};
} catch (e) {
return {
success: false,
errors: [(e as Error)?.message ?? 'Unknown error'],
};
}
},
calculateCreditcardTransactionsDebitDate: async (_, __, { injector }) => {
try {
const { ownerId } = await injector.get(AdminContextProvider).getVerifiedAdminContext();
await injector.get(CronJobsProvider).calculateCreditcardDebitDate({ ownerId });
return true;
} catch (e) {
console.error(e);
throw new GraphQLError('Failed to calculate creditcard transactions debit date');
}
},
},
};