@silexpert/core 2.0.120 → 2.0.121
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/{index-BvApezAZ.d.mts → index-CQ4tY4GS.d.mts} +1176 -1113
- package/dist/index-CQ4tY4GS.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +1 -1
- package/package.json +1 -1
- package/ts/api/index.ts +19 -2
- package/ts/api/resources/TeamSystemSignature.ts +16 -0
- package/ts/api/resources.ts +16 -0
- package/ts/types/Enum/CustomerSignature.ts +1 -0
- package/ts/types/Enum/LetterType.ts +8 -0
- package/ts/types/Enum/MealExpenseThresholds.ts +4 -0
- package/ts/types/Interface/api/appointment/Appointment.ts +1 -1
- package/ts/types/Interface/api/commercialManagement/Create.ts +6 -1
- package/ts/types/Interface/api/commercialManagement/CreateProductInvoice.ts +60 -0
- package/ts/types/Interface/api/product/CreateProduct.ts +3 -34
- package/ts/types/Interface/api/product/ProductLineInputs.ts +37 -0
- package/ts/types/Interface/api/refund/QueryRefundPaginated.ts +5 -0
- package/ts/types/Interface/api/teamSystemSignature/ReadTeamSystemSignature.ts +18 -0
- package/ts/types/Interface/api/teamSystemSignature/SendTeamSystemSignature.ts +23 -0
- package/ts/types/Interface/api/teamSystemSignature/index.ts +2 -0
- package/ts/types/Interface/models/ICustomerSignature.ts +2 -0
- package/ts/types/Interface/models/IEstimateInvoice.ts +4 -0
- package/ts/types/index.ts +3 -0
- package/ts/utils/tests/payment.spec.ts +0 -70
- package/ts/utils/validators/nestedArray.validator.ts +42 -0
- package/dist/index-BvApezAZ.d.mts.map +0 -1
package/dist/server/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __name } from "../rolldown-runtime-BhWHdk3m.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { KJ as CreateInvoiceDocument, Xq as ReadCommercialDocumentTemplate, YJ as CreatePreSaleDocument, Zq as ReadCommercialMailTemplate, mX as EstimateInvoiceType, qJ as CreateMailHeader, sW as IUser } from "../index-CQ4tY4GS.mjs";
|
|
3
3
|
import "dayjs/locale/fr.js";
|
|
4
4
|
//#region ts/utils/email.d.ts
|
|
5
5
|
export declare function getHoraires(user: IUser): "Du lundi au vendredi de 9h à 18h" | "Du lundi au jeudi de 9h à 17h<br/>Le vendredi de 9h à 12h";
|
package/package.json
CHANGED
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
|
);
|
|
@@ -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
|
+
}
|
package/ts/api/resources.ts
CHANGED
|
@@ -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 = {
|
|
@@ -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
|
};
|
|
@@ -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 {
|
|
@@ -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
|
+
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { IsBoolean,
|
|
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 {
|
|
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
|
+
}
|
|
@@ -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';
|
|
@@ -13,7 +13,6 @@ describe('Payment', () => {
|
|
|
13
13
|
const idSociety = 1;
|
|
14
14
|
const yearlyAmountNonExpress = 1800;
|
|
15
15
|
const nextYearlyAmountNonExpress = 1800;
|
|
16
|
-
const appCost = 14.9;
|
|
17
16
|
|
|
18
17
|
const firstExerciceNonExpresssEndDate = dayjs().add(11, 'month').endOf('month').toDate();
|
|
19
18
|
const prestationList = {
|
|
@@ -290,39 +289,6 @@ describe('Payment', () => {
|
|
|
290
289
|
});
|
|
291
290
|
// annual price increase
|
|
292
291
|
// @ts-ignore
|
|
293
|
-
test('should apply annual price increase (2,75%) if signed before last 3 months of civil year', () => {
|
|
294
|
-
const mockedDate = dayjs('2024-08-15').toDate();
|
|
295
|
-
MockDate.set(mockedDate);
|
|
296
|
-
|
|
297
|
-
const newFirstExerciceNonExpresssEndDate = dayjs().add(11, 'month').endOf('month').toDate();
|
|
298
|
-
|
|
299
|
-
const payments = calculatePaymentsAuto({
|
|
300
|
-
idTypeBrand: 1,
|
|
301
|
-
firstExerciceNonExpresssEndDate: newFirstExerciceNonExpresssEndDate,
|
|
302
|
-
idPrestation,
|
|
303
|
-
prestationList,
|
|
304
|
-
idVat,
|
|
305
|
-
listPartialExercicePrestationExpress: [],
|
|
306
|
-
listRegulations: [
|
|
307
|
-
{
|
|
308
|
-
amount: 50,
|
|
309
|
-
amountUsed: 0,
|
|
310
|
-
} as IRegulation,
|
|
311
|
-
],
|
|
312
|
-
yearlyAmountNonExpress,
|
|
313
|
-
nextYearlyAmountNonExpress,
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
const listNonExpressPayments = payments.filter(
|
|
317
|
-
(p) => dayjs(p.closingDate).diff(newFirstExerciceNonExpresssEndDate) === 0,
|
|
318
|
-
);
|
|
319
|
-
const firstPaymentWithTaxRateForced = listNonExpressPayments[1].amount * 1.0275;
|
|
320
|
-
// @ts-ignore
|
|
321
|
-
expect(firstPaymentWithTaxRateForced - listNonExpressPayments.splice(-2)[0].amount).toBeLessThanOrEqual(0.01); //Permet de gérer le pb d'arrondi
|
|
322
|
-
|
|
323
|
-
MockDate.reset();
|
|
324
|
-
});
|
|
325
|
-
// @ts-ignore
|
|
326
292
|
test('should not apply annual price increase (2,75%) if signed in last 3 months of civil year', () => {
|
|
327
293
|
const mockedDate = dayjs('2024-11-15').toDate();
|
|
328
294
|
MockDate.set(mockedDate);
|
|
@@ -353,42 +319,6 @@ describe('Payment', () => {
|
|
|
353
319
|
MockDate.reset();
|
|
354
320
|
});
|
|
355
321
|
|
|
356
|
-
// @ts-ignore
|
|
357
|
-
test('should apply 14,9€ HT increase for the second exercice created (only offered on first exo) (no rules for 3 last months)', () => {
|
|
358
|
-
const mockedDate = dayjs('2024-06-15').toDate();
|
|
359
|
-
MockDate.set(mockedDate);
|
|
360
|
-
|
|
361
|
-
const newFirstExerciceNonExpresssEndDate = dayjs().add(12, 'month').endOf('month').toDate();
|
|
362
|
-
|
|
363
|
-
const payments = calculatePaymentsAuto({
|
|
364
|
-
idTypeBrand: 1,
|
|
365
|
-
firstExerciceNonExpresssEndDate: newFirstExerciceNonExpresssEndDate,
|
|
366
|
-
idPrestation,
|
|
367
|
-
prestationList,
|
|
368
|
-
idVat,
|
|
369
|
-
listPartialExercicePrestationExpress: [],
|
|
370
|
-
listRegulations: [
|
|
371
|
-
{
|
|
372
|
-
amount: 50,
|
|
373
|
-
amountUsed: 50,
|
|
374
|
-
} as IRegulation,
|
|
375
|
-
],
|
|
376
|
-
yearlyAmountNonExpress,
|
|
377
|
-
nextYearlyAmountNonExpress,
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
const paymentsOfFirstExo =
|
|
381
|
-
payments.filter((p) => dayjs(p.datePayment).diff(dayjs('2025-06-01')) === 0)[0].amount ?? 0;
|
|
382
|
-
const paymentsOfSecondExo =
|
|
383
|
-
payments.filter((p) => dayjs(p.datePayment).diff(dayjs('2025-07-01')) === 0).splice(-1)[0].amount ?? 0;
|
|
384
|
-
// @ts-ignore
|
|
385
|
-
expect(
|
|
386
|
-
Math.round(100 * (paymentsOfFirstExo + getTaxesIncludedAmount(appCost, idVat) * 1.0275)) / 100,
|
|
387
|
-
).toStrictEqual(paymentsOfSecondExo);
|
|
388
|
-
|
|
389
|
-
MockDate.reset();
|
|
390
|
-
});
|
|
391
|
-
|
|
392
322
|
// misc
|
|
393
323
|
// @ts-ignore
|
|
394
324
|
test('should payments been generated sorted by exercices start date', () => {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { plainToInstance } from 'class-transformer';
|
|
2
|
+
import type { ClassConstructor } from 'class-transformer';
|
|
3
|
+
import { registerDecorator, validateSync } from 'class-validator';
|
|
4
|
+
import type { ValidationArguments, ValidationError, ValidationOptions } from 'class-validator';
|
|
5
|
+
|
|
6
|
+
function getItemErrors<T extends object>(cls: ClassConstructor<T>, item: unknown): string[] {
|
|
7
|
+
if (typeof item !== 'object' || item === null) return ['must be an object'];
|
|
8
|
+
|
|
9
|
+
// Spread into a plain object: the API implicit conversion may have rebuilt the item as an Array instance
|
|
10
|
+
const errors: ValidationError[] = validateSync(plainToInstance(cls, { ...item }));
|
|
11
|
+
return errors.flatMap((error) =>
|
|
12
|
+
Object.values(error.constraints ?? {}).map((constraint) => `${error.property}: ${constraint}`),
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Validates each array item against `cls`. Replaces `@ValidateNested()` + `@Type()`: `@Type()` requires `reflect-metadata`
|
|
17
|
+
// at runtime (breaks browser / SSR consumers), and without it the implicit conversion does not instantiate the items.
|
|
18
|
+
export function ValidateNestedArrayOf<T extends object>(
|
|
19
|
+
cls: ClassConstructor<T>,
|
|
20
|
+
validationOptions?: ValidationOptions,
|
|
21
|
+
) {
|
|
22
|
+
return function validator(object: object, propertyName: string) {
|
|
23
|
+
registerDecorator({
|
|
24
|
+
name: 'ValidateNestedArrayOf',
|
|
25
|
+
target: object.constructor,
|
|
26
|
+
propertyName,
|
|
27
|
+
options: validationOptions,
|
|
28
|
+
validator: {
|
|
29
|
+
validate(value: unknown) {
|
|
30
|
+
return Array.isArray(value) && value.every((item) => getItemErrors(cls, item).length === 0);
|
|
31
|
+
},
|
|
32
|
+
defaultMessage(args: ValidationArguments) {
|
|
33
|
+
if (!Array.isArray(args.value)) return `${propertyName} must be an array`;
|
|
34
|
+
|
|
35
|
+
return (args.value as unknown[])
|
|
36
|
+
.flatMap((item, index) => getItemErrors(cls, item).map((error) => `${propertyName}[${index}].${error}`))
|
|
37
|
+
.join(', ');
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
}
|