@hed-hog/finance 0.0.274 → 0.0.276

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.
Files changed (40) hide show
  1. package/README.md +228 -126
  2. package/dist/dto/create-bank-reconciliation.dto.d.ts +8 -0
  3. package/dist/dto/create-bank-reconciliation.dto.d.ts.map +1 -0
  4. package/dist/dto/create-bank-reconciliation.dto.js +43 -0
  5. package/dist/dto/create-bank-reconciliation.dto.js.map +1 -0
  6. package/dist/finance-data.controller.d.ts +2 -0
  7. package/dist/finance-data.controller.d.ts.map +1 -1
  8. package/dist/finance-statements.controller.d.ts +42 -0
  9. package/dist/finance-statements.controller.d.ts.map +1 -1
  10. package/dist/finance-statements.controller.js +13 -0
  11. package/dist/finance-statements.controller.js.map +1 -1
  12. package/dist/finance.service.d.ts +44 -0
  13. package/dist/finance.service.d.ts.map +1 -1
  14. package/dist/finance.service.js +98 -9
  15. package/dist/finance.service.js.map +1 -1
  16. package/hedhog/data/route.yaml +9 -0
  17. package/hedhog/frontend/app/_components/person-field-with-create.tsx.ejs +126 -126
  18. package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +373 -373
  19. package/hedhog/frontend/app/accounts-payable/installments/[id]/page.tsx.ejs +1270 -1270
  20. package/hedhog/frontend/app/accounts-receivable/installments/[id]/page.tsx.ejs +982 -982
  21. package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +686 -686
  22. package/hedhog/frontend/app/cash-and-banks/bank-reconciliation/page.tsx.ejs +152 -32
  23. package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +986 -986
  24. package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +492 -492
  25. package/hedhog/frontend/app/page.tsx.ejs +372 -372
  26. package/hedhog/frontend/app/planning/cash-flow-forecast/page.tsx.ejs +329 -329
  27. package/hedhog/frontend/app/planning/receivables-calendar/page.tsx.ejs +227 -227
  28. package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +408 -408
  29. package/hedhog/frontend/messages/en.json +15 -5
  30. package/hedhog/frontend/messages/pt.json +15 -5
  31. package/package.json +7 -7
  32. package/src/dto/create-bank-reconciliation.dto.ts +24 -0
  33. package/src/finance-statements.controller.ts +14 -0
  34. package/src/finance.module.ts +43 -43
  35. package/src/finance.service.ts +118 -0
  36. package/src/index.ts +14 -14
  37. package/dist/finance.controller.d.ts +0 -276
  38. package/dist/finance.controller.d.ts.map +0 -1
  39. package/dist/finance.controller.js +0 -110
  40. package/dist/finance.controller.js.map +0 -1
@@ -100,11 +100,11 @@
100
100
  }
101
101
  },
102
102
  "PersonFieldWithCreate": {
103
- "sheet": {
104
- "title": "New {entityLabel}",
105
- "description": "Only name and type are required. You can complete the remaining fields now or later.",
106
- "descriptionIndividualOnly": "Only name is required. You can complete the remaining fields now or later."
107
- },
103
+ "sheet": {
104
+ "title": "New {entityLabel}",
105
+ "description": "Only name and type are required. You can complete the remaining fields now or later.",
106
+ "descriptionIndividualOnly": "Only name is required. You can complete the remaining fields now or later."
107
+ },
108
108
  "common": {
109
109
  "select": "Select"
110
110
  },
@@ -928,6 +928,8 @@
928
928
  "statement": {
929
929
  "title": "Statement Transactions",
930
930
  "description": "Select a transaction to reconcile",
931
+ "reconciledTitle": "Reconciled transactions",
932
+ "reconciledDescription": "You can undo reconciliations when needed.",
931
933
  "emptyTitle": "All reconciled!",
932
934
  "emptyDescription": "There are no pending transactions."
933
935
  },
@@ -941,6 +943,14 @@
941
943
  "ready": {
942
944
  "title": "Ready to Reconcile",
943
945
  "description": "Transaction and title selected. Click \"Reconcile\" to link them."
946
+ },
947
+ "unreconcile": {
948
+ "action": "Unreconcile",
949
+ "title": "Undo reconciliation",
950
+ "description": "Do you really want to undo this reconciliation? The transaction will return to pending.",
951
+ "confirm": "Unreconcile",
952
+ "success": "Reconciliation undone successfully",
953
+ "error": "Could not undo reconciliation"
944
954
  }
945
955
  },
946
956
  "StatementsPage": {
@@ -100,11 +100,11 @@
100
100
  }
101
101
  },
102
102
  "PersonFieldWithCreate": {
103
- "sheet": {
104
- "title": "Novo {entityLabel}",
105
- "description": "Apenas nome e tipo são obrigatórios. Você pode completar os demais dados agora ou depois.",
106
- "descriptionIndividualOnly": "Apenas nome é obrigatório. Você pode completar os demais dados agora ou depois."
107
- },
103
+ "sheet": {
104
+ "title": "Novo {entityLabel}",
105
+ "description": "Apenas nome e tipo são obrigatórios. Você pode completar os demais dados agora ou depois.",
106
+ "descriptionIndividualOnly": "Apenas nome é obrigatório. Você pode completar os demais dados agora ou depois."
107
+ },
108
108
  "common": {
109
109
  "select": "Selecione"
110
110
  },
@@ -928,6 +928,8 @@
928
928
  "statement": {
929
929
  "title": "Transações do Extrato",
930
930
  "description": "Selecione uma transação para conciliar",
931
+ "reconciledTitle": "Transações conciliadas",
932
+ "reconciledDescription": "Você pode desfazer conciliações quando necessário.",
931
933
  "emptyTitle": "Tudo conciliado!",
932
934
  "emptyDescription": "Não há transações pendentes."
933
935
  },
@@ -941,6 +943,14 @@
941
943
  "ready": {
942
944
  "title": "Pronto para Conciliar",
943
945
  "description": "Transação e título selecionados. Clique em \"Conciliar\" para vincular."
946
+ },
947
+ "unreconcile": {
948
+ "action": "Desconciliar",
949
+ "title": "Desfazer conciliação",
950
+ "description": "Deseja realmente desfazer esta conciliação? A transação voltará para pendente.",
951
+ "confirm": "Desconciliar",
952
+ "success": "Conciliação desfeita com sucesso",
953
+ "error": "Não foi possível desfazer a conciliação"
944
954
  }
945
955
  },
946
956
  "StatementsPage": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/finance",
3
- "version": "0.0.274",
3
+ "version": "0.0.276",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -9,14 +9,14 @@
9
9
  "@nestjs/core": "^11",
10
10
  "@nestjs/jwt": "^11",
11
11
  "@nestjs/mapped-types": "*",
12
- "@hed-hog/contact": "0.0.274",
13
- "@hed-hog/api-prisma": "0.0.5",
14
- "@hed-hog/api-pagination": "0.0.6",
12
+ "@hed-hog/contact": "0.0.276",
15
13
  "@hed-hog/api": "0.0.4",
16
- "@hed-hog/api-types": "0.0.1",
17
- "@hed-hog/tag": "0.0.274",
14
+ "@hed-hog/api-prisma": "0.0.5",
15
+ "@hed-hog/tag": "0.0.276",
18
16
  "@hed-hog/api-locale": "0.0.13",
19
- "@hed-hog/core": "0.0.274"
17
+ "@hed-hog/api-types": "0.0.1",
18
+ "@hed-hog/api-pagination": "0.0.6",
19
+ "@hed-hog/core": "0.0.276"
20
20
  },
21
21
  "exports": {
22
22
  ".": {
@@ -0,0 +1,24 @@
1
+ import { Type } from 'class-transformer';
2
+ import { IsInt, IsOptional, IsString } from 'class-validator';
3
+
4
+ export class CreateBankReconciliationDto {
5
+ @Type(() => Number)
6
+ @IsInt()
7
+ title_id: number;
8
+
9
+ @Type(() => Number)
10
+ @IsInt()
11
+ installment_id: number;
12
+
13
+ @Type(() => Number)
14
+ @IsInt()
15
+ bank_statement_line_id: number;
16
+
17
+ @IsOptional()
18
+ @IsString()
19
+ payment_channel?: string;
20
+
21
+ @IsOptional()
22
+ @IsString()
23
+ description?: string;
24
+ }
@@ -13,6 +13,7 @@ import {
13
13
  } from '@nestjs/common';
14
14
  import { FileInterceptor } from '@nestjs/platform-express';
15
15
  import { Response } from 'express';
16
+ import { CreateBankReconciliationDto } from './dto/create-bank-reconciliation.dto';
16
17
  import { CreateBankStatementAdjustmentDto } from './dto/create-bank-statement-adjustment.dto';
17
18
  import { FinanceService } from './finance.service';
18
19
 
@@ -49,6 +50,19 @@ export class FinanceStatementsController {
49
50
  return this.financeService.getBankReconciliationSummary(parsedBankAccountId);
50
51
  }
51
52
 
53
+ @Post('bank-reconciliations')
54
+ async createBankReconciliation(
55
+ @Body() data: CreateBankReconciliationDto,
56
+ @Locale() locale: string,
57
+ @User() user,
58
+ ) {
59
+ return this.financeService.createBankReconciliation(
60
+ data,
61
+ locale,
62
+ user?.id,
63
+ );
64
+ }
65
+
52
66
  @Get('statements/export')
53
67
  async exportBankStatementsCsv(
54
68
  @Query('bank_account_id') bankAccountId: string,
@@ -1,43 +1,43 @@
1
- import { LocaleModule } from '@hed-hog/api-locale';
2
- import { PaginationModule } from '@hed-hog/api-pagination';
3
- import { PrismaModule } from '@hed-hog/api-prisma';
4
- import { AiModule, FileModule } from '@hed-hog/core';
5
- import { forwardRef, Module } from '@nestjs/common';
6
- import { ConfigModule } from '@nestjs/config';
7
- import { FinanceAuditLogsController } from './finance-audit-logs.controller';
8
- import { FinanceBankAccountsController } from './finance-bank-accounts.controller';
9
- import { FinanceCategoriesController } from './finance-categories.controller';
10
- import { FinanceCollectionsController } from './finance-collections.controller';
11
- import { FinanceCostCentersController } from './finance-cost-centers.controller';
12
- import { FinanceDataController } from './finance-data.controller';
13
- import { FinanceInstallmentsController } from './finance-installments.controller';
14
- import { FinancePeriodCloseController } from './finance-period-close.controller';
15
- import { FinanceStatementsController } from './finance-statements.controller';
16
- import { FinanceTransfersController } from './finance-transfers.controller';
17
- import { FinanceService } from './finance.service';
18
-
19
- @Module({
20
- imports: [
21
- ConfigModule.forRoot(),
22
- forwardRef(() => PaginationModule),
23
- forwardRef(() => PrismaModule),
24
- forwardRef(() => LocaleModule),
25
- forwardRef(() => AiModule),
26
- forwardRef(() => FileModule),
27
- ],
28
- controllers: [
29
- FinanceAuditLogsController,
30
- FinanceDataController,
31
- FinanceInstallmentsController,
32
- FinanceBankAccountsController,
33
- FinanceCategoriesController,
34
- FinanceCollectionsController,
35
- FinanceCostCentersController,
36
- FinancePeriodCloseController,
37
- FinanceStatementsController,
38
- FinanceTransfersController,
39
- ],
40
- providers: [FinanceService],
41
- exports: [FinanceService],
42
- })
43
- export class FinanceModule {}
1
+ import { LocaleModule } from '@hed-hog/api-locale';
2
+ import { PaginationModule } from '@hed-hog/api-pagination';
3
+ import { PrismaModule } from '@hed-hog/api-prisma';
4
+ import { AiModule, FileModule } from '@hed-hog/core';
5
+ import { forwardRef, Module } from '@nestjs/common';
6
+ import { ConfigModule } from '@nestjs/config';
7
+ import { FinanceAuditLogsController } from './finance-audit-logs.controller';
8
+ import { FinanceBankAccountsController } from './finance-bank-accounts.controller';
9
+ import { FinanceCategoriesController } from './finance-categories.controller';
10
+ import { FinanceCollectionsController } from './finance-collections.controller';
11
+ import { FinanceCostCentersController } from './finance-cost-centers.controller';
12
+ import { FinanceDataController } from './finance-data.controller';
13
+ import { FinanceInstallmentsController } from './finance-installments.controller';
14
+ import { FinancePeriodCloseController } from './finance-period-close.controller';
15
+ import { FinanceStatementsController } from './finance-statements.controller';
16
+ import { FinanceTransfersController } from './finance-transfers.controller';
17
+ import { FinanceService } from './finance.service';
18
+
19
+ @Module({
20
+ imports: [
21
+ ConfigModule.forRoot(),
22
+ forwardRef(() => PaginationModule),
23
+ forwardRef(() => PrismaModule),
24
+ forwardRef(() => LocaleModule),
25
+ forwardRef(() => AiModule),
26
+ forwardRef(() => FileModule),
27
+ ],
28
+ controllers: [
29
+ FinanceAuditLogsController,
30
+ FinanceDataController,
31
+ FinanceInstallmentsController,
32
+ FinanceBankAccountsController,
33
+ FinanceCategoriesController,
34
+ FinanceCollectionsController,
35
+ FinanceCostCentersController,
36
+ FinancePeriodCloseController,
37
+ FinanceStatementsController,
38
+ FinanceTransfersController,
39
+ ],
40
+ providers: [FinanceService],
41
+ exports: [FinanceService],
42
+ })
43
+ export class FinanceModule {}
@@ -18,6 +18,7 @@ import {
18
18
  import { createHash } from 'node:crypto';
19
19
  import { readFile } from 'node:fs/promises';
20
20
  import { CreateBankAccountDto } from './dto/create-bank-account.dto';
21
+ import { CreateBankReconciliationDto } from './dto/create-bank-reconciliation.dto';
21
22
  import { CreateBankStatementAdjustmentDto } from './dto/create-bank-statement-adjustment.dto';
22
23
  import { CreateCostCenterDto } from './dto/create-cost-center.dto';
23
24
  import { CreateFinanceCategoryDto } from './dto/create-finance-category.dto';
@@ -2742,6 +2743,21 @@ export class FinanceService {
2742
2743
  id: true,
2743
2744
  },
2744
2745
  },
2746
+ bank_reconciliation: {
2747
+ where: {
2748
+ status: {
2749
+ in: ['pending', 'reconciled', 'adjusted'],
2750
+ },
2751
+ },
2752
+ select: {
2753
+ id: true,
2754
+ settlement_id: true,
2755
+ },
2756
+ orderBy: {
2757
+ id: 'desc',
2758
+ },
2759
+ take: 1,
2760
+ },
2745
2761
  },
2746
2762
  orderBy: [{ posted_date: 'desc' }, { id: 'desc' }],
2747
2763
  });
@@ -2754,9 +2770,111 @@ export class FinanceService {
2754
2770
  valor: this.fromCents(statement.amount_cents),
2755
2771
  tipo: statement.amount_cents >= 0 ? 'entrada' : 'saida',
2756
2772
  statusConciliacao: this.mapStatementStatusToPt(statement.status),
2773
+ reconciliationId: statement.bank_reconciliation[0]?.id
2774
+ ? String(statement.bank_reconciliation[0].id)
2775
+ : null,
2776
+ settlementId: statement.bank_reconciliation[0]?.settlement_id
2777
+ ? String(statement.bank_reconciliation[0].settlement_id)
2778
+ : null,
2757
2779
  }));
2758
2780
  }
2759
2781
 
2782
+ async createBankReconciliation(
2783
+ data: CreateBankReconciliationDto,
2784
+ locale: string,
2785
+ userId?: number,
2786
+ ) {
2787
+ const installment = await this.prisma.financial_installment.findUnique({
2788
+ where: {
2789
+ id: data.installment_id,
2790
+ },
2791
+ select: {
2792
+ id: true,
2793
+ title_id: true,
2794
+ },
2795
+ });
2796
+
2797
+ if (!installment) {
2798
+ throw new NotFoundException('Installment not found');
2799
+ }
2800
+
2801
+ if (installment.title_id !== data.title_id) {
2802
+ throw new ConflictException('Installment does not belong to informed title');
2803
+ }
2804
+
2805
+ const title = await this.prisma.financial_title.findUnique({
2806
+ where: {
2807
+ id: data.title_id,
2808
+ },
2809
+ select: {
2810
+ id: true,
2811
+ title_type: true,
2812
+ },
2813
+ });
2814
+
2815
+ if (!title) {
2816
+ throw new NotFoundException(
2817
+ getLocaleText(
2818
+ 'itemNotFound',
2819
+ locale,
2820
+ `Financial title with ID ${data.title_id} not found`,
2821
+ ).replace('{{item}}', 'Financial title'),
2822
+ );
2823
+ }
2824
+
2825
+ const statementLine = await this.prisma.bank_statement_line.findUnique({
2826
+ where: {
2827
+ id: data.bank_statement_line_id,
2828
+ },
2829
+ select: {
2830
+ id: true,
2831
+ bank_account_id: true,
2832
+ posted_date: true,
2833
+ amount_cents: true,
2834
+ description: true,
2835
+ status: true,
2836
+ },
2837
+ });
2838
+
2839
+ if (!statementLine) {
2840
+ throw new NotFoundException('Bank statement line not found');
2841
+ }
2842
+
2843
+ if (!['pending', 'imported'].includes(statementLine.status)) {
2844
+ throw new ConflictException('Bank statement line already reconciled');
2845
+ }
2846
+
2847
+ const isIncoming = statementLine.amount_cents >= 0;
2848
+
2849
+ if (isIncoming && title.title_type !== 'receivable') {
2850
+ throw new ConflictException(
2851
+ 'Incoming bank statements can only be reconciled with receivable titles',
2852
+ );
2853
+ }
2854
+
2855
+ if (!isIncoming && title.title_type !== 'payable') {
2856
+ throw new ConflictException(
2857
+ 'Outgoing bank statements can only be reconciled with payable titles',
2858
+ );
2859
+ }
2860
+
2861
+ return this.settleTitleInstallment(
2862
+ title.id,
2863
+ {
2864
+ installment_id: installment.id,
2865
+ amount: this.fromCents(Math.abs(statementLine.amount_cents)),
2866
+ settled_at: statementLine.posted_date.toISOString(),
2867
+ bank_account_id: statementLine.bank_account_id,
2868
+ bank_statement_line_id: statementLine.id,
2869
+ payment_channel: data.payment_channel || 'transferencia',
2870
+ description: data.description?.trim() || statementLine.description,
2871
+ },
2872
+ title.title_type as TitleType,
2873
+ locale,
2874
+ userId,
2875
+ );
2876
+ }
2877
+
2760
2878
  async getBankReconciliationSummary(bankAccountId: number) {
2761
2879
  const pendingStatements = await this.prisma.bank_statement_line.findMany({
2762
2880
  where: {
package/src/index.ts CHANGED
@@ -1,14 +1,14 @@
1
- export * from './dto/create-financial-title.dto';
2
- export * from './finance-audit-logs.controller';
3
- export * from './finance-bank-accounts.controller';
4
- export * from './finance-categories.controller';
5
- export * from './finance-collections.controller';
6
- export * from './finance-cost-centers.controller';
7
- export * from './finance-data.controller';
8
- export * from './finance-installments.controller';
9
- export * from './finance-period-close.controller';
10
- export * from './finance-statements.controller';
11
- export * from './finance-transfers.controller';
12
- export * from './finance.module';
13
- export * from './finance.service';
14
-
1
+ export * from './dto/create-financial-title.dto';
2
+ export * from './finance-audit-logs.controller';
3
+ export * from './finance-bank-accounts.controller';
4
+ export * from './finance-categories.controller';
5
+ export * from './finance-collections.controller';
6
+ export * from './finance-cost-centers.controller';
7
+ export * from './finance-data.controller';
8
+ export * from './finance-installments.controller';
9
+ export * from './finance-period-close.controller';
10
+ export * from './finance-statements.controller';
11
+ export * from './finance-transfers.controller';
12
+ export * from './finance.module';
13
+ export * from './finance.service';
14
+