@hed-hog/finance 0.0.252 → 0.0.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dto/reverse-settlement.dto.d.ts +1 -0
- package/dist/dto/reverse-settlement.dto.d.ts.map +1 -1
- package/dist/dto/reverse-settlement.dto.js +5 -0
- package/dist/dto/reverse-settlement.dto.js.map +1 -1
- package/dist/finance-installments.controller.d.ts +40 -2
- package/dist/finance-installments.controller.d.ts.map +1 -1
- package/dist/finance-installments.controller.js +38 -2
- package/dist/finance-installments.controller.js.map +1 -1
- package/dist/finance.service.d.ts +38 -0
- package/dist/finance.service.d.ts.map +1 -1
- package/dist/finance.service.js +307 -118
- package/dist/finance.service.js.map +1 -1
- package/hedhog/data/route.yaml +27 -0
- package/hedhog/frontend/app/accounts-payable/installments/[id]/page.tsx.ejs +308 -99
- package/hedhog/query/settlement-auditability.sql +175 -0
- package/hedhog/table/bank_reconciliation.yaml +11 -0
- package/hedhog/table/settlement.yaml +17 -1
- package/hedhog/table/settlement_allocation.yaml +3 -0
- package/package.json +5 -5
- package/src/dto/reverse-settlement.dto.ts +4 -0
- package/src/finance-installments.controller.ts +45 -12
- package/src/finance.service.ts +439 -139
package/dist/finance.service.js
CHANGED
|
@@ -690,6 +690,138 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
690
690
|
async reverseAccountsReceivableSettlement(id, settlementId, data, locale, userId) {
|
|
691
691
|
return this.reverseTitleSettlement(id, settlementId, data, 'receivable', locale, userId);
|
|
692
692
|
}
|
|
693
|
+
async getTitleSettlementsHistory(titleId, locale) {
|
|
694
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
695
|
+
const title = await this.prisma.financial_title.findUnique({
|
|
696
|
+
where: { id: titleId },
|
|
697
|
+
select: { id: true },
|
|
698
|
+
});
|
|
699
|
+
if (!title) {
|
|
700
|
+
throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('itemNotFound', locale, `Financial title with ID ${titleId} not found`).replace('{{item}}', 'Financial title'));
|
|
701
|
+
}
|
|
702
|
+
const rows = await this.prisma.$queryRaw `
|
|
703
|
+
SELECT
|
|
704
|
+
s.id AS normal_id,
|
|
705
|
+
s.settled_at AS normal_paid_at,
|
|
706
|
+
s.amount_cents AS normal_amount_cents,
|
|
707
|
+
pm.type::text AS normal_method,
|
|
708
|
+
s.bank_account_id AS normal_account_id,
|
|
709
|
+
ba.name AS normal_account_name,
|
|
710
|
+
s.created_at AS normal_created_at,
|
|
711
|
+
u.name AS normal_created_by,
|
|
712
|
+
s.description AS normal_memo,
|
|
713
|
+
br.id AS reconciliation_id,
|
|
714
|
+
br.status::text AS reconciliation_status,
|
|
715
|
+
fi.id AS installment_id,
|
|
716
|
+
fi.installment_number AS installment_seq,
|
|
717
|
+
COALESCE(sa.amount_cents, sa.allocated_amount_cents) AS allocation_amount_cents,
|
|
718
|
+
r.id AS reversal_id,
|
|
719
|
+
r.settled_at AS reversal_paid_at,
|
|
720
|
+
r.amount_cents AS reversal_amount_cents,
|
|
721
|
+
r.created_at AS reversal_created_at,
|
|
722
|
+
ur.name AS reversal_created_by,
|
|
723
|
+
r.description AS reversal_memo
|
|
724
|
+
FROM settlement s
|
|
725
|
+
INNER JOIN settlement_allocation sa ON sa.settlement_id = s.id
|
|
726
|
+
INNER JOIN financial_installment fi ON fi.id = sa.installment_id
|
|
727
|
+
LEFT JOIN payment_method pm ON pm.id = s.payment_method_id
|
|
728
|
+
LEFT JOIN bank_account ba ON ba.id = s.bank_account_id
|
|
729
|
+
LEFT JOIN "user" u ON u.id = s.created_by_user_id
|
|
730
|
+
LEFT JOIN bank_reconciliation br ON br.settlement_id = s.id
|
|
731
|
+
LEFT JOIN settlement r ON r.reverses_settlement_id = s.id
|
|
732
|
+
LEFT JOIN "user" ur ON ur.id = r.created_by_user_id
|
|
733
|
+
WHERE fi.title_id = ${titleId}
|
|
734
|
+
AND COALESCE(s.entry_type::text, 'normal') = 'normal'
|
|
735
|
+
ORDER BY s.settled_at DESC, s.id DESC, fi.installment_number ASC
|
|
736
|
+
`;
|
|
737
|
+
const groups = new Map();
|
|
738
|
+
for (const row of rows) {
|
|
739
|
+
const key = String(row.normal_id);
|
|
740
|
+
const existing = groups.get(key);
|
|
741
|
+
if (!existing) {
|
|
742
|
+
groups.set(key, {
|
|
743
|
+
normal: {
|
|
744
|
+
id: key,
|
|
745
|
+
paidAt: ((_b = (_a = row.normal_paid_at) === null || _a === void 0 ? void 0 : _a.toISOString) === null || _b === void 0 ? void 0 : _b.call(_a)) || null,
|
|
746
|
+
amountCents: Number(row.normal_amount_cents || 0),
|
|
747
|
+
type: 'NORMAL',
|
|
748
|
+
method: this.mapPaymentMethodToPt(row.normal_method) || row.normal_method,
|
|
749
|
+
account: row.normal_account_name || null,
|
|
750
|
+
accountId: row.normal_account_id
|
|
751
|
+
? String(row.normal_account_id)
|
|
752
|
+
: null,
|
|
753
|
+
createdAt: ((_d = (_c = row.normal_created_at) === null || _c === void 0 ? void 0 : _c.toISOString) === null || _d === void 0 ? void 0 : _d.call(_c)) || null,
|
|
754
|
+
createdBy: row.normal_created_by || null,
|
|
755
|
+
memo: row.normal_memo || null,
|
|
756
|
+
reconciled: row.reconciliation_status === 'reconciled',
|
|
757
|
+
reconciliationId: row.reconciliation_id
|
|
758
|
+
? String(row.reconciliation_id)
|
|
759
|
+
: null,
|
|
760
|
+
},
|
|
761
|
+
reversal: row.reversal_id
|
|
762
|
+
? {
|
|
763
|
+
id: String(row.reversal_id),
|
|
764
|
+
paidAt: ((_f = (_e = row.reversal_paid_at) === null || _e === void 0 ? void 0 : _e.toISOString) === null || _f === void 0 ? void 0 : _f.call(_e)) || null,
|
|
765
|
+
amountCents: Number(row.reversal_amount_cents || 0),
|
|
766
|
+
type: 'REVERSAL',
|
|
767
|
+
createdAt: ((_h = (_g = row.reversal_created_at) === null || _g === void 0 ? void 0 : _g.toISOString) === null || _h === void 0 ? void 0 : _h.call(_g)) || null,
|
|
768
|
+
createdBy: row.reversal_created_by || null,
|
|
769
|
+
memo: row.reversal_memo || null,
|
|
770
|
+
}
|
|
771
|
+
: null,
|
|
772
|
+
allocations: [],
|
|
773
|
+
statusLabel: row.reversal_id ? 'ESTORNADO' : 'ATIVO',
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
groups.get(key).allocations.push({
|
|
777
|
+
installmentId: String(row.installment_id),
|
|
778
|
+
installmentSeq: Number(row.installment_seq || 0),
|
|
779
|
+
amountCents: Number(row.allocation_amount_cents || 0),
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
return Array.from(groups.values());
|
|
783
|
+
}
|
|
784
|
+
async reverseSettlementById(settlementId, data, locale, userId) {
|
|
785
|
+
const updatedTitle = await this.reverseSettlementInternal(settlementId, data, locale, userId);
|
|
786
|
+
return this.mapTitleToFront(updatedTitle);
|
|
787
|
+
}
|
|
788
|
+
async unreconcileBankReconciliation(id, userId) {
|
|
789
|
+
const reconciliation = await this.prisma.bank_reconciliation.findUnique({
|
|
790
|
+
where: { id },
|
|
791
|
+
select: {
|
|
792
|
+
id: true,
|
|
793
|
+
settlement_id: true,
|
|
794
|
+
bank_statement_line_id: true,
|
|
795
|
+
},
|
|
796
|
+
});
|
|
797
|
+
if (!reconciliation) {
|
|
798
|
+
throw new common_1.NotFoundException('Conciliação bancária não encontrada');
|
|
799
|
+
}
|
|
800
|
+
await this.prisma.$transaction(async (tx) => {
|
|
801
|
+
await tx.bank_reconciliation.delete({
|
|
802
|
+
where: { id: reconciliation.id },
|
|
803
|
+
});
|
|
804
|
+
await tx.bank_statement_line.updateMany({
|
|
805
|
+
where: {
|
|
806
|
+
id: reconciliation.bank_statement_line_id,
|
|
807
|
+
status: {
|
|
808
|
+
in: ['reconciled', 'adjusted'],
|
|
809
|
+
},
|
|
810
|
+
},
|
|
811
|
+
data: {
|
|
812
|
+
status: 'pending',
|
|
813
|
+
},
|
|
814
|
+
});
|
|
815
|
+
await this.createAuditLog(tx, {
|
|
816
|
+
action: 'UNRECONCILE_SETTLEMENT',
|
|
817
|
+
entityTable: 'bank_reconciliation',
|
|
818
|
+
entityId: String(reconciliation.id),
|
|
819
|
+
actorUserId: userId,
|
|
820
|
+
summary: `Unreconciled settlement ${reconciliation.settlement_id}`,
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
return { success: true };
|
|
824
|
+
}
|
|
693
825
|
async createTag(data) {
|
|
694
826
|
const slug = this.normalizeTagSlug(data.name);
|
|
695
827
|
if (!slug) {
|
|
@@ -2022,6 +2154,7 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2022
2154
|
}
|
|
2023
2155
|
async cancelTitle(titleId, data, titleType, locale, userId) {
|
|
2024
2156
|
const updatedTitle = await this.prisma.$transaction(async (tx) => {
|
|
2157
|
+
var _a;
|
|
2025
2158
|
const title = await tx.financial_title.findFirst({
|
|
2026
2159
|
where: {
|
|
2027
2160
|
id: titleId,
|
|
@@ -2039,21 +2172,19 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2039
2172
|
if (title.status === 'settled' || title.status === 'canceled') {
|
|
2040
2173
|
throw new common_1.BadRequestException('Title cannot be canceled in current status');
|
|
2041
2174
|
}
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
},
|
|
2056
|
-
});
|
|
2175
|
+
const activeSettlements = await tx.$queryRaw `
|
|
2176
|
+
SELECT EXISTS (
|
|
2177
|
+
SELECT 1
|
|
2178
|
+
FROM settlement_allocation sa
|
|
2179
|
+
INNER JOIN financial_installment fi ON fi.id = sa.installment_id
|
|
2180
|
+
INNER JOIN settlement s ON s.id = sa.settlement_id
|
|
2181
|
+
LEFT JOIN settlement r ON r.reverses_settlement_id = s.id
|
|
2182
|
+
WHERE fi.title_id = ${title.id}
|
|
2183
|
+
AND COALESCE(s.entry_type::text, 'normal') = 'normal'
|
|
2184
|
+
AND r.id IS NULL
|
|
2185
|
+
) AS has_active
|
|
2186
|
+
`;
|
|
2187
|
+
const hasActiveSettlements = (_a = activeSettlements[0]) === null || _a === void 0 ? void 0 : _a.has_active;
|
|
2057
2188
|
if (hasActiveSettlements) {
|
|
2058
2189
|
throw new common_1.ConflictException('Não é possível cancelar enquanto houver liquidações ativas. Estorne primeiro.');
|
|
2059
2190
|
}
|
|
@@ -2270,69 +2401,157 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2270
2401
|
}
|
|
2271
2402
|
}
|
|
2272
2403
|
async reverseTitleSettlement(titleId, settlementId, data, titleType, locale, userId) {
|
|
2273
|
-
const updatedTitle = await this.
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
due_date: true,
|
|
2310
|
-
status: true,
|
|
2311
|
-
},
|
|
2312
|
-
},
|
|
2313
|
-
},
|
|
2314
|
-
},
|
|
2315
|
-
},
|
|
2316
|
-
});
|
|
2404
|
+
const updatedTitle = await this.reverseSettlementInternal(settlementId, data, locale, userId, {
|
|
2405
|
+
titleId,
|
|
2406
|
+
titleType,
|
|
2407
|
+
});
|
|
2408
|
+
if (!updatedTitle) {
|
|
2409
|
+
throw new common_1.NotFoundException('Financial title not found');
|
|
2410
|
+
}
|
|
2411
|
+
return this.mapTitleToFront(updatedTitle);
|
|
2412
|
+
}
|
|
2413
|
+
async reverseSettlementInternal(settlementId, data, locale, userId, scope) {
|
|
2414
|
+
const { title } = await this.prisma.$transaction(async (tx) => {
|
|
2415
|
+
var _a, _b, _c, _d, _e;
|
|
2416
|
+
const settlementRows = await tx.$queryRaw `
|
|
2417
|
+
SELECT DISTINCT
|
|
2418
|
+
s.id,
|
|
2419
|
+
s.settlement_type::text,
|
|
2420
|
+
s.settled_at,
|
|
2421
|
+
s.amount_cents,
|
|
2422
|
+
s.description,
|
|
2423
|
+
s.person_id,
|
|
2424
|
+
s.bank_account_id,
|
|
2425
|
+
s.payment_method_id,
|
|
2426
|
+
s.created_by_user_id,
|
|
2427
|
+
COALESCE(s.entry_type::text, 'normal') AS entry_type,
|
|
2428
|
+
ft.id AS title_id,
|
|
2429
|
+
ft.title_type::text AS title_type,
|
|
2430
|
+
ft.status::text AS title_status,
|
|
2431
|
+
ft.competence_date AS title_competence_date
|
|
2432
|
+
FROM settlement s
|
|
2433
|
+
INNER JOIN settlement_allocation sa ON sa.settlement_id = s.id
|
|
2434
|
+
INNER JOIN financial_installment fi ON fi.id = sa.installment_id
|
|
2435
|
+
INNER JOIN financial_title ft ON ft.id = fi.title_id
|
|
2436
|
+
WHERE s.id = ${settlementId}
|
|
2437
|
+
FOR UPDATE OF s
|
|
2438
|
+
`;
|
|
2439
|
+
const settlement = settlementRows[0];
|
|
2317
2440
|
if (!settlement) {
|
|
2441
|
+
throw new common_1.NotFoundException('Settlement not found');
|
|
2442
|
+
}
|
|
2443
|
+
if ((scope === null || scope === void 0 ? void 0 : scope.titleId) && settlement.title_id !== scope.titleId) {
|
|
2318
2444
|
throw new common_1.NotFoundException('Settlement not found for this title');
|
|
2319
2445
|
}
|
|
2320
|
-
if (settlement.
|
|
2446
|
+
if ((scope === null || scope === void 0 ? void 0 : scope.titleType) && settlement.title_type !== scope.titleType) {
|
|
2447
|
+
throw new common_1.NotFoundException('Settlement not found for this title type');
|
|
2448
|
+
}
|
|
2449
|
+
if (settlement.entry_type !== 'normal') {
|
|
2450
|
+
throw new common_1.BadRequestException('Somente liquidações normais podem ser estornadas');
|
|
2451
|
+
}
|
|
2452
|
+
await this.assertDateNotInClosedPeriod(tx, settlement.title_competence_date, 'reverse settlement');
|
|
2453
|
+
const alreadyReversed = await tx.$queryRaw `
|
|
2454
|
+
SELECT id
|
|
2455
|
+
FROM settlement
|
|
2456
|
+
WHERE reverses_settlement_id = ${settlement.id}
|
|
2457
|
+
LIMIT 1
|
|
2458
|
+
`;
|
|
2459
|
+
if (alreadyReversed.length > 0) {
|
|
2321
2460
|
throw new common_1.ConflictException('Liquidação já estornada.');
|
|
2322
2461
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2462
|
+
const isReconciled = await tx.$queryRaw `
|
|
2463
|
+
SELECT id
|
|
2464
|
+
FROM bank_reconciliation
|
|
2465
|
+
WHERE settlement_id = ${settlement.id}
|
|
2466
|
+
AND status = 'reconciled'
|
|
2467
|
+
LIMIT 1
|
|
2468
|
+
`;
|
|
2469
|
+
if (isReconciled.length > 0) {
|
|
2470
|
+
throw new common_1.ConflictException('Desconciliar primeiro');
|
|
2471
|
+
}
|
|
2472
|
+
const allocations = await tx.$queryRaw `
|
|
2473
|
+
SELECT
|
|
2474
|
+
sa.id,
|
|
2475
|
+
sa.installment_id,
|
|
2476
|
+
sa.allocated_amount_cents,
|
|
2477
|
+
sa.amount_cents,
|
|
2478
|
+
sa.discount_cents,
|
|
2479
|
+
sa.interest_cents,
|
|
2480
|
+
sa.penalty_cents,
|
|
2481
|
+
fi.amount_cents AS installment_amount_cents,
|
|
2482
|
+
fi.open_amount_cents AS installment_open_amount_cents,
|
|
2483
|
+
fi.due_date AS installment_due_date,
|
|
2484
|
+
fi.status::text AS installment_status
|
|
2485
|
+
FROM settlement_allocation sa
|
|
2486
|
+
INNER JOIN financial_installment fi ON fi.id = sa.installment_id
|
|
2487
|
+
WHERE sa.settlement_id = ${settlement.id}
|
|
2488
|
+
FOR UPDATE OF fi
|
|
2489
|
+
`;
|
|
2490
|
+
if (allocations.length === 0) {
|
|
2491
|
+
throw new common_1.BadRequestException('Settlement has no allocations to reverse');
|
|
2492
|
+
}
|
|
2493
|
+
const reversalMemo = ((_a = data.reason) === null || _a === void 0 ? void 0 : _a.trim()) || ((_b = data.memo) === null || _b === void 0 ? void 0 : _b.trim()) || 'Estorno';
|
|
2494
|
+
const reversalAmountCents = -Math.abs(Number(settlement.amount_cents || 0));
|
|
2495
|
+
const reversalResult = await tx.$queryRaw `
|
|
2496
|
+
INSERT INTO settlement (
|
|
2497
|
+
person_id,
|
|
2498
|
+
bank_account_id,
|
|
2499
|
+
payment_method_id,
|
|
2500
|
+
settlement_type,
|
|
2501
|
+
entry_type,
|
|
2502
|
+
status,
|
|
2503
|
+
settled_at,
|
|
2504
|
+
amount_cents,
|
|
2505
|
+
description,
|
|
2506
|
+
external_reference,
|
|
2507
|
+
created_by_user_id,
|
|
2508
|
+
reverses_settlement_id,
|
|
2509
|
+
created_at,
|
|
2510
|
+
updated_at
|
|
2511
|
+
)
|
|
2512
|
+
VALUES (
|
|
2513
|
+
${settlement.person_id},
|
|
2514
|
+
${settlement.bank_account_id},
|
|
2515
|
+
${settlement.payment_method_id},
|
|
2516
|
+
${settlement.settlement_type}::settlement_settlement_type_enum,
|
|
2517
|
+
'reversal'::settlement_entry_type_enum,
|
|
2518
|
+
'confirmed'::settlement_status_enum,
|
|
2519
|
+
NOW(),
|
|
2520
|
+
${reversalAmountCents},
|
|
2521
|
+
${reversalMemo},
|
|
2522
|
+
NULL,
|
|
2523
|
+
${userId || settlement.created_by_user_id || null},
|
|
2524
|
+
${settlement.id},
|
|
2525
|
+
NOW(),
|
|
2526
|
+
NOW()
|
|
2527
|
+
)
|
|
2528
|
+
RETURNING id
|
|
2529
|
+
`;
|
|
2530
|
+
const reversalId = (_c = reversalResult[0]) === null || _c === void 0 ? void 0 : _c.id;
|
|
2531
|
+
if (!reversalId) {
|
|
2532
|
+
throw new common_1.BadRequestException('Could not create reversal settlement');
|
|
2533
|
+
}
|
|
2534
|
+
for (const allocation of allocations) {
|
|
2535
|
+
const originalAmount = Number((_e = (_d = allocation.amount_cents) !== null && _d !== void 0 ? _d : allocation.allocated_amount_cents) !== null && _e !== void 0 ? _e : 0);
|
|
2536
|
+
await tx.settlement_allocation.create({
|
|
2537
|
+
data: {
|
|
2538
|
+
settlement_id: reversalId,
|
|
2539
|
+
installment_id: allocation.installment_id,
|
|
2540
|
+
allocated_amount_cents: -Math.abs(originalAmount),
|
|
2541
|
+
discount_cents: -Math.abs(allocation.discount_cents || 0),
|
|
2542
|
+
interest_cents: -Math.abs(allocation.interest_cents || 0),
|
|
2543
|
+
penalty_cents: -Math.abs(allocation.penalty_cents || 0),
|
|
2544
|
+
},
|
|
2545
|
+
});
|
|
2546
|
+
const nextOpenAmountCents = Number(allocation.installment_open_amount_cents || 0) +
|
|
2547
|
+
Math.abs(originalAmount);
|
|
2548
|
+
if (nextOpenAmountCents > Number(allocation.installment_amount_cents || 0)) {
|
|
2549
|
+
throw new common_1.ConflictException(`Estorno excederia o valor original da parcela ${allocation.installment_id}`);
|
|
2331
2550
|
}
|
|
2332
|
-
const nextInstallmentStatus = this.resolveInstallmentStatus(
|
|
2551
|
+
const nextInstallmentStatus = this.resolveInstallmentStatus(Number(allocation.installment_amount_cents || 0), nextOpenAmountCents, new Date(allocation.installment_due_date), allocation.installment_status);
|
|
2333
2552
|
await tx.financial_installment.update({
|
|
2334
2553
|
where: {
|
|
2335
|
-
id:
|
|
2554
|
+
id: allocation.installment_id,
|
|
2336
2555
|
},
|
|
2337
2556
|
data: {
|
|
2338
2557
|
open_amount_cents: nextOpenAmountCents,
|
|
@@ -2340,69 +2559,39 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2340
2559
|
},
|
|
2341
2560
|
});
|
|
2342
2561
|
}
|
|
2343
|
-
await tx
|
|
2344
|
-
where: {
|
|
2345
|
-
id: settlement.id,
|
|
2346
|
-
},
|
|
2347
|
-
data: {
|
|
2348
|
-
status: 'reversed',
|
|
2349
|
-
description: [
|
|
2350
|
-
settlement.description,
|
|
2351
|
-
data.reason ? `Reversed: ${data.reason.trim()}` : 'Reversed',
|
|
2352
|
-
]
|
|
2353
|
-
.filter(Boolean)
|
|
2354
|
-
.join(' | '),
|
|
2355
|
-
},
|
|
2356
|
-
});
|
|
2357
|
-
await tx.bank_reconciliation.updateMany({
|
|
2358
|
-
where: {
|
|
2359
|
-
settlement_id: settlement.id,
|
|
2360
|
-
status: 'pending',
|
|
2361
|
-
},
|
|
2362
|
-
data: {
|
|
2363
|
-
status: 'reversed',
|
|
2364
|
-
},
|
|
2365
|
-
});
|
|
2366
|
-
await tx.bank_reconciliation.updateMany({
|
|
2367
|
-
where: {
|
|
2368
|
-
settlement_id: settlement.id,
|
|
2369
|
-
status: {
|
|
2370
|
-
in: ['reconciled', 'adjusted'],
|
|
2371
|
-
},
|
|
2372
|
-
},
|
|
2373
|
-
data: {
|
|
2374
|
-
status: 'adjusted',
|
|
2375
|
-
},
|
|
2376
|
-
});
|
|
2377
|
-
const previousTitleStatus = title.status;
|
|
2378
|
-
const nextTitleStatus = await this.recalculateTitleStatus(tx, title.id);
|
|
2562
|
+
const nextTitleStatus = await this.recalculateTitleStatus(tx, settlement.title_id);
|
|
2379
2563
|
await this.createAuditLog(tx, {
|
|
2380
2564
|
action: 'REVERSE_SETTLEMENT',
|
|
2381
2565
|
entityTable: 'financial_title',
|
|
2382
|
-
entityId: String(
|
|
2566
|
+
entityId: String(settlement.title_id),
|
|
2383
2567
|
actorUserId: userId,
|
|
2384
|
-
summary: `
|
|
2568
|
+
summary: `Created reversal ${reversalId} for settlement ${settlement.id}`,
|
|
2385
2569
|
beforeData: JSON.stringify({
|
|
2386
|
-
title_status:
|
|
2387
|
-
|
|
2570
|
+
title_status: settlement.title_status,
|
|
2571
|
+
settlement_id: settlement.id,
|
|
2572
|
+
settlement_entry_type: settlement.entry_type,
|
|
2388
2573
|
}),
|
|
2389
2574
|
afterData: JSON.stringify({
|
|
2390
2575
|
title_status: nextTitleStatus,
|
|
2391
|
-
|
|
2576
|
+
settlement_id: settlement.id,
|
|
2577
|
+
reversal_settlement_id: reversalId,
|
|
2392
2578
|
}),
|
|
2393
2579
|
});
|
|
2394
|
-
|
|
2580
|
+
const updatedTitle = await tx.financial_title.findFirst({
|
|
2395
2581
|
where: {
|
|
2396
|
-
id:
|
|
2397
|
-
title_type:
|
|
2582
|
+
id: settlement.title_id,
|
|
2583
|
+
title_type: settlement.title_type,
|
|
2398
2584
|
},
|
|
2399
2585
|
include: this.defaultTitleInclude(),
|
|
2400
2586
|
});
|
|
2587
|
+
if (!updatedTitle) {
|
|
2588
|
+
throw new common_1.NotFoundException('Financial title not found');
|
|
2589
|
+
}
|
|
2590
|
+
return {
|
|
2591
|
+
title: updatedTitle,
|
|
2592
|
+
};
|
|
2401
2593
|
});
|
|
2402
|
-
|
|
2403
|
-
throw new common_1.NotFoundException('Financial title not found');
|
|
2404
|
-
}
|
|
2405
|
-
return this.mapTitleToFront(updatedTitle);
|
|
2594
|
+
return title;
|
|
2406
2595
|
}
|
|
2407
2596
|
async updateTitleTags(titleId, titleType, tagIds, locale) {
|
|
2408
2597
|
const title = await this.getTitleById(titleId, titleType, locale);
|