tychat-contracts 1.0.98 → 1.0.100
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/analytics/analytics-query.dto.d.ts +32 -0
- package/dist/analytics/analytics-query.dto.d.ts.map +1 -1
- package/dist/analytics/analytics-query.dto.js +113 -1
- package/dist/analytics/event-analytic.enum.d.ts +1 -1
- package/dist/analytics/event-analytic.enum.d.ts.map +1 -1
- package/dist/analytics/event-analytic.enum.js +2 -0
- package/dist/appointments/list-appointments-query.dto.d.ts +2 -1
- package/dist/appointments/list-appointments-query.dto.d.ts.map +1 -1
- package/dist/appointments/list-appointments-query.dto.js +17 -3
- package/package.json +1 -1
- package/src/analytics/analytics-query.dto.ts +83 -0
- package/src/analytics/event-analytic.enum.ts +2 -0
- package/src/appointments/list-appointments-query.dto.ts +15 -3
|
@@ -22,4 +22,36 @@ export declare class AnalyticsDashboardQueryDto {
|
|
|
22
22
|
startDate: string;
|
|
23
23
|
endDate: string;
|
|
24
24
|
}
|
|
25
|
+
/** Resumo financeiro agregado a partir de eventos de analytics (pagamentos + faturamento). */
|
|
26
|
+
export declare class AnalyticsDashboardFinancialDto {
|
|
27
|
+
revenue: number;
|
|
28
|
+
averageTicket: number;
|
|
29
|
+
pending: number;
|
|
30
|
+
}
|
|
31
|
+
export declare class AnalyticsDashboardTopProcedureDto {
|
|
32
|
+
name: string;
|
|
33
|
+
count: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resposta enriquecida de `GET /analytics/dashboard` (mantém campos legados `total`, `byEventType`, `byDomain`).
|
|
37
|
+
*/
|
|
38
|
+
export declare class AnalyticsDashboardResponseDto {
|
|
39
|
+
appointmentsCreated: number;
|
|
40
|
+
appointmentsFinished: number;
|
|
41
|
+
proceduresScheduled: number;
|
|
42
|
+
proceduresFinished: number;
|
|
43
|
+
satisfactionAverage: number | null;
|
|
44
|
+
noShowRatePercent: number;
|
|
45
|
+
financialSummary: AnalyticsDashboardFinancialDto;
|
|
46
|
+
topProcedures: AnalyticsDashboardTopProcedureDto[];
|
|
47
|
+
total: number;
|
|
48
|
+
byEventType: Array<{
|
|
49
|
+
eventType: string;
|
|
50
|
+
count: number;
|
|
51
|
+
}>;
|
|
52
|
+
byDomain: Array<{
|
|
53
|
+
domain: string;
|
|
54
|
+
count: number;
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
25
57
|
//# sourceMappingURL=analytics-query.dto.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics-query.dto.d.ts","sourceRoot":"","sources":["../../src/analytics/analytics-query.dto.ts"],"names":[],"mappings":"AAYA,OAAO,EAAwB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,kBAAkB,2CAA4C,CAAC;AAC5E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE;;GAEG;AACH,qBAAa,uBAAuB;IAMlC,SAAS,EAAE,MAAM,CAAC;IAOlB,OAAO,EAAE,MAAM,CAAC;IAShB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAS9B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAO3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAOd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,0BAA0B;IAMrC,SAAS,EAAE,MAAM,CAAC;IAOlB,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"analytics-query.dto.d.ts","sourceRoot":"","sources":["../../src/analytics/analytics-query.dto.ts"],"names":[],"mappings":"AAYA,OAAO,EAAwB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,kBAAkB,2CAA4C,CAAC;AAC5E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE;;GAEG;AACH,qBAAa,uBAAuB;IAMlC,SAAS,EAAE,MAAM,CAAC;IAOlB,OAAO,EAAE,MAAM,CAAC;IAShB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAS9B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAO3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAOd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,0BAA0B;IAMrC,SAAS,EAAE,MAAM,CAAC;IAOlB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8FAA8F;AAC9F,qBAAa,8BAA8B;IAKzC,OAAO,EAAE,MAAM,CAAC;IAMhB,aAAa,EAAE,MAAM,CAAC;IAMtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,iCAAiC;IAE5C,IAAI,EAAE,MAAM,CAAC;IAGb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,6BAA6B;IAExC,mBAAmB,EAAE,MAAM,CAAC;IAG5B,oBAAoB,EAAE,MAAM,CAAC;IAM7B,mBAAmB,EAAE,MAAM,CAAC;IAK5B,kBAAkB,EAAE,MAAM,CAAC;IAO3B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IAMnC,iBAAiB,EAAE,MAAM,CAAC;IAG1B,gBAAgB,EAAE,8BAA8B,CAAC;IAGjD,aAAa,EAAE,iCAAiC,EAAE,CAAC;IAGnD,KAAK,EAAE,MAAM,CAAC;IAKd,WAAW,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAKzD,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD"}
|
|
@@ -9,7 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AnalyticsDashboardQueryDto = exports.AnalyticsReportQueryDto = exports.ANALYTICS_GROUP_BY = void 0;
|
|
12
|
+
exports.AnalyticsDashboardResponseDto = exports.AnalyticsDashboardTopProcedureDto = exports.AnalyticsDashboardFinancialDto = exports.AnalyticsDashboardQueryDto = exports.AnalyticsReportQueryDto = exports.ANALYTICS_GROUP_BY = void 0;
|
|
13
13
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const class_transformer_1 = require("class-transformer");
|
|
@@ -106,3 +106,115 @@ __decorate([
|
|
|
106
106
|
(0, class_validator_1.IsISO8601)(),
|
|
107
107
|
__metadata("design:type", String)
|
|
108
108
|
], AnalyticsDashboardQueryDto.prototype, "endDate", void 0);
|
|
109
|
+
/** Resumo financeiro agregado a partir de eventos de analytics (pagamentos + faturamento). */
|
|
110
|
+
class AnalyticsDashboardFinancialDto {
|
|
111
|
+
revenue;
|
|
112
|
+
averageTicket;
|
|
113
|
+
pending;
|
|
114
|
+
}
|
|
115
|
+
exports.AnalyticsDashboardFinancialDto = AnalyticsDashboardFinancialDto;
|
|
116
|
+
__decorate([
|
|
117
|
+
(0, swagger_1.ApiProperty)({
|
|
118
|
+
description: 'Receita no período: soma de `payment.payed` e `billing.invoice_paid` (valores em metadata.amount)',
|
|
119
|
+
}),
|
|
120
|
+
__metadata("design:type", Number)
|
|
121
|
+
], AnalyticsDashboardFinancialDto.prototype, "revenue", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
(0, swagger_1.ApiProperty)({
|
|
124
|
+
description: 'Ticket médio: revenue / número de eventos pagos (payment.payed + billing.invoice_paid); 0 se não houver pagamentos',
|
|
125
|
+
}),
|
|
126
|
+
__metadata("design:type", Number)
|
|
127
|
+
], AnalyticsDashboardFinancialDto.prototype, "averageTicket", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
(0, swagger_1.ApiProperty)({
|
|
130
|
+
description: 'Volume de cobranças criadas no período ainda não quitadas no momento do registro: soma de `payment.created` + faturas `billing.invoice_created` com status PENDING ou OVERDUE no metadata (aproximação; não substitui saldo contábil)',
|
|
131
|
+
}),
|
|
132
|
+
__metadata("design:type", Number)
|
|
133
|
+
], AnalyticsDashboardFinancialDto.prototype, "pending", void 0);
|
|
134
|
+
class AnalyticsDashboardTopProcedureDto {
|
|
135
|
+
name;
|
|
136
|
+
count;
|
|
137
|
+
}
|
|
138
|
+
exports.AnalyticsDashboardTopProcedureDto = AnalyticsDashboardTopProcedureDto;
|
|
139
|
+
__decorate([
|
|
140
|
+
(0, swagger_1.ApiProperty)({ description: 'Nome do procedimento (agendamento)' }),
|
|
141
|
+
__metadata("design:type", String)
|
|
142
|
+
], AnalyticsDashboardTopProcedureDto.prototype, "name", void 0);
|
|
143
|
+
__decorate([
|
|
144
|
+
(0, swagger_1.ApiProperty)({ description: 'Quantidade de ocorrências no período' }),
|
|
145
|
+
__metadata("design:type", Number)
|
|
146
|
+
], AnalyticsDashboardTopProcedureDto.prototype, "count", void 0);
|
|
147
|
+
/**
|
|
148
|
+
* Resposta enriquecida de `GET /analytics/dashboard` (mantém campos legados `total`, `byEventType`, `byDomain`).
|
|
149
|
+
*/
|
|
150
|
+
class AnalyticsDashboardResponseDto {
|
|
151
|
+
appointmentsCreated;
|
|
152
|
+
appointmentsFinished;
|
|
153
|
+
proceduresScheduled;
|
|
154
|
+
proceduresFinished;
|
|
155
|
+
satisfactionAverage;
|
|
156
|
+
noShowRatePercent;
|
|
157
|
+
financialSummary;
|
|
158
|
+
topProcedures;
|
|
159
|
+
total;
|
|
160
|
+
byEventType;
|
|
161
|
+
byDomain;
|
|
162
|
+
}
|
|
163
|
+
exports.AnalyticsDashboardResponseDto = AnalyticsDashboardResponseDto;
|
|
164
|
+
__decorate([
|
|
165
|
+
(0, swagger_1.ApiProperty)({ description: 'Agendamentos criados no período (`appointment.created`)' }),
|
|
166
|
+
__metadata("design:type", Number)
|
|
167
|
+
], AnalyticsDashboardResponseDto.prototype, "appointmentsCreated", void 0);
|
|
168
|
+
__decorate([
|
|
169
|
+
(0, swagger_1.ApiProperty)({ description: 'Agendamentos finalizados no período (`appointment.finished`)' }),
|
|
170
|
+
__metadata("design:type", Number)
|
|
171
|
+
], AnalyticsDashboardResponseDto.prototype, "appointmentsFinished", void 0);
|
|
172
|
+
__decorate([
|
|
173
|
+
(0, swagger_1.ApiProperty)({
|
|
174
|
+
description: 'Procedimentos agendados: soma dos itens em metadata.procedures em `appointment.created` + vínculos posteriores (`appointment.updated` com reason procedure_added)',
|
|
175
|
+
}),
|
|
176
|
+
__metadata("design:type", Number)
|
|
177
|
+
], AnalyticsDashboardResponseDto.prototype, "proceduresScheduled", void 0);
|
|
178
|
+
__decorate([
|
|
179
|
+
(0, swagger_1.ApiProperty)({
|
|
180
|
+
description: 'Procedimentos marcados como concluídos no período (`appointment.procedure_finished`)',
|
|
181
|
+
}),
|
|
182
|
+
__metadata("design:type", Number)
|
|
183
|
+
], AnalyticsDashboardResponseDto.prototype, "proceduresFinished", void 0);
|
|
184
|
+
__decorate([
|
|
185
|
+
(0, swagger_1.ApiProperty)({
|
|
186
|
+
description: 'Média das notas 1–5 em respostas de satisfação (followup booking + pós-atendimento); null se não houver respostas',
|
|
187
|
+
nullable: true,
|
|
188
|
+
}),
|
|
189
|
+
__metadata("design:type", Object)
|
|
190
|
+
], AnalyticsDashboardResponseDto.prototype, "satisfactionAverage", void 0);
|
|
191
|
+
__decorate([
|
|
192
|
+
(0, swagger_1.ApiProperty)({
|
|
193
|
+
description: 'Taxa de no-show (%): appointment.no_show / appointment.created no período (0 se não houver criações)',
|
|
194
|
+
}),
|
|
195
|
+
__metadata("design:type", Number)
|
|
196
|
+
], AnalyticsDashboardResponseDto.prototype, "noShowRatePercent", void 0);
|
|
197
|
+
__decorate([
|
|
198
|
+
(0, swagger_1.ApiProperty)({ type: AnalyticsDashboardFinancialDto }),
|
|
199
|
+
__metadata("design:type", AnalyticsDashboardFinancialDto)
|
|
200
|
+
], AnalyticsDashboardResponseDto.prototype, "financialSummary", void 0);
|
|
201
|
+
__decorate([
|
|
202
|
+
(0, swagger_1.ApiProperty)({ type: [AnalyticsDashboardTopProcedureDto], maxItems: 5 }),
|
|
203
|
+
__metadata("design:type", Array)
|
|
204
|
+
], AnalyticsDashboardResponseDto.prototype, "topProcedures", void 0);
|
|
205
|
+
__decorate([
|
|
206
|
+
(0, swagger_1.ApiProperty)({ description: 'Total de eventos de analytics no período (legado)' }),
|
|
207
|
+
__metadata("design:type", Number)
|
|
208
|
+
], AnalyticsDashboardResponseDto.prototype, "total", void 0);
|
|
209
|
+
__decorate([
|
|
210
|
+
(0, swagger_1.ApiProperty)({
|
|
211
|
+
description: 'Contagens por eventType (legado)',
|
|
212
|
+
}),
|
|
213
|
+
__metadata("design:type", Array)
|
|
214
|
+
], AnalyticsDashboardResponseDto.prototype, "byEventType", void 0);
|
|
215
|
+
__decorate([
|
|
216
|
+
(0, swagger_1.ApiProperty)({
|
|
217
|
+
description: 'Contagens por domínio (prefixo antes do ponto no eventType) (legado)',
|
|
218
|
+
}),
|
|
219
|
+
__metadata("design:type", Array)
|
|
220
|
+
], AnalyticsDashboardResponseDto.prototype, "byDomain", void 0);
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Enum of all analytic event types emitted by microservices.
|
|
3
3
|
* Each value follows the pattern: `domain.action`.
|
|
4
4
|
*/
|
|
5
|
-
export declare const EVENT_ANALYTIC_TYPES: readonly ["patient.created", "patient.updated", "patient.deleted", "patient.status_changed", "appointment.created", "appointment.updated", "appointment.canceled", "appointment.rescheduled", "appointment.no_show", "appointment.finished", "checkin.effectued", "checkout.effectued", "message.sent", "message.received", "conversation.session_started", "conversation.session_ended", "conversation.transferred_to_human", "followup.abandonment.sent", "followup.appointment_confirmation.sent", "followup.satisfaction_booking.sent", "followup.satisfaction_finished.sent", "followup.no_show_reschedule.sent", "followup.wellness_check.sent", "followup.return_suggestion.sent", "followup.satisfaction_booking.response_received", "followup.satisfaction_finished.response_received", "followup.config_updated", "payment.created", "payment.payed", "payment.refunded", "payment.canceled", "payment.overdue", "payment_gateway.payment_created", "payment_gateway.payment_confirmed", "payment_gateway.payment_failed", "payment_gateway.payment_refunded", "payment_gateway.payment_canceled", "payment_gateway.payment_expired", "payment_gateway.webhook_received", "billing.invoice_created", "billing.invoice_paid", "ai.interaction", "ai.fallback", "auth.login", "auth.logout", "auth.password_reset", "user.created", "user.updated", "user.deleted", "notification.sent", "notification.failed", "whatsapp.connection_established", "whatsapp.connection_lost", "procedure.created", "procedure.updated", "procedure.deleted", "specialty.created", "specialty.updated", "specialty.deleted", "professional.created", "professional.updated", "professional.deleted", "configuration.updated", "storage.file_uploaded", "storage.file_deleted", "tenant.created", "tenant.updated"];
|
|
5
|
+
export declare const EVENT_ANALYTIC_TYPES: readonly ["patient.created", "patient.updated", "patient.deleted", "patient.status_changed", "appointment.created", "appointment.updated", "appointment.canceled", "appointment.rescheduled", "appointment.no_show", "appointment.finished", "appointment.procedure_finished", "checkin.effectued", "checkout.effectued", "message.sent", "message.received", "conversation.session_started", "conversation.session_ended", "conversation.transferred_to_human", "followup.abandonment.sent", "followup.appointment_confirmation.sent", "followup.satisfaction_booking.sent", "followup.satisfaction_finished.sent", "followup.no_show_reschedule.sent", "followup.wellness_check.sent", "followup.return_suggestion.sent", "followup.satisfaction_booking.response_received", "followup.satisfaction_finished.response_received", "followup.config_updated", "payment.created", "payment.payed", "payment.refunded", "payment.canceled", "payment.overdue", "payment_gateway.payment_created", "payment_gateway.payment_confirmed", "payment_gateway.payment_failed", "payment_gateway.payment_refunded", "payment_gateway.payment_canceled", "payment_gateway.payment_expired", "payment_gateway.webhook_received", "billing.invoice_created", "billing.invoice_paid", "ai.interaction", "ai.fallback", "auth.login", "auth.logout", "auth.password_reset", "user.created", "user.updated", "user.deleted", "notification.sent", "notification.failed", "whatsapp.connection_established", "whatsapp.connection_lost", "procedure.created", "procedure.updated", "procedure.deleted", "specialty.created", "specialty.updated", "specialty.deleted", "professional.created", "professional.updated", "professional.deleted", "configuration.updated", "storage.file_uploaded", "storage.file_deleted", "tenant.created", "tenant.updated"];
|
|
6
6
|
export type EventAnalyticType = (typeof EVENT_ANALYTIC_TYPES)[number];
|
|
7
7
|
//# sourceMappingURL=event-analytic.enum.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-analytic.enum.d.ts","sourceRoot":"","sources":["../../src/analytics/event-analytic.enum.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"event-analytic.enum.d.ts","sourceRoot":"","sources":["../../src/analytics/event-analytic.enum.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,8uDA6GvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -18,6 +18,8 @@ exports.EVENT_ANALYTIC_TYPES = [
|
|
|
18
18
|
'appointment.rescheduled',
|
|
19
19
|
'appointment.no_show',
|
|
20
20
|
'appointment.finished',
|
|
21
|
+
/** Procedimento do agendamento marcado como concluído (add/update com finished). */
|
|
22
|
+
'appointment.procedure_finished',
|
|
21
23
|
// ── Check-in / Check-out events ─────────────────────────────────
|
|
22
24
|
'checkin.effectued',
|
|
23
25
|
'checkout.effectued',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AppointmentDto } from './appointment.dto';
|
|
2
2
|
import { AppointmentStatusDto } from './appointment-status.dto';
|
|
3
3
|
/** Campo principal de ordenação na listagem de agendamentos. */
|
|
4
|
-
export declare const APPOINTMENT_LIST_SORT_BY: readonly ["date", "checkin_completed"];
|
|
4
|
+
export declare const APPOINTMENT_LIST_SORT_BY: readonly ["date", "checkin_completed", "checkout_completed"];
|
|
5
5
|
export type AppointmentListSortByDto = (typeof APPOINTMENT_LIST_SORT_BY)[number];
|
|
6
6
|
export declare const APPOINTMENT_LIST_SORT_ORDER: readonly ["ASC", "DESC"];
|
|
7
7
|
export type AppointmentListSortOrderDto = (typeof APPOINTMENT_LIST_SORT_ORDER)[number];
|
|
@@ -12,6 +12,7 @@ export declare class ListAppointmentsQueryDto {
|
|
|
12
12
|
dateTo?: string;
|
|
13
13
|
userId?: string;
|
|
14
14
|
checkinCompleted?: boolean;
|
|
15
|
+
checkoutCompleted?: boolean;
|
|
15
16
|
patientId?: string;
|
|
16
17
|
status?: AppointmentStatusDto;
|
|
17
18
|
sortBy?: AppointmentListSortByDto;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-appointments-query.dto.d.ts","sourceRoot":"","sources":["../../src/appointments/list-appointments-query.dto.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAwB,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEtF,gEAAgE;AAChE,eAAO,MAAM,wBAAwB,
|
|
1
|
+
{"version":3,"file":"list-appointments-query.dto.d.ts","sourceRoot":"","sources":["../../src/appointments/list-appointments-query.dto.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAwB,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEtF,gEAAgE;AAChE,eAAO,MAAM,wBAAwB,8DAI3B,CAAC;AACX,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,eAAO,MAAM,2BAA2B,0BAA2B,CAAC;AACpE,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvF,qBAAa,wBAAwB;IAUnC,IAAI,CAAC,EAAE,MAAM,CAAC;IAad,KAAK,CAAC,EAAE,MAAM,CAAC;IAQf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAQlB,MAAM,CAAC,EAAE,MAAM,CAAC;IAQhB,MAAM,CAAC,EAAE,MAAM,CAAC;IAQhB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAQ3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAQ5B,SAAS,CAAC,EAAE,MAAM,CAAC;IAUnB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAU9B,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAUlC,SAAS,CAAC,EAAE,2BAA2B,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -14,7 +14,11 @@ const swagger_1 = require("@nestjs/swagger");
|
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const appointment_status_dto_1 = require("./appointment-status.dto");
|
|
16
16
|
/** Campo principal de ordenação na listagem de agendamentos. */
|
|
17
|
-
exports.APPOINTMENT_LIST_SORT_BY = [
|
|
17
|
+
exports.APPOINTMENT_LIST_SORT_BY = [
|
|
18
|
+
'date',
|
|
19
|
+
'checkin_completed',
|
|
20
|
+
'checkout_completed',
|
|
21
|
+
];
|
|
18
22
|
exports.APPOINTMENT_LIST_SORT_ORDER = ['ASC', 'DESC'];
|
|
19
23
|
class ListAppointmentsQueryDto {
|
|
20
24
|
page;
|
|
@@ -23,6 +27,7 @@ class ListAppointmentsQueryDto {
|
|
|
23
27
|
dateTo;
|
|
24
28
|
userId;
|
|
25
29
|
checkinCompleted;
|
|
30
|
+
checkoutCompleted;
|
|
26
31
|
patientId;
|
|
27
32
|
status;
|
|
28
33
|
sortBy;
|
|
@@ -91,6 +96,15 @@ __decorate([
|
|
|
91
96
|
(0, class_validator_1.IsBoolean)(),
|
|
92
97
|
__metadata("design:type", Boolean)
|
|
93
98
|
], ListAppointmentsQueryDto.prototype, "checkinCompleted", void 0);
|
|
99
|
+
__decorate([
|
|
100
|
+
(0, swagger_1.ApiPropertyOptional)({
|
|
101
|
+
description: 'Filtrar por status de check-out realizado',
|
|
102
|
+
example: false,
|
|
103
|
+
}),
|
|
104
|
+
(0, class_validator_1.IsOptional)(),
|
|
105
|
+
(0, class_validator_1.IsBoolean)(),
|
|
106
|
+
__metadata("design:type", Boolean)
|
|
107
|
+
], ListAppointmentsQueryDto.prototype, "checkoutCompleted", void 0);
|
|
94
108
|
__decorate([
|
|
95
109
|
(0, swagger_1.ApiPropertyOptional)({
|
|
96
110
|
description: 'Filtrar por paciente (UUID) - histórico de consultas',
|
|
@@ -113,7 +127,7 @@ __decorate([
|
|
|
113
127
|
], ListAppointmentsQueryDto.prototype, "status", void 0);
|
|
114
128
|
__decorate([
|
|
115
129
|
(0, swagger_1.ApiPropertyOptional)({
|
|
116
|
-
description: 'Ordenação principal: `date` (
|
|
130
|
+
description: 'Ordenação principal: `date`, `checkin_completed` (check-in pendente vs concluído) ou `checkout_completed` (check-out pendente vs concluído). Omisso = `date`.',
|
|
117
131
|
enum: exports.APPOINTMENT_LIST_SORT_BY,
|
|
118
132
|
example: 'checkin_completed',
|
|
119
133
|
}),
|
|
@@ -123,7 +137,7 @@ __decorate([
|
|
|
123
137
|
], ListAppointmentsQueryDto.prototype, "sortBy", void 0);
|
|
124
138
|
__decorate([
|
|
125
139
|
(0, swagger_1.ApiPropertyOptional)({
|
|
126
|
-
description: 'Direção: `ASC` ou `DESC`. Com `
|
|
140
|
+
description: 'Direção: `ASC` ou `DESC`. Com `checkin_completed` ou `checkout_completed`, `ASC` coloca pendentes (false) primeiro; `DESC` coloca concluídos (true) primeiro. Com `date`, aplica-se à coluna `date`.',
|
|
127
141
|
enum: exports.APPOINTMENT_LIST_SORT_ORDER,
|
|
128
142
|
example: 'ASC',
|
|
129
143
|
}),
|
package/package.json
CHANGED
|
@@ -87,3 +87,86 @@ export class AnalyticsDashboardQueryDto {
|
|
|
87
87
|
@IsISO8601()
|
|
88
88
|
endDate: string;
|
|
89
89
|
}
|
|
90
|
+
|
|
91
|
+
/** Resumo financeiro agregado a partir de eventos de analytics (pagamentos + faturamento). */
|
|
92
|
+
export class AnalyticsDashboardFinancialDto {
|
|
93
|
+
@ApiProperty({
|
|
94
|
+
description:
|
|
95
|
+
'Receita no período: soma de `payment.payed` e `billing.invoice_paid` (valores em metadata.amount)',
|
|
96
|
+
})
|
|
97
|
+
revenue: number;
|
|
98
|
+
|
|
99
|
+
@ApiProperty({
|
|
100
|
+
description:
|
|
101
|
+
'Ticket médio: revenue / número de eventos pagos (payment.payed + billing.invoice_paid); 0 se não houver pagamentos',
|
|
102
|
+
})
|
|
103
|
+
averageTicket: number;
|
|
104
|
+
|
|
105
|
+
@ApiProperty({
|
|
106
|
+
description:
|
|
107
|
+
'Volume de cobranças criadas no período ainda não quitadas no momento do registro: soma de `payment.created` + faturas `billing.invoice_created` com status PENDING ou OVERDUE no metadata (aproximação; não substitui saldo contábil)',
|
|
108
|
+
})
|
|
109
|
+
pending: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export class AnalyticsDashboardTopProcedureDto {
|
|
113
|
+
@ApiProperty({ description: 'Nome do procedimento (agendamento)' })
|
|
114
|
+
name: string;
|
|
115
|
+
|
|
116
|
+
@ApiProperty({ description: 'Quantidade de ocorrências no período' })
|
|
117
|
+
count: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Resposta enriquecida de `GET /analytics/dashboard` (mantém campos legados `total`, `byEventType`, `byDomain`).
|
|
122
|
+
*/
|
|
123
|
+
export class AnalyticsDashboardResponseDto {
|
|
124
|
+
@ApiProperty({ description: 'Agendamentos criados no período (`appointment.created`)' })
|
|
125
|
+
appointmentsCreated: number;
|
|
126
|
+
|
|
127
|
+
@ApiProperty({ description: 'Agendamentos finalizados no período (`appointment.finished`)' })
|
|
128
|
+
appointmentsFinished: number;
|
|
129
|
+
|
|
130
|
+
@ApiProperty({
|
|
131
|
+
description:
|
|
132
|
+
'Procedimentos agendados: soma dos itens em metadata.procedures em `appointment.created` + vínculos posteriores (`appointment.updated` com reason procedure_added)',
|
|
133
|
+
})
|
|
134
|
+
proceduresScheduled: number;
|
|
135
|
+
|
|
136
|
+
@ApiProperty({
|
|
137
|
+
description: 'Procedimentos marcados como concluídos no período (`appointment.procedure_finished`)',
|
|
138
|
+
})
|
|
139
|
+
proceduresFinished: number;
|
|
140
|
+
|
|
141
|
+
@ApiProperty({
|
|
142
|
+
description:
|
|
143
|
+
'Média das notas 1–5 em respostas de satisfação (followup booking + pós-atendimento); null se não houver respostas',
|
|
144
|
+
nullable: true,
|
|
145
|
+
})
|
|
146
|
+
satisfactionAverage: number | null;
|
|
147
|
+
|
|
148
|
+
@ApiProperty({
|
|
149
|
+
description:
|
|
150
|
+
'Taxa de no-show (%): appointment.no_show / appointment.created no período (0 se não houver criações)',
|
|
151
|
+
})
|
|
152
|
+
noShowRatePercent: number;
|
|
153
|
+
|
|
154
|
+
@ApiProperty({ type: AnalyticsDashboardFinancialDto })
|
|
155
|
+
financialSummary: AnalyticsDashboardFinancialDto;
|
|
156
|
+
|
|
157
|
+
@ApiProperty({ type: [AnalyticsDashboardTopProcedureDto], maxItems: 5 })
|
|
158
|
+
topProcedures: AnalyticsDashboardTopProcedureDto[];
|
|
159
|
+
|
|
160
|
+
@ApiProperty({ description: 'Total de eventos de analytics no período (legado)' })
|
|
161
|
+
total: number;
|
|
162
|
+
|
|
163
|
+
@ApiProperty({
|
|
164
|
+
description: 'Contagens por eventType (legado)',
|
|
165
|
+
})
|
|
166
|
+
byEventType: Array<{ eventType: string; count: number }>;
|
|
167
|
+
|
|
168
|
+
@ApiProperty({
|
|
169
|
+
description: 'Contagens por domínio (prefixo antes do ponto no eventType) (legado)',
|
|
170
|
+
})
|
|
171
|
+
byDomain: Array<{ domain: string; count: number }>;
|
|
172
|
+
}
|
|
@@ -16,6 +16,8 @@ export const EVENT_ANALYTIC_TYPES = [
|
|
|
16
16
|
'appointment.rescheduled',
|
|
17
17
|
'appointment.no_show',
|
|
18
18
|
'appointment.finished',
|
|
19
|
+
/** Procedimento do agendamento marcado como concluído (add/update com finished). */
|
|
20
|
+
'appointment.procedure_finished',
|
|
19
21
|
|
|
20
22
|
// ── Check-in / Check-out events ─────────────────────────────────
|
|
21
23
|
'checkin.effectued',
|
|
@@ -4,7 +4,11 @@ import { AppointmentDto } from './appointment.dto';
|
|
|
4
4
|
import { APPOINTMENT_STATUSES, AppointmentStatusDto } from './appointment-status.dto';
|
|
5
5
|
|
|
6
6
|
/** Campo principal de ordenação na listagem de agendamentos. */
|
|
7
|
-
export const APPOINTMENT_LIST_SORT_BY = [
|
|
7
|
+
export const APPOINTMENT_LIST_SORT_BY = [
|
|
8
|
+
'date',
|
|
9
|
+
'checkin_completed',
|
|
10
|
+
'checkout_completed',
|
|
11
|
+
] as const;
|
|
8
12
|
export type AppointmentListSortByDto = (typeof APPOINTMENT_LIST_SORT_BY)[number];
|
|
9
13
|
|
|
10
14
|
export const APPOINTMENT_LIST_SORT_ORDER = ['ASC', 'DESC'] as const;
|
|
@@ -67,6 +71,14 @@ export class ListAppointmentsQueryDto {
|
|
|
67
71
|
@IsBoolean()
|
|
68
72
|
checkinCompleted?: boolean;
|
|
69
73
|
|
|
74
|
+
@ApiPropertyOptional({
|
|
75
|
+
description: 'Filtrar por status de check-out realizado',
|
|
76
|
+
example: false,
|
|
77
|
+
})
|
|
78
|
+
@IsOptional()
|
|
79
|
+
@IsBoolean()
|
|
80
|
+
checkoutCompleted?: boolean;
|
|
81
|
+
|
|
70
82
|
@ApiPropertyOptional({
|
|
71
83
|
description: 'Filtrar por paciente (UUID) - histórico de consultas',
|
|
72
84
|
example: '550e8400-e29b-41d4-a716-446655440000',
|
|
@@ -87,7 +99,7 @@ export class ListAppointmentsQueryDto {
|
|
|
87
99
|
|
|
88
100
|
@ApiPropertyOptional({
|
|
89
101
|
description:
|
|
90
|
-
'Ordenação principal: `date` (
|
|
102
|
+
'Ordenação principal: `date`, `checkin_completed` (check-in pendente vs concluído) ou `checkout_completed` (check-out pendente vs concluído). Omisso = `date`.',
|
|
91
103
|
enum: APPOINTMENT_LIST_SORT_BY,
|
|
92
104
|
example: 'checkin_completed',
|
|
93
105
|
})
|
|
@@ -97,7 +109,7 @@ export class ListAppointmentsQueryDto {
|
|
|
97
109
|
|
|
98
110
|
@ApiPropertyOptional({
|
|
99
111
|
description:
|
|
100
|
-
'Direção: `ASC` ou `DESC`. Com `
|
|
112
|
+
'Direção: `ASC` ou `DESC`. Com `checkin_completed` ou `checkout_completed`, `ASC` coloca pendentes (false) primeiro; `DESC` coloca concluídos (true) primeiro. Com `date`, aplica-se à coluna `date`.',
|
|
101
113
|
enum: APPOINTMENT_LIST_SORT_ORDER,
|
|
102
114
|
example: 'ASC',
|
|
103
115
|
})
|