@hed-hog/finance 0.0.250 → 0.0.252
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/finance.service.d.ts +1 -0
- package/dist/finance.service.d.ts.map +1 -1
- package/dist/finance.service.js +205 -137
- package/dist/finance.service.js.map +1 -1
- package/hedhog/frontend/app/accounts-payable/installments/[id]/page.tsx.ejs +176 -70
- package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +100 -5
- package/hedhog/frontend/app/accounts-receivable/installments/[id]/page.tsx.ejs +19 -20
- package/hedhog/frontend/app/page.tsx.ejs +11 -4
- package/hedhog/frontend/messages/en.json +44 -0
- package/hedhog/frontend/messages/pt.json +44 -0
- package/hedhog/query/constraints.sql +3 -1
- package/package.json +7 -7
- package/src/finance.service.ts +98 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finance.service.d.ts","sourceRoot":"","sources":["../src/finance.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"finance.service.d.ts","sourceRoot":"","sources":["../src/finance.service.ts"],"names":[],"mappings":"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"}
|
package/dist/finance.service.js
CHANGED
|
@@ -591,7 +591,7 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
591
591
|
const today = this.startOfDay(new Date());
|
|
592
592
|
const day7 = this.addDays(today, 7);
|
|
593
593
|
const day30 = this.addDays(today, 30);
|
|
594
|
-
const payableInstallments = this.extractOpenInstallments(payables);
|
|
594
|
+
const payableInstallments = this.extractOpenInstallments((payables || []).filter((title) => this.isPayableTitleApproved(title)));
|
|
595
595
|
const receivableInstallments = this.extractOpenInstallments(receivables);
|
|
596
596
|
const saldoCaixa = (bankAccounts || [])
|
|
597
597
|
.filter((account) => (account === null || account === void 0 ? void 0 : account.ativo) !== false)
|
|
@@ -617,6 +617,10 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
617
617
|
(installment === null || installment === void 0 ? void 0 : installment.status) === 'vencido' ||
|
|
618
618
|
(installment === null || installment === void 0 ? void 0 : installment.status) === 'parcial'));
|
|
619
619
|
}
|
|
620
|
+
isPayableTitleApproved(title) {
|
|
621
|
+
const status = String((title === null || title === void 0 ? void 0 : title.status) || '').toLowerCase();
|
|
622
|
+
return status !== 'rascunho' && status !== 'cancelado';
|
|
623
|
+
}
|
|
620
624
|
sumInstallmentsDueBetween(installments, startDate, endDate) {
|
|
621
625
|
return (installments || [])
|
|
622
626
|
.filter((installment) => {
|
|
@@ -2035,7 +2039,36 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2035
2039
|
if (title.status === 'settled' || title.status === 'canceled') {
|
|
2036
2040
|
throw new common_1.BadRequestException('Title cannot be canceled in current status');
|
|
2037
2041
|
}
|
|
2042
|
+
const hasActiveSettlements = await tx.settlement_allocation.findFirst({
|
|
2043
|
+
where: {
|
|
2044
|
+
financial_installment: {
|
|
2045
|
+
title_id: title.id,
|
|
2046
|
+
},
|
|
2047
|
+
settlement: {
|
|
2048
|
+
status: {
|
|
2049
|
+
not: 'reversed',
|
|
2050
|
+
},
|
|
2051
|
+
},
|
|
2052
|
+
},
|
|
2053
|
+
select: {
|
|
2054
|
+
id: true,
|
|
2055
|
+
},
|
|
2056
|
+
});
|
|
2057
|
+
if (hasActiveSettlements) {
|
|
2058
|
+
throw new common_1.ConflictException('Não é possível cancelar enquanto houver liquidações ativas. Estorne primeiro.');
|
|
2059
|
+
}
|
|
2038
2060
|
await this.assertDateNotInClosedPeriod(tx, title.competence_date, 'cancel title');
|
|
2061
|
+
await tx.financial_installment.updateMany({
|
|
2062
|
+
where: {
|
|
2063
|
+
title_id: title.id,
|
|
2064
|
+
status: {
|
|
2065
|
+
not: 'canceled',
|
|
2066
|
+
},
|
|
2067
|
+
},
|
|
2068
|
+
data: {
|
|
2069
|
+
status: 'canceled',
|
|
2070
|
+
},
|
|
2071
|
+
});
|
|
2039
2072
|
await tx.financial_title.update({
|
|
2040
2073
|
where: { id: title.id },
|
|
2041
2074
|
data: {
|
|
@@ -2076,150 +2109,165 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2076
2109
|
if (Number.isNaN(settledAt.getTime())) {
|
|
2077
2110
|
throw new common_1.BadRequestException('Invalid settlement date');
|
|
2078
2111
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
select: {
|
|
2087
|
-
id: true,
|
|
2088
|
-
person_id: true,
|
|
2089
|
-
status: true,
|
|
2090
|
-
competence_date: true,
|
|
2091
|
-
},
|
|
2092
|
-
});
|
|
2093
|
-
if (!title) {
|
|
2094
|
-
throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('itemNotFound', locale, `Financial title with ID ${titleId} not found`).replace('{{item}}', 'Financial title'));
|
|
2095
|
-
}
|
|
2096
|
-
if (!['open', 'partial'].includes(title.status)) {
|
|
2097
|
-
throw new common_1.BadRequestException('Only open/partial titles can be settled');
|
|
2098
|
-
}
|
|
2099
|
-
await this.assertDateNotInClosedPeriod(tx, title.competence_date, 'settle installment');
|
|
2100
|
-
const installment = await tx.financial_installment.findFirst({
|
|
2101
|
-
where: {
|
|
2102
|
-
id: data.installment_id,
|
|
2103
|
-
title_id: title.id,
|
|
2104
|
-
},
|
|
2105
|
-
select: {
|
|
2106
|
-
id: true,
|
|
2107
|
-
title_id: true,
|
|
2108
|
-
amount_cents: true,
|
|
2109
|
-
open_amount_cents: true,
|
|
2110
|
-
due_date: true,
|
|
2111
|
-
status: true,
|
|
2112
|
-
},
|
|
2113
|
-
});
|
|
2114
|
-
if (!installment) {
|
|
2115
|
-
throw new common_1.BadRequestException('Installment not found for this title');
|
|
2116
|
-
}
|
|
2117
|
-
if (installment.status === 'settled' || installment.status === 'canceled') {
|
|
2118
|
-
throw new common_1.BadRequestException('This installment cannot be settled');
|
|
2119
|
-
}
|
|
2120
|
-
if (amountCents > installment.open_amount_cents) {
|
|
2121
|
-
throw new common_1.BadRequestException('Settlement amount exceeds open amount');
|
|
2122
|
-
}
|
|
2123
|
-
const paymentMethodId = await this.resolvePaymentMethodId(tx, data.payment_channel);
|
|
2124
|
-
const settlement = await tx.settlement.create({
|
|
2125
|
-
data: {
|
|
2126
|
-
person_id: title.person_id,
|
|
2127
|
-
bank_account_id: data.bank_account_id || null,
|
|
2128
|
-
payment_method_id: paymentMethodId,
|
|
2129
|
-
settlement_type: titleType,
|
|
2130
|
-
status: 'confirmed',
|
|
2131
|
-
settled_at: settledAt,
|
|
2132
|
-
amount_cents: amountCents,
|
|
2133
|
-
description: ((_a = data.description) === null || _a === void 0 ? void 0 : _a.trim()) || null,
|
|
2134
|
-
created_by_user_id: userId,
|
|
2135
|
-
},
|
|
2136
|
-
});
|
|
2137
|
-
await tx.settlement_allocation.create({
|
|
2138
|
-
data: {
|
|
2139
|
-
settlement_id: settlement.id,
|
|
2140
|
-
installment_id: installment.id,
|
|
2141
|
-
allocated_amount_cents: amountCents,
|
|
2142
|
-
discount_cents: this.toCents(data.discount || 0),
|
|
2143
|
-
interest_cents: this.toCents(data.interest || 0),
|
|
2144
|
-
penalty_cents: this.toCents(data.penalty || 0),
|
|
2145
|
-
},
|
|
2146
|
-
});
|
|
2147
|
-
const decrementResult = await tx.financial_installment.updateMany({
|
|
2148
|
-
where: {
|
|
2149
|
-
id: installment.id,
|
|
2150
|
-
open_amount_cents: {
|
|
2151
|
-
gte: amountCents,
|
|
2112
|
+
try {
|
|
2113
|
+
const result = await this.prisma.$transaction(async (tx) => {
|
|
2114
|
+
var _a;
|
|
2115
|
+
const title = await tx.financial_title.findFirst({
|
|
2116
|
+
where: {
|
|
2117
|
+
id: titleId,
|
|
2118
|
+
title_type: titleType,
|
|
2152
2119
|
},
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2120
|
+
select: {
|
|
2121
|
+
id: true,
|
|
2122
|
+
person_id: true,
|
|
2123
|
+
status: true,
|
|
2124
|
+
competence_date: true,
|
|
2157
2125
|
},
|
|
2158
|
-
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2126
|
+
});
|
|
2127
|
+
if (!title) {
|
|
2128
|
+
throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('itemNotFound', locale, `Financial title with ID ${titleId} not found`).replace('{{item}}', 'Financial title'));
|
|
2129
|
+
}
|
|
2130
|
+
if (!['open', 'partial'].includes(title.status)) {
|
|
2131
|
+
if (title.status === 'canceled') {
|
|
2132
|
+
throw new common_1.ConflictException('Título cancelado não pode receber baixa');
|
|
2133
|
+
}
|
|
2134
|
+
throw new common_1.BadRequestException('Only open/partial titles can be settled');
|
|
2135
|
+
}
|
|
2136
|
+
await this.assertDateNotInClosedPeriod(tx, settledAt, 'settle installment');
|
|
2137
|
+
const installment = await tx.financial_installment.findFirst({
|
|
2138
|
+
where: {
|
|
2139
|
+
id: data.installment_id,
|
|
2140
|
+
title_id: title.id,
|
|
2141
|
+
},
|
|
2142
|
+
select: {
|
|
2143
|
+
id: true,
|
|
2144
|
+
title_id: true,
|
|
2145
|
+
amount_cents: true,
|
|
2146
|
+
open_amount_cents: true,
|
|
2147
|
+
due_date: true,
|
|
2148
|
+
status: true,
|
|
2149
|
+
},
|
|
2150
|
+
});
|
|
2151
|
+
if (!installment) {
|
|
2152
|
+
throw new common_1.BadRequestException('Installment not found for this title');
|
|
2153
|
+
}
|
|
2154
|
+
if (installment.status === 'settled' || installment.status === 'canceled') {
|
|
2155
|
+
if (installment.status === 'settled') {
|
|
2156
|
+
throw new common_1.ConflictException('Parcela já liquidada');
|
|
2157
|
+
}
|
|
2158
|
+
throw new common_1.ConflictException('Parcela cancelada não pode receber baixa');
|
|
2159
|
+
}
|
|
2160
|
+
if (amountCents > installment.open_amount_cents) {
|
|
2161
|
+
throw new common_1.ConflictException('Settlement amount exceeds open amount');
|
|
2162
|
+
}
|
|
2163
|
+
const paymentMethodId = await this.resolvePaymentMethodId(tx, data.payment_channel);
|
|
2164
|
+
const settlement = await tx.settlement.create({
|
|
2165
|
+
data: {
|
|
2166
|
+
person_id: title.person_id,
|
|
2167
|
+
bank_account_id: data.bank_account_id || null,
|
|
2168
|
+
payment_method_id: paymentMethodId,
|
|
2169
|
+
settlement_type: titleType,
|
|
2170
|
+
status: 'confirmed',
|
|
2171
|
+
settled_at: settledAt,
|
|
2172
|
+
amount_cents: amountCents,
|
|
2173
|
+
description: ((_a = data.description) === null || _a === void 0 ? void 0 : _a.trim()) || null,
|
|
2174
|
+
created_by_user_id: userId,
|
|
2175
|
+
},
|
|
2176
|
+
});
|
|
2177
|
+
await tx.settlement_allocation.create({
|
|
2178
|
+
data: {
|
|
2179
|
+
settlement_id: settlement.id,
|
|
2180
|
+
installment_id: installment.id,
|
|
2181
|
+
allocated_amount_cents: amountCents,
|
|
2182
|
+
discount_cents: this.toCents(data.discount || 0),
|
|
2183
|
+
interest_cents: this.toCents(data.interest || 0),
|
|
2184
|
+
penalty_cents: this.toCents(data.penalty || 0),
|
|
2185
|
+
},
|
|
2186
|
+
});
|
|
2187
|
+
const decrementResult = await tx.financial_installment.updateMany({
|
|
2181
2188
|
where: {
|
|
2182
|
-
id:
|
|
2189
|
+
id: installment.id,
|
|
2190
|
+
open_amount_cents: {
|
|
2191
|
+
gte: amountCents,
|
|
2192
|
+
},
|
|
2183
2193
|
},
|
|
2184
2194
|
data: {
|
|
2185
|
-
|
|
2195
|
+
open_amount_cents: {
|
|
2196
|
+
decrement: amountCents,
|
|
2197
|
+
},
|
|
2186
2198
|
},
|
|
2187
2199
|
});
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
}
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2200
|
+
if (decrementResult.count !== 1) {
|
|
2201
|
+
throw new common_1.BadRequestException('Installment was updated concurrently, please try again');
|
|
2202
|
+
}
|
|
2203
|
+
const updatedInstallment = await tx.financial_installment.findUnique({
|
|
2204
|
+
where: {
|
|
2205
|
+
id: installment.id,
|
|
2206
|
+
},
|
|
2207
|
+
select: {
|
|
2208
|
+
id: true,
|
|
2209
|
+
amount_cents: true,
|
|
2210
|
+
open_amount_cents: true,
|
|
2211
|
+
due_date: true,
|
|
2212
|
+
status: true,
|
|
2213
|
+
},
|
|
2214
|
+
});
|
|
2215
|
+
if (!updatedInstallment) {
|
|
2216
|
+
throw new common_1.NotFoundException('Installment not found');
|
|
2217
|
+
}
|
|
2218
|
+
const nextInstallmentStatus = this.resolveInstallmentStatus(updatedInstallment.amount_cents, updatedInstallment.open_amount_cents, updatedInstallment.due_date);
|
|
2219
|
+
if (updatedInstallment.status !== nextInstallmentStatus) {
|
|
2220
|
+
await tx.financial_installment.update({
|
|
2221
|
+
where: {
|
|
2222
|
+
id: updatedInstallment.id,
|
|
2223
|
+
},
|
|
2224
|
+
data: {
|
|
2225
|
+
status: nextInstallmentStatus,
|
|
2226
|
+
},
|
|
2227
|
+
});
|
|
2228
|
+
}
|
|
2229
|
+
const previousTitleStatus = title.status;
|
|
2230
|
+
const nextTitleStatus = await this.recalculateTitleStatus(tx, title.id);
|
|
2231
|
+
await this.createAuditLog(tx, {
|
|
2232
|
+
action: 'SETTLE_INSTALLMENT',
|
|
2233
|
+
entityTable: 'financial_title',
|
|
2234
|
+
entityId: String(title.id),
|
|
2235
|
+
actorUserId: userId,
|
|
2236
|
+
summary: `Settled installment ${installment.id} of title ${title.id}`,
|
|
2237
|
+
beforeData: JSON.stringify({
|
|
2238
|
+
title_status: previousTitleStatus,
|
|
2239
|
+
installment_open_amount_cents: installment.open_amount_cents,
|
|
2240
|
+
}),
|
|
2241
|
+
afterData: JSON.stringify({
|
|
2242
|
+
title_status: nextTitleStatus,
|
|
2243
|
+
installment_open_amount_cents: updatedInstallment.open_amount_cents,
|
|
2244
|
+
settlement_id: settlement.id,
|
|
2245
|
+
}),
|
|
2246
|
+
});
|
|
2247
|
+
const updatedTitle = await tx.financial_title.findFirst({
|
|
2248
|
+
where: {
|
|
2249
|
+
id: title.id,
|
|
2250
|
+
title_type: titleType,
|
|
2251
|
+
},
|
|
2252
|
+
include: this.defaultTitleInclude(),
|
|
2253
|
+
});
|
|
2254
|
+
if (!updatedTitle) {
|
|
2255
|
+
throw new common_1.NotFoundException('Financial title not found');
|
|
2256
|
+
}
|
|
2257
|
+
return {
|
|
2258
|
+
title: updatedTitle,
|
|
2259
|
+
settlementId: settlement.id,
|
|
2260
|
+
};
|
|
2213
2261
|
});
|
|
2214
|
-
|
|
2215
|
-
|
|
2262
|
+
return Object.assign(Object.assign({}, this.mapTitleToFront(result.title)), { settlementId: String(result.settlementId) });
|
|
2263
|
+
}
|
|
2264
|
+
catch (error) {
|
|
2265
|
+
const message = String((error === null || error === void 0 ? void 0 : error.message) || '');
|
|
2266
|
+
if (message.includes('Soma de settlement_allocation')) {
|
|
2267
|
+
throw new common_1.ConflictException('Não foi possível registrar a baixa. Existe alocação ativa acima do limite da parcela.');
|
|
2216
2268
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
settlementId: settlement.id,
|
|
2220
|
-
};
|
|
2221
|
-
});
|
|
2222
|
-
return Object.assign(Object.assign({}, this.mapTitleToFront(result.title)), { settlementId: String(result.settlementId) });
|
|
2269
|
+
throw error;
|
|
2270
|
+
}
|
|
2223
2271
|
}
|
|
2224
2272
|
async reverseTitleSettlement(titleId, settlementId, data, titleType, locale, userId) {
|
|
2225
2273
|
const updatedTitle = await this.prisma.$transaction(async (tx) => {
|
|
@@ -2270,7 +2318,7 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2270
2318
|
throw new common_1.NotFoundException('Settlement not found for this title');
|
|
2271
2319
|
}
|
|
2272
2320
|
if (settlement.status === 'reversed') {
|
|
2273
|
-
throw new common_1.
|
|
2321
|
+
throw new common_1.ConflictException('Liquidação já estornada.');
|
|
2274
2322
|
}
|
|
2275
2323
|
for (const allocation of settlement.settlement_allocation) {
|
|
2276
2324
|
const installment = allocation.financial_installment;
|
|
@@ -2306,6 +2354,26 @@ let FinanceService = FinanceService_1 = class FinanceService {
|
|
|
2306
2354
|
.join(' | '),
|
|
2307
2355
|
},
|
|
2308
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
|
+
});
|
|
2309
2377
|
const previousTitleStatus = title.status;
|
|
2310
2378
|
const nextTitleStatus = await this.recalculateTitleStatus(tx, title.id);
|
|
2311
2379
|
await this.createAuditLog(tx, {
|