repzo 1.0.289 → 1.0.290
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/changelog.md +5 -0
- package/lib/index.d.ts +19 -2
- package/lib/index.js +37 -0
- package/lib/types/index.d.ts +149 -2
- package/package.json +1 -1
- package/src/index.ts +84 -0
- package/src/oas/bulk-export.yaml +272 -0
- package/src/oas/geo-zone.yaml +349 -0
- package/src/oas/rep.yaml +45 -0
- package/src/oas/settings.yaml +60 -0
- package/src/types/index.ts +210 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Repzo API - Bulk Export
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
Exports large datasets to **Excel** or **Parquet**. Starting an export
|
|
7
|
+
(`POST /bulk-export`) creates a job for one of ~50 supported entity types
|
|
8
|
+
(`clients`, `products`, `contracts`, `reps`, ...) selected via the `type`
|
|
9
|
+
query parameter; the job runs the aggregation, writes the file to media
|
|
10
|
+
storage, and records a `status` and a download `link`. `GET /bulk-export`
|
|
11
|
+
lists the export jobs (see also `bulk-export-report`).
|
|
12
|
+
|
|
13
|
+
**Who calls it.** Back-office admins — the `creator` audit stamp is always
|
|
14
|
+
an admin, set server-side from the session token.
|
|
15
|
+
|
|
16
|
+
**Multi-tenancy & lifecycle.** Jobs are scoped by `company_namespace[]`
|
|
17
|
+
(injected from session — never sent in the body). A job moves through
|
|
18
|
+
`processing` then `success` / `fail`; on success, `link` (and the `media`
|
|
19
|
+
storage id) point at the generated file.
|
|
20
|
+
|
|
21
|
+
**Unsupported operations.** Only find (list jobs) and create (start a job)
|
|
22
|
+
are available. `GET /bulk-export/{id}`, `update`, `patch`, and `remove` are
|
|
23
|
+
rejected with `400`.
|
|
24
|
+
servers:
|
|
25
|
+
- url: https://sv.api.repzo.me
|
|
26
|
+
security:
|
|
27
|
+
- ApiKeyAuth: []
|
|
28
|
+
- JwtAuth: []
|
|
29
|
+
paths:
|
|
30
|
+
/bulk-export:
|
|
31
|
+
get:
|
|
32
|
+
summary: List bulk-export jobs
|
|
33
|
+
operationId: findBulkExports
|
|
34
|
+
parameters:
|
|
35
|
+
- in: query
|
|
36
|
+
name: _id
|
|
37
|
+
description: Filter by job `_id`. Pass once or as `?_id[]=...` for multiple.
|
|
38
|
+
schema:
|
|
39
|
+
oneOf:
|
|
40
|
+
- type: string
|
|
41
|
+
- type: array
|
|
42
|
+
items: { type: string }
|
|
43
|
+
- in: query
|
|
44
|
+
name: type
|
|
45
|
+
description: Filter by exported entity type.
|
|
46
|
+
schema:
|
|
47
|
+
$ref: "#/components/schemas/BulkExportType"
|
|
48
|
+
- in: query
|
|
49
|
+
name: status
|
|
50
|
+
description: Filter by job status.
|
|
51
|
+
schema:
|
|
52
|
+
type: string
|
|
53
|
+
enum: [processing, success, fail]
|
|
54
|
+
- in: query
|
|
55
|
+
name: export_type
|
|
56
|
+
description: Filter by output format.
|
|
57
|
+
schema:
|
|
58
|
+
type: string
|
|
59
|
+
enum: [excel, parquet]
|
|
60
|
+
- in: query
|
|
61
|
+
name: export
|
|
62
|
+
description: When truthy, schedule the export as an emailed job instead of returning it inline.
|
|
63
|
+
schema: { type: boolean }
|
|
64
|
+
- in: query
|
|
65
|
+
name: from_updatedAt
|
|
66
|
+
description: Cursor — jobs updated on or after this Unix timestamp (ms).
|
|
67
|
+
schema: { type: number }
|
|
68
|
+
- in: query
|
|
69
|
+
name: to_updatedAt
|
|
70
|
+
description: Cursor — jobs updated on or before this Unix timestamp (ms).
|
|
71
|
+
schema: { type: number }
|
|
72
|
+
- in: query
|
|
73
|
+
name: per_page
|
|
74
|
+
schema: { type: integer, minimum: 1, maximum: 50000 }
|
|
75
|
+
example: 20
|
|
76
|
+
- in: query
|
|
77
|
+
name: page
|
|
78
|
+
schema: { type: integer, minimum: 1 }
|
|
79
|
+
example: 1
|
|
80
|
+
responses:
|
|
81
|
+
"200":
|
|
82
|
+
description: A paginated list of export jobs.
|
|
83
|
+
content:
|
|
84
|
+
application/json:
|
|
85
|
+
schema:
|
|
86
|
+
$ref: "#/components/schemas/BulkExportFindResult"
|
|
87
|
+
post:
|
|
88
|
+
summary: Start a bulk export
|
|
89
|
+
operationId: createBulkExport
|
|
90
|
+
parameters:
|
|
91
|
+
- in: query
|
|
92
|
+
name: type
|
|
93
|
+
required: true
|
|
94
|
+
description: Entity type to export. Sent as a query parameter, not in the body.
|
|
95
|
+
schema:
|
|
96
|
+
$ref: "#/components/schemas/BulkExportType"
|
|
97
|
+
requestBody:
|
|
98
|
+
required: true
|
|
99
|
+
content:
|
|
100
|
+
application/json:
|
|
101
|
+
schema:
|
|
102
|
+
$ref: "#/components/schemas/BulkExportCreateBody"
|
|
103
|
+
responses:
|
|
104
|
+
"201":
|
|
105
|
+
description: The created export job — `status` reflects progress and `link` is populated when the file is ready.
|
|
106
|
+
content:
|
|
107
|
+
application/json:
|
|
108
|
+
schema:
|
|
109
|
+
$ref: "#/components/schemas/BulkExportSchema"
|
|
110
|
+
components:
|
|
111
|
+
securitySchemes:
|
|
112
|
+
ApiKeyAuth:
|
|
113
|
+
type: apiKey
|
|
114
|
+
in: header
|
|
115
|
+
name: api-key
|
|
116
|
+
description: |
|
|
117
|
+
Server-issued API key. Also accepted via the `x-api-key` header or the
|
|
118
|
+
`?apiKey=` query parameter as fallbacks.
|
|
119
|
+
JwtAuth:
|
|
120
|
+
type: apiKey
|
|
121
|
+
in: header
|
|
122
|
+
name: Authorization
|
|
123
|
+
description: |
|
|
124
|
+
Raw JWT in the `Authorization` header — **no `Bearer ` prefix**. Obtained
|
|
125
|
+
from `POST /authenticate` (admin login).
|
|
126
|
+
schemas:
|
|
127
|
+
BulkExportType:
|
|
128
|
+
type: string
|
|
129
|
+
description: One of the supported export entity types.
|
|
130
|
+
enum:
|
|
131
|
+
- clients
|
|
132
|
+
- products
|
|
133
|
+
- variants
|
|
134
|
+
- categories
|
|
135
|
+
- subCategories
|
|
136
|
+
- availabilityMsl
|
|
137
|
+
- availabilityMslWithProducts
|
|
138
|
+
- reps
|
|
139
|
+
- mslWithVariants
|
|
140
|
+
- jobCategories
|
|
141
|
+
- jobs
|
|
142
|
+
- tags
|
|
143
|
+
- routes
|
|
144
|
+
- routesWithClients
|
|
145
|
+
- plans
|
|
146
|
+
- planWithRules
|
|
147
|
+
- targetRulesWithClients
|
|
148
|
+
- rulesWithRoutes
|
|
149
|
+
- targetRulesWithReps
|
|
150
|
+
- adjustAccount
|
|
151
|
+
- rules
|
|
152
|
+
- warehouses
|
|
153
|
+
- productGroups
|
|
154
|
+
- priceListItems
|
|
155
|
+
- measureunit
|
|
156
|
+
- measureunitFamily
|
|
157
|
+
- lineTarget
|
|
158
|
+
- clientLineClassification
|
|
159
|
+
- retailExecutionPresets
|
|
160
|
+
- promotions
|
|
161
|
+
- customListItems
|
|
162
|
+
- assets
|
|
163
|
+
- assetUnits
|
|
164
|
+
- speciality
|
|
165
|
+
- clientLocation
|
|
166
|
+
- reminders
|
|
167
|
+
- admins
|
|
168
|
+
- companyGroup
|
|
169
|
+
- company
|
|
170
|
+
- variantBatch
|
|
171
|
+
- banksList
|
|
172
|
+
- clientUblInfo
|
|
173
|
+
- supplier
|
|
174
|
+
- contractInstallment
|
|
175
|
+
- targetRule
|
|
176
|
+
- contracts
|
|
177
|
+
- assetPartTypes
|
|
178
|
+
- assetParts
|
|
179
|
+
- clientUblInfo_JO
|
|
180
|
+
- clientUblInfo_SA
|
|
181
|
+
- nameSpaceFreshnessWindowCodes
|
|
182
|
+
BulkExportCreateBody:
|
|
183
|
+
type: object
|
|
184
|
+
description: |
|
|
185
|
+
Export options. `type` is sent as a query parameter (not in the body).
|
|
186
|
+
The `creator` audit stamp and `company_namespace` are normally injected
|
|
187
|
+
from session and can be omitted — both are optional here for
|
|
188
|
+
integration / cross-namespace callers.
|
|
189
|
+
properties:
|
|
190
|
+
export_type:
|
|
191
|
+
type: string
|
|
192
|
+
enum: [excel, parquet]
|
|
193
|
+
default: excel
|
|
194
|
+
columns:
|
|
195
|
+
type: object
|
|
196
|
+
additionalProperties: true
|
|
197
|
+
description: Map of column paths to include / label in the generated file.
|
|
198
|
+
name:
|
|
199
|
+
type: string
|
|
200
|
+
description: Optional label for the export job.
|
|
201
|
+
creator:
|
|
202
|
+
$ref: "#/components/schemas/BulkExportCreator"
|
|
203
|
+
company_namespace:
|
|
204
|
+
type: array
|
|
205
|
+
items: { type: string }
|
|
206
|
+
description: Tenant key — normally injected from session; optional, for cross-namespace callers.
|
|
207
|
+
BulkExportCreator:
|
|
208
|
+
type: object
|
|
209
|
+
description: Audit stamp of the admin who started the job. Set server-side from the session token — never sent by the client.
|
|
210
|
+
properties:
|
|
211
|
+
_id: { type: string }
|
|
212
|
+
type: { type: string, enum: [admin] }
|
|
213
|
+
name: { type: string }
|
|
214
|
+
admin: { type: string }
|
|
215
|
+
BulkExportSchema:
|
|
216
|
+
type: object
|
|
217
|
+
description: A bulk-export job document as stored.
|
|
218
|
+
properties:
|
|
219
|
+
_id: { type: string }
|
|
220
|
+
creator:
|
|
221
|
+
$ref: "#/components/schemas/BulkExportCreator"
|
|
222
|
+
type:
|
|
223
|
+
$ref: "#/components/schemas/BulkExportType"
|
|
224
|
+
status:
|
|
225
|
+
type: string
|
|
226
|
+
enum: [processing, success, fail]
|
|
227
|
+
messages:
|
|
228
|
+
type: array
|
|
229
|
+
items: { type: object }
|
|
230
|
+
_errors:
|
|
231
|
+
type: array
|
|
232
|
+
items: { type: object }
|
|
233
|
+
start_time: { type: integer, format: int64 }
|
|
234
|
+
end_time: { type: integer, format: int64 }
|
|
235
|
+
bucket_name: { type: string }
|
|
236
|
+
region: { type: string }
|
|
237
|
+
key: { type: string }
|
|
238
|
+
link: { type: string, description: Download URL of the generated file. }
|
|
239
|
+
media:
|
|
240
|
+
type: array
|
|
241
|
+
items: { type: string }
|
|
242
|
+
description: "Media-storage `_id`(s) of the generated file (ref `media-storage`)."
|
|
243
|
+
teams:
|
|
244
|
+
type: array
|
|
245
|
+
items: { type: string }
|
|
246
|
+
export_type:
|
|
247
|
+
type: string
|
|
248
|
+
enum: [excel, parquet]
|
|
249
|
+
row_count: { type: number }
|
|
250
|
+
company_namespace:
|
|
251
|
+
type: array
|
|
252
|
+
items: { type: string }
|
|
253
|
+
createdAt: { type: string, format: date-time }
|
|
254
|
+
updatedAt: { type: string, format: date-time }
|
|
255
|
+
BulkExportFindResult:
|
|
256
|
+
type: object
|
|
257
|
+
description: Paginated list of export jobs.
|
|
258
|
+
properties:
|
|
259
|
+
data:
|
|
260
|
+
type: array
|
|
261
|
+
items:
|
|
262
|
+
$ref: "#/components/schemas/BulkExportSchema"
|
|
263
|
+
total_result: { type: number }
|
|
264
|
+
current_count: { type: number }
|
|
265
|
+
total_pages: { type: number }
|
|
266
|
+
current_page: { type: number }
|
|
267
|
+
per_page: { type: number }
|
|
268
|
+
first_page_url: { type: string }
|
|
269
|
+
last_page_url: { type: string }
|
|
270
|
+
next_page_url: { type: string, nullable: true }
|
|
271
|
+
prev_page_url: { type: string, nullable: true }
|
|
272
|
+
path: { type: string }
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Repzo API - Geo Zone
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
A **Geo Zone** is a named geographic area defined by a single GeoJSON
|
|
7
|
+
polygon. Zones are assigned to reps (via the rep's `assigned_geo_zones`
|
|
8
|
+
array — currently capped at one zone per rep) so the mobile app can
|
|
9
|
+
enforce location policies — e.g. whether a rep may start the day or
|
|
10
|
+
start a visit while outside their zone.
|
|
11
|
+
|
|
12
|
+
**Who uses it.** Admins manage zones from the back office and assign
|
|
13
|
+
them through the `rep` service. The mobile app reads zones (with the
|
|
14
|
+
incremental `from_updatedAt` cursor) to evaluate policies offline.
|
|
15
|
+
|
|
16
|
+
**Multi-tenancy & lifecycle.** Records are scoped by
|
|
17
|
+
`company_namespace[]` (injected from session — never sent in the body)
|
|
18
|
+
and use **soft-delete** via `disabled: true`. `name` is unique per
|
|
19
|
+
namespace among non-deleted zones. A zone that is still assigned to one
|
|
20
|
+
or more reps **cannot be disabled or deleted** — the request is rejected
|
|
21
|
+
with `400` naming the assigned reps; reassign them first.
|
|
22
|
+
|
|
23
|
+
**Validation.** A zone cannot be saved without a `name` and a valid
|
|
24
|
+
polygon: the polygon needs at least one closed linear ring of 4+
|
|
25
|
+
`[longitude, latitude]` positions (first and last must match, longitude
|
|
26
|
+
in ±180, latitude in ±90). Violations return a `400` naming the failing
|
|
27
|
+
ring.
|
|
28
|
+
|
|
29
|
+
**Key relationships.** Referenced by `rep.assigned_geo_zones`. The
|
|
30
|
+
`editor` audit object (who created / last updated the zone) is stamped
|
|
31
|
+
server-side from the session token.
|
|
32
|
+
servers:
|
|
33
|
+
- url: https://sv.api.repzo.me
|
|
34
|
+
security:
|
|
35
|
+
- ApiKeyAuth: []
|
|
36
|
+
- JwtAuth: []
|
|
37
|
+
paths:
|
|
38
|
+
/geo-zone:
|
|
39
|
+
get:
|
|
40
|
+
summary: Find geo zones
|
|
41
|
+
operationId: findGeoZones
|
|
42
|
+
parameters:
|
|
43
|
+
- in: query
|
|
44
|
+
name: _id
|
|
45
|
+
description: Filter by zone `_id`. Pass once or as `?_id[]=...` for multiple.
|
|
46
|
+
schema:
|
|
47
|
+
oneOf:
|
|
48
|
+
- type: string
|
|
49
|
+
- type: array
|
|
50
|
+
items: { type: string }
|
|
51
|
+
- in: query
|
|
52
|
+
name: name
|
|
53
|
+
description: Exact-match on zone name. Pass once or as `?name[]=...` for multiple.
|
|
54
|
+
schema:
|
|
55
|
+
oneOf:
|
|
56
|
+
- type: string
|
|
57
|
+
- type: array
|
|
58
|
+
items: { type: string }
|
|
59
|
+
- in: query
|
|
60
|
+
name: search
|
|
61
|
+
description: Case-insensitive substring search on `name`.
|
|
62
|
+
schema: { type: string }
|
|
63
|
+
example: north
|
|
64
|
+
- in: query
|
|
65
|
+
name: disabled
|
|
66
|
+
description: Include disabled (soft-deleted) zones. Defaults to `false`.
|
|
67
|
+
schema: { type: boolean, default: false }
|
|
68
|
+
- in: query
|
|
69
|
+
name: inject_assigned_reps
|
|
70
|
+
description: |
|
|
71
|
+
When truthy, each returned zone is enriched with an
|
|
72
|
+
`assigned_reps[]` array (`_id`, `name`) of the active reps whose
|
|
73
|
+
`assigned_geo_zones` contains it.
|
|
74
|
+
schema: { type: boolean, default: false }
|
|
75
|
+
- in: query
|
|
76
|
+
name: from_updatedAt
|
|
77
|
+
description: Cursor — zones updated on or after this Unix timestamp (ms). Used by the mobile app for incremental sync.
|
|
78
|
+
schema: { type: number }
|
|
79
|
+
- in: query
|
|
80
|
+
name: to_updatedAt
|
|
81
|
+
description: Cursor — zones updated on or before this Unix timestamp (ms).
|
|
82
|
+
schema: { type: number }
|
|
83
|
+
- in: query
|
|
84
|
+
name: from_createdAt
|
|
85
|
+
description: Cursor — zones created on or after this Unix timestamp (ms).
|
|
86
|
+
schema: { type: number }
|
|
87
|
+
- in: query
|
|
88
|
+
name: to_createdAt
|
|
89
|
+
description: Cursor — zones created on or before this Unix timestamp (ms).
|
|
90
|
+
schema: { type: number }
|
|
91
|
+
- in: query
|
|
92
|
+
name: per_page
|
|
93
|
+
description: Page size. Defaults to the server's configured pagination limit.
|
|
94
|
+
schema: { type: integer, minimum: 1, maximum: 500 }
|
|
95
|
+
example: 50
|
|
96
|
+
- in: query
|
|
97
|
+
name: page
|
|
98
|
+
description: 1-indexed page number.
|
|
99
|
+
schema: { type: integer, minimum: 1 }
|
|
100
|
+
example: 1
|
|
101
|
+
responses:
|
|
102
|
+
"200":
|
|
103
|
+
description: A paginated list of geo zones matching the filter.
|
|
104
|
+
content:
|
|
105
|
+
application/json:
|
|
106
|
+
schema:
|
|
107
|
+
$ref: "#/components/schemas/GeoZoneFindResult"
|
|
108
|
+
post:
|
|
109
|
+
summary: Create a geo zone
|
|
110
|
+
operationId: createGeoZone
|
|
111
|
+
requestBody:
|
|
112
|
+
required: true
|
|
113
|
+
content:
|
|
114
|
+
application/json:
|
|
115
|
+
schema:
|
|
116
|
+
$ref: "#/components/schemas/GeoZoneCreateBody"
|
|
117
|
+
responses:
|
|
118
|
+
"201":
|
|
119
|
+
description: The newly-created geo zone. `editor` is stamped from the session token.
|
|
120
|
+
content:
|
|
121
|
+
application/json:
|
|
122
|
+
schema:
|
|
123
|
+
$ref: "#/components/schemas/GeoZoneSchema"
|
|
124
|
+
"400":
|
|
125
|
+
description: |
|
|
126
|
+
Validation failure — missing `name`, missing polygon, or an
|
|
127
|
+
invalid polygon (open ring, fewer than 4 positions, out-of-range
|
|
128
|
+
coordinates). The message names the failing ring. Also returned
|
|
129
|
+
when the zone name already exists in the namespace.
|
|
130
|
+
/geo-zone/{id}:
|
|
131
|
+
get:
|
|
132
|
+
summary: Get a geo zone by ID
|
|
133
|
+
operationId: getGeoZone
|
|
134
|
+
parameters:
|
|
135
|
+
- in: path
|
|
136
|
+
name: id
|
|
137
|
+
required: true
|
|
138
|
+
schema: { type: string }
|
|
139
|
+
- in: query
|
|
140
|
+
name: inject_assigned_reps
|
|
141
|
+
description: When truthy, the zone is enriched with an `assigned_reps[]` array (`_id`, `name`).
|
|
142
|
+
schema: { type: boolean, default: false }
|
|
143
|
+
responses:
|
|
144
|
+
"200":
|
|
145
|
+
description: The geo zone document for the given `_id`.
|
|
146
|
+
content:
|
|
147
|
+
application/json:
|
|
148
|
+
schema:
|
|
149
|
+
$ref: "#/components/schemas/GeoZoneSchema"
|
|
150
|
+
put:
|
|
151
|
+
summary: Update a geo zone
|
|
152
|
+
operationId: updateGeoZone
|
|
153
|
+
description: |
|
|
154
|
+
Partial update — only the fields present in the body are changed.
|
|
155
|
+
`polygon`, when sent, replaces the zone's polygon and is validated
|
|
156
|
+
like create. Setting `disabled: true` deactivates the zone and is
|
|
157
|
+
**rejected with `400` while any rep is still assigned to it**;
|
|
158
|
+
reassign those reps first.
|
|
159
|
+
parameters:
|
|
160
|
+
- in: path
|
|
161
|
+
name: id
|
|
162
|
+
required: true
|
|
163
|
+
schema: { type: string }
|
|
164
|
+
requestBody:
|
|
165
|
+
required: true
|
|
166
|
+
content:
|
|
167
|
+
application/json:
|
|
168
|
+
schema:
|
|
169
|
+
$ref: "#/components/schemas/GeoZoneUpdateBody"
|
|
170
|
+
responses:
|
|
171
|
+
"200":
|
|
172
|
+
description: The geo zone document after the update is applied.
|
|
173
|
+
content:
|
|
174
|
+
application/json:
|
|
175
|
+
schema:
|
|
176
|
+
$ref: "#/components/schemas/GeoZoneSchema"
|
|
177
|
+
"400":
|
|
178
|
+
description: Zone not found, polygon validation failure, or the zone is being disabled while reps are still assigned to it.
|
|
179
|
+
delete:
|
|
180
|
+
summary: Remove a geo zone (soft-delete)
|
|
181
|
+
operationId: removeGeoZone
|
|
182
|
+
description: |
|
|
183
|
+
Soft-deletes the zone (`disabled: true`). Rejected with `400` while
|
|
184
|
+
any rep is still assigned to it — the error names the assigned reps;
|
|
185
|
+
reassign them to another zone first.
|
|
186
|
+
parameters:
|
|
187
|
+
- in: path
|
|
188
|
+
name: id
|
|
189
|
+
required: true
|
|
190
|
+
schema: { type: string }
|
|
191
|
+
responses:
|
|
192
|
+
"200":
|
|
193
|
+
description: "The geo zone document after soft-deletion (`disabled: true`)."
|
|
194
|
+
content:
|
|
195
|
+
application/json:
|
|
196
|
+
schema:
|
|
197
|
+
$ref: "#/components/schemas/GeoZoneSchema"
|
|
198
|
+
"400":
|
|
199
|
+
description: Zone not found, or the zone is still assigned to one or more reps.
|
|
200
|
+
components:
|
|
201
|
+
securitySchemes:
|
|
202
|
+
ApiKeyAuth:
|
|
203
|
+
type: apiKey
|
|
204
|
+
in: header
|
|
205
|
+
name: api-key
|
|
206
|
+
description: |
|
|
207
|
+
Server-issued API key. Also accepted via the `x-api-key` header or the
|
|
208
|
+
`?apiKey=` query parameter as fallbacks.
|
|
209
|
+
JwtAuth:
|
|
210
|
+
type: apiKey
|
|
211
|
+
in: header
|
|
212
|
+
name: Authorization
|
|
213
|
+
description: |
|
|
214
|
+
Raw JWT in the `Authorization` header — **no `Bearer ` prefix**. Obtained from
|
|
215
|
+
`POST /authenticate` (admin / rep / client login).
|
|
216
|
+
schemas:
|
|
217
|
+
GeoZoneFindResult:
|
|
218
|
+
type: object
|
|
219
|
+
description: Paginated list of geo zones.
|
|
220
|
+
properties:
|
|
221
|
+
data:
|
|
222
|
+
type: array
|
|
223
|
+
items:
|
|
224
|
+
$ref: "#/components/schemas/GeoZoneSchema"
|
|
225
|
+
total_result: { type: number }
|
|
226
|
+
current_count: { type: number }
|
|
227
|
+
total_pages: { type: number }
|
|
228
|
+
current_page: { type: number }
|
|
229
|
+
per_page: { type: number }
|
|
230
|
+
first_page_url: { type: string }
|
|
231
|
+
last_page_url: { type: string }
|
|
232
|
+
next_page_url: { type: string, nullable: true }
|
|
233
|
+
prev_page_url: { type: string, nullable: true }
|
|
234
|
+
path: { type: string }
|
|
235
|
+
GeoZoneSchema:
|
|
236
|
+
type: object
|
|
237
|
+
description: Geo zone document as stored.
|
|
238
|
+
properties:
|
|
239
|
+
_id: { type: string }
|
|
240
|
+
name:
|
|
241
|
+
{
|
|
242
|
+
type: string,
|
|
243
|
+
description: Unique per namespace among non-deleted zones.,
|
|
244
|
+
}
|
|
245
|
+
description: { type: string }
|
|
246
|
+
polygon:
|
|
247
|
+
$ref: "#/components/schemas/GeoZonePolygon"
|
|
248
|
+
disabled:
|
|
249
|
+
{ type: boolean, description: Soft-delete / deactivation flag. }
|
|
250
|
+
editor:
|
|
251
|
+
$ref: "#/components/schemas/GeoZoneEditor"
|
|
252
|
+
assigned_reps:
|
|
253
|
+
type: array
|
|
254
|
+
description: "Present only when the request sent `inject_assigned_reps=true` — the active reps assigned to this zone."
|
|
255
|
+
items:
|
|
256
|
+
type: object
|
|
257
|
+
properties:
|
|
258
|
+
_id: { type: string }
|
|
259
|
+
name: { type: string }
|
|
260
|
+
company_namespace:
|
|
261
|
+
type: array
|
|
262
|
+
items: { type: string }
|
|
263
|
+
description: Tenant key set on save from session.
|
|
264
|
+
createdAt: { type: string, format: date-time }
|
|
265
|
+
updatedAt: { type: string, format: date-time }
|
|
266
|
+
__v: { type: number }
|
|
267
|
+
GeoZonePolygon:
|
|
268
|
+
type: object
|
|
269
|
+
description: |
|
|
270
|
+
A GeoJSON Polygon. `coordinates` is an array of linear rings; the
|
|
271
|
+
first ring is the outer boundary, any further rings are holes.
|
|
272
|
+
required: [coordinates]
|
|
273
|
+
properties:
|
|
274
|
+
type:
|
|
275
|
+
type: string
|
|
276
|
+
enum: [Polygon]
|
|
277
|
+
default: Polygon
|
|
278
|
+
coordinates:
|
|
279
|
+
type: array
|
|
280
|
+
minItems: 1
|
|
281
|
+
description: |
|
|
282
|
+
Array of linear rings. Each ring is an array of at least 4
|
|
283
|
+
positions and must be closed (first position equals the last).
|
|
284
|
+
Positions are ordered as **longitude, latitude** (longitude
|
|
285
|
+
first) — longitude in [-180, 180], latitude in [-90, 90].
|
|
286
|
+
items:
|
|
287
|
+
type: array
|
|
288
|
+
minItems: 4
|
|
289
|
+
description: "A closed linear ring of `[longitude, latitude]` positions."
|
|
290
|
+
items:
|
|
291
|
+
type: array
|
|
292
|
+
minItems: 2
|
|
293
|
+
maxItems: 2
|
|
294
|
+
items: { type: number }
|
|
295
|
+
example:
|
|
296
|
+
- - [35.910, 31.954]
|
|
297
|
+
- [35.930, 31.954]
|
|
298
|
+
- [35.930, 31.970]
|
|
299
|
+
- [35.910, 31.954]
|
|
300
|
+
GeoZoneEditor:
|
|
301
|
+
type: object
|
|
302
|
+
description: Audit stamp of who created / last updated the zone. Set server-side from the session token — never sent by the client.
|
|
303
|
+
properties:
|
|
304
|
+
_id: { type: string }
|
|
305
|
+
type: { type: string, enum: [admin, rep, tenant, client] }
|
|
306
|
+
name: { type: string }
|
|
307
|
+
rep: { type: string }
|
|
308
|
+
admin: { type: string }
|
|
309
|
+
client: { type: string }
|
|
310
|
+
tenant: { type: string }
|
|
311
|
+
GeoZoneCreateBody:
|
|
312
|
+
type: object
|
|
313
|
+
description: |
|
|
314
|
+
Body for creating a geo zone. The `editor` audit stamp is stamped
|
|
315
|
+
server-side from the session token (not accepted on create). The tenant
|
|
316
|
+
key (`company_namespace`) is normally injected from session and can be
|
|
317
|
+
omitted — it is optional here for integration / cross-namespace callers.
|
|
318
|
+
The soft-delete flag (`disabled`) defaults to `false`.
|
|
319
|
+
required:
|
|
320
|
+
- name
|
|
321
|
+
- polygon
|
|
322
|
+
properties:
|
|
323
|
+
name:
|
|
324
|
+
type: string
|
|
325
|
+
description: Zone name — required and unique per namespace among non-deleted zones.
|
|
326
|
+
description: { type: string }
|
|
327
|
+
polygon:
|
|
328
|
+
$ref: "#/components/schemas/GeoZonePolygon"
|
|
329
|
+
company_namespace:
|
|
330
|
+
type: array
|
|
331
|
+
items: { type: string }
|
|
332
|
+
description: Tenant key — normally injected from session; optional, for cross-namespace callers.
|
|
333
|
+
GeoZoneUpdateBody:
|
|
334
|
+
type: object
|
|
335
|
+
description: |
|
|
336
|
+
Body for updating a geo zone — only the fields present are changed.
|
|
337
|
+
The tenant key (`company_namespace`) is derived from session. The
|
|
338
|
+
`editor` audit stamp is normally refreshed server-side but may be
|
|
339
|
+
provided (optional).
|
|
340
|
+
properties:
|
|
341
|
+
name: { type: string }
|
|
342
|
+
description: { type: string }
|
|
343
|
+
polygon:
|
|
344
|
+
$ref: "#/components/schemas/GeoZonePolygon"
|
|
345
|
+
disabled:
|
|
346
|
+
type: boolean
|
|
347
|
+
description: "Soft-delete / deactivation flag. Setting `true` is rejected while any rep is still assigned to this zone."
|
|
348
|
+
editor:
|
|
349
|
+
$ref: "#/components/schemas/GeoZoneEditor"
|