@silexpert/core 2.0.126-beta.0 → 2.0.126
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-CvxgpFhm.d.mts → index-dbXTxwtd.d.mts} +93 -7
- package/dist/index-dbXTxwtd.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +1 -1
- package/package.json +1 -1
- package/ts/api/resources/User.ts +16 -0
- package/ts/types/Enum/ExternalAuthenticationLinkPurpose.ts +2 -0
- package/ts/types/Enum/RegistrationSource.ts +1 -0
- package/ts/types/Enum/Signup.ts +19 -0
- package/ts/types/Interface/api/companyMarketingInformation/CompanyMarketingInformationPayload.ts +4 -0
- package/ts/types/Interface/api/registration/CreateRegistration.ts +0 -6
- package/ts/types/Interface/api/user/RegisterProspect.ts +1 -1
- package/ts/types/Interface/api/user/Signup.ts +185 -0
- package/ts/types/index.ts +2 -0
- package/ts/utils/decorators/isE164PhoneNumber.decorator.ts +3 -1
- package/dist/index-CvxgpFhm.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 { RW as IUser, UK as ReadCommercialDocumentTemplate, WK as ReadCommercialMailTemplate, dq as CreateInvoiceDocument, eY as EstimateInvoiceType, fq as CreateMailHeader, mq as CreatePreSaleDocument } from "../index-dbXTxwtd.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/resources/User.ts
CHANGED
|
@@ -18,6 +18,10 @@ import {
|
|
|
18
18
|
GetSocietyFromUser,
|
|
19
19
|
RegisterProspectBody,
|
|
20
20
|
RegisterProspectResponse,
|
|
21
|
+
SignupBody,
|
|
22
|
+
ResendActivationBody,
|
|
23
|
+
ActivateAccountBody,
|
|
24
|
+
ReadActivateAccount,
|
|
21
25
|
QueryGet,
|
|
22
26
|
BasePaginate,
|
|
23
27
|
QueryGetAllUsersPaginated,
|
|
@@ -193,6 +197,18 @@ export class User extends Resource {
|
|
|
193
197
|
registerProspect(body: RegisterProspectBody): Promise<RegisterProspectResponse> {
|
|
194
198
|
return this.axios.$post('users/prospect', body);
|
|
195
199
|
}
|
|
200
|
+
|
|
201
|
+
signup(body: SignupBody): Promise<void> {
|
|
202
|
+
return this.axios.$post('users/signup', body);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
resendActivation(body: ResendActivationBody): Promise<void> {
|
|
206
|
+
return this.axios.$post('users/signup/resend-activation', body);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
activate(body: ActivateAccountBody): Promise<ReadActivateAccount> {
|
|
210
|
+
return this.axios.$post('users/signup/activate', body);
|
|
211
|
+
}
|
|
196
212
|
updateCoworkerWorkingSchedules(idUser: number, workingSchedules: IWorkingSchedule[]): Promise<IWorkingSchedule[]> {
|
|
197
213
|
return this.axios.$post(`users/coworker/${idUser}/working-schedules`, workingSchedules);
|
|
198
214
|
}
|
|
@@ -2,10 +2,12 @@ export enum ExternalAuthenticationLinkPurpose {
|
|
|
2
2
|
LOGIN = 'LOGIN',
|
|
3
3
|
APPOINTMENT = 'APPOINTMENT',
|
|
4
4
|
RESET_PASSWORD = 'RESET_PASSWORD',
|
|
5
|
+
ACTIVATION = 'ACTIVATION',
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
export enum ExternalAuthenticationLinkPurposeExpiration {
|
|
8
9
|
LOGIN = 10, // 10 minutes
|
|
9
10
|
APPOINTMENT = 60 * 24 * 7, // 7 days
|
|
10
11
|
RESET_PASSWORD = 60 * 24 * 3, // 3 days
|
|
12
|
+
ACTIVATION = 60 * 24 * 7, // 7 days
|
|
11
13
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Who the prospect declares to be when signing up in-app */
|
|
2
|
+
export enum SignupProfile {
|
|
3
|
+
SOCIETY = 'SOCIETY',
|
|
4
|
+
ACCOUNTANT = 'ACCOUNTANT',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* How the company of the signup was provided: picked from the company search (SIREN / SIRET known), or typed
|
|
9
|
+
* by the prospect when the company is not found or not registered yet.
|
|
10
|
+
*/
|
|
11
|
+
export enum SignupSocietySource {
|
|
12
|
+
SEARCH = 'SEARCH',
|
|
13
|
+
MANUAL = 'MANUAL',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const SignupProfileDetails = {
|
|
17
|
+
SOCIETY: { id: SignupProfile.SOCIETY, label: 'Entreprise' },
|
|
18
|
+
ACCOUNTANT: { id: SignupProfile.ACCOUNTANT, label: 'Expert-comptable' },
|
|
19
|
+
} as const;
|
package/ts/types/Interface/api/companyMarketingInformation/CompanyMarketingInformationPayload.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { SignupProfile } from '../../../Enum/Signup.js';
|
|
2
|
+
|
|
1
3
|
export class CompanyMarketingInformationPayload {
|
|
4
|
+
/* Profile declared at the in-app signup */
|
|
5
|
+
declaredProfile?: SignupProfile | null;
|
|
2
6
|
/* Comment nous a-t-il connu ? */
|
|
3
7
|
findUs?: number | null; // 0 = Autre | 1 = Pub internet | 2 = Bouche à oreille | 3 = Presse | 4 = a cherché "expert comptable" ou un terme similaire sur un moteur de recherche et a trouvé notre site | 5 = Réseaux sociaux
|
|
4
8
|
findUsDetails?: string | null;
|
|
@@ -130,12 +130,6 @@ export class UpdateOrCreateVatRegistration {
|
|
|
130
130
|
@ToBoolean()
|
|
131
131
|
@IsOptional()
|
|
132
132
|
isManuallyRegistered?: boolean;
|
|
133
|
-
|
|
134
|
-
// Base64-encoded PDF note; validated so non-string values are rejected instead of failing later in Buffer.from
|
|
135
|
-
@ApiPropertyOptional()
|
|
136
|
-
@IsString()
|
|
137
|
-
@IsOptional()
|
|
138
|
-
base64Note?: string | null;
|
|
139
133
|
}
|
|
140
134
|
|
|
141
135
|
export class CreateRegistrationDetail {
|
|
@@ -174,7 +174,7 @@ class ReferalProgramBody implements ReferalProgram {
|
|
|
174
174
|
lastname: string;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
class AnalyticsUtmBody implements Omit<Partial<IAnalyticsUtm>, 'idSociety'> {
|
|
177
|
+
export class AnalyticsUtmBody implements Omit<Partial<IAnalyticsUtm>, 'idSociety'> {
|
|
178
178
|
@ApiPropertyOptional()
|
|
179
179
|
@IsOptional()
|
|
180
180
|
@IsNumber()
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
2
|
+
import {
|
|
3
|
+
IsEmail,
|
|
4
|
+
IsEnum,
|
|
5
|
+
IsNotEmpty,
|
|
6
|
+
IsOptional,
|
|
7
|
+
IsString,
|
|
8
|
+
Matches,
|
|
9
|
+
MaxLength,
|
|
10
|
+
Validate,
|
|
11
|
+
ValidateIf,
|
|
12
|
+
ValidateNested,
|
|
13
|
+
} from 'class-validator';
|
|
14
|
+
import { IsE164PhoneNumber } from '../../../../utils/decorators/isE164PhoneNumber.decorator.js';
|
|
15
|
+
import { LegalFormTypeEnum } from '../../../Enum/LegalForm.js';
|
|
16
|
+
import { SignupProfile, SignupSocietySource } from '../../../Enum/Signup.js';
|
|
17
|
+
import { AnalyticsUtmBody } from './RegisterProspect.js';
|
|
18
|
+
|
|
19
|
+
const SIREN_REGEX = /^\d{9}$/;
|
|
20
|
+
const SIRET_REGEX = /^\d{14}$/;
|
|
21
|
+
const NAME_MAX_LENGTH = 100;
|
|
22
|
+
const EMAIL_MAX_LENGTH = 255;
|
|
23
|
+
const SOCIETY_FIELD_MAX_LENGTH = 255;
|
|
24
|
+
const PASSWORD_MAX_LENGTH = 128;
|
|
25
|
+
const ZIP_CODE_REGEX = /^\d{5}$/;
|
|
26
|
+
const GCLID_MAX_LENGTH = 255;
|
|
27
|
+
|
|
28
|
+
const isSearchedSociety = (society: SignupSocietyBody): boolean => society.source === SignupSocietySource.SEARCH;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The company of the signup, either picked from the company search (`SEARCH`: SIREN or SIRET required, the API
|
|
32
|
+
* verifies and enriches it through Sirene when available) or typed by the prospect (`MANUAL`: a company not found
|
|
33
|
+
* or not registered yet, no identifier required). The descriptive fields are the snapshot the API falls back to
|
|
34
|
+
* when Sirene has no answer, so `name` is always required. `@IsOptional()` is intentionally not used on `siren`
|
|
35
|
+
* / `siret`: it would skip the validation when both are missing in `SEARCH` mode.
|
|
36
|
+
*/
|
|
37
|
+
export class SignupSocietyBody {
|
|
38
|
+
@ApiProperty({ enum: SignupSocietySource, description: 'Entreprise issue de la recherche ou saisie manuellement' })
|
|
39
|
+
@IsEnum(SignupSocietySource)
|
|
40
|
+
source: SignupSocietySource;
|
|
41
|
+
|
|
42
|
+
@ApiPropertyOptional({ description: 'SIREN (9 chiffres). Requis en mode SEARCH si le SIRET est absent.' })
|
|
43
|
+
@ValidateIf(
|
|
44
|
+
(society: SignupSocietyBody) => society.siren != null || (isSearchedSociety(society) && society.siret == null),
|
|
45
|
+
)
|
|
46
|
+
@IsString()
|
|
47
|
+
@Matches(SIREN_REGEX, { message: 'Le SIREN doit comporter 9 chiffres' })
|
|
48
|
+
siren?: string;
|
|
49
|
+
|
|
50
|
+
@ApiPropertyOptional({ description: 'SIRET (14 chiffres). Requis en mode SEARCH si le SIREN est absent.' })
|
|
51
|
+
@ValidateIf(
|
|
52
|
+
(society: SignupSocietyBody) => society.siret != null || (isSearchedSociety(society) && society.siren == null),
|
|
53
|
+
)
|
|
54
|
+
@IsString()
|
|
55
|
+
@Matches(SIRET_REGEX, { message: 'Le SIRET doit comporter 14 chiffres' })
|
|
56
|
+
siret?: string;
|
|
57
|
+
|
|
58
|
+
@ApiProperty({ description: 'Raison sociale' })
|
|
59
|
+
@IsString()
|
|
60
|
+
@IsNotEmpty()
|
|
61
|
+
@MaxLength(SOCIETY_FIELD_MAX_LENGTH)
|
|
62
|
+
name: string;
|
|
63
|
+
|
|
64
|
+
@ApiPropertyOptional({ enum: LegalFormTypeEnum, description: 'Forme juridique. Requise en mode MANUAL.' })
|
|
65
|
+
@ValidateIf((society: SignupSocietyBody) => society.idLegalForm != null || !isSearchedSociety(society))
|
|
66
|
+
@IsEnum(LegalFormTypeEnum)
|
|
67
|
+
idLegalForm?: LegalFormTypeEnum;
|
|
68
|
+
|
|
69
|
+
@ApiPropertyOptional()
|
|
70
|
+
@IsOptional()
|
|
71
|
+
@IsString()
|
|
72
|
+
@MaxLength(SOCIETY_FIELD_MAX_LENGTH)
|
|
73
|
+
address?: string;
|
|
74
|
+
|
|
75
|
+
@ApiPropertyOptional()
|
|
76
|
+
@IsOptional()
|
|
77
|
+
@IsString()
|
|
78
|
+
@Matches(ZIP_CODE_REGEX, { message: 'Le code postal doit comporter 5 chiffres' })
|
|
79
|
+
zipCode?: string;
|
|
80
|
+
|
|
81
|
+
@ApiPropertyOptional()
|
|
82
|
+
@IsOptional()
|
|
83
|
+
@IsString()
|
|
84
|
+
@MaxLength(SOCIETY_FIELD_MAX_LENGTH)
|
|
85
|
+
city?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export class SignupBody {
|
|
89
|
+
@ApiProperty()
|
|
90
|
+
@IsString()
|
|
91
|
+
@IsNotEmpty()
|
|
92
|
+
@MaxLength(NAME_MAX_LENGTH)
|
|
93
|
+
firstname: string;
|
|
94
|
+
|
|
95
|
+
@ApiProperty()
|
|
96
|
+
@IsString()
|
|
97
|
+
@IsNotEmpty()
|
|
98
|
+
@MaxLength(NAME_MAX_LENGTH)
|
|
99
|
+
lastname: string;
|
|
100
|
+
|
|
101
|
+
@ApiProperty()
|
|
102
|
+
@IsString()
|
|
103
|
+
@IsEmail()
|
|
104
|
+
@MaxLength(EMAIL_MAX_LENGTH)
|
|
105
|
+
email: string;
|
|
106
|
+
|
|
107
|
+
@ApiProperty({ description: 'Numéro au format international E.164 (ex. +33612345678)' })
|
|
108
|
+
@IsString()
|
|
109
|
+
@Validate(IsE164PhoneNumber, { message: "Le numéro de téléphone n'est pas valide" })
|
|
110
|
+
phone: string;
|
|
111
|
+
|
|
112
|
+
@ApiProperty({ enum: SignupProfile, description: 'Entreprise ou expert-comptable' })
|
|
113
|
+
@IsEnum(SignupProfile)
|
|
114
|
+
profile: SignupProfile;
|
|
115
|
+
|
|
116
|
+
@ApiProperty()
|
|
117
|
+
@IsString()
|
|
118
|
+
@IsNotEmpty()
|
|
119
|
+
@MaxLength(PASSWORD_MAX_LENGTH)
|
|
120
|
+
password: string;
|
|
121
|
+
|
|
122
|
+
@ApiProperty({ type: SignupSocietyBody })
|
|
123
|
+
@ValidateNested()
|
|
124
|
+
society: SignupSocietyBody;
|
|
125
|
+
|
|
126
|
+
@ApiProperty()
|
|
127
|
+
@IsString()
|
|
128
|
+
recaptcha: string;
|
|
129
|
+
|
|
130
|
+
@ApiPropertyOptional({ description: 'Cookie HubSpot `hubspotutk`' })
|
|
131
|
+
@IsOptional()
|
|
132
|
+
@IsString()
|
|
133
|
+
hutk?: string;
|
|
134
|
+
|
|
135
|
+
@ApiPropertyOptional({ type: AnalyticsUtmBody })
|
|
136
|
+
@IsOptional()
|
|
137
|
+
@ValidateNested()
|
|
138
|
+
utm?: AnalyticsUtmBody;
|
|
139
|
+
|
|
140
|
+
/** Google Ads click id, forwarded to HubSpot as `utm_gclid`; it is not stored on the society */
|
|
141
|
+
@ApiPropertyOptional({ description: 'Identifiant de clic Google Ads (`gclid`)' })
|
|
142
|
+
@IsOptional()
|
|
143
|
+
@IsString()
|
|
144
|
+
@MaxLength(GCLID_MAX_LENGTH)
|
|
145
|
+
gclid?: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export class ResendActivationBody {
|
|
149
|
+
@ApiProperty()
|
|
150
|
+
@IsString()
|
|
151
|
+
@IsEmail()
|
|
152
|
+
@MaxLength(EMAIL_MAX_LENGTH)
|
|
153
|
+
email: string;
|
|
154
|
+
|
|
155
|
+
@ApiProperty()
|
|
156
|
+
@IsString()
|
|
157
|
+
recaptcha: string;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The password chosen at signup is required again: the activation link alone proves ownership of the
|
|
162
|
+
* email, not of the signup request. It prevents a pending account created with someone else's email from
|
|
163
|
+
* being activated (and then used with the password the author chose) by the email owner clicking the link.
|
|
164
|
+
*/
|
|
165
|
+
export class ActivateAccountBody {
|
|
166
|
+
@ApiProperty()
|
|
167
|
+
@IsString()
|
|
168
|
+
@IsNotEmpty()
|
|
169
|
+
token: string;
|
|
170
|
+
|
|
171
|
+
@ApiProperty()
|
|
172
|
+
@IsString()
|
|
173
|
+
@IsNotEmpty()
|
|
174
|
+
@MaxLength(PASSWORD_MAX_LENGTH)
|
|
175
|
+
password: string;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface ReadActivateAccount {
|
|
179
|
+
idUser: number;
|
|
180
|
+
idSociety: number;
|
|
181
|
+
societyName: string;
|
|
182
|
+
idTypeBrand: number;
|
|
183
|
+
/** `bearer <jwt>`, same shape as `POST /authenticate/external/exchange` */
|
|
184
|
+
token: string;
|
|
185
|
+
}
|
package/ts/types/index.ts
CHANGED
|
@@ -544,6 +544,7 @@ export * from './Enum/UrgencyLevel.js';
|
|
|
544
544
|
export * from './Enum/Formalism.js';
|
|
545
545
|
export * from './Enum/Kyc.js';
|
|
546
546
|
export * from './Enum/ExternalAuthenticationLinkPurpose.js';
|
|
547
|
+
export * from './Enum/Signup.js';
|
|
547
548
|
|
|
548
549
|
// Interfaces API
|
|
549
550
|
export * from './Interface/api/accountingTransaction/Create.js';
|
|
@@ -1135,6 +1136,7 @@ export * from './Interface/api/config/ConfigType.js';
|
|
|
1135
1136
|
export * from './Interface/api/card/Cron.js';
|
|
1136
1137
|
export * from './Interface/api/user/RegisterProspect.js';
|
|
1137
1138
|
export * from './Interface/api/user/RegisterWebhook.js';
|
|
1139
|
+
export * from './Interface/api/user/Signup.js';
|
|
1138
1140
|
export * from './Interface/api/stateBankAccount/Query.js';
|
|
1139
1141
|
export * from './Interface/api/absenceRequest/QueryAbsenceRequest.js';
|
|
1140
1142
|
export * from './Interface/api/absenceRequest/QueryCalendarAbsenceRequest.js';
|
|
@@ -3,7 +3,9 @@ import { parsePhoneNumberFromString } from 'libphonenumber-js';
|
|
|
3
3
|
|
|
4
4
|
@ValidatorConstraint({ name: 'isE164Phone', async: false })
|
|
5
5
|
export class IsE164PhoneNumber implements ValidatorConstraintInterface {
|
|
6
|
-
validate(text:
|
|
6
|
+
validate(text: unknown): boolean {
|
|
7
|
+
// class-validator runs every validator of the property: a missing or non-string value must not throw
|
|
8
|
+
if (typeof text !== 'string') return false;
|
|
7
9
|
const phoneNumber = parsePhoneNumberFromString(text);
|
|
8
10
|
return isDefined(phoneNumber) && phoneNumber.number === text && phoneNumber.isValid();
|
|
9
11
|
}
|