@hed-hog/contact 0.0.299 → 0.0.301

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 (81) hide show
  1. package/dist/contact.module.d.ts.map +1 -1
  2. package/dist/contact.module.js +2 -0
  3. package/dist/contact.module.js.map +1 -1
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +3 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/person/person.service.js +350 -350
  9. package/dist/proposal/dto/proposal.dto.d.ts +152 -0
  10. package/dist/proposal/dto/proposal.dto.d.ts.map +1 -0
  11. package/dist/proposal/dto/proposal.dto.js +396 -0
  12. package/dist/proposal/dto/proposal.dto.js.map +1 -0
  13. package/dist/proposal/proposal-contract.subscriber.d.ts +11 -0
  14. package/dist/proposal/proposal-contract.subscriber.d.ts.map +1 -0
  15. package/dist/proposal/proposal-contract.subscriber.js +51 -0
  16. package/dist/proposal/proposal-contract.subscriber.js.map +1 -0
  17. package/dist/proposal/proposal-event.types.d.ts +122 -0
  18. package/dist/proposal/proposal-event.types.d.ts.map +1 -0
  19. package/dist/proposal/proposal-event.types.js +13 -0
  20. package/dist/proposal/proposal-event.types.js.map +1 -0
  21. package/dist/proposal/proposal.controller.d.ts +56 -0
  22. package/dist/proposal/proposal.controller.d.ts.map +1 -0
  23. package/dist/proposal/proposal.controller.js +191 -0
  24. package/dist/proposal/proposal.controller.js.map +1 -0
  25. package/dist/proposal/proposal.module.d.ts +3 -0
  26. package/dist/proposal/proposal.module.d.ts.map +1 -0
  27. package/dist/proposal/proposal.module.js +32 -0
  28. package/dist/proposal/proposal.module.js.map +1 -0
  29. package/dist/proposal/proposal.service.d.ts +95 -0
  30. package/dist/proposal/proposal.service.d.ts.map +1 -0
  31. package/dist/proposal/proposal.service.js +1914 -0
  32. package/dist/proposal/proposal.service.js.map +1 -0
  33. package/dist/proposal/proposal.service.spec.d.ts +2 -0
  34. package/dist/proposal/proposal.service.spec.d.ts.map +1 -0
  35. package/dist/proposal/proposal.service.spec.js +187 -0
  36. package/dist/proposal/proposal.service.spec.js.map +1 -0
  37. package/hedhog/data/dashboard.yaml +6 -0
  38. package/hedhog/data/dashboard_component.yaml +87 -0
  39. package/hedhog/data/dashboard_component_role.yaml +55 -0
  40. package/hedhog/data/dashboard_item.yaml +95 -0
  41. package/hedhog/data/dashboard_role.yaml +6 -0
  42. package/hedhog/data/route.yaml +112 -68
  43. package/hedhog/frontend/app/dashboard/_components/dashboard-widgets.tsx.ejs +508 -0
  44. package/hedhog/frontend/app/dashboard/_components/use-crm-dashboard-data.ts.ejs +104 -0
  45. package/hedhog/frontend/app/dashboard/page.tsx.ejs +37 -431
  46. package/hedhog/frontend/app/pipeline/_components/lead-detail-sheet.tsx.ejs +252 -209
  47. package/hedhog/frontend/app/pipeline/_components/lead-proposals-tab.tsx.ejs +1584 -0
  48. package/hedhog/frontend/messages/en.json +136 -42
  49. package/hedhog/frontend/messages/pt.json +135 -41
  50. package/hedhog/frontend/widgets/next-actions.tsx.ejs +40 -0
  51. package/hedhog/frontend/widgets/overview-kpis.tsx.ejs +47 -0
  52. package/hedhog/frontend/widgets/owner-performance.tsx.ejs +42 -0
  53. package/hedhog/frontend/widgets/quick-access.tsx.ejs +29 -0
  54. package/hedhog/frontend/widgets/source-breakdown.tsx.ejs +40 -0
  55. package/hedhog/frontend/widgets/stage-distribution.tsx.ejs +40 -0
  56. package/hedhog/frontend/widgets/top-owners.tsx.ejs +42 -0
  57. package/hedhog/frontend/widgets/unattended.tsx.ejs +40 -0
  58. package/hedhog/table/crm_activity.yaml +68 -68
  59. package/hedhog/table/crm_stage_history.yaml +34 -34
  60. package/hedhog/table/person_company.yaml +27 -27
  61. package/hedhog/table/proposal.yaml +112 -0
  62. package/hedhog/table/proposal_approval.yaml +63 -0
  63. package/hedhog/table/proposal_document.yaml +77 -0
  64. package/hedhog/table/proposal_item.yaml +64 -0
  65. package/hedhog/table/proposal_revision.yaml +78 -0
  66. package/package.json +6 -5
  67. package/src/contact.module.ts +2 -0
  68. package/src/index.ts +3 -0
  69. package/src/person/dto/account.dto.ts +100 -100
  70. package/src/person/dto/activity.dto.ts +54 -54
  71. package/src/person/dto/dashboard-query.dto.ts +25 -25
  72. package/src/person/dto/followup-query.dto.ts +25 -25
  73. package/src/person/dto/reports-query.dto.ts +25 -25
  74. package/src/person/person.controller.ts +176 -176
  75. package/src/person/person.service.ts +4825 -4825
  76. package/src/proposal/dto/proposal.dto.ts +341 -0
  77. package/src/proposal/proposal-contract.subscriber.ts +43 -0
  78. package/src/proposal/proposal-event.types.ts +130 -0
  79. package/src/proposal/proposal.controller.ts +168 -0
  80. package/src/proposal/proposal.module.ts +19 -0
  81. package/src/proposal/proposal.service.ts +2525 -0
@@ -0,0 +1,78 @@
1
+ columns:
2
+ - type: pk
3
+ - name: proposal_id
4
+ type: fk
5
+ references:
6
+ table: proposal
7
+ column: id
8
+ onDelete: CASCADE
9
+ onUpdate: CASCADE
10
+ - name: revision_number
11
+ type: int
12
+ - name: status
13
+ type: enum
14
+ values: [draft, pending_approval, approved, rejected, cancelled, superseded]
15
+ default: draft
16
+ - name: generation_mode
17
+ type: enum
18
+ values: [manual, ai_assisted, duplicated, imported]
19
+ default: manual
20
+ - name: title
21
+ type: varchar
22
+ length: 180
23
+ - name: summary
24
+ type: text
25
+ isNullable: true
26
+ - name: content_html
27
+ type: text
28
+ isNullable: true
29
+ - name: snapshot_json
30
+ type: json
31
+ isNullable: true
32
+ - name: valid_until
33
+ type: datetime
34
+ isNullable: true
35
+ - name: subtotal_amount_cents
36
+ type: int
37
+ default: 0
38
+ - name: discount_amount_cents
39
+ type: int
40
+ default: 0
41
+ - name: tax_amount_cents
42
+ type: int
43
+ default: 0
44
+ - name: total_amount_cents
45
+ type: int
46
+ default: 0
47
+ - name: submitted_at
48
+ type: datetime
49
+ isNullable: true
50
+ - name: approved_at
51
+ type: datetime
52
+ isNullable: true
53
+ - name: is_current
54
+ type: boolean
55
+ default: true
56
+ - name: created_by_user_id
57
+ type: fk
58
+ isNullable: true
59
+ references:
60
+ table: user
61
+ column: id
62
+ onDelete: SET NULL
63
+ onUpdate: CASCADE
64
+ - name: deleted_at
65
+ type: datetime
66
+ isNullable: true
67
+ - type: created_at
68
+ - type: updated_at
69
+
70
+ indices:
71
+ - columns: [proposal_id, revision_number]
72
+ isUnique: true
73
+ - columns: [proposal_id]
74
+ - columns: [proposal_id, is_current]
75
+ - columns: [status]
76
+ - columns: [submitted_at]
77
+ - columns: [approved_at]
78
+ - columns: [deleted_at]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/contact",
3
- "version": "0.0.299",
3
+ "version": "0.0.301",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -9,13 +9,13 @@
9
9
  "@nestjs/core": "^11",
10
10
  "@nestjs/jwt": "^11",
11
11
  "@nestjs/mapped-types": "*",
12
+ "@hed-hog/core": "0.0.301",
12
13
  "@hed-hog/api-mail": "0.0.9",
13
- "@hed-hog/core": "0.0.299",
14
- "@hed-hog/address": "0.0.299",
15
14
  "@hed-hog/api-prisma": "0.0.6",
15
+ "@hed-hog/address": "0.0.301",
16
16
  "@hed-hog/api": "0.0.6",
17
- "@hed-hog/api-locale": "0.0.14",
18
- "@hed-hog/api-pagination": "0.0.7"
17
+ "@hed-hog/api-pagination": "0.0.7",
18
+ "@hed-hog/api-locale": "0.0.14"
19
19
  },
20
20
  "exports": {
21
21
  ".": {
@@ -31,6 +31,7 @@
31
31
  ],
32
32
  "scripts": {
33
33
  "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
34
+ "test": "jest --config jest.config.ts --runInBand",
34
35
  "prebuild": "pnpm --dir ../.. exec ts-node ./scripts/build-dependencies.ts libraries/contact",
35
36
  "build": "tsc --project tsconfig.production.json",
36
37
  "patch": "npx ts-node ../../scripts/patch.ts libraries/contact",
@@ -11,6 +11,7 @@ import { ContactService } from './contact.service';
11
11
  import { PersonDocumentTypeModule } from './document-type/document-type.module';
12
12
  import { PersonRelationTypeModule } from './person-relation-type/person-relation-type.module';
13
13
  import { PersonModule } from './person/person.module';
14
+ import { ProposalModule } from './proposal/proposal.module';
14
15
 
15
16
  @Module({
16
17
  imports: [
@@ -33,6 +34,7 @@ import { PersonModule } from './person/person.module';
33
34
  forwardRef(() => PrismaModule),
34
35
  forwardRef(() => PaginationModule),
35
36
  forwardRef(() => PersonModule),
37
+ forwardRef(() => ProposalModule),
36
38
  forwardRef(() => PersonContactTypeModule),
37
39
  forwardRef(() => PersonDocumentTypeModule),
38
40
  forwardRef(() => PersonRelationTypeModule),
package/src/index.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export * from './contact.module';
2
2
  export * from './contact.service';
3
+ export * from './proposal/proposal-event.types';
4
+ export * from './proposal/proposal.module';
5
+ export * from './proposal/proposal.service';
3
6
 
4
7
  export * from './address-type.enum';
5
8
  export * from './contact-type/contact-type.enum';
@@ -1,100 +1,100 @@
1
- import { Type } from 'class-transformer';
2
- import {
3
- IsEmail,
4
- IsIn,
5
- IsInt,
6
- IsNumber,
7
- IsOptional,
8
- IsString,
9
- MaxLength,
10
- } from 'class-validator';
11
- import { PersonStatus } from './create.dto';
12
-
13
- export const ACCOUNT_LIFECYCLE_STAGES = [
14
- 'prospect',
15
- 'customer',
16
- 'churned',
17
- 'inactive',
18
- ] as const;
19
-
20
- export type AccountLifecycleStage = (typeof ACCOUNT_LIFECYCLE_STAGES)[number];
21
-
22
- export class AccountListQueryDTO {
23
- @IsOptional()
24
- @IsString()
25
- search?: string;
26
-
27
- @IsOptional()
28
- @IsIn(['all', PersonStatus.ACTIVE, PersonStatus.INACTIVE])
29
- status?: 'all' | PersonStatus;
30
-
31
- @IsOptional()
32
- @IsIn(['all', ...ACCOUNT_LIFECYCLE_STAGES])
33
- lifecycle_stage?: 'all' | AccountLifecycleStage;
34
-
35
- @IsOptional()
36
- @IsIn(['name', 'created_at'])
37
- sortField?: 'name' | 'created_at';
38
-
39
- @IsOptional()
40
- @IsIn(['asc', 'desc'])
41
- sortOrder?: 'asc' | 'desc';
42
- }
43
-
44
- export class CreateAccountDTO {
45
- @IsString()
46
- name: string;
47
-
48
- @IsOptional()
49
- @IsString()
50
- trade_name?: string | null;
51
-
52
- @IsIn([PersonStatus.ACTIVE, PersonStatus.INACTIVE])
53
- status: PersonStatus;
54
-
55
- @IsOptional()
56
- @IsString()
57
- industry?: string | null;
58
-
59
- @IsOptional()
60
- @IsString()
61
- website?: string | null;
62
-
63
- @IsOptional()
64
- @IsEmail()
65
- email?: string | null;
66
-
67
- @IsOptional()
68
- @IsString()
69
- phone?: string | null;
70
-
71
- @IsOptional()
72
- @Type(() => Number)
73
- @IsInt()
74
- owner_user_id?: number | null;
75
-
76
- @IsOptional()
77
- @Type(() => Number)
78
- @IsNumber()
79
- annual_revenue?: number | null;
80
-
81
- @IsOptional()
82
- @Type(() => Number)
83
- @IsInt()
84
- employee_count?: number | null;
85
-
86
- @IsOptional()
87
- @IsIn(ACCOUNT_LIFECYCLE_STAGES)
88
- lifecycle_stage?: AccountLifecycleStage | null;
89
-
90
- @IsOptional()
91
- @IsString()
92
- city?: string | null;
93
-
94
- @IsOptional()
95
- @IsString()
96
- @MaxLength(2)
97
- state?: string | null;
98
- }
99
-
100
- export class UpdateAccountDTO extends CreateAccountDTO {}
1
+ import { Type } from 'class-transformer';
2
+ import {
3
+ IsEmail,
4
+ IsIn,
5
+ IsInt,
6
+ IsNumber,
7
+ IsOptional,
8
+ IsString,
9
+ MaxLength,
10
+ } from 'class-validator';
11
+ import { PersonStatus } from './create.dto';
12
+
13
+ export const ACCOUNT_LIFECYCLE_STAGES = [
14
+ 'prospect',
15
+ 'customer',
16
+ 'churned',
17
+ 'inactive',
18
+ ] as const;
19
+
20
+ export type AccountLifecycleStage = (typeof ACCOUNT_LIFECYCLE_STAGES)[number];
21
+
22
+ export class AccountListQueryDTO {
23
+ @IsOptional()
24
+ @IsString()
25
+ search?: string;
26
+
27
+ @IsOptional()
28
+ @IsIn(['all', PersonStatus.ACTIVE, PersonStatus.INACTIVE])
29
+ status?: 'all' | PersonStatus;
30
+
31
+ @IsOptional()
32
+ @IsIn(['all', ...ACCOUNT_LIFECYCLE_STAGES])
33
+ lifecycle_stage?: 'all' | AccountLifecycleStage;
34
+
35
+ @IsOptional()
36
+ @IsIn(['name', 'created_at'])
37
+ sortField?: 'name' | 'created_at';
38
+
39
+ @IsOptional()
40
+ @IsIn(['asc', 'desc'])
41
+ sortOrder?: 'asc' | 'desc';
42
+ }
43
+
44
+ export class CreateAccountDTO {
45
+ @IsString()
46
+ name: string;
47
+
48
+ @IsOptional()
49
+ @IsString()
50
+ trade_name?: string | null;
51
+
52
+ @IsIn([PersonStatus.ACTIVE, PersonStatus.INACTIVE])
53
+ status: PersonStatus;
54
+
55
+ @IsOptional()
56
+ @IsString()
57
+ industry?: string | null;
58
+
59
+ @IsOptional()
60
+ @IsString()
61
+ website?: string | null;
62
+
63
+ @IsOptional()
64
+ @IsEmail()
65
+ email?: string | null;
66
+
67
+ @IsOptional()
68
+ @IsString()
69
+ phone?: string | null;
70
+
71
+ @IsOptional()
72
+ @Type(() => Number)
73
+ @IsInt()
74
+ owner_user_id?: number | null;
75
+
76
+ @IsOptional()
77
+ @Type(() => Number)
78
+ @IsNumber()
79
+ annual_revenue?: number | null;
80
+
81
+ @IsOptional()
82
+ @Type(() => Number)
83
+ @IsInt()
84
+ employee_count?: number | null;
85
+
86
+ @IsOptional()
87
+ @IsIn(ACCOUNT_LIFECYCLE_STAGES)
88
+ lifecycle_stage?: AccountLifecycleStage | null;
89
+
90
+ @IsOptional()
91
+ @IsString()
92
+ city?: string | null;
93
+
94
+ @IsOptional()
95
+ @IsString()
96
+ @MaxLength(2)
97
+ state?: string | null;
98
+ }
99
+
100
+ export class UpdateAccountDTO extends CreateAccountDTO {}
@@ -1,54 +1,54 @@
1
- import { getLocaleText } from '@hed-hog/api-locale';
2
- import { IsIn, IsOptional, IsString } from 'class-validator';
3
-
4
- export const CRM_ACTIVITY_TYPES = [
5
- 'call',
6
- 'email',
7
- 'meeting',
8
- 'whatsapp',
9
- 'task',
10
- 'note',
11
- ] as const;
12
-
13
- export const CRM_ACTIVITY_PRIORITIES = ['high', 'medium', 'low'] as const;
14
- export const CRM_ACTIVITY_STATUSES = [
15
- 'pending',
16
- 'overdue',
17
- 'completed',
18
- ] as const;
19
- export const CRM_ACTIVITY_SOURCE_KINDS = [
20
- 'manual',
21
- 'followup',
22
- 'interaction',
23
- ] as const;
24
-
25
- export type CrmActivityType = (typeof CRM_ACTIVITY_TYPES)[number];
26
- export type CrmActivityPriority = (typeof CRM_ACTIVITY_PRIORITIES)[number];
27
- export type CrmActivityStatus = (typeof CRM_ACTIVITY_STATUSES)[number];
28
- export type CrmActivitySourceKind = (typeof CRM_ACTIVITY_SOURCE_KINDS)[number];
29
-
30
- export class ActivityListQueryDTO {
31
- @IsOptional()
32
- @IsString({
33
- message: (args) => getLocaleText('validation.stringRequired', args.value),
34
- })
35
- search?: string;
36
-
37
- @IsOptional()
38
- @IsIn(['all', ...CRM_ACTIVITY_STATUSES], {
39
- message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
40
- })
41
- status?: 'all' | CrmActivityStatus;
42
-
43
- @IsOptional()
44
- @IsIn(['all', ...CRM_ACTIVITY_TYPES], {
45
- message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
46
- })
47
- type?: 'all' | CrmActivityType;
48
-
49
- @IsOptional()
50
- @IsIn(['all', ...CRM_ACTIVITY_PRIORITIES], {
51
- message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
52
- })
53
- priority?: 'all' | CrmActivityPriority;
54
- }
1
+ import { getLocaleText } from '@hed-hog/api-locale';
2
+ import { IsIn, IsOptional, IsString } from 'class-validator';
3
+
4
+ export const CRM_ACTIVITY_TYPES = [
5
+ 'call',
6
+ 'email',
7
+ 'meeting',
8
+ 'whatsapp',
9
+ 'task',
10
+ 'note',
11
+ ] as const;
12
+
13
+ export const CRM_ACTIVITY_PRIORITIES = ['high', 'medium', 'low'] as const;
14
+ export const CRM_ACTIVITY_STATUSES = [
15
+ 'pending',
16
+ 'overdue',
17
+ 'completed',
18
+ ] as const;
19
+ export const CRM_ACTIVITY_SOURCE_KINDS = [
20
+ 'manual',
21
+ 'followup',
22
+ 'interaction',
23
+ ] as const;
24
+
25
+ export type CrmActivityType = (typeof CRM_ACTIVITY_TYPES)[number];
26
+ export type CrmActivityPriority = (typeof CRM_ACTIVITY_PRIORITIES)[number];
27
+ export type CrmActivityStatus = (typeof CRM_ACTIVITY_STATUSES)[number];
28
+ export type CrmActivitySourceKind = (typeof CRM_ACTIVITY_SOURCE_KINDS)[number];
29
+
30
+ export class ActivityListQueryDTO {
31
+ @IsOptional()
32
+ @IsString({
33
+ message: (args) => getLocaleText('validation.stringRequired', args.value),
34
+ })
35
+ search?: string;
36
+
37
+ @IsOptional()
38
+ @IsIn(['all', ...CRM_ACTIVITY_STATUSES], {
39
+ message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
40
+ })
41
+ status?: 'all' | CrmActivityStatus;
42
+
43
+ @IsOptional()
44
+ @IsIn(['all', ...CRM_ACTIVITY_TYPES], {
45
+ message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
46
+ })
47
+ type?: 'all' | CrmActivityType;
48
+
49
+ @IsOptional()
50
+ @IsIn(['all', ...CRM_ACTIVITY_PRIORITIES], {
51
+ message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
52
+ })
53
+ priority?: 'all' | CrmActivityPriority;
54
+ }
@@ -1,25 +1,25 @@
1
- import { Type } from 'class-transformer';
2
- import { IsDateString, IsIn, IsInt, IsOptional } from 'class-validator';
3
-
4
- export const CRM_DASHBOARD_PERIODS = ['7d', '30d', '90d', 'custom'] as const;
5
-
6
- export type CrmDashboardPeriod = (typeof CRM_DASHBOARD_PERIODS)[number];
7
-
8
- export class DashboardQueryDTO {
9
- @IsOptional()
10
- @Type(() => Number)
11
- @IsInt()
12
- owner_user_id?: number;
13
-
14
- @IsOptional()
15
- @IsIn(CRM_DASHBOARD_PERIODS)
16
- period?: CrmDashboardPeriod;
17
-
18
- @IsOptional()
19
- @IsDateString()
20
- date_from?: string;
21
-
22
- @IsOptional()
23
- @IsDateString()
24
- date_to?: string;
25
- }
1
+ import { Type } from 'class-transformer';
2
+ import { IsDateString, IsIn, IsInt, IsOptional } from 'class-validator';
3
+
4
+ export const CRM_DASHBOARD_PERIODS = ['7d', '30d', '90d', 'custom'] as const;
5
+
6
+ export type CrmDashboardPeriod = (typeof CRM_DASHBOARD_PERIODS)[number];
7
+
8
+ export class DashboardQueryDTO {
9
+ @IsOptional()
10
+ @Type(() => Number)
11
+ @IsInt()
12
+ owner_user_id?: number;
13
+
14
+ @IsOptional()
15
+ @IsIn(CRM_DASHBOARD_PERIODS)
16
+ period?: CrmDashboardPeriod;
17
+
18
+ @IsOptional()
19
+ @IsDateString()
20
+ date_from?: string;
21
+
22
+ @IsOptional()
23
+ @IsDateString()
24
+ date_to?: string;
25
+ }
@@ -1,25 +1,25 @@
1
- import { IsIn, IsOptional, IsString, Matches } from 'class-validator';
2
-
3
- export class FollowupListQueryDTO {
4
- @IsOptional()
5
- @IsString()
6
- search?: string;
7
-
8
- @IsOptional()
9
- @IsIn(['all', 'today', 'upcoming', 'overdue'])
10
- status?: 'all' | 'today' | 'upcoming' | 'overdue';
11
-
12
- @IsOptional()
13
- @Matches(/^\d{4}-\d{2}-\d{2}$/)
14
- date_from?: string;
15
-
16
- @IsOptional()
17
- @Matches(/^\d{4}-\d{2}-\d{2}$/)
18
- date_to?: string;
19
- }
20
-
21
- export class FollowupStatsQueryDTO {
22
- @IsOptional()
23
- @IsString()
24
- search?: string;
25
- }
1
+ import { IsIn, IsOptional, IsString, Matches } from 'class-validator';
2
+
3
+ export class FollowupListQueryDTO {
4
+ @IsOptional()
5
+ @IsString()
6
+ search?: string;
7
+
8
+ @IsOptional()
9
+ @IsIn(['all', 'today', 'upcoming', 'overdue'])
10
+ status?: 'all' | 'today' | 'upcoming' | 'overdue';
11
+
12
+ @IsOptional()
13
+ @Matches(/^\d{4}-\d{2}-\d{2}$/)
14
+ date_from?: string;
15
+
16
+ @IsOptional()
17
+ @Matches(/^\d{4}-\d{2}-\d{2}$/)
18
+ date_to?: string;
19
+ }
20
+
21
+ export class FollowupStatsQueryDTO {
22
+ @IsOptional()
23
+ @IsString()
24
+ search?: string;
25
+ }
@@ -1,25 +1,25 @@
1
- import { getLocaleText } from '@hed-hog/api-locale';
2
- import { IsDateString, IsIn } from 'class-validator';
3
-
4
- export const CRM_REPORT_GROUP_BY = ['day', 'week', 'month', 'year'] as const;
5
-
6
- export type CrmReportGroupBy = (typeof CRM_REPORT_GROUP_BY)[number];
7
-
8
- export class ReportsQueryDTO {
9
- @IsDateString(
10
- {},
11
- { message: (args) => getLocaleText('validation.dateMustBeString', args.value) },
12
- )
13
- date_from: string;
14
-
15
- @IsDateString(
16
- {},
17
- { message: (args) => getLocaleText('validation.dateMustBeString', args.value) },
18
- )
19
- date_to: string;
20
-
21
- @IsIn(CRM_REPORT_GROUP_BY, {
22
- message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
23
- })
24
- group_by: CrmReportGroupBy;
25
- }
1
+ import { getLocaleText } from '@hed-hog/api-locale';
2
+ import { IsDateString, IsIn } from 'class-validator';
3
+
4
+ export const CRM_REPORT_GROUP_BY = ['day', 'week', 'month', 'year'] as const;
5
+
6
+ export type CrmReportGroupBy = (typeof CRM_REPORT_GROUP_BY)[number];
7
+
8
+ export class ReportsQueryDTO {
9
+ @IsDateString(
10
+ {},
11
+ { message: (args) => getLocaleText('validation.dateMustBeString', args.value) },
12
+ )
13
+ date_from: string;
14
+
15
+ @IsDateString(
16
+ {},
17
+ { message: (args) => getLocaleText('validation.dateMustBeString', args.value) },
18
+ )
19
+ date_to: string;
20
+
21
+ @IsIn(CRM_REPORT_GROUP_BY, {
22
+ message: (args) => getLocaleText('validation.typeMustBeEnum', args.value),
23
+ })
24
+ group_by: CrmReportGroupBy;
25
+ }