UNPKG

@accounter/server

Version:

247 lines (242 loc) • 11.4 kB
import { GraphQLError } from 'graphql'; import { ChargesProvider } from '@modules/charges/providers/charges.provider.js'; import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js'; import { DEFAULT_LOCAL_CURRENCY } from '@shared/constants'; import { Resolvers } from '@shared/gql-types'; import { formatFinancialAmount } from '@shared/helpers'; import { filterSalaryRecordsByCharge } from '../helpers/filter-salaries-by-charge.js'; import { getSalaryMonth } from '../helpers/get-month.helper.js'; import { SalariesProvider } from '../providers/salaries.provider.js'; import type { SalariesModule } from '../types.js'; import { insertSalaryRecords } from './insert-salary.resolver.js'; import { updateSalaryRecord } from './update-salary.resolver.js'; export const salariesResolvers: SalariesModule.Resolvers & Pick<Resolvers, 'UpdateSalaryRecordResult' | 'InsertSalaryRecordsResult'> = { Query: { salaryRecordsByCharge: async (_, { chargeId }, { injector }) => { const salaryRecords = await injector .get(SalariesProvider) .getSalaryRecordsByChargeIdLoader.load(chargeId); return salaryRecords; }, salaryRecordsByDates: async (_, { fromDate, toDate, employeeIDs }, { injector }) => { const fromDateMonth = fromDate.slice(0, 7); const toDateMonth = toDate.slice(0, 7); try { const salaryRecords = await injector .get(SalariesProvider) .getSalaryRecordsByDates({ fromDate: fromDateMonth, toDate: toDateMonth }); return salaryRecords .filter(record => (employeeIDs ? employeeIDs.includes(record.employee_id) : true)) .sort((a, b) => a.month.localeCompare(b.month)); } catch (e) { throw new GraphQLError(`Failed to get salary records by dates: ${(e as Error).message}`); } }, }, Mutation: { insertSalaryRecords, updateSalaryRecord, insertOrUpdateSalaryRecords: async (_, params, { injector }) => { try { const recordsPromises = params.salaryRecords.map(async salaryRecord => { try { const res = await injector.get(SalariesProvider).updateSalaryRecord(salaryRecord); if (res.length !== 1) { throw new Error(); } return res[0]; } catch (e) { /* empty */ } try { const salaryRecords = params.salaryRecords.map(salaryRecord => ({ ...salaryRecord, addedVacationDays: salaryRecord.addedVacationDays ?? null, baseSalary: salaryRecord.baseSalary ?? null, bonus: salaryRecord.bonus ?? null, chargeId: salaryRecord.chargeId ?? null, compensationsEmployerAmount: salaryRecord.compensationsEmployerAmount ?? null, compensationsEmployerPercentage: salaryRecord.compensationsEmployerPercentage ?? null, gift: salaryRecord.gift ?? null, globalAdditionalHours: salaryRecord.globalAdditionalHours ?? null, healthPaymentAmount: salaryRecord.healthPaymentAmount ?? null, hourlyRate: salaryRecord.hourlyRate ?? null, hours: salaryRecord.hours ?? null, pensionEmployeeAmount: salaryRecord.pensionEmployeeAmount ?? null, pensionEmployeePercentage: salaryRecord.pensionEmployeePercentage ?? null, pensionEmployerAmount: salaryRecord.pensionEmployerAmount ?? null, pensionEmployerPercentage: salaryRecord.pensionEmployerPercentage ?? null, pensionFundId: salaryRecord.pensionFundId ?? null, recovery: salaryRecord.recovery ?? null, sicknessDaysBalance: salaryRecord.sicknessDaysBalance ?? null, socialSecurityAmountEmployee: salaryRecord.socialSecurityAmountEmployee ?? null, socialSecurityAmountEmployer: salaryRecord.socialSecurityAmountEmployer ?? null, taxAmount: salaryRecord.taxAmount ?? null, trainingFundEmployeeAmount: salaryRecord.trainingFundEmployeeAmount ?? null, trainingFundEmployeePercentage: salaryRecord.trainingFundEmployeePercentage ?? null, trainingFundEmployerAmount: salaryRecord.trainingFundEmployerAmount ?? null, trainingFundEmployerPercentage: salaryRecord.trainingFundEmployerPercentage ?? null, trainingFundId: salaryRecord.trainingFundId ?? null, vacationDaysBalance: salaryRecord.vacationDaysBalance ?? null, vacationTakeout: salaryRecord.vacationTakeout ?? null, workDays: salaryRecord.workDays ?? null, zkufot: salaryRecord.zkufot ?? null, })); const res = await injector.get(SalariesProvider).insertSalaryRecords({ salaryRecords }); if (res.length !== 1) { throw new Error(); } return res[0]; } catch (e) { /* empty */ } throw new Error( `Failed to update salary record of employee ID=${salaryRecord.employeeId} on month ${salaryRecord.month}`, ); }); const updatedRecords = await Promise.all(recordsPromises); return { salaryRecords: updatedRecords, }; } catch (e) { return { __typename: 'CommonError', message: (e as Error)?.message ?? (e as { errors: Error[] })?.errors.map(e => e.message).toString() ?? 'Unknown error', }; } }, }, UpdateSalaryRecordResult: { __resolveType: obj => { if ('__typename' in obj && obj.__typename === 'CommonError') return 'CommonError'; return 'UpdateSalaryRecordSuccessfulResult'; }, }, InsertSalaryRecordsResult: { __resolveType: obj => { if ('__typename' in obj && obj.__typename === 'CommonError') return 'CommonError'; return 'InsertSalaryRecordsSuccessfulResult'; }, }, SalaryCharge: { salaryRecords: (DbCharge, _, { injector }) => { return injector.get(SalariesProvider).getSalaryRecordsByChargeIdLoader.load(DbCharge.id); }, salaryRecordsSuggestions: (DbCharge, _, { injector }) => { const dateString = DbCharge.transactions_min_event_date?.toISOString().slice(0, 7); if (!dateString) { return []; } const month = getSalaryMonth(DbCharge); if (!month) { return []; } return injector .get(SalariesProvider) .getSalaryRecordsByMonthLoader.load(month) .then(res => filterSalaryRecordsByCharge(DbCharge, res)); }, employees: async (DbCharge, _, { injector }) => { const salaryRecords = await injector .get(SalariesProvider) .getSalaryRecordsByChargeIdLoader.load(DbCharge.id); return injector .get(BusinessesProvider) .getBusinessByIdLoader.loadMany(salaryRecords.map(salaryRecord => salaryRecord.employee_id)) .then( res => res.map(employee => { if (!employee || employee instanceof Error) { throw new GraphQLError( `Employee not found for one of the salary record of charge ${DbCharge.id}`, ); } return employee; }) ?? [], ); }, }, Salary: { directAmount: DbSalary => formatFinancialAmount(DbSalary.direct_payment_amount, DEFAULT_LOCAL_CURRENCY), baseAmount: DbSalary => DbSalary.base_salary ? formatFinancialAmount(DbSalary.base_salary, DEFAULT_LOCAL_CURRENCY) : null, employee: (DbSalary, _, { injector }) => injector .get(BusinessesProvider) .getBusinessByIdLoader.load(DbSalary.employee_id) .then(res => res ?? null), employer: (DbSalary, _, { injector }) => injector .get(BusinessesProvider) .getBusinessByIdLoader.load(DbSalary.employer) .then(res => res ?? null), pensionFund: (DbSalary, _, { injector }) => DbSalary.pension_fund_id ? injector .get(BusinessesProvider) .getBusinessByIdLoader.load(DbSalary.pension_fund_id) .then(res => res ?? null) : null, pensionEmployeeAmount: DbSalary => formatFinancialAmount(DbSalary.pension_employee_amount, DEFAULT_LOCAL_CURRENCY), pensionEmployeePercentage: DbSalary => DbSalary.pension_employee_percentage, pensionEmployerAmount: DbSalary => formatFinancialAmount(DbSalary.pension_employer_amount, DEFAULT_LOCAL_CURRENCY), pensionEmployerPercentage: DbSalary => DbSalary.pension_employer_percentage, compensationsAmount: DbSalary => formatFinancialAmount(DbSalary.compensations_employer_amount, DEFAULT_LOCAL_CURRENCY), compensationsPercentage: DbSalary => DbSalary.compensations_employer_percentage, trainingFund: (DbSalary, _, { injector }) => DbSalary.training_fund_id ? injector .get(BusinessesProvider) .getBusinessByIdLoader.load(DbSalary.training_fund_id) .then(res => res ?? null) : null, trainingFundEmployeeAmount: DbSalary => formatFinancialAmount(DbSalary.training_fund_employee_amount, DEFAULT_LOCAL_CURRENCY), trainingFundEmployeePercentage: DbSalary => DbSalary.training_fund_employee_percentage, trainingFundEmployerAmount: DbSalary => formatFinancialAmount(DbSalary.training_fund_employer_amount, DEFAULT_LOCAL_CURRENCY), trainingFundEmployerPercentage: DbSalary => DbSalary.training_fund_employer_percentage, socialSecurityEmployeeAmount: DbSalary => formatFinancialAmount(DbSalary.social_security_amount_employee, DEFAULT_LOCAL_CURRENCY), socialSecurityEmployerAmount: DbSalary => formatFinancialAmount(DbSalary.social_security_amount_employer, DEFAULT_LOCAL_CURRENCY), incomeTaxAmount: DbSalary => formatFinancialAmount(DbSalary.tax_amount, DEFAULT_LOCAL_CURRENCY), healthInsuranceAmount: DbSalary => formatFinancialAmount(DbSalary.health_payment_amount, DEFAULT_LOCAL_CURRENCY), globalAdditionalHoursAmount: DbSalary => formatFinancialAmount(DbSalary.global_additional_hours, DEFAULT_LOCAL_CURRENCY), bonus: DbSalary => formatFinancialAmount(DbSalary.bonus, DEFAULT_LOCAL_CURRENCY), gift: DbSalary => formatFinancialAmount(DbSalary.gift, DEFAULT_LOCAL_CURRENCY), recovery: DbSalary => formatFinancialAmount(DbSalary.recovery, DEFAULT_LOCAL_CURRENCY), vacationTakeout: DbSalary => formatFinancialAmount(DbSalary.vacation_takeout, DEFAULT_LOCAL_CURRENCY), notionalExpense: DbSalary => formatFinancialAmount(DbSalary.zkufot, DEFAULT_LOCAL_CURRENCY), vacationDays: DbSalary => ({ added: DbSalary.added_vacation_days ? Number(DbSalary.added_vacation_days) : null, balance: DbSalary.vacation_days_balance ? Number(DbSalary.vacation_days_balance) : null, }), workDays: DbSalary => (DbSalary.work_days ? Number(DbSalary.work_days) : null), sicknessDays: DbSalary => ({ balance: DbSalary.sickness_days_balance ? Number(DbSalary.sickness_days_balance) : null, }), charge: (DbSalary, _, { injector }) => { if (!DbSalary.charge_id) { return null; } return injector .get(ChargesProvider) .getChargeByIdLoader.load(DbSalary.charge_id) .then(res => res ?? null); }, }, };