Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,14 @@ aws-run-reports:

run-test:
@echo "+\n++ Make: Running test build ...\n+"
@docker-compose -f docker-compose.ci.yml up --build -d
@docker-compose -f docker-compose.ci.yml up --build -d --force-recreate

run-test-pipeline:
@docker exec -i pcc-backend-test yarn run test:pipeline

run-test-coverage:
@docker exec -i pcc-backend-test yarn run test:cov

close-test:
@echo "+\n++ Make: Closing test container ...\n+"
@docker-compose -f docker-compose.ci.yml down
Expand Down Expand Up @@ -285,8 +288,6 @@ drop:
dev-docs:
@docker exec -it $(PROJECT)-backend yarn run compodoc

generateMockData:
@docker exec -it $(PROJECT)-backend ./node_modules/.bin/ts-node -e 'require("./apps/backend/test/mocks/generate-data/mock-data-generator.ts")'

# ===================================
# Migrations
Expand Down
16 changes: 12 additions & 4 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest --verbose --forceExit --runInBand",
"test:watch": "jest --watch --maxWorkers=1",
"test:cov": "jest --coverage",
"test:cov": "NODE_ENV=ci RUNTIME_ENV=ci jest",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json --runInBand",
"test:pipeline": "NODE_ENV=ci RUNTIME_ENV=ci jest --config ./test/jest.json --runInBand --detectOpenHandles",
Expand Down Expand Up @@ -62,6 +62,7 @@
"devDependencies": {
"@compodoc/compodoc": "1.1.19",
"@faker-js/faker": "7.6.0",
"@golevelup/ts-jest": "0.3.7",
"@nestjs/cli": "9.1.8",
"@nestjs/schematics": "9.0.4",
"@nestjs/testing": "9.2.1",
Expand Down Expand Up @@ -105,10 +106,17 @@
"transform": {
".+\\.(t|j)s$": "ts-jest"
},
"coverageDirectory": "./coverage",
"testEnvironment": "node",
"collectCoverage": true,
"testPathIgnorePatterns": [
"./src/docs"
],
"collectCoverageFrom": [
"**/*.(t|j)s"
"./src/**"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
"coverageReporters": [
"html"
]
}
}
27 changes: 27 additions & 0 deletions apps/backend/src/common/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { AggregatedPayment } from '../../../src/reconciliation/types';
import { PaymentEntity } from '../../../src/transaction/entities';

export const aggregatedPayments = (payments: PaymentEntity[]) => {
const groupedPayments = payments.reduce(
/*eslint-disable */
(acc: any, payment: PaymentEntity) => {
const key = `${payment.transaction.fiscal_close_date}${payment.status}`;
if (!acc[key]) {
acc[key] = {
status: payment.status,
fiscal_close_date: payment.transaction.fiscal_close_date,
amount: 0,
payments: []
};
}
acc[key].amount += parseFloat(payment.amount.toFixed(2));
acc[key].payments.push(payment);
return acc;
},
{}
);
const aggPayments: AggregatedPayment[] = Object.values(groupedPayments);
return aggPayments.sort(
(a: AggregatedPayment, b: AggregatedPayment) => a.amount - b.amount
);
};
7 changes: 4 additions & 3 deletions apps/backend/src/deposits/cash-deposit.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { InjectRepository } from '@nestjs/typeorm';
import { In, LessThanOrEqual, Raw, Repository } from 'typeorm';
import { CashDepositEntity } from './entities/cash-deposit.entity';
import { MatchStatus } from '../common/const';
import { MatchStatusAll } from '../common/const';
import { mapLimit } from '../common/promises';
import { DateRange, Ministries } from '../constants';
import { LocationEntity } from '../location/entities';
import { AppLogger } from '../logger/logger.service';
import { MatchStatusAll } from './../common/const';

@Injectable()
export class CashDepositService {
Expand Down Expand Up @@ -79,7 +79,7 @@ export class CashDepositService {
location: LocationEntity
): Promise<string[]> {
const { to_date, from_date } = dateRange;
const dates = await this.cashDepositRepo.find({
const dates: CashDepositEntity[] = await this.cashDepositRepo.find({
where: {
pt_location_id: location.pt_location_id,
metadata: { program },
Expand All @@ -92,7 +92,8 @@ export class CashDepositService {
deposit_date: 'ASC'
}
});
return Array.from(new Set(dates.map((itm) => itm.deposit_date)));
const uniqueDates = dates.map((d) => d.deposit_date);
return Array.from(new Set(uniqueDates));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/deposits/entities/cash-deposit.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {
Entity,
PrimaryGeneratedColumn
} from 'typeorm';
import { FileTypes } from './../../constants';
import { FileMetadata } from '../../common/columns/metadata';
import { MatchStatus } from '../../common/const';
import { ColumnNumericTransformer } from '../../common/transformers/numericColumnTransformer';
import { FileTypes } from '../../constants';
import { TDI17Details } from '../../flat-files';
import { PaymentEntity } from '../../transaction/entities/payment.entity';

Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/deposits/entities/pos-deposit.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class POSDepositEntity {
@JoinColumn({ name: 'payment_method', referencedColumnName: 'method' })
payment_method: Relation<PaymentMethodEntity>;

constructor(data: TDI34Details) {
constructor(data?: TDI34Details) {
Object.assign(this, data?.resource);
}

Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/deposits/pos-deposit.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { DateRange, Ministries } from '../constants';
import { LocationEntity } from '../location/entities';
import { LocationService } from '../location/location.service';
import { AppLogger } from '../logger/logger.service';
import { PaymentMethodEntity } from './../transaction/entities/payment-method.entity';
import { PaymentMethodEntity } from '../transaction/entities/payment-method.entity';

@Injectable()
export class PosDepositService {
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/excelexport/excelexport.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import * as Excel from 'exceljs';
import * as path from 'path';
import { Stream } from 'stream';
import { AppLogger } from '../logger/logger.service';
import { Placement } from '../reporting/interfaces';
import { S3ManagerService } from '../s3-manager/s3-manager.service';
import { Placement } from './../reporting/interfaces';

@Injectable()
export class ExcelExportService {
Expand Down
127 changes: 58 additions & 69 deletions apps/backend/src/lambdas/reconcile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { eachDayOfInterval, format } from 'date-fns';
import { AppModule } from '../app.module';
import { LocationEntity } from '../location/entities/master-location-data.entity';
import { LocationService } from '../location/location.service';
import { CashExceptionsService } from '../reconciliation/cash-exceptions.service';
import { CashReconciliationService } from '../reconciliation/cash-reconciliation.service';
import { POSReconciliationService } from '../reconciliation/pos-reconciliation.service';
import { ReconciliationConfigInput } from '../reconciliation/types';
Expand All @@ -15,8 +16,9 @@ export const handler = async (
context?: Context
) => {
const app = await NestFactory.createApplicationContext(AppModule);
const cashRecon = app.get(CashReconciliationService);
const posRecon = app.get(POSReconciliationService);
const cashReconciliationService = app.get(CashReconciliationService);
const posReconciliationService = app.get(POSReconciliationService);
const cashExceptionsService = app.get(CashExceptionsService);
const locationService = app.get(LocationService);
const reportingService = app.get(ReportingService);
const appLogger = new Logger();
Expand All @@ -32,32 +34,33 @@ export const handler = async (
event.location_ids
);

const posReconciled = await runPosReconciliation(
const posReconciliationRun = await runPosReconciliation(
event,
locations,
appLogger,
posRecon
posReconciliationService
);

appLogger.log({ posReconciled }, CashReconciliationService.name);
appLogger.log({ posReconciliationRun }, POSReconciliationService.name);

const cashReconciled = await runCashReconciliation(
const cashReconciliationRun = await runCashReconciliation(
event,
locations,
appLogger,
cashRecon
cashReconciliationService
);

appLogger.log({ cashReconciled }, CashReconciliationService.name);
appLogger.log({ cashReconciliationRun }, CashReconciliationService.name);

const cashExceptions = await runCashExceptions(
const cashExceptionsRun = await runCashExceptions(
event,
locations,
appLogger,
cashRecon
cashReconciliationService,
cashExceptionsService
);

appLogger.log({ cashExceptions }, CashReconciliationService.name);
appLogger.log({ cashExceptionsRun }, CashReconciliationService.name);

appLogger.log('\n\n=========POS Summary Report: =========\n');
const posReport = await reportingService.reportPosMatchSummaryByDate();
Expand All @@ -74,7 +77,7 @@ const runPosReconciliation = async (
event: ReconciliationConfigInput,
locations: LocationEntity[],
appLogger: Logger,
posRecon: POSReconciliationService
posReconciliationService: POSReconciliationService
): Promise<void> => {
for (const location of locations) {
const dates: Date[] = eachDayOfInterval({
Expand All @@ -89,12 +92,12 @@ const runPosReconciliation = async (
POSReconciliationService.name
);

const posReconciliation = await posRecon.reconcile(
const results = await posReconciliationService.reconcile(
location,
event.program,
format(dates[index], 'yyyy-MM-dd')
);
appLogger.log({ posReconciliation }, POSReconciliationService.name);
appLogger.log({ results }, POSReconciliationService.name);
}
}
};
Expand All @@ -103,32 +106,31 @@ const runCashReconciliation = async (
{ program, period }: ReconciliationConfigInput,
locations: LocationEntity[],
appLogger: Logger,
cashRecon: CashReconciliationService
cashReconciliationService: CashReconciliationService
): Promise<void> => {
for (const location of locations) {
const cashDates = await cashRecon.findCashDepositDatesByLocation(
program,
{
to_date: period.to,
from_date: period.from
},
location
);
const cashDates =
await cashReconciliationService.findCashDepositDatesByLocation(
program,
{
to_date: period.to,
from_date: period.from
},
location
);
for (const [dindex, date] of cashDates.entries()) {
const lastDepositDate =
cashDates[dindex - 2] ?? format(new Date(period.from), 'yyyy-MM-dd');

const dateRange = {
from_date:
cashDates[dindex - 2] ?? format(new Date(period.from), 'yyyy-MM-dd'),
from_date: lastDepositDate,
to_date: date
};

appLogger.log({ dateRange }, CashReconciliationService.name);

appLogger.log(
`Processing CASH Reconciliation for: ${location.description} (${location.location_id})`,
CashReconciliationService.name
);
appLogger.log(
`PREVIOUS DEPOSIT DATE: ${dateRange.from_date}`,
`Processing Cash Reconciliation for: ${location.description} (${location.location_id}) for ${dateRange.from_date} - ${dateRange.to_date}`,
CashReconciliationService.name
);

Expand All @@ -137,12 +139,13 @@ const runCashReconciliation = async (
CashReconciliationService.name
);

const cashReconciliation = await cashRecon.reconcileCash(
const results = await cashReconciliationService.reconcileCash(
location,
program,
dateRange
);
appLogger.log({ cashReconciliation }, CashReconciliationService.name);

appLogger.log({ results }, CashReconciliationService.name);
}
}
};
Expand All @@ -151,48 +154,34 @@ const runCashExceptions = async (
event: ReconciliationConfigInput,
locations: LocationEntity[],
appLogger: Logger,
cashRecon: CashReconciliationService
cashReconciliationService: CashReconciliationService,
cashExceptionsService: CashExceptionsService
): Promise<void> => {
for (const location of locations) {
const cashDates: string[] = await cashRecon.findCashDepositDatesByLocation(
event.program,
{
to_date: event.period.to,
from_date: event.period.from
},
location
);
const cashDates: string[] =
await cashReconciliationService.findCashDepositDatesByLocation(
event.program,
{
to_date: event.period.to,
from_date: event.period.from
},
location
);
for (const [dindex, date] of cashDates.entries()) {
const pastDueDate = cashDates[dindex - 2]
? cashDates[dindex - 2]
: cashDates[dindex - 1]
? cashDates[dindex - 1]
: cashDates[dindex]
? cashDates[dindex]
: event.period.from;
console.log(pastDueDate);
if (pastDueDate) {
appLogger.log(
`Processing CASH EXCEPTIONS for: ${location.description} (${location.location_id})`,
CashReconciliationService.name
);
appLogger.log(
`EXCEPTIONS DATE: ${pastDueDate}`,
CashReconciliationService.name
);
const exceptionsDate =
cashDates[dindex - 2] ?? cashDates[dindex - 1] ?? event.period.from;

appLogger.log(
`CURRENT DEPOSIT DATE: ${date}`,
CashReconciliationService.name
);
appLogger.log(
`Processing Cash Exceptions for: ${location.description} (${location.location_id}) for ${exceptionsDate} - ${date}`,
CashReconciliationService.name
);

const exceptions = await cashRecon.findExceptions(
location,
event.program,
pastDueDate
);
appLogger.log({ exceptions }, CashReconciliationService.name);
}
const exceptions = await cashExceptionsService.findExceptions(
location,
event.program,
exceptionsDate
);
appLogger.log({ exceptions }, CashReconciliationService.name);
}
}
};
Loading