repzo 1.0.289 → 1.0.291

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.
@@ -0,0 +1,415 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: Repzo API - Day Shift
4
+ version: 1.0.0
5
+ description: |
6
+ **Day shifts** are reusable weekly work schedules assigned to sales reps.
7
+ Each shift holds a `schedule[]` of per-weekday entries
8
+ (`{ day, work_time[] }`); every `work_time` range is a `HH:mm` wall-clock
9
+ interval in the company time zone, and a range whose `to <= from` crosses
10
+ midnight into the next calendar date (e.g. `18:00 → 02:00`).
11
+
12
+ **Why it matters.** Repzo keys all daily data on a **business-day string**
13
+ (`"2026-07-14"`), derived from a per-company `end_of_day` cut. A shift acts
14
+ as a **per-weekday override of that cut**: yesterday's overnight spill can
15
+ raise the boundary (so early-morning activity still belongs to the prior
16
+ working day) and today's early shift start can pull it down. When a rep has
17
+ **no shift assigned**, business-day resolution is byte-identical to the
18
+ legacy company `end_of_day` behaviour. See the shift-aware resolver in
19
+ `src/util.ts` (`resolveBusinessDay`, `findDay`, `findTimeFrame`).
20
+
21
+ **Assignment.** A rep is assigned a shift through the rep's own
22
+ `assigned_shift` field (see the Rep service). The resolved schedule is
23
+ snapshotted onto the rep's `day` document at day-open — together with the
24
+ business-day context it was stamped with (`EOD`, `timeZone`) — and every
25
+ business-day stamping site (visits, activities, day close/recalc,
26
+ transactional documents) resolves against that full snapshot while the
27
+ day is open: neither a mid-day shift reassignment / schedule edit nor an
28
+ owner changing the company `end_of_day` / `time_zone` moves an in-flight
29
+ day's boundaries or stamps new documents onto a different business day
30
+ than the open day. The rep's current shift and the namespace's current
31
+ settings only apply when no day is open (i.e. from the next day-open
32
+ onward).
33
+
34
+ **Who calls it.** Admins manage shifts from the back-office UI. Reps are
35
+ notified of changes via the `update-day-shift` command (real-time push).
36
+
37
+ **Multi-tenancy & lifecycle.** Records are scoped by `company_namespace[]`
38
+ (server-injected from session). Soft-delete via `disabled: true`; deletion
39
+ is rejected while any active rep's `assigned_shift` still points at the
40
+ shift. `designation` is an optional free-text label. `name` is unique per
41
+ namespace among active rows (compound unique index
42
+ `(company_namespace, name)`, partial on `disabled: false`).
43
+
44
+ **Validation.** On create/update the `schedule` is validated so business-day
45
+ resolution stays well-defined: each weekday appears at most once; every
46
+ range has a valid, non-equal `from`/`to`; per day, ranges are
47
+ non-overlapping and only the **last** range may cross midnight; a day's
48
+ overnight tail must not overlap the next weekday's earliest start; and,
49
+ against the namespace's `end_of_day`, no weekday's business day may be
50
+ eliminated — a shift whose end reaches or passes the FOLLOWING weekday's
51
+ end-of-day cut while that weekday has no ranges (e.g. `end_of_day` 12:00
52
+ with Monday 22:00→13:00 and Tuesday off) is rejected, since the label in
53
+ between could never own a single instant.
54
+
55
+ **Key relationships.** Referenced by `representatives` via the rep's
56
+ `assigned_shift` field.
57
+
58
+ **Events.** Create / update / remove emit `update-day-shift`, which notifies
59
+ reps in the namespace. Bulk `patch` is not supported.
60
+ servers:
61
+ - url: https://sv.api.repzo.me
62
+ security:
63
+ - ApiKeyAuth: []
64
+ - JwtAuth: []
65
+ paths:
66
+ /day-shift:
67
+ get:
68
+ summary: Find day shifts
69
+ operationId: findDayShifts
70
+ parameters:
71
+ - in: query
72
+ name: _id
73
+ description: |
74
+ "Filter by shift `_id`. Pass once for a single match, or as
75
+ `?_id[]=...&_id[]=...` for multiple."
76
+ schema:
77
+ oneOf:
78
+ - type: string
79
+ - type: array
80
+ items: { type: string }
81
+ - in: query
82
+ name: name
83
+ description: |
84
+ Exact-match on shift `name` **or** `designation` (the value is
85
+ expanded to match either field).
86
+ schema:
87
+ oneOf:
88
+ - type: string
89
+ - type: array
90
+ items: { type: string }
91
+ - in: query
92
+ name: designation
93
+ description: Exact-match on shift `designation`.
94
+ schema:
95
+ oneOf:
96
+ - type: string
97
+ - type: array
98
+ items: { type: string }
99
+ - in: query
100
+ name: disabled
101
+ description: Include disabled (soft-deleted) shifts. Defaults to `false`.
102
+ schema: { type: boolean, default: false }
103
+ - in: query
104
+ name: from_updatedAt
105
+ description: |
106
+ Cursor — return only shifts with `updatedAt` greater than this Unix
107
+ timestamp (ms). Used by sync clients.
108
+ schema: { type: number }
109
+ - in: query
110
+ name: inject_assigned_reps
111
+ description: |
112
+ When truthy, each returned shift is enriched with an
113
+ `assigned_reps[]` array (`_id`, `name`) of the active reps whose
114
+ `assigned_shift` points at it.
115
+ schema: { type: boolean, default: false }
116
+ - in: query
117
+ name: from__id
118
+ description: Cursor — return records with `_id` greater than this value.
119
+ schema: { type: string }
120
+ - in: query
121
+ name: to__id
122
+ description: Cursor — return records with `_id` less than this value.
123
+ schema: { type: string }
124
+ - in: query
125
+ name: per_page
126
+ description: Page size. Defaults to the server's configured pagination limit.
127
+ schema: { type: integer, minimum: 1, maximum: 500 }
128
+ example: 50
129
+ - in: query
130
+ name: page
131
+ description: 1-indexed page number.
132
+ schema: { type: integer, minimum: 1 }
133
+ example: 1
134
+ - in: query
135
+ name: sortBy
136
+ description: |
137
+ Sort directives. Encoded with `qs` bracket notation, e.g.
138
+ `?sortBy[0][field]=_id&sortBy[0][type]=desc`.
139
+ schema:
140
+ type: array
141
+ items:
142
+ type: object
143
+ properties:
144
+ field:
145
+ type: string
146
+ enum: [_id]
147
+ type:
148
+ type: string
149
+ enum: [asc, desc]
150
+ responses:
151
+ "200":
152
+ description: Paginated list of shifts.
153
+ content:
154
+ application/json:
155
+ schema:
156
+ $ref: "#/components/schemas/ShiftFindResult"
157
+ post:
158
+ summary: Create a day shift
159
+ description: |
160
+ Creates a shift. The `schedule` is validated (see the service
161
+ description). Emits `update-day-shift`.
162
+ operationId: createDayShift
163
+ requestBody:
164
+ required: true
165
+ content:
166
+ application/json:
167
+ schema:
168
+ $ref: "#/components/schemas/ShiftCreateBody"
169
+ responses:
170
+ "201":
171
+ description: The newly-created shift document.
172
+ content:
173
+ application/json:
174
+ schema:
175
+ $ref: "#/components/schemas/ShiftSchema"
176
+ /day-shift/{id}:
177
+ get:
178
+ summary: Get a day shift by id
179
+ operationId: getDayShift
180
+ parameters:
181
+ - in: path
182
+ name: id
183
+ required: true
184
+ schema: { type: string }
185
+ responses:
186
+ "200":
187
+ description: The shift document for the given `_id`.
188
+ content:
189
+ application/json:
190
+ schema:
191
+ $ref: "#/components/schemas/ShiftSchema"
192
+ put:
193
+ summary: Update a day shift
194
+ description: |
195
+ Standard put. When `schedule` is present it is validated. Setting
196
+ `disabled: true` soft-deletes the shift and — like DELETE — is
197
+ rejected with a `BadRequest` while any active rep's `assigned_shift`
198
+ still points at it. Emits `update-day-shift`.
199
+ operationId: updateDayShift
200
+ parameters:
201
+ - in: path
202
+ name: id
203
+ required: true
204
+ schema: { type: string }
205
+ requestBody:
206
+ required: true
207
+ content:
208
+ application/json:
209
+ schema:
210
+ $ref: "#/components/schemas/ShiftUpdateBody"
211
+ responses:
212
+ "200":
213
+ description: The shift document after the update is applied.
214
+ content:
215
+ application/json:
216
+ schema:
217
+ $ref: "#/components/schemas/ShiftSchema"
218
+ delete:
219
+ summary: Soft-delete a day shift
220
+ description: |
221
+ Soft-deletes the shift (`disabled: true`). Rejected with a
222
+ `BadRequest` while any active rep's `assigned_shift` still points at
223
+ it. Emits `update-day-shift`.
224
+ operationId: removeDayShift
225
+ parameters:
226
+ - in: path
227
+ name: id
228
+ required: true
229
+ schema: { type: string }
230
+ responses:
231
+ "200":
232
+ description: "The shift document after soft-deletion (`disabled: true`)."
233
+ content:
234
+ application/json:
235
+ schema:
236
+ $ref: "#/components/schemas/ShiftSchema"
237
+ components:
238
+ securitySchemes:
239
+ ApiKeyAuth:
240
+ type: apiKey
241
+ in: header
242
+ name: api-key
243
+ description: |
244
+ Server-issued API key. Also accepted via the `x-api-key` header or the
245
+ `?apiKey=` query parameter as fallbacks.
246
+ JwtAuth:
247
+ type: apiKey
248
+ in: header
249
+ name: Authorization
250
+ description: |
251
+ Raw JWT in the `Authorization` header — **no `Bearer ` prefix**.
252
+ Obtained from `POST /authenticate` (admin / rep / client login).
253
+ schemas:
254
+ ShiftRange:
255
+ type: object
256
+ description: |
257
+ A single work interval in `HH:mm` wall-clock time (company time zone).
258
+ A range whose `to <= from` crosses midnight into the next calendar date.
259
+ required:
260
+ - from
261
+ - to
262
+ properties:
263
+ from:
264
+ type: string
265
+ pattern: "^([01]\\d|2[0-3]):[0-5]\\d$"
266
+ example: "18:00"
267
+ to:
268
+ type: string
269
+ pattern: "^([01]\\d|2[0-3]):[0-5]\\d$"
270
+ example: "02:00"
271
+ ShiftEntry:
272
+ type: object
273
+ description: One weekday's work_time ranges.
274
+ required:
275
+ - day
276
+ - work_time
277
+ properties:
278
+ day:
279
+ type: string
280
+ enum: [sunday, monday, tuesday, wednesday, thursday, friday, saturday]
281
+ work_time:
282
+ type: array
283
+ minItems: 1
284
+ items:
285
+ $ref: "#/components/schemas/ShiftRange"
286
+ ShiftSchema:
287
+ type: object
288
+ description: Shift document.
289
+ properties:
290
+ _id:
291
+ type: string
292
+ description: Unique identifier for the shift.
293
+ name:
294
+ type: string
295
+ description: Display name.
296
+ designation:
297
+ type: string
298
+ description: Optional free-text label for the shift.
299
+ disabled:
300
+ type: boolean
301
+ description: Soft-delete flag.
302
+ schedule:
303
+ type: array
304
+ minItems: 1
305
+ items:
306
+ $ref: "#/components/schemas/ShiftEntry"
307
+ description: Weekly work schedule (per-weekday work_time ranges).
308
+ total_working_hours:
309
+ type: number
310
+ description: |
311
+ Server-computed total working hours across the schedule
312
+ (cross-midnight ranges counted correctly). Derived on write.
313
+ total_working_days:
314
+ type: number
315
+ description: |
316
+ Server-computed count of weekdays with at least one work_time
317
+ range. Derived on write.
318
+ company_namespace:
319
+ type: array
320
+ items: { type: string }
321
+ description: Tenant key. Server-injected — never accept from clients.
322
+ createdAt:
323
+ type: string
324
+ format: date-time
325
+ description: Creation timestamp.
326
+ updatedAt:
327
+ type: string
328
+ format: date-time
329
+ description: Last update timestamp.
330
+ ShiftCreateBody:
331
+ type: object
332
+ description: |
333
+ Body for creating a shift. The tenant key (`company_namespace`) is
334
+ optional for SDK callers and is otherwise injected from the caller's
335
+ session. `schedule` is validated on write.
336
+ required:
337
+ - name
338
+ - schedule
339
+ properties:
340
+ name:
341
+ type: string
342
+ description: Display name.
343
+ designation:
344
+ type: string
345
+ description: Optional free-text label for the shift.
346
+ schedule:
347
+ type: array
348
+ minItems: 1
349
+ items:
350
+ $ref: "#/components/schemas/ShiftEntry"
351
+ company_namespace:
352
+ type: array
353
+ items: { type: string }
354
+ description: Optional tenant namespace override for SDK callers.
355
+ ShiftUpdateBody:
356
+ type: object
357
+ description: |
358
+ Body for updating a shift. The tenant key (`company_namespace`) is
359
+ derived from the caller's session — do not send it. When `schedule` is
360
+ present it is validated. Set `disabled: true` to soft-delete.
361
+ properties:
362
+ name:
363
+ type: string
364
+ designation:
365
+ type: string
366
+ schedule:
367
+ type: array
368
+ minItems: 1
369
+ items:
370
+ $ref: "#/components/schemas/ShiftEntry"
371
+ disabled:
372
+ type: boolean
373
+ description: |
374
+ Soft-delete flag. Set to `true` to disable the shift — rejected
375
+ while any active rep is still assigned to it.
376
+ ShiftFindResult:
377
+ type: object
378
+ description: Standard paginated result envelope.
379
+ properties:
380
+ data:
381
+ type: array
382
+ items:
383
+ $ref: "#/components/schemas/ShiftSchema"
384
+ total_result:
385
+ type: number
386
+ description: Total number of shifts matching the filter.
387
+ current_count:
388
+ type: number
389
+ description: Count of shifts on the current page.
390
+ total_pages:
391
+ type: number
392
+ description: Total number of pages.
393
+ current_page:
394
+ type: number
395
+ description: Current page number.
396
+ per_page:
397
+ type: number
398
+ description: Number of shifts per page.
399
+ first_page_url:
400
+ type: string
401
+ description: URL for the first page.
402
+ last_page_url:
403
+ type: string
404
+ description: URL for the last page.
405
+ next_page_url:
406
+ type: string
407
+ nullable: true
408
+ description: URL for the next page.
409
+ prev_page_url:
410
+ type: string
411
+ nullable: true
412
+ description: URL for the previous page.
413
+ path:
414
+ type: string
415
+ description: Base URL path.
package/src/oas/day.yaml CHANGED
@@ -30,12 +30,20 @@ paths:
30
30
  items:
31
31
  type: string
32
32
  - type: string
33
+ reps:
34
+ oneOf:
35
+ - type: array
36
+ items:
37
+ type: string
38
+ - type: string
33
39
  date:
34
40
  type: string
35
41
  format: date
36
42
  status:
37
43
  type: string
38
44
  enum: [open, closed, submitted]
45
+ not_working_day:
46
+ type: boolean
39
47
  from_date:
40
48
  type: string
41
49
  format: date
@@ -151,6 +159,9 @@ components:
151
159
  type: string
152
160
  enum: [open, closed, submitted]
153
161
  description: Status of the day
162
+ not_working_day:
163
+ type: boolean
164
+ description: Server-set flag for days that fall on a scheduled day off of the rep's assigned shift.
154
165
  visits:
155
166
  type: array
156
167
  items: