Saltar al contenido principal

Entity Parameters

Overview

The Entity Parameters module provides a flexible key-value configuration and feature-flag system. It allows business-level and entity-level (e.g., location) parameter overrides by linking entries from a Parameter Catalog to specific entities.

Architecture

entity-parameters/
├── entity-parameters.module.ts # NestJS module (DI wiring)
├── domain/
│ └── entity-parameters-repository.domain.ts # Port interface + DI token + parseBooleanParameterValue
├── application/
│ └── entity-parameters.service.ts # Use cases (CRUD + getBooleanForBusiness)
├── infrastructure/
│ ├── entity-parameters.repository.ts # Kysely DB adapter
│ └── feature-parameter.guard.ts # LoyaltyEnabledGuard, StoreCreditEnabledGuard
└── interfaces/
├── entity-parameters.controller.ts # REST endpoints (/entity-parameters)
├── dtos/
│ ├── create-entity-parameter.dto.ts
│ └── update-entity-parameter.dto.ts
└── query/
└── paginate-entity-parameters.query.ts

Dependency flow: Controller -> Service -> Repository (via domain port)

Domain Concepts

Parameter Catalog

A catalog of available parameters (e.g., LOYALTY_ENABLED, BARCODE_SCAN_INPUT_ENABLED). Each entry defines:

  • code — unique parameter key
  • dataType — expected type (boolean, string, number)
  • entityType — scope level (business, location)
  • defaultValue / allowedValues — constraints

Entity Parameter

A concrete assignment of a catalog parameter to a business entity:

  • parameterCatalogId — links to the catalog entry
  • parameterValue — JSON object, convention: { "value": <actual_value> }
  • businessId — owning business
  • entityType + entityId — target entity (null entityId = business-wide default)

Priority Resolution

When resolving a parameter value for a business:

  1. Specific entity match (entityId = businessId) takes priority
  2. Business-wide default (entityId = null) is the fallback
  3. null if no parameter is set

Feature Guards

The module exports two NestJS guards for feature-gating:

GuardParameter CodePurpose
LoyaltyEnabledGuardLOYALTY_ENABLEDGates loyalty program endpoints
StoreCreditEnabledGuardSTORE_CREDIT_ENABLEDGates store credit endpoints

Both guards resolve businessId from: Firebase claims -> request body -> query params -> locationId DB lookup.

Available Parameter Codes

CodeTypeEntity TypeDescription
SERVICE_BOOKING_ENABLEDbooleanbusinessEnable service booking
SERVICE_BOOKING_REQUIREDbooleanbusinessRequire service booking in documents
ASSIGN_CUSTOMER_FROM_BOOKING_PLATFORMbooleanbusinessAuto-assign booking customer
CASH_REGISTER_DISCREPANCY_APPROVAL_THRESHOLDnumberbusinessApproval threshold amount
CASH_REGISTER_CASH_OUT_APPROVAL_THRESHOLDnumberbusinessCash-out threshold amount
REQUIRE_CASH_REGISTER_SESSION_FOR_ADD_DOCUMENTbooleanbusinessRequire cash session for docs
LOYALTY_ENABLEDbooleanbusinessEnable loyalty program
STORE_CREDIT_ENABLEDbooleanbusinessEnable store credit wallet
BARCODE_SCAN_INPUT_ENABLEDbooleanlocationEnable barcode scan input

API Endpoints

All endpoints require Bearer token authentication.

MethodPathDescription
POST/entity-parametersCreate entity parameter
GET/entity-parametersList with pagination/search
GET/entity-parameters/:idGet by ID
PATCH/entity-parameters/:idUpdate (partial)
DELETE/entity-parameters/:idDelete

Create Entity Parameter

POST /entity-parameters
{
"parameterCatalogId": "<uuid>",
"parameterValue": { "value": true },
"businessId": "<uuid>",
"isActive": true,
"createdBy": "<uuid>",
"entityType": "business",
"entityId": "<uuid or omit for business-wide>"
}

List Entity Parameters

GET /entity-parameters?businessId=<uuid>&page=1&size=20&search=LOYALTY

Update Entity Parameter

PATCH /entity-parameters/:id
{
"parameterValue": { "value": false },
"updatedBy": "<uuid>"
}

Design Decisions

  1. Parameter values are JSON objects ({ "value": ... }) rather than raw primitives — this allows future extension with metadata (e.g., { "value": true, "overriddenAt": "..." }).

  2. parseBooleanParameterValue lives in the domain layer — it encodes business rules about how to interpret parameter values and is framework-agnostic.

  3. Repository is injected via DI token (ENTITY_PARAMETERS_REPOSITORY Symbol) — the service depends on the domain port interface, not the concrete Kysely implementation.

  4. Feature guards use shared resolveBusinessId helper — centralizes the multi-source businessId resolution logic.