@silexpert/core 2.0.120 → 2.0.122

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 (45) hide show
  1. package/dist/{index-BvApezAZ.d.mts → index-BTRchHCY.d.mts} +1187 -1114
  2. package/dist/index-BTRchHCY.d.mts.map +1 -0
  3. package/dist/index.d.mts +2 -2
  4. package/dist/index.mjs +6 -6
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/{product-BCFrBxXc.mjs → product-B35JCiip.mjs} +2 -2
  7. package/dist/product-B35JCiip.mjs.map +1 -0
  8. package/dist/server/index.d.mts +1 -1
  9. package/dist/server/index.mjs +3 -3
  10. package/dist/server/index.mjs.map +1 -1
  11. package/package.json +1 -1
  12. package/ts/api/index.ts +19 -2
  13. package/ts/api/resources/Exercice.ts +5 -0
  14. package/ts/api/resources/TeamSystemSignature.ts +16 -0
  15. package/ts/api/resources.ts +16 -0
  16. package/ts/types/Enum/CustomerSignature.ts +1 -0
  17. package/ts/types/Enum/EInvoicingStatusCode.ts +15 -1
  18. package/ts/types/Enum/LetterType.ts +8 -0
  19. package/ts/types/Enum/MealExpenseThresholds.ts +4 -0
  20. package/ts/types/Enum/Unit.ts +7 -0
  21. package/ts/types/Interface/api/appointment/Appointment.ts +1 -1
  22. package/ts/types/Interface/api/balanceSheet/UpdateBalanceSheet.ts +5 -0
  23. package/ts/types/Interface/api/commercialManagement/Create.ts +6 -1
  24. package/ts/types/Interface/api/commercialManagement/CreateProductInvoice.ts +60 -0
  25. package/ts/types/Interface/api/commercialManagement/Read.ts +1 -0
  26. package/ts/types/Interface/api/exercice/QueryExercice.ts +8 -2
  27. package/ts/types/Interface/api/product/CreateProduct.ts +3 -34
  28. package/ts/types/Interface/api/product/ProductLineInputs.ts +37 -0
  29. package/ts/types/Interface/api/refund/QueryRefundPaginated.ts +5 -0
  30. package/ts/types/Interface/api/teamSystemSignature/ReadTeamSystemSignature.ts +18 -0
  31. package/ts/types/Interface/api/teamSystemSignature/SendTeamSystemSignature.ts +23 -0
  32. package/ts/types/Interface/api/teamSystemSignature/index.ts +2 -0
  33. package/ts/types/Interface/models/IBalanceSheet.ts +1 -0
  34. package/ts/types/Interface/models/ICustomerSignature.ts +2 -0
  35. package/ts/types/Interface/models/IEstimateInvoice.ts +4 -0
  36. package/ts/types/index.ts +3 -0
  37. package/ts/utils/amount.ts +7 -0
  38. package/ts/utils/commercialManagement/document.ts +1 -1
  39. package/ts/utils/commercialManagement/product.ts +7 -3
  40. package/ts/utils/commercialManagement/vat.ts +9 -11
  41. package/ts/utils/tests/document.spec.ts +95 -0
  42. package/ts/utils/tests/payment.spec.ts +0 -70
  43. package/ts/utils/validators/nestedArray.validator.ts +42 -0
  44. package/dist/index-BvApezAZ.d.mts.map +0 -1
  45. package/dist/product-BCFrBxXc.mjs.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silexpert/core",
3
- "version": "2.0.120",
3
+ "version": "2.0.122",
4
4
  "description": "Silex Core perform HTTP Request and object binding. Silex core helps developers to retrieve and return formatted object",
5
5
  "keywords": [
6
6
  "accounting",
package/ts/api/index.ts CHANGED
@@ -41,11 +41,28 @@ export const Silex = (params: { url: string; loginWith?: any; setToken?: any })
41
41
  },
42
42
  });
43
43
 
44
+ const wrappedAxios = wrapAxios(axiosInstance);
45
+
46
+ const instantiateResource = (value: any): any => {
47
+ if (typeof value === 'function') {
48
+ return new value(wrappedAxios);
49
+ }
50
+ if (typeof value === 'object' && value !== null) {
51
+ return Object.entries(value).reduce(
52
+ (acc, [k, v]) => ({
53
+ ...acc,
54
+ [k]: instantiateResource(v),
55
+ }),
56
+ {},
57
+ );
58
+ }
59
+ return value;
60
+ };
61
+
44
62
  const _resources = Object.entries(resources).reduce(
45
63
  (acc, [name, value]) => ({
46
64
  ...acc,
47
-
48
- [name]: new value(wrapAxios(axiosInstance)),
65
+ [name]: instantiateResource(value),
49
66
  }),
50
67
  {},
51
68
  );
@@ -10,6 +10,7 @@ import {
10
10
  GenerateProjectExercice,
11
11
  IGedFile,
12
12
  SendPreviewProjectExercice,
13
+ QuerySignUrlForProject,
13
14
  } from '../../types/index.js';
14
15
  import { Resource } from '../Resource.js';
15
16
 
@@ -71,6 +72,10 @@ export class Exercice extends Resource {
71
72
  });
72
73
  }
73
74
 
75
+ getSignUrlForProject(params: QuerySignUrlForProject): Promise<string> {
76
+ return this.axios.$get('exercices/project/sign-url', { params });
77
+ }
78
+
74
79
  getProgress(idExercice: number): Promise<number> {
75
80
  return this.axios.$get(`exercices/${idExercice}/progress`);
76
81
  }
@@ -0,0 +1,16 @@
1
+ import { SendTeamSystemSignature, ReadTeamSystemSignature } from '../../types/index.js';
2
+ import { Resource } from '../Resource.js';
3
+
4
+ export class TeamSystemSignature extends Resource {
5
+ sendForSignature(idDocument: number, payload: SendTeamSystemSignature): Promise<ReadTeamSystemSignature> {
6
+ return this.axios.$post(`/connectors/team-system/signatures/documents/${idDocument}/send-for-signature`, payload);
7
+ }
8
+
9
+ startSession(token: string): Promise<{ url: string }> {
10
+ return this.axios.$get(`/connectors/team-system/signatures/start-session/${token}`);
11
+ }
12
+
13
+ getSignatureStatus(idDocument: number): Promise<ReadTeamSystemSignature> {
14
+ return this.axios.$get(`/connectors/team-system/signatures/documents/${idDocument}/signature-status`);
15
+ }
16
+ }
@@ -118,6 +118,8 @@ import { Prestations } from './resources/Prestations.js';
118
118
  import { StatisticCustomerSuccess } from './resources/statistic/CustomerSuccess.js';
119
119
  import { CommercialImport } from './resources/CommercialImport.js';
120
120
  import { Team } from './resources/Team.js';
121
+ import { TeamSystemSignature } from './resources/TeamSystemSignature.js';
122
+
121
123
  import { CashAndExpense } from './resources/CashAndExpense.js';
122
124
  import { Archive } from './resources/Archive.js';
123
125
  import { AccountsSector } from './resources/AccountsSectors.js';
@@ -392,6 +394,9 @@ export const resources = {
392
394
  docoon: Docoon,
393
395
  usersHistory: UsersHistory,
394
396
  acd: Acd,
397
+ teamSystem: {
398
+ signature: TeamSystemSignature,
399
+ },
395
400
  zendesk: Zendesk,
396
401
  formalism: Formalism,
397
402
  financialProjection: FinancialProjection,
@@ -403,3 +408,14 @@ export const resources = {
403
408
  };
404
409
 
405
410
  export * from './resources/Cache.js';
411
+ export * from './resources/TeamSystemSignature.js';
412
+
413
+ export type SilexResourceInstance<T> = T extends new (...args: any) => infer R
414
+ ? R
415
+ : T extends object
416
+ ? { [K in keyof T]: SilexResourceInstance<T[K]> }
417
+ : never;
418
+
419
+ export type SilexResources = {
420
+ [K in keyof typeof resources]: SilexResourceInstance<(typeof resources)[K]>;
421
+ };
@@ -19,6 +19,7 @@ export enum SignatureType {
19
19
  EQUIPMENT = 'equipment',
20
20
  MANDAT = 'mandat', // N'est plus utilisé, permet de distinguer les mandats signés avant ajout de la signature Clementine
21
21
  MANDAT_PA_EC = 'mandat_pa_ec',
22
+ COMMERCIAL_DOCUMENT = 'commercial_document',
22
23
  }
23
24
 
24
25
  export const SignatureStatusDetail = {
@@ -17,89 +17,103 @@ export enum EInvoicingStatusCode {
17
17
 
18
18
  export const EInvoicingStatusCodeMetadata: Record<
19
19
  EInvoicingStatusCode,
20
- { shortLabel: string; label: string; color: string; description?: string }
20
+ { shortLabel: string; label: string; pluralLabel: string; color: string; description?: string }
21
21
  > = {
22
22
  [EInvoicingStatusCode.DEPOSITED]: {
23
23
  shortLabel: 'Déposée',
24
24
  label: 'Déposée',
25
+ pluralLabel: 'Déposées',
25
26
  color: 'cerulean',
26
27
  description: 'Facture déposée et contrôles techniques validés.',
27
28
  },
28
29
  [EInvoicingStatusCode.ISSUED]: {
29
30
  shortLabel: 'Émise',
30
31
  label: 'Émise par la plateforme',
32
+ pluralLabel: 'Émises',
31
33
  color: 'success',
32
34
  description: 'Facture transmise au réseau de facturation.',
33
35
  },
34
36
  [EInvoicingStatusCode.RECEIVED]: {
35
37
  shortLabel: 'Reçue',
36
38
  label: 'Reçue',
39
+ pluralLabel: 'Reçues',
37
40
  color: 'success',
38
41
  description: 'Facture reçue par la plateforme du destinataire.',
39
42
  },
40
43
  [EInvoicingStatusCode.MADE_AVAILABLE]: {
41
44
  shortLabel: 'Mise à disposition',
42
45
  label: 'Mise à disposition',
46
+ pluralLabel: 'Mises à disposition',
43
47
  color: 'fire',
44
48
  description: 'Facture disponible pour le destinataire.',
45
49
  },
46
50
  [EInvoicingStatusCode.HANDLED]: {
47
51
  shortLabel: 'Prise en charge',
48
52
  label: 'Prise en charge',
53
+ pluralLabel: 'Prises en charge',
49
54
  color: 'fire',
50
55
  description: 'Facture en cours de traitement par le destinataire.',
51
56
  },
52
57
  [EInvoicingStatusCode.APPROVED]: {
53
58
  shortLabel: 'Approuvée',
54
59
  label: 'Approuvée',
60
+ pluralLabel: 'Approuvées',
55
61
  color: 'success',
56
62
  description: 'Facture entièrement acceptée.',
57
63
  },
58
64
  [EInvoicingStatusCode.PARTIALLY_APPROVED]: {
59
65
  shortLabel: 'Approbation partielle',
60
66
  label: 'Approbation partielle',
67
+ pluralLabel: 'Approbations partielles',
61
68
  color: 'error',
62
69
  description: 'Facture partiellement acceptée.',
63
70
  },
64
71
  [EInvoicingStatusCode.IN_DISPUTE]: {
65
72
  shortLabel: 'En litige',
66
73
  label: 'En litige',
74
+ pluralLabel: 'En litige',
67
75
  color: 'error',
68
76
  description: 'Facture contestée par le destinataire.',
69
77
  },
70
78
  [EInvoicingStatusCode.SUSPENDED]: {
71
79
  shortLabel: 'Suspendue',
72
80
  label: 'Suspendue',
81
+ pluralLabel: 'Suspendues',
73
82
  color: 'error',
74
83
  description: 'Traitement suspendu, informations attendues.',
75
84
  },
76
85
  [EInvoicingStatusCode.COMPLETED]: {
77
86
  shortLabel: 'Complétée',
78
87
  label: 'Complétée',
88
+ pluralLabel: 'Complétées',
79
89
  color: 'fire',
80
90
  description: 'Informations complémentaires transmises.',
81
91
  },
82
92
  [EInvoicingStatusCode.REFUSED]: {
83
93
  shortLabel: 'Refusée',
84
94
  label: 'Refusée',
95
+ pluralLabel: 'Refusées',
85
96
  color: 'error',
86
97
  description: 'Facture refusée par le destinataire.',
87
98
  },
88
99
  [EInvoicingStatusCode.PAYMENT_TRANSMITTED]: {
89
100
  shortLabel: 'Paiement transmis',
90
101
  label: 'Paiement transmis',
102
+ pluralLabel: 'Paiements transmis',
91
103
  color: 'success',
92
104
  description: 'Paiement déclaré par le destinataire.',
93
105
  },
94
106
  [EInvoicingStatusCode.PAID]: {
95
107
  shortLabel: 'Encaissée',
96
108
  label: 'Encaissée',
109
+ pluralLabel: 'Encaissées',
97
110
  color: 'success',
98
111
  description: 'Paiement reçu et confirmé.',
99
112
  },
100
113
  [EInvoicingStatusCode.REJECTED]: {
101
114
  shortLabel: 'Rejetée',
102
115
  label: 'Rejetée',
116
+ pluralLabel: 'Rejetées',
103
117
  color: 'error',
104
118
  description: 'Facture rejetée, correction nécessaire.',
105
119
  },
@@ -47,4 +47,12 @@ export const LetterType = {
47
47
  id: 12,
48
48
  name: 'Bilan avec observation',
49
49
  },
50
+ RESIGNATION_OF_MISSION_LRAR: {
51
+ id: 13,
52
+ name: 'LRAR démission de la mission',
53
+ },
54
+ TERMINATION_MANDATE_ELECTRONIC_INVOICING: {
55
+ id: 14,
56
+ name: 'Résiliation mandat facturation électronique',
57
+ },
50
58
  };
@@ -30,4 +30,8 @@ export const MealExpenseThresholds: IMealExpenseThresholds = {
30
30
  min: 5.5,
31
31
  max: 21.1,
32
32
  },
33
+ 2026: {
34
+ min: 5.5,
35
+ max: 21.4,
36
+ },
33
37
  };
@@ -30,6 +30,7 @@ export enum UnitId {
30
30
  HECTARE = 20,
31
31
  MINUTE = 21,
32
32
  GRAM = 22,
33
+ UNIT = 23,
33
34
  }
34
35
 
35
36
  export type IUnitList = Array<{ name: string; id: number; shortName: string; eInvoicingCode: string | null }>;
@@ -41,6 +42,12 @@ export const Unit: IUnit = {
41
42
  shortName: 'art',
42
43
  codeEN16931: 'NAR',
43
44
  },
45
+ UNIT: {
46
+ id: UnitId.UNIT,
47
+ name: 'Unité',
48
+ shortName: 'u',
49
+ codeEN16931: 'NAR',
50
+ },
44
51
  HOUR: {
45
52
  id: UnitId.HOUR,
46
53
  name: 'Heure',
@@ -24,12 +24,12 @@ export class CreateAppointmentLink {
24
24
 
25
25
  export interface AppointmentContext {
26
26
  isProspect: boolean;
27
- isSoftware: boolean;
28
27
  isInCreation: boolean;
29
28
  hasAcceptedLab: boolean;
30
29
  hasJuridicalPrestation: boolean;
31
30
  hasExpertAccountantPrestation: boolean;
32
31
  existingAppointments: Array<{ id: number; idTimeSlot: number; startDate: Date }>;
32
+ hasSocietyCreation: boolean;
33
33
  }
34
34
 
35
35
  export class QueryAppointmentAvailability {
@@ -54,4 +54,9 @@ export class UpdateBalanceSheet {
54
54
  @IsString()
55
55
  @IsOptional()
56
56
  token?: string;
57
+
58
+ @ApiPropertyOptional()
59
+ @IsString()
60
+ @IsOptional()
61
+ projectSignatureLink?: string;
57
62
  }
@@ -29,6 +29,8 @@ import { IThirdParty } from '../../models/IThirdParty.js';
29
29
  import { IEstimateInvoice } from '../../models/IEstimateInvoice.js';
30
30
  import { ToBoolean } from '../../../../utils/transforms/boolean.transform.js';
31
31
  import { ToNumericEnum } from '../../../../utils/transforms/numericEnum.transform.js';
32
+ import { ValidateNestedArrayOf } from '../../../../utils/validators/nestedArray.validator.js';
33
+ import { CreateProductInvoice } from './CreateProductInvoice.js';
32
34
 
33
35
  export type IProductInvoiceToCreate = IProductInvoice & { save?: boolean };
34
36
 
@@ -430,8 +432,11 @@ export class CommercialDocumentInputs {
430
432
  @ApiProperty({ description: 'Conditions de réglement' })
431
433
  termsOfPayment: string | null;
432
434
 
433
- @ApiProperty()
435
+ @ApiProperty({ type: [CreateProductInvoice] })
434
436
  @IsArray()
437
+ @ValidateNestedArrayOf(CreateProductInvoice)
438
+ // Lines are validated as CreateProductInvoice, but stay typed as IProductInvoice because the same objects feed the
439
+ // document rendering helpers (ReadProductEditing) shared with the front-end apps
435
440
  products: Array<IProductInvoiceToCreate>;
436
441
 
437
442
  @ApiProperty({ description: 'Escompte' })
@@ -0,0 +1,60 @@
1
+ import { IsBoolean, IsEnum, IsIn, IsInt, IsNumber, IsOptional, IsString } from 'class-validator';
2
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
3
+ import { DiscountType } from '../../../Enum/CommercialManagement.js';
4
+ import { Vat } from '../../../Enum/Vat.js';
5
+ import type { VatType } from '../../../Enum/Vat.js';
6
+ import { ProductLineInputs } from '../product/ProductLineInputs.js';
7
+
8
+ const VAT_IDS: number[] = (Object.values(Vat) as VatType[]).map((vat) => vat.id);
9
+
10
+ export class CreateProductInvoice extends ProductLineInputs {
11
+ @ApiPropertyOptional({
12
+ description: 'Absente lorsque la société ne facture pas la TVA : la ligne est alors Hors-Taxe',
13
+ })
14
+ @IsIn(VAT_IDS)
15
+ @IsOptional()
16
+ idVat?: number | null;
17
+
18
+ @ApiProperty({ description: 'Peut être négatif (remise, avoir)' })
19
+ @IsNumber()
20
+ priceTaxExcluded: number;
21
+
22
+ @ApiProperty()
23
+ @IsNumber()
24
+ quantity: number;
25
+
26
+ @ApiPropertyOptional()
27
+ @IsString()
28
+ @IsOptional()
29
+ itemSaleName?: string | null;
30
+
31
+ @ApiPropertyOptional({ description: "Référence de l'article" })
32
+ @IsString()
33
+ @IsOptional()
34
+ itemCodeProduct?: string | null;
35
+
36
+ @ApiPropertyOptional()
37
+ @IsInt()
38
+ @IsOptional()
39
+ idProduct?: number | null;
40
+
41
+ @ApiPropertyOptional()
42
+ @IsNumber()
43
+ @IsOptional()
44
+ discount2?: number | null;
45
+
46
+ @ApiPropertyOptional({ enum: DiscountType })
47
+ @IsEnum(DiscountType)
48
+ @IsOptional()
49
+ discountType?: DiscountType | null;
50
+
51
+ @ApiPropertyOptional()
52
+ @IsInt()
53
+ @IsOptional()
54
+ reorder?: number | null;
55
+
56
+ @ApiPropertyOptional({ description: "Enregistre l'article dans le catalogue de produits" })
57
+ @IsBoolean()
58
+ @IsOptional()
59
+ save?: boolean;
60
+ }
@@ -21,6 +21,7 @@ export type ReadEstimateInvoice = IEstimateInvoice & { id: number };
21
21
 
22
22
  export type ReadProductEditing = IProductInvoice & {
23
23
  totalTaxExcluded: number;
24
+ totalTaxExcludedRounded: number;
24
25
  unitFormatted: string;
25
26
  vatFormatted: string;
26
27
  discountFormatted: string | null;
@@ -1,5 +1,5 @@
1
- import { IsBoolean, IsDate, IsIn, IsOptional } from 'class-validator';
2
- import { ApiPropertyOptional } from '@nestjs/swagger';
1
+ import { IsBoolean, IsDate, IsIn, IsOptional, IsString } from 'class-validator';
2
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
3
3
  import { ToBoolean } from '../../../../utils/transforms/boolean.transform.js';
4
4
 
5
5
  export class QueryExercice {
@@ -44,3 +44,9 @@ export class QueryExerciceProject {
44
44
  @IsOptional()
45
45
  type?: 'juridical' | 'default';
46
46
  }
47
+
48
+ export class QuerySignUrlForProject {
49
+ @ApiProperty()
50
+ @IsString()
51
+ token: string;
52
+ }
@@ -1,10 +1,9 @@
1
- import { IsBoolean, IsInt, IsNumber, IsOptional, IsString, Min } from 'class-validator';
2
- import { ProductType, Unit } from '../../../index.js';
1
+ import { IsBoolean, IsNumber, IsOptional, IsString, Min } from 'class-validator';
3
2
  import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
4
3
  import { ToBoolean } from '../../../../utils/transforms/boolean.transform.js';
5
- import { IsObjectId } from '../../../../utils/validators/objectId.validator.js';
4
+ import { ProductLineInputs } from './ProductLineInputs.js';
6
5
 
7
- export class CreateProduct {
6
+ export class CreateProduct extends ProductLineInputs {
8
7
  @ApiProperty()
9
8
  @IsString()
10
9
  name: string;
@@ -19,44 +18,14 @@ export class CreateProduct {
19
18
  @IsNumber()
20
19
  idVat: number;
21
20
 
22
- @ApiPropertyOptional()
23
- @IsNumber()
24
- @IsOptional()
25
- marginVatType?: number;
26
-
27
- @ApiPropertyOptional()
28
- @IsNumber()
29
- @IsOptional()
30
- amountOfPurchase?: number;
31
-
32
21
  @ApiPropertyOptional()
33
22
  @IsBoolean()
34
23
  @ToBoolean()
35
24
  @IsOptional()
36
25
  isFree?: boolean;
37
26
 
38
- @ApiProperty()
39
- @IsNumber()
40
- @IsObjectId(Unit)
41
- unit: number;
42
-
43
- @ApiProperty()
44
- @IsNumber()
45
- @IsObjectId(ProductType)
46
- type: number;
47
-
48
- @ApiPropertyOptional()
49
- @IsString()
50
- @IsOptional()
51
- comment?: string;
52
-
53
27
  @ApiPropertyOptional()
54
28
  @IsString()
55
29
  @IsOptional()
56
30
  codeProduct?: string;
57
-
58
- @ApiPropertyOptional()
59
- @IsInt()
60
- @IsOptional()
61
- idAccount?: number;
62
31
  }
@@ -0,0 +1,37 @@
1
+ import { IsInt, IsNumber, IsOptional, IsString } from 'class-validator';
2
+ import { ProductType, Unit } from '../../../index.js';
3
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
4
+ import { IsObjectId } from '../../../../utils/validators/objectId.validator.js';
5
+
6
+ // Fields shared by a catalog product and a commercial document line, validated the same way in both contexts
7
+ export class ProductLineInputs {
8
+ @ApiProperty()
9
+ @IsNumber()
10
+ @IsObjectId(Unit)
11
+ unit: number;
12
+
13
+ @ApiProperty()
14
+ @IsNumber()
15
+ @IsObjectId(ProductType)
16
+ type: number;
17
+
18
+ @ApiPropertyOptional()
19
+ @IsNumber()
20
+ @IsOptional()
21
+ marginVatType?: number;
22
+
23
+ @ApiPropertyOptional()
24
+ @IsNumber()
25
+ @IsOptional()
26
+ amountOfPurchase?: number | null;
27
+
28
+ @ApiPropertyOptional()
29
+ @IsString()
30
+ @IsOptional()
31
+ comment?: string | null;
32
+
33
+ @ApiPropertyOptional()
34
+ @IsInt()
35
+ @IsOptional()
36
+ idAccount?: number | null;
37
+ }
@@ -14,6 +14,11 @@ export class QueryRefundPaginated extends RequiredQueryPaginate implements Order
14
14
  @IsOptional()
15
15
  motif?: number;
16
16
 
17
+ @ApiPropertyOptional()
18
+ @IsOptional()
19
+ @IsInt()
20
+ idSociety?: number;
21
+
17
22
  @ApiPropertyOptional()
18
23
  @IsOptional()
19
24
  startDate?: Date;
@@ -0,0 +1,18 @@
1
+ import { ApiPropertyOptional } from '@nestjs/swagger';
2
+
3
+ export class ReadTeamSystemSignature {
4
+ @ApiPropertyOptional()
5
+ tsDocumentId?: string | null;
6
+
7
+ @ApiPropertyOptional()
8
+ tsSignStatus?: string | null;
9
+
10
+ @ApiPropertyOptional()
11
+ tsSignUrl?: string | null;
12
+
13
+ @ApiPropertyOptional()
14
+ tsSignedAt?: Date | null;
15
+
16
+ @ApiPropertyOptional()
17
+ success?: boolean;
18
+ }
@@ -0,0 +1,23 @@
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+ import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
3
+
4
+ export class SendTeamSystemSignature {
5
+ @ApiProperty({ description: 'Prénom du signataire' })
6
+ @IsString()
7
+ @IsNotEmpty()
8
+ signerFirstName: string;
9
+
10
+ @ApiProperty({ description: 'Nom du signataire' })
11
+ @IsString()
12
+ @IsNotEmpty()
13
+ signerLastName: string;
14
+
15
+ @ApiProperty({ description: 'Email du signataire' })
16
+ @IsEmail()
17
+ signerEmail: string;
18
+
19
+ @ApiProperty({ description: 'Numéro de téléphone du signataire' })
20
+ @IsString()
21
+ @IsNotEmpty()
22
+ signerPhone: string;
23
+ }
@@ -0,0 +1,2 @@
1
+ export * from './SendTeamSystemSignature.js';
2
+ export * from './ReadTeamSystemSignature.js';
@@ -17,6 +17,7 @@ export class IBalanceSheet {
17
17
  netIncome?: number;
18
18
  total?: number;
19
19
  token?: string | null;
20
+ projectSignatureLink?: string | null;
20
21
  idFile?: number;
21
22
  attestationDetail?: string;
22
23
  endDate?: Date;
@@ -16,6 +16,8 @@ export class ICustomerSignature {
16
16
  tokenSigner?: string;
17
17
  mailSigner: string;
18
18
  phoneSigner: string;
19
+ firstNameSigner?: string | null;
20
+ lastNameSigner?: string | null;
19
21
  idSendMethod: number;
20
22
  idStatusSignature: number;
21
23
  idPrestation?: number | null;
@@ -8,6 +8,7 @@ import { IInvoiceRecurrence } from './IInvoiceRecurrence.js';
8
8
  import type { ReadEstimateInvoiceStatus } from '../api/commercialManagement/Read.js';
9
9
  import { AccountingCategoryId, InvoiceLanguage } from '../../Enum/CommercialManagement.js';
10
10
  import { IReminder } from './IReminder.js';
11
+ import { ICustomerSignature } from './ICustomerSignature.js';
11
12
 
12
13
  // estimatesInvoices
13
14
  export class IEstimateInvoice {
@@ -57,9 +58,12 @@ export class IEstimateInvoice {
57
58
  updatedAt?: Date | null;
58
59
  deletedAt?: Date | null;
59
60
 
61
+ idCustomerSignature?: number | null;
62
+
60
63
  // Associations
61
64
  products?: IProductInvoice[];
62
65
  thirdParty?: IThirdParty;
66
+ signature?: ICustomerSignature | null;
63
67
  type?: IEstimateInvoiceType;
64
68
  customerPayment?: IPaymentExpectationCustomer;
65
69
  society?: ISociety;
package/ts/types/index.ts CHANGED
@@ -289,6 +289,7 @@ export * from './Interface/models/IRevenueMovement.js';
289
289
  export * from './Interface/models/IRevenueSnapshot.js';
290
290
  export * from './Interface/models/IEInvoicingEligibilityRequest.js';
291
291
  export * from './Interface/models/IUsersHistory.js';
292
+ export * from './Interface/api/teamSystemSignature/index.js';
292
293
  export * from './Interface/models/IEInvoicingKycAndMandate.js';
293
294
  export * from './Interface/models/IConnectorTracking.js';
294
295
  export * from './Interface/models/IEInvoicing.js';
@@ -894,6 +895,7 @@ export * from './Interface/api/vehicle/CreateSocietyVehicle.js';
894
895
  export * from './Interface/api/vehicle/UpdateSocietyVehicle.js';
895
896
  export * from './Interface/api/fecFile/QueryFecFile.js';
896
897
  export * from './Interface/api/product/CreateProduct.js';
898
+ export * from './Interface/api/product/ProductLineInputs.js';
897
899
  export * from './Interface/api/product/UpdateProduct.js';
898
900
  export * from './Interface/api/product/QueryProduct.js';
899
901
  export * from './Interface/api/registration/ReadRegistration.js';
@@ -983,6 +985,7 @@ export * from './Interface/api/customerActivity/CreateCustomerActivityReport.js'
983
985
  export * from './Interface/api/customerActivity/Query.js';
984
986
  export * from './Interface/api/customerActivity/Create.js';
985
987
  export * from './Interface/api/commercialManagement/Create.js';
988
+ export * from './Interface/api/commercialManagement/CreateProductInvoice.js';
986
989
  export * from './Interface/api/commercialManagement/Read.js';
987
990
  export * from './Interface/api/commercialManagement/Query.js';
988
991
  export * from './Interface/api/commercialManagement/Update.js';
@@ -1,6 +1,13 @@
1
1
  import { MathematicalSign } from '../types/Enum/Util.js';
2
2
  import { FormattedAmount } from '../types/Interface/api/amount/FormattedAmount.js';
3
3
 
4
+ // Round the magnitude first so negative half-cent values match the formatter's symmetric rounding.
5
+ export function roundAmountToInteger(value: number): number {
6
+ const roundedAbsoluteValue = Math.round(Math.abs(value));
7
+ if (roundedAbsoluteValue === 0) return 0;
8
+ return value < 0 ? -roundedAbsoluteValue : roundedAbsoluteValue;
9
+ }
10
+
4
11
  export function integerToFormattedAmountString(value: number): string {
5
12
  const abs = Math.abs(value / 100);
6
13
  let integer = Math.trunc(abs);
@@ -73,7 +73,7 @@ export function generateCommercialDocument(
73
73
  }
74
74
 
75
75
  const totalVats = sumBy(vats, (v) => round(v.amount));
76
- const totalTaxExcluded = sumBy(products, (p) => round(p.totalTaxExcluded));
76
+ const totalTaxExcluded = sumBy(products, 'totalTaxExcludedRounded');
77
77
 
78
78
  const totalTaxIncluded = totalTaxExcluded + totalVats;
79
79