@primocaredentgroup/prescriptions-component 0.1.0

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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/_internal/client/PrescriptionsComponentClient.d.ts +25 -0
  4. package/dist/_internal/client/PrescriptionsComponentClient.d.ts.map +1 -0
  5. package/dist/_internal/client/PrescriptionsComponentClient.js +61 -0
  6. package/dist/_internal/client/PrescriptionsComponentClient.js.map +1 -0
  7. package/dist/_internal/client/index.d.ts +3 -0
  8. package/dist/_internal/client/index.d.ts.map +1 -0
  9. package/dist/_internal/client/index.js +2 -0
  10. package/dist/_internal/client/index.js.map +1 -0
  11. package/dist/_internal/client/types.d.ts +47 -0
  12. package/dist/_internal/client/types.d.ts.map +1 -0
  13. package/dist/_internal/client/types.js +2 -0
  14. package/dist/_internal/client/types.js.map +1 -0
  15. package/dist/_internal/component/convex.config.d.ts +7 -0
  16. package/dist/_internal/component/convex.config.d.ts.map +1 -0
  17. package/dist/_internal/component/convex.config.js +8 -0
  18. package/dist/_internal/component/convex.config.js.map +1 -0
  19. package/dist/_internal/component/functions.d.ts +9 -0
  20. package/dist/_internal/component/functions.d.ts.map +1 -0
  21. package/dist/_internal/component/functions.js +11 -0
  22. package/dist/_internal/component/functions.js.map +1 -0
  23. package/dist/_internal/component/index.d.ts +18 -0
  24. package/dist/_internal/component/index.d.ts.map +1 -0
  25. package/dist/_internal/component/index.js +20 -0
  26. package/dist/_internal/component/index.js.map +1 -0
  27. package/dist/_internal/component/schema.d.ts +2 -0
  28. package/dist/_internal/component/schema.d.ts.map +1 -0
  29. package/dist/_internal/component/schema.js +2 -0
  30. package/dist/_internal/component/schema.js.map +1 -0
  31. package/dist/_internal/react/PrescriptionsWidget.d.ts +18 -0
  32. package/dist/_internal/react/PrescriptionsWidget.d.ts.map +1 -0
  33. package/dist/_internal/react/PrescriptionsWidget.js +137 -0
  34. package/dist/_internal/react/PrescriptionsWidget.js.map +1 -0
  35. package/dist/_internal/react/index.d.ts +3 -0
  36. package/dist/_internal/react/index.d.ts.map +1 -0
  37. package/dist/_internal/react/index.js +2 -0
  38. package/dist/_internal/react/index.js.map +1 -0
  39. package/dist/client/index.d.ts +1 -0
  40. package/dist/client/index.js +1 -0
  41. package/dist/component/convex.config.d.ts +2 -0
  42. package/dist/component/convex.config.js +2 -0
  43. package/dist/component/index.d.ts +1 -0
  44. package/dist/component/index.js +1 -0
  45. package/dist/convex/lib/auth.d.ts +7 -0
  46. package/dist/convex/lib/auth.d.ts.map +1 -0
  47. package/dist/convex/lib/auth.js +38 -0
  48. package/dist/convex/lib/auth.js.map +1 -0
  49. package/dist/convex/lib/clinicalNormalize.d.ts +13 -0
  50. package/dist/convex/lib/clinicalNormalize.d.ts.map +1 -0
  51. package/dist/convex/lib/clinicalNormalize.js +82 -0
  52. package/dist/convex/lib/clinicalNormalize.js.map +1 -0
  53. package/dist/convex/lib/dental.d.ts +13 -0
  54. package/dist/convex/lib/dental.d.ts.map +1 -0
  55. package/dist/convex/lib/dental.js +79 -0
  56. package/dist/convex/lib/dental.js.map +1 -0
  57. package/dist/convex/lib/dynamicFieldsStrict.d.ts +9 -0
  58. package/dist/convex/lib/dynamicFieldsStrict.d.ts.map +1 -0
  59. package/dist/convex/lib/dynamicFieldsStrict.js +65 -0
  60. package/dist/convex/lib/dynamicFieldsStrict.js.map +1 -0
  61. package/dist/convex/lib/dynamicRules.d.ts +61 -0
  62. package/dist/convex/lib/dynamicRules.d.ts.map +1 -0
  63. package/dist/convex/lib/dynamicRules.js +221 -0
  64. package/dist/convex/lib/dynamicRules.js.map +1 -0
  65. package/dist/convex/lib/storage.d.ts +59 -0
  66. package/dist/convex/lib/storage.d.ts.map +1 -0
  67. package/dist/convex/lib/storage.js +120 -0
  68. package/dist/convex/lib/storage.js.map +1 -0
  69. package/dist/convex/lib/utils.d.ts +61 -0
  70. package/dist/convex/lib/utils.d.ts.map +1 -0
  71. package/dist/convex/lib/utils.js +135 -0
  72. package/dist/convex/lib/utils.js.map +1 -0
  73. package/dist/convex/lib/validation.d.ts +24 -0
  74. package/dist/convex/lib/validation.d.ts.map +1 -0
  75. package/dist/convex/lib/validation.js +333 -0
  76. package/dist/convex/lib/validation.js.map +1 -0
  77. package/dist/convex/mutations/digitalAssets.d.ts +54 -0
  78. package/dist/convex/mutations/digitalAssets.d.ts.map +1 -0
  79. package/dist/convex/mutations/digitalAssets.js +297 -0
  80. package/dist/convex/mutations/digitalAssets.js.map +1 -0
  81. package/dist/convex/mutations/operational.d.ts +38 -0
  82. package/dist/convex/mutations/operational.d.ts.map +1 -0
  83. package/dist/convex/mutations/operational.js +226 -0
  84. package/dist/convex/mutations/operational.js.map +1 -0
  85. package/dist/convex/mutations/phases.d.ts +45 -0
  86. package/dist/convex/mutations/phases.d.ts.map +1 -0
  87. package/dist/convex/mutations/phases.js +334 -0
  88. package/dist/convex/mutations/phases.js.map +1 -0
  89. package/dist/convex/mutations/prescriptions.d.ts +191 -0
  90. package/dist/convex/mutations/prescriptions.d.ts.map +1 -0
  91. package/dist/convex/mutations/prescriptions.js +1263 -0
  92. package/dist/convex/mutations/prescriptions.js.map +1 -0
  93. package/dist/convex/mutations/syncJobs.d.ts +37 -0
  94. package/dist/convex/mutations/syncJobs.d.ts.map +1 -0
  95. package/dist/convex/mutations/syncJobs.js +238 -0
  96. package/dist/convex/mutations/syncJobs.js.map +1 -0
  97. package/dist/convex/prescriptions/fields.d.ts +50 -0
  98. package/dist/convex/prescriptions/fields.d.ts.map +1 -0
  99. package/dist/convex/prescriptions/fields.js +242 -0
  100. package/dist/convex/prescriptions/fields.js.map +1 -0
  101. package/dist/convex/queries/dynamicFields.d.ts +27 -0
  102. package/dist/convex/queries/dynamicFields.d.ts.map +1 -0
  103. package/dist/convex/queries/dynamicFields.js +119 -0
  104. package/dist/convex/queries/dynamicFields.js.map +1 -0
  105. package/dist/convex/queries/prescriptions.d.ts +583 -0
  106. package/dist/convex/queries/prescriptions.d.ts.map +1 -0
  107. package/dist/convex/queries/prescriptions.js +208 -0
  108. package/dist/convex/queries/prescriptions.js.map +1 -0
  109. package/dist/convex/schema.d.ts +962 -0
  110. package/dist/convex/schema.d.ts.map +1 -0
  111. package/dist/convex/schema.js +434 -0
  112. package/dist/convex/schema.js.map +1 -0
  113. package/dist/convex/types.d.ts +267 -0
  114. package/dist/convex/types.d.ts.map +1 -0
  115. package/dist/convex/types.js +2 -0
  116. package/dist/convex/types.js.map +1 -0
  117. package/dist/react/index.d.ts +1 -0
  118. package/dist/react/index.js +1 -0
  119. package/dist/react/styles.css +54 -0
  120. package/package.json +82 -0
@@ -0,0 +1,297 @@
1
+ import { mutation } from "../_generated/server";
2
+ import { ConvexError, v } from "convex/values";
3
+ import { generateUploadUrl, createDigitalAsset, validateFile, deleteFile, STORAGE_CONFIG, } from "../lib/storage";
4
+ import { requireIdentityUser, assertPrescriptionAccess } from "../lib/auth";
5
+ // ============================================
6
+ // DIGITAL ASSETS MUTATIONS
7
+ // ============================================
8
+ // Gestione file STL per prescrizioni digitali
9
+ // ============================================
10
+ /**
11
+ * Genera un URL per l'upload di un file STL.
12
+ * Il client usa questo URL per caricare direttamente il file.
13
+ */
14
+ export const generateStlUploadUrl = mutation({
15
+ args: {
16
+ prescriptionId: v.id("prescriptions"),
17
+ },
18
+ handler: async (ctx, args) => {
19
+ let user;
20
+ try {
21
+ user = await requireIdentityUser(ctx);
22
+ }
23
+ catch (error) {
24
+ if (error instanceof ConvexError)
25
+ throw error;
26
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
27
+ }
28
+ // 1. Verifica prescrizione
29
+ const prescription = await ctx.db.get(args.prescriptionId);
30
+ if (!prescription) {
31
+ throw new Error("Prescrizione non trovata");
32
+ }
33
+ assertPrescriptionAccess(user, prescription);
34
+ // 2. Verifica che sia in DRAFT
35
+ if (prescription.status !== "DRAFT") {
36
+ throw new Error("È possibile caricare file STL solo per prescrizioni in bozza");
37
+ }
38
+ // 3. Verifica numero massimo file
39
+ const currentAssets = prescription.digitalAssets || [];
40
+ if (currentAssets.length >= STORAGE_CONFIG.maxFilesPerPrescription) {
41
+ throw new Error(`Massimo ${STORAGE_CONFIG.maxFilesPerPrescription} file per prescrizione`);
42
+ }
43
+ // 5. Genera URL upload
44
+ const uploadUrl = await generateUploadUrl(ctx);
45
+ return { uploadUrl };
46
+ },
47
+ });
48
+ /**
49
+ * Conferma l'upload di un file STL.
50
+ * Chiamato dopo che il client ha caricato il file sull'URL generato.
51
+ */
52
+ export const confirmStlUpload = mutation({
53
+ args: {
54
+ prescriptionId: v.id("prescriptions"),
55
+ storageId: v.string(),
56
+ fileName: v.string(),
57
+ fileSize: v.number(),
58
+ mimeType: v.string(),
59
+ description: v.optional(v.string()),
60
+ },
61
+ handler: async (ctx, args) => {
62
+ const now = Date.now();
63
+ let user;
64
+ try {
65
+ user = await requireIdentityUser(ctx);
66
+ }
67
+ catch (error) {
68
+ if (error instanceof ConvexError)
69
+ throw error;
70
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
71
+ }
72
+ // 1. Verifica prescrizione
73
+ const prescription = await ctx.db.get(args.prescriptionId);
74
+ if (!prescription) {
75
+ throw new Error("Prescrizione non trovata");
76
+ }
77
+ assertPrescriptionAccess(user, prescription);
78
+ // 2. Verifica stato
79
+ if (prescription.status !== "DRAFT") {
80
+ throw new Error("È possibile caricare file STL solo per prescrizioni in bozza");
81
+ }
82
+ // 3. Valida file
83
+ const validation = validateFile(args.fileName, args.fileSize, args.mimeType);
84
+ if (!validation.valid) {
85
+ throw new Error(validation.error || "File non valido");
86
+ }
87
+ // 5. Verifica numero massimo file
88
+ const currentAssets = prescription.digitalAssets || [];
89
+ if (currentAssets.length >= STORAGE_CONFIG.maxFilesPerPrescription) {
90
+ throw new Error(`Massimo ${STORAGE_CONFIG.maxFilesPerPrescription} file per prescrizione`);
91
+ }
92
+ // 6. Crea asset
93
+ const asset = createDigitalAsset(args.storageId, args.fileName, args.fileSize, args.mimeType, user._id, args.description);
94
+ // 7. Aggiorna prescrizione
95
+ await ctx.db.patch(args.prescriptionId, {
96
+ digitalAssets: [...currentAssets, asset],
97
+ // Se carica un STL, imposta automaticamente il tipo a DIGITAL
98
+ prescriptionType: "DIGITAL",
99
+ updatedAt: now,
100
+ });
101
+ // 8. Audit
102
+ await ctx.db.insert("auditEvents", {
103
+ auditEventId: 0, // Will be backfilled
104
+ prescriptionRef: args.prescriptionId,
105
+ at: now,
106
+ actorUserId: user._id,
107
+ actorRole: user.role,
108
+ type: "STL_UPLOADED",
109
+ payload: {
110
+ assetId: asset.assetId,
111
+ fileName: asset.fileName,
112
+ fileSize: asset.fileSize,
113
+ },
114
+ });
115
+ return { success: true, asset };
116
+ },
117
+ });
118
+ /**
119
+ * Elimina un file STL da una prescrizione.
120
+ */
121
+ export const deleteStlFile = mutation({
122
+ args: {
123
+ prescriptionId: v.id("prescriptions"),
124
+ assetId: v.string(),
125
+ },
126
+ handler: async (ctx, args) => {
127
+ const now = Date.now();
128
+ let user;
129
+ try {
130
+ user = await requireIdentityUser(ctx);
131
+ }
132
+ catch (error) {
133
+ if (error instanceof ConvexError)
134
+ throw error;
135
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
136
+ }
137
+ // 1. Verifica prescrizione
138
+ const prescription = await ctx.db.get(args.prescriptionId);
139
+ if (!prescription) {
140
+ throw new Error("Prescrizione non trovata");
141
+ }
142
+ assertPrescriptionAccess(user, prescription);
143
+ // 2. Verifica stato
144
+ if (prescription.status !== "DRAFT") {
145
+ throw new Error("È possibile eliminare file STL solo per prescrizioni in bozza");
146
+ }
147
+ // 3. Trova asset
148
+ const currentAssets = prescription.digitalAssets || [];
149
+ const assetIndex = currentAssets.findIndex(a => a.assetId === args.assetId);
150
+ if (assetIndex === -1) {
151
+ throw new Error("File non trovato");
152
+ }
153
+ const asset = currentAssets[assetIndex];
154
+ // 5. Elimina file dallo storage
155
+ await deleteFile(ctx, asset);
156
+ // 6. Rimuovi asset dalla lista
157
+ const newAssets = currentAssets.filter(a => a.assetId !== args.assetId);
158
+ // 7. Aggiorna prescrizione
159
+ // Se non ci sono più file STL e il tipo è DIGITAL, torna ad ANALOG
160
+ const newType = newAssets.length === 0 ? "ANALOG" : prescription.prescriptionType;
161
+ await ctx.db.patch(args.prescriptionId, {
162
+ digitalAssets: newAssets,
163
+ prescriptionType: newType,
164
+ updatedAt: now,
165
+ });
166
+ // 8. Audit
167
+ await ctx.db.insert("auditEvents", {
168
+ auditEventId: 0, // Will be backfilled
169
+ prescriptionRef: args.prescriptionId,
170
+ at: now,
171
+ actorUserId: user._id,
172
+ actorRole: user.role,
173
+ type: "STL_DELETED",
174
+ payload: {
175
+ assetId: args.assetId,
176
+ fileName: asset.fileName,
177
+ },
178
+ });
179
+ return { success: true };
180
+ },
181
+ });
182
+ /**
183
+ * Cambia il tipo di prescrizione (ANALOG <-> DIGITAL).
184
+ * Solo in stato DRAFT.
185
+ */
186
+ export const setPrescriptionType = mutation({
187
+ args: {
188
+ prescriptionId: v.id("prescriptions"),
189
+ prescriptionType: v.union(v.literal("ANALOG"), v.literal("DIGITAL")),
190
+ },
191
+ handler: async (ctx, args) => {
192
+ const now = Date.now();
193
+ let user;
194
+ try {
195
+ user = await requireIdentityUser(ctx);
196
+ }
197
+ catch (error) {
198
+ if (error instanceof ConvexError)
199
+ throw error;
200
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
201
+ }
202
+ // 1. Verifica prescrizione
203
+ const prescription = await ctx.db.get(args.prescriptionId);
204
+ if (!prescription) {
205
+ throw new Error("Prescrizione non trovata");
206
+ }
207
+ assertPrescriptionAccess(user, prescription);
208
+ // 2. Verifica stato
209
+ if (prescription.status !== "DRAFT") {
210
+ throw new Error("È possibile cambiare il tipo solo per prescrizioni in bozza");
211
+ }
212
+ // 3. Se passa a ANALOG, elimina tutti i file STL
213
+ if (args.prescriptionType === "ANALOG" && prescription.digitalAssets?.length) {
214
+ // Elimina file dallo storage
215
+ for (const asset of prescription.digitalAssets) {
216
+ await deleteFile(ctx, asset);
217
+ }
218
+ }
219
+ // 5. Aggiorna prescrizione
220
+ await ctx.db.patch(args.prescriptionId, {
221
+ prescriptionType: args.prescriptionType,
222
+ // Se passa a ANALOG, svuota gli asset
223
+ digitalAssets: args.prescriptionType === "ANALOG" ? [] : prescription.digitalAssets,
224
+ updatedAt: now,
225
+ });
226
+ // 6. Audit
227
+ await ctx.db.insert("auditEvents", {
228
+ auditEventId: 0, // Will be backfilled
229
+ prescriptionRef: args.prescriptionId,
230
+ at: now,
231
+ actorUserId: user._id,
232
+ actorRole: user.role,
233
+ type: "PRESCRIPTION_TYPE_CHANGED",
234
+ payload: {
235
+ previousType: prescription.prescriptionType || "ANALOG",
236
+ newType: args.prescriptionType,
237
+ },
238
+ });
239
+ return { success: true };
240
+ },
241
+ });
242
+ /**
243
+ * Aggiorna la descrizione di un file STL.
244
+ */
245
+ export const updateStlDescription = mutation({
246
+ args: {
247
+ prescriptionId: v.id("prescriptions"),
248
+ assetId: v.string(),
249
+ description: v.string(),
250
+ },
251
+ handler: async (ctx, args) => {
252
+ const now = Date.now();
253
+ let user;
254
+ try {
255
+ user = await requireIdentityUser(ctx);
256
+ }
257
+ catch (error) {
258
+ if (error instanceof ConvexError)
259
+ throw error;
260
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
261
+ }
262
+ // 1. Verifica prescrizione
263
+ const prescription = await ctx.db.get(args.prescriptionId);
264
+ if (!prescription) {
265
+ throw new Error("Prescrizione non trovata");
266
+ }
267
+ assertPrescriptionAccess(user, prescription);
268
+ // 2. Verifica stato
269
+ if (prescription.status !== "DRAFT") {
270
+ throw new Error("È possibile modificare solo prescrizioni in bozza");
271
+ }
272
+ // 3. Trova e aggiorna asset
273
+ const currentAssets = prescription.digitalAssets || [];
274
+ const newAssets = currentAssets.map(a => a.assetId === args.assetId
275
+ ? { ...a, description: args.description }
276
+ : a);
277
+ // 4. Aggiorna prescrizione
278
+ await ctx.db.patch(args.prescriptionId, {
279
+ digitalAssets: newAssets,
280
+ updatedAt: now,
281
+ });
282
+ // 5. Audit
283
+ await ctx.db.insert("auditEvents", {
284
+ auditEventId: 0,
285
+ prescriptionRef: args.prescriptionId,
286
+ at: now,
287
+ actorUserId: user._id,
288
+ actorRole: user.role,
289
+ type: "STL_DESCRIPTION_UPDATED",
290
+ payload: {
291
+ assetId: args.assetId,
292
+ },
293
+ });
294
+ return { success: true };
295
+ },
296
+ });
297
+ //# sourceMappingURL=digitalAssets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digitalAssets.js","sourceRoot":"","sources":["../../../convex/mutations/digitalAssets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Aggiorna le note interne.
3
+ */
4
+ export declare const updateNotes: import("convex/server").RegisteredMutation<"public", {
5
+ prescriptionId: import("convex/values").GenericId<"prescriptions">;
6
+ noteInterne: string;
7
+ }, Promise<{
8
+ success: boolean;
9
+ }>>;
10
+ /**
11
+ * Aggiunge un allegato.
12
+ */
13
+ export declare const addAttachment: import("convex/server").RegisteredMutation<"public", {
14
+ fileName: string;
15
+ prescriptionId: import("convex/values").GenericId<"prescriptions">;
16
+ fileId: string;
17
+ }, Promise<{
18
+ success: boolean;
19
+ }>>;
20
+ /**
21
+ * Rimuove un allegato.
22
+ */
23
+ export declare const removeAttachment: import("convex/server").RegisteredMutation<"public", {
24
+ prescriptionId: import("convex/values").GenericId<"prescriptions">;
25
+ fileId: string;
26
+ }, Promise<{
27
+ success: boolean;
28
+ }>>;
29
+ /**
30
+ * Salva lo stato UI.
31
+ */
32
+ export declare const saveUiState: import("convex/server").RegisteredMutation<"public", {
33
+ prescriptionId: import("convex/values").GenericId<"prescriptions">;
34
+ uiState: any;
35
+ }, Promise<{
36
+ success: boolean;
37
+ }>>;
38
+ //# sourceMappingURL=operational.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operational.d.ts","sourceRoot":"","sources":["../../../convex/mutations/operational.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;GAuDtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;GAmExB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;GAkD3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;GAkDtB,CAAC"}
@@ -0,0 +1,226 @@
1
+ import { mutation } from "../_generated/server";
2
+ import { ConvexError, v } from "convex/values";
3
+ import { requireIdentityUser, assertPrescriptionAccess } from "../lib/auth";
4
+ // ============================================
5
+ // OPERATIONAL DATA MUTATIONS
6
+ // ============================================
7
+ /**
8
+ * Aggiorna le note interne.
9
+ */
10
+ export const updateNotes = mutation({
11
+ args: {
12
+ prescriptionId: v.id("prescriptions"),
13
+ noteInterne: v.string(),
14
+ },
15
+ handler: async (ctx, args) => {
16
+ const now = Date.now();
17
+ let user;
18
+ try {
19
+ user = await requireIdentityUser(ctx);
20
+ }
21
+ catch (error) {
22
+ if (error instanceof ConvexError)
23
+ throw error;
24
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
25
+ }
26
+ // 1. Verifica prescrizione/accesso
27
+ const prescription = await ctx.db.get(args.prescriptionId);
28
+ if (!prescription) {
29
+ throw new Error("Prescrizione non trovata");
30
+ }
31
+ assertPrescriptionAccess(user, prescription);
32
+ // 2. Carica o crea operational data
33
+ let opData = await ctx.db
34
+ .query("operationalData")
35
+ .withIndex("by_prescriptionRef", (q) => q.eq("prescriptionRef", args.prescriptionId))
36
+ .first();
37
+ if (opData) {
38
+ await ctx.db.patch(opData._id, {
39
+ noteInterne: args.noteInterne,
40
+ });
41
+ }
42
+ else {
43
+ await ctx.db.insert("operationalData", {
44
+ operationalDataId: 0, // Will be backfilled
45
+ prescriptionRef: args.prescriptionId,
46
+ noteInterne: args.noteInterne,
47
+ });
48
+ }
49
+ // 3. Audit
50
+ await ctx.db.insert("auditEvents", {
51
+ auditEventId: 0, // Will be backfilled
52
+ prescriptionRef: args.prescriptionId,
53
+ at: now,
54
+ actorUserId: user._id,
55
+ actorRole: user.role,
56
+ type: "OPERATIONAL_NOTES_UPDATED",
57
+ payload: {},
58
+ });
59
+ return { success: true };
60
+ },
61
+ });
62
+ /**
63
+ * Aggiunge un allegato.
64
+ */
65
+ export const addAttachment = mutation({
66
+ args: {
67
+ prescriptionId: v.id("prescriptions"),
68
+ fileId: v.string(),
69
+ fileName: v.string(),
70
+ },
71
+ handler: async (ctx, args) => {
72
+ const now = Date.now();
73
+ let user;
74
+ try {
75
+ user = await requireIdentityUser(ctx);
76
+ }
77
+ catch (error) {
78
+ if (error instanceof ConvexError)
79
+ throw error;
80
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
81
+ }
82
+ // 1. Verifica prescrizione/accesso
83
+ const prescription = await ctx.db.get(args.prescriptionId);
84
+ if (!prescription) {
85
+ throw new Error("Prescrizione non trovata");
86
+ }
87
+ assertPrescriptionAccess(user, prescription);
88
+ // 2. Carica o crea operational data
89
+ let opData = await ctx.db
90
+ .query("operationalData")
91
+ .withIndex("by_prescriptionRef", (q) => q.eq("prescriptionRef", args.prescriptionId))
92
+ .first();
93
+ const newAttachment = {
94
+ fileId: args.fileId,
95
+ fileName: args.fileName,
96
+ uploadedAt: now,
97
+ uploadedBy: user._id,
98
+ };
99
+ if (opData) {
100
+ const allegati = opData.allegati ?? [];
101
+ await ctx.db.patch(opData._id, {
102
+ allegati: [...allegati, newAttachment],
103
+ });
104
+ }
105
+ else {
106
+ await ctx.db.insert("operationalData", {
107
+ operationalDataId: 0, // Will be backfilled
108
+ prescriptionRef: args.prescriptionId,
109
+ allegati: [newAttachment],
110
+ });
111
+ }
112
+ // 3. Audit
113
+ await ctx.db.insert("auditEvents", {
114
+ auditEventId: 0, // Will be backfilled
115
+ prescriptionRef: args.prescriptionId,
116
+ at: now,
117
+ actorUserId: user._id,
118
+ actorRole: user.role,
119
+ type: "ATTACHMENT_ADDED",
120
+ payload: {
121
+ fileId: args.fileId,
122
+ fileName: args.fileName,
123
+ },
124
+ });
125
+ return { success: true };
126
+ },
127
+ });
128
+ /**
129
+ * Rimuove un allegato.
130
+ */
131
+ export const removeAttachment = mutation({
132
+ args: {
133
+ prescriptionId: v.id("prescriptions"),
134
+ fileId: v.string(),
135
+ },
136
+ handler: async (ctx, args) => {
137
+ const now = Date.now();
138
+ let user;
139
+ try {
140
+ user = await requireIdentityUser(ctx);
141
+ }
142
+ catch (error) {
143
+ if (error instanceof ConvexError)
144
+ throw error;
145
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
146
+ }
147
+ // 1. Verifica prescrizione/accesso
148
+ const prescription = await ctx.db.get(args.prescriptionId);
149
+ if (!prescription) {
150
+ throw new Error("Prescrizione non trovata");
151
+ }
152
+ assertPrescriptionAccess(user, prescription);
153
+ // 2. Carica operational data
154
+ const opData = await ctx.db
155
+ .query("operationalData")
156
+ .withIndex("by_prescriptionRef", (q) => q.eq("prescriptionRef", args.prescriptionId))
157
+ .first();
158
+ if (!opData || !opData.allegati) {
159
+ throw new Error("Allegato non trovato");
160
+ }
161
+ const allegati = opData.allegati.filter((a) => a.fileId !== args.fileId);
162
+ await ctx.db.patch(opData._id, { allegati });
163
+ // 3. Audit
164
+ await ctx.db.insert("auditEvents", {
165
+ auditEventId: 0, // Will be backfilled
166
+ prescriptionRef: args.prescriptionId,
167
+ at: now,
168
+ actorUserId: user._id,
169
+ actorRole: user.role,
170
+ type: "ATTACHMENT_REMOVED",
171
+ payload: { fileId: args.fileId },
172
+ });
173
+ return { success: true };
174
+ },
175
+ });
176
+ /**
177
+ * Salva lo stato UI.
178
+ */
179
+ export const saveUiState = mutation({
180
+ args: {
181
+ prescriptionId: v.id("prescriptions"),
182
+ uiState: v.any(),
183
+ },
184
+ handler: async (ctx, args) => {
185
+ const now = Date.now();
186
+ let user;
187
+ try {
188
+ user = await requireIdentityUser(ctx);
189
+ }
190
+ catch (error) {
191
+ if (error instanceof ConvexError)
192
+ throw error;
193
+ throw new ConvexError({ code: "UNAUTHORIZED", message: "Accesso non autorizzato" });
194
+ }
195
+ const prescription = await ctx.db.get(args.prescriptionId);
196
+ if (!prescription) {
197
+ throw new Error("Prescrizione non trovata");
198
+ }
199
+ assertPrescriptionAccess(user, prescription);
200
+ let opData = await ctx.db
201
+ .query("operationalData")
202
+ .withIndex("by_prescriptionRef", (q) => q.eq("prescriptionRef", args.prescriptionId))
203
+ .first();
204
+ if (opData) {
205
+ await ctx.db.patch(opData._id, { uiState: args.uiState });
206
+ }
207
+ else {
208
+ await ctx.db.insert("operationalData", {
209
+ operationalDataId: 0, // Will be backfilled
210
+ prescriptionRef: args.prescriptionId,
211
+ uiState: args.uiState,
212
+ });
213
+ }
214
+ await ctx.db.insert("auditEvents", {
215
+ auditEventId: 0,
216
+ prescriptionRef: args.prescriptionId,
217
+ at: now,
218
+ actorUserId: user._id,
219
+ actorRole: user.role,
220
+ type: "OPERATIONAL_UI_STATE_SAVED",
221
+ payload: {},
222
+ });
223
+ return { success: true };
224
+ },
225
+ });
226
+ //# sourceMappingURL=operational.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operational.js","sourceRoot":"","sources":["../../../convex/mutations/operational.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Aggiorna il feedback di una fase.
3
+ * Enforcement forward-only (non si può tornare indietro).
4
+ */
5
+ export declare const updateFeedback: import("convex/server").RegisteredMutation<"public", {
6
+ comment?: string | undefined;
7
+ outcome: "OK" | "KO" | null;
8
+ phaseInstanceId: import("convex/values").GenericId<"phaseInstances">;
9
+ }, Promise<{
10
+ success: boolean;
11
+ newStatus: "NOT_STARTED" | "SCHEDULED" | "DONE_OK" | "DONE_KO" | "SKIPPED" | "REPEAT";
12
+ }>>;
13
+ /**
14
+ * Schedula un appuntamento per una fase.
15
+ * Crea un sync job per PrimoCore.
16
+ */
17
+ export declare const scheduleAppointment: import("convex/server").RegisteredMutation<"public", {
18
+ startAt: number;
19
+ endAt: number;
20
+ doctorId: string;
21
+ phaseInstanceId: import("convex/values").GenericId<"phaseInstances">;
22
+ }, Promise<{
23
+ success: boolean;
24
+ syncJobId: import("convex/values").GenericId<"syncJobs">;
25
+ }>>;
26
+ /**
27
+ * Ripete una fase (se repeatable).
28
+ */
29
+ export declare const repeatPhase: import("convex/server").RegisteredMutation<"public", {
30
+ phaseInstanceId: import("convex/values").GenericId<"phaseInstances">;
31
+ reason: string;
32
+ }, Promise<{
33
+ success: boolean;
34
+ newPhaseId: import("convex/values").GenericId<"phaseInstances">;
35
+ }>>;
36
+ /**
37
+ * Salta una fase (se non required).
38
+ */
39
+ export declare const skipPhase: import("convex/server").RegisteredMutation<"public", {
40
+ phaseInstanceId: import("convex/values").GenericId<"phaseInstances">;
41
+ reason: string;
42
+ }, Promise<{
43
+ success: boolean;
44
+ }>>;
45
+ //# sourceMappingURL=phases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phases.d.ts","sourceRoot":"","sources":["../../../convex/mutations/phases.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;GAuFzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;GA4F9B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;GAsFtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;GA8EpB,CAAC"}