# Release Notes

## [unreleased](<>)

### Added

- add: LineTarget service and type; OAS YAML
- add: TargetRule, Plan, and Calendar services and types; OAS YAMLs for each
- add: Automatic retry logic for HTTP requests with exponential backoff (default: 3 attempts, configurable via `retryAttempts` option)
- add: `retryAttempts` option to SDK constructor for configuring retry behavior @mkhamis
- add: 401 error protection - authentication errors are never retried @mkhamis
- add: asset-part-type, asset-part, asset-part-unit, asset-part-transfer, asset-part-receival, return-asset-part-unit & store-asset-part-unit @maramalshen
- update adjustInventory @maramalshen
- update FullInvoice with ubl keys @maramalshen
- add: approval-request @maramalshen
- add: workorder-request @maramalshen
- add: approval @maramalshen
- add: apps-management, reset-company-namespace & test-reset-company-namespace @maramalshen
- add: `rep_can_edit_invoice_discount` & `rep_can_edit_sales_order_discount` to RepPermissions and the Rep find-params filters — gate the header discount overwrite (`overwriteDeductionFixed`/`overwriteDeductionRatio`) on invoices and Sales Orders @mkhamis
- add: header total `total_before_deduction_and_tax` (+ `pre_`/`return_` legs) on FullInvoice, Proforma and Cart (Schema, CreateBody, UpdateBody) — `total_before_tax + totalDeductionBeforeTax`, i.e. the net-of-tax subtotal before the cart (header) deduction; net of tax for inclusive-tax lines too, unlike `taxable_subtotal`. The Proforma types were also missing the `total_before_tax` / `pre_` / `return_` trio the backend has stored all along, so those are added alongside @mkhamis
- add: geo-zone (GeoZone) service and types — `find`/`get`/`create`/`update`/`remove`, `inject_assigned_reps` on find/get, GeoJSON `Polygon` (`{ type: "Polygon"; coordinates }`) with server-side ring validation, soft-delete via `disabled`, and the server-stamped `editor` audit object; `NotificationsCenter.Command` gains `update-geo-zone`; OAS `geo-zone.yaml`
- add: Rep `assigned_geo_zones` (RepSchema, RepBody, find-params filter, populated keys, RepWithPopulatedKeysSchema) — links a rep to geo zone(s) (currently at most one); OAS `rep.yaml`
- add: `rep_can_start_visit_out_of_geofence` & `rep_can_create_approval_request_to_start_visit_out_of_geofence` to RepPermissions and the Rep find-params filters — gate starting a visit while outside the geofence / assigned geo zone
- add: Settings geo-zone enforcement fields — `start_day_outside_active_zone_action` / `start_visit_outside_active_zone_action` / `work_outside_active_zone_action` (`monitor`/`warning`/`block`), `no_active_zone_action` (`allow`/`block`), `use_accuracy_radius_near_zone_boundary`, `zone_boundary_grace_minutes` (Settings.Data + UpdateBody); OAS `settings.yaml`
- add: bulkExport (BulkExport) service + types — `find` (list export jobs) and `create` (start an Excel/Parquet export job for ~50 entity types, keyed by `type`); mirrors `bulkImport` (the backend rejects get/update/patch/remove with 400); OAS `bulk-export.yaml`
- add: aiObjectDetectionDataset (AiObjectDetectionDataset) service + types — `find`/`get`/`create`/`update`/`remove`, filters by `dataset_labels`/`default_model`/`default_model_version` plus `populatedKeys` (`dataset_labels` / `default_model` / `default_model_version` → `*_populated`) and the `latest`/`null` sentinel that makes `default_model_version` track the model's `current_model_version` (soft-delete via `disabled`; backend rejects patch); OAS `ai-object-detection-dataset.yaml` @moalnatour
- add: aiObjectDetectionModel (AiObjectDetectionModel) service + types — `find`/`get`/`create`/`update`/`remove`, `train_settings[]`/`predict_settings[]`, `validation_size`/`test_size` split ratios and the auto-advancing `current_model_version` pointer (populate it with `populatedKeys=current_model_version` → `current_model_version_populated`, weights/train-data/confusion-matrix media populated in place; soft-delete via `disabled`; backend rejects patch); OAS `ai-object-detection-model.yaml` @moalnatour
- add: aiObjectDetectionModelVersion (AiObjectDetectionModelVersion) service + types — `find`/`get`/`create`/`remove` (backend rejects update/patch: a version is immutable), `create` stamps `creator`, assigns the per-model `version_code`, unions the datasets' labels into `dataset_labels`, sets `status: initiated` and queues the YOLO dataset-prep job (progress in `status`/`_errors`, output in `train_data`/`tasks_size`/`annotations_per_label`; `trained` + `metrics`/`model_stats` once weights upload via ul-hub); filters by `model`/`version_code`/`dataset`/`dataset_labels` and 19 `populatedKeys` (`model`, `dataset`, `dataset_labels`, `train_data`, weights and every plot/artifact media → `*_populated`); OAS `ai-object-detection-model-version.yaml` @moalnatour
- add: aiObjectDetectionModelVersionEpoch (AiObjectDetectionModelVersionEpoch) service + types — read-only `find`/`get`; `find` requires `model_version` and returns the whole run un-paginated in `_index` order (`{ data, total_result, summary }`, with per-epoch `train_loss_metrics`/`val_loss_metrics`/`performance_metrics`/`model_stats` and a derived `summary` of best vs final mAP/precision/recall and `final_generalization_gap`); rows are written by the Ultralytics HUB ingest, so the backend rejects create/update/patch/remove; OAS `ai-object-detection-model-version-epoch.yaml` @moalnatour
- add: aiObjectDetectionModelVersionTrainAgent (AiObjectDetectionModelVersionTrainAgent) service + types — `get(modelVersionId)` only (backend rejects find/create/update/patch/remove), returns the ordered Ultralytics bootstrap `steps[]` (`code_message` snippets: pinned `pip install ultralytics==8.4.114`, HUB-client training against Repzo's `ul-hub`, artifacts upload) plus `ultralytics_version`; OAS `ai-object-detection-model-version-train-agent.yaml` @moalnatour
- add: aiObjectDetectionLabel (AiObjectDetectionLabel) service + types — `find`/`get`/`create`/`update`/`remove`, filters by every product-side link (`variants`/`products`/`product_categories`/`product_subcategories`/`product_brands`/`product_groups`) plus `label_group`, `populatedKeys[]` on find/get (`<field>_populated`), `keyboard_shortcut`, `physical_size` (cm) for the dims reclassifier, soft-delete blocked while a dataset lists the label; OAS `ai-object-detection-label.yaml` @moalnatour
- add: aiObjectDetectionLabelGroup (AiObjectDetectionLabelGroup) service + types — `find`/`get`/`create`/`update`/`remove(id, { force? })`, sibling-label families for the dims reclassifier; delete is rejected while member labels remain unless `force=true` detaches them first; OAS `ai-object-detection-label-group.yaml` @moalnatour
- add: aiObjectDetectionCategory (AiObjectDetectionCategory) service + types — `find`/`get`/`create`/`update`/`remove(id, { force? })`, per-category `model_settings[]` auto-analysis recipes (`model`, optional `model_version` = latest, `config`) and tracked `labels[]`, `populatedKeys` `labels` / `model_settings.model` / `model_settings.model_version`; delete is rejected while sessions reference the category unless `force=true`; OAS `ai-object-detection-category.yaml` @moalnatour
- add: aiObjectDetectionSegment (AiObjectDetectionSegment) service + types — `find`/`get`/`create`/`update`/`remove`, reusable named label sets that share-of-shelf metrics reference (`labels` filter + `populatedKeys: ["labels"]`), server-stamped `creator`/`editor`, PUT requires a non-blank `name`, delete rejected while an active metric references the segment; OAS `ai-object-detection-segment.yaml` @moalnatour
- add: aiObjectDetectionLabelReport (AiObjectDetectionLabelReport) service + types — read-only `find` with two modes: `{ dataset, label, mode?: all|smart, ...item filters }` returns the label's per-dataset annotation-health `summary` + paginated `items[]` (`included_in_training`/`included_in_val` eligibility), and `{ mode: "dims", label, sample?, z_threshold?, ... }` returns the smart dims analyzer (MAD outlier rejection, proposed `physical_size` cm); OAS `ai-object-detection-label-report.yaml` @moalnatour
- add: aiObjectDetectionSettings (AiObjectDetectionSettings) service + types — `find`/`get`/`create`/`update`/`patch`/`remove`, the per-namespace ANALYZE-defaults knob bag (`analyze_config`, a free-form `SceneMathConfig` subset): one document per namespace, `find`/`get` never 404 (`is_default: true` + `{}` when unsaved), POST/PUT/PATCH upsert the same document (path id ignored), DELETE resets to factory defaults; responses are single objects, not paginated; OAS `ai-object-detection-settings.yaml` @moalnatour
- add: aiObjectDetectionDetectionSettings (AiObjectDetectionDetectionSettings) service + types — `find`/`get`/`create`/`update`/`patch`/`remove`, the per-namespace unified CAPTURE / frame warn-error limits / election / session-gate config the mobile pulls on session start: reads return the engine defaults deep-merged with the saved `overrides` (`config`), writes upsert a partial `DetectionConfigOverrides` (replacing the stored overrides), DELETE resets to defaults; single-object responses; OAS `ai-object-detection-detection-settings.yaml` @moalnatour
- add: aiObjectDetectionInference (AiObjectDetectionInference) service + types — `create` only (the backend rejects find/get/update/patch/remove with 400): runs trained (YOLO lambda) or zero-shot (Qwen-VL) detection on one task by `task_id`, resolves the model via `model_version`/`model`/dataset default, back-projects AR session frames (`world_position`, `ignore_reason`), runs the dims reclassifier + size gate, optionally saves an `auto` annotation group, and returns XAI (`explain` / `explain_only`); full `SceneMathConfig` knob typing; OAS `ai-object-detection-inference.yaml` @moalnatour
- add: aiObjectDetectionTask (AiObjectDetectionTask) service + types — `find`/`get`/`create`/`update`/`patch`/`remove`; filters `session`, `frame_meta.frame_id`, `task_dataset.dataset`, `annotated`, `annotated_label`, `annotation_status` (pending/confirmed/manual/auto_edited/auto) + created/updated ranges, 13 `populatedKeys` (top-level refs under `*_populated`, nested refs inline), bulk `patch(params, body)` with a `writeQuery[]` returning `{ nFound, nModified }`, full annotation-group / AR `frame_meta` / XAI typing; OAS `ai-object-detection-task.yaml` @moalnatour
- add: aiObjectDetectionSession (AiObjectDetectionSession) service + types — `find`/`get`/`create`/`update`/`patch`/`remove`, filters by `session_id`/`status`/`client`/`category`/`rep`/`visit_id`/`route`/`creator._id`/`inference_runs.model_version` + `from_/to_createdAt|updatedAt`, `populatedKeys` (`client`→`client_populated`, `category`→`category_populated`, in-place `inference_runs.model_version`/`objects.label_id`/`scene.point_cloud_media`), bulk `patch(params, { writeQuery })` → `{ nFound, nModified }`, `remove(id, { cascade })` also soft-deletes child tasks; OAS `ai-object-detection-session.yaml` @moalnatour
- add: activityAiObjectDetectionSessionFrame (ActivityAiObjectDetectionSessionFrame) service + types — `create` only (the AR frame intake: `media_id` + `client` + `meta_inline` upserts the parent session, materializes a task and returns `FrameResult`; `session_complete: true` flips the session to `uploaded` and fires the category auto-analysis, returning `SessionCompleteResult`); backend rejects find/get/update/patch/remove; OAS `activity-ai-object-detection-session-frame.yaml` @moalnatour
- add: aiObjectDetectionSessionAnalysis (AiObjectDetectionSessionAnalysis) service + types — `find`/`get`/`create`/`update`/`patch`/`remove`; `create` starts the async cross-frame fusion run for a `session` (returns the `pending` doc + `message`, poll until `status` is `success`/`failed`) or, with `recompute: "compose"` + `analysis`, recomposes shelves synchronously; full `SceneMathConfig` knobs, `objects[]`/`concluded_labels[]`/`detections[]` ledger/`funnel`/`shelf_composition`/`scene` result shapes; filters `session`/`model_version`/`status`/`creator._id` + `from_/to_createdAt|updatedAt`, in-place `populatedKeys`; bulk `patch(params, { writeQuery })`; OAS `ai-object-detection-session-analysis.yaml` @moalnatour
- add: aiObjectDetectionSessionElection (AiObjectDetectionSessionElection) service + types — `create` only (materializes an election-playground result as a NEW session: clones the source session with a `-E<n>` `session_id` + `source_session`, screens the elected `task_ids` against the error-tier limits, stamps `session_score`/`session_verdict`/`rejection_reasons`/`election_excluded` and duplicates the surviving tasks onto it); backend rejects find/get/update/patch/remove with MethodNotAllowed; OAS `ai-object-detection-session-election.yaml` @moalnatour
- add: aiObjectDetectionSessionInsight (AiObjectDetectionSessionInsight) service + types — `find({ session | analysis, include_objects?, include_adjacency? })`, `get(sessionId)` and `create(body)` (POST with up to 20 free-text/structured `questions` → `answers[]`); computed on read from the session's latest successful analysis — returns a single payload (not paginated) with `shelves[]`, `share_of_shelf`/`blocking` rollups per label/label-group/brand/category/subcategory/product, optional planogram `objects[]` and `adjacency[]`; backend rejects update/patch/remove; OAS `ai-object-detection-session-insight.yaml` @moalnatour
- add: aiObjectDetectionMetric (AiObjectDetectionMetric) service + types — `find`/`get`/`create`/`update`/`remove`, schema-strict planogram metric definitions (`adjacent_block` / `facings_count` / `on_shelf_availability` / `share_of_shelf` with per-type `args`), `find({ registry: true })` returns the type registry (`Find.RegistryResult`) instead of documents, `PUT` is a full re-definition (`type` + `args` required), soft-delete via `disabled`; OAS `ai-object-detection-metric.yaml` @moalnatour
- add: aiObjectDetectionMetricResult (AiObjectDetectionMetricResult) service + types — `find`/`get`/`create`/`update`/`remove`; per-(analysis, metric) results with the machine `computed` layer (strict per-type shapes incl. `SegmentOutput`) and the human `overwrite`/`flag`/`confirmed_edit` layer, effective `score`/`answer`/`ratio`, denormalized scan context; `create` = recalculate an analysis (`{ analysis, metrics? }` → evaluation summary), `update` = human override only, `populatedKeys` `metric`/`analysis`/`session`; OAS `ai-object-detection-metric-result.yaml` @moalnatour
- add: aiObjectDetectionMission (AiObjectDetectionMission) service + types — `find`/`get`/`create`/`update`/`remove`; weighted metric groups (`metrics[]` of `{ metric, weight }` required on create AND update, `min_score` completion threshold, optional `category`), `find({ scores_for: analysisId })` returns resolved per-mission scores with `assigned`/`via_sets`/`requirement_mode`/`completed` (`Find.ScoresResult`) instead of documents, soft-delete via `disabled`; OAS `ai-object-detection-mission.yaml` @moalnatour
- add: aiObjectDetectionMissionSet (AiObjectDetectionMissionSet) service + types — `find`/`get`/`create`/`update`/`remove`; named mission groups (`missions[]` of mission ids, required ≥ 1 on create AND update) that assignment rules target, `enabled` toggle, filters `_id`/`name`/`enabled`/`search`/`from_`+`to_` timestamps, soft-delete via `disabled`; OAS `ai-object-detection-mission-set.yaml` @moalnatour
- add: aiObjectDetectionMissionResults (AiObjectDetectionMissionResults) service + types — `find`/`get`/`update`/`remove` (no `create`: rows are written by the metric evaluator); one stored outcome per (session, mission) with effective `score`/`completed`, derived `flagged`, admin-only `update({ resolved })` review verdict, list defaults to a 30-day `from_time`/`to_time` window newest first, admin `rep` narrowing on find/get; OAS `ai-object-detection-mission-results.yaml` @moalnatour
- add: aiObjectDetectionAssignmentRule (AiObjectDetectionAssignmentRule) service + types — `find`/`get`/`create`/`update`/`remove`, a rule attaches mission sets (each with a `requirement_mode`) to clients through AND-ed `conditions` lines plus a `frequency` demand, filter by `mission_sets.mission_set` / `enabled` / `search`, soft-delete via `disabled` (PUT is a full re-validation and the backend rejects PATCH); OAS `ai-object-detection-assignment-rule.yaml` @moalnatour
- add: aiObjectDetectionAssignedMissions (AiObjectDetectionAssignedMissions) service + types — `find`/`get` (read-only, computed per client: `client` required, optional `rep` and device `visit` scope; `get(id)` treats the id as the client), returns every enabled rule with per-condition verdicts plus the assigned missions with `requirements[]`, the strictest `requirement_mode` and a business-day-windowed `done` flag; OAS `ai-object-detection-assigned-missions.yaml` @moalnatour
- add: objectDetectionAnalyticsReport (ObjectDetectionAnalyticsReport) service + types — `find` (legacy GET adapter) / `create` (V2 body: `view` metrics|segments, `anyOf[0].criteria` filters incl. label-attribute keys, `group`, `projection`, `options`), every read time-bounded (default last 30 days), drilldown-compatible query filters ride along on both verbs and `export=excel` queues the emailed report; OAS `object-detection-analytics-report.yaml` @moalnatour
- add: `object-detection-metrics` & `object-detection-segments` to the top-level `ReportType` union — the report column/sort rows returned by `objectDetectionAnalyticsReport` carry these `report_types` values @moalnatour

### Changed

- All HTTP methods (\_fetch, \_create, \_update, \_patch, \_delete) now support automatic retry with exponential backoff @mkhamis

### Fixed

### Removed

## [v1.0.0 (2022-03-14)](https://github.com/Repzo/repzo-ts.git)

### Added

- add files src/ [index, client, types], test/ [index] @maramalshen
- add Services: Product, Variant @maramalshen
- add Services: Category @maramalshen
- add Services: SubCategory, Brand, ProductGroup, measureunit, measureunitFamily, media, priceList, priceListItem, teams, Rep, Tag, warehouse, channel, paymentTerm, bank, customList, full_invoice, proforma, payment, cycle, transfer, AdjustInventory, inventory @maramalshen
- update Product schema with populatedKeys @maramalshen
- add ActionLogs, CommandLog, ReturnReason @maramalshen
- add IntegrationApp @maramalshen
- add new Action: Refund @maramalshen
- update setStatus.error @maramalshen
- update payment.listOfAcceptedKeys @maramalshen
- add Service: BankList @maramalshen
- Update JoinActionsWeHook.JoinData @maramalshen
- Patch Action @maramalshen
- UpdateIntegrationMeta @maramalshen
- update type of patchAction.writeQuery @maramalshen
- update item.promotions schema @maramalshen

### Changed

### Fixed

### Removed

## [unreleased (date)](path)
