{"openapi":"3.0.0","paths":{"/api/v1/tenants":{"get":{"operationId":"TenantController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"status","required":false,"in":"query","description":"Filter by tenant status (e.g. ACTIVE, SUSPENDED)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TenantEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all tenants","tags":["Tenants"]}},"/api/v1/tenants/{id}":{"get":{"operationId":"TenantController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TenantEntity"}}}]}}}},"404":{"description":"Tenant not found."}},"security":[{"bearer":[]}],"summary":"Get a tenant by ID","tags":["Tenants"]},"patch":{"operationId":"TenantController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TenantEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a tenant","tags":["Tenants"]}},"/api/v1/users":{"post":{"operationId":"UserController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UserEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new user","tags":["Users"]},"get":{"operationId":"UserController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"status","required":false,"in":"query","description":"Filter by user status (e.g. ACTIVE, SUSPENDED)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UserEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all users","tags":["Users"]}},"/api/v1/users/{id}":{"get":{"operationId":"UserController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UserEntity"}}}]}}}},"404":{"description":"User not found."}},"security":[{"bearer":[]}],"summary":"Get a user by ID","tags":["Users"]},"patch":{"operationId":"UserController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UserEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a user","tags":["Users"]},"delete":{"operationId":"UserController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UserEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a user","tags":["Users"]}},"/api/v1/auth/signin":{"post":{"description":"The tenant is taken from the account, so no tenantId is sent. Pass branchId to start in a specific branch; otherwise the branch is auto-selected when the user has exactly one, and `access[]` lists every branch they may switch to.","operationId":"AuthController_signIn_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignInDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoginResponseDto"}}}]}}}},"201":{"description":""},"401":{"description":"Invalid credentials, the account is not active, or its tenant is suspended, inactive or deleted."},"429":{"description":"Too many login attempts."}},"summary":"Sign in","tags":["Auth"]}},"/api/v1/auth/set-active-branch":{"post":{"operationId":"AuthController_setActiveBranch_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetActiveBranchDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoginResponseDto"}}}]}}}},"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Switch the active branch, re-issuing the token for that branch","tags":["Auth"]}},"/api/v1/auth/session":{"get":{"operationId":"AuthController_getSession_v1","parameters":[],"responses":{"200":{"description":"Return current user info."}},"security":[{"bearer":[]}],"summary":"Get current session info","tags":["Auth"]}},"/api/v1/system-admin/tenants/onboard":{"post":{"operationId":"SystemAdminController_onboardTenant_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardTenantDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/OnboardTenantResponseDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardTenantResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Onboard a new tenant: creates the tenant, a branch, its enabled modules, starter roles and the owner user in one transaction","tags":["System Admin"]}},"/api/v1/system-admin/tenants/{id}/modules":{"get":{"operationId":"SystemAdminController_getTenantModules_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TenantModulesDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Read which modules a tenant may build roles from","tags":["System Admin"]},"put":{"operationId":"SystemAdminController_setTenantModules_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantModulesDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SetTenantModulesResultDto"}}}]}}}},"400":{"description":"Unknown module name, or the tenant does not exist."}},"security":[{"bearer":[]}],"summary":"Set which modules a tenant may build roles from. Disabling a module strips its permissions from the tenant’s roles.","tags":["System Admin"]}},"/api/v1/system-admin/tenants/{id}":{"delete":{"operationId":"SystemAdminController_removeTenant_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenant deleted successfully."}},"security":[{"bearer":[]}],"summary":"Delete a tenant and all its data","tags":["System Admin"]}},"/api/v1/system-admin/users":{"post":{"operationId":"SystemAdminController_createUser_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserAsAdminDto"}}}},"responses":{"201":{"description":"User created successfully."}},"security":[{"bearer":[]}],"summary":"Create a user with explicit tenant context","tags":["System Admin"]}},"/api/v1/system-admin/roles/assign-permissions":{"post":{"operationId":"SystemAdminController_assignPermissionsToRole_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignPermissionToRoleDto"}}}},"responses":{"201":{"description":"Permissions assigned successfully."}},"security":[{"bearer":[]}],"summary":"Assign permissions to a role","tags":["System Admin"]}},"/api/v1/system-admin/users/assign-role":{"post":{"operationId":"SystemAdminController_assignRoleToUser_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleToUserDto"}}}},"responses":{"201":{"description":"Role assigned successfully."}},"security":[{"bearer":[]}],"summary":"Assign a role to a user at a branch","tags":["System Admin"]}},"/api/v1/branches":{"post":{"operationId":"BranchController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBranchDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BranchEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new branch","tags":["Branches"]},"get":{"operationId":"BranchController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"status","required":false,"in":"query","description":"Filter by branch status (e.g. ACTIVE, INACTIVE)","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by branch type (e.g. RETAIL, WAREHOUSE)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BranchEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all branches","tags":["Branches"]}},"/api/v1/branches/{id}":{"get":{"operationId":"BranchController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BranchEntity"}}}]}}}},"404":{"description":"Branch not found."}},"security":[{"bearer":[]}],"summary":"Get a branch by ID","tags":["Branches"]},"patch":{"operationId":"BranchController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBranchDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BranchEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a branch","tags":["Branches"]},"delete":{"operationId":"BranchController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BranchEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a branch","tags":["Branches"]}},"/api/v1/roles":{"post":{"operationId":"RoleController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RoleEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new role in your tenant","tags":["Roles"]},"get":{"operationId":"RoleController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RoleEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all roles","tags":["Roles"]}},"/api/v1/roles/available-permissions":{"get":{"operationId":"RoleController_availablePermissions_v1","parameters":[{"name":"search","required":false,"in":"query","description":"Filter by module:subject:action substring.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PermissionEntity"}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List the permissions your tenant may assign, based on its enabled modules","tags":["Roles"]}},"/api/v1/roles/{id}":{"get":{"operationId":"RoleController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RoleEntity"}}}]}}}},"404":{"description":"Role not found."}},"security":[{"bearer":[]}],"summary":"Get a role by ID","tags":["Roles"]},"patch":{"operationId":"RoleController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RoleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Rename or re-parent a role","tags":["Roles"]},"delete":{"operationId":"RoleController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RoleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a role","tags":["Roles"]}},"/api/v1/roles/{id}/permissions":{"post":{"operationId":"RoleController_assignPermissions_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignPermissionToRoleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RolePermissionsResultDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RolePermissionsResultDto"}}}},"403":{"description":"A permission is outside the tenant’s modules, or you do not hold it yourself."}},"security":[{"bearer":[]}],"summary":"Add permissions to a role, keeping the ones it already has","tags":["Roles"]},"put":{"operationId":"RoleController_setPermissions_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetRolePermissionsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RolePermissionsResultDto"}}}]}}}},"403":{"description":"A permission is outside the tenant’s modules, or you do not hold it yourself."}},"security":[{"bearer":[]}],"summary":"Set the role’s permissions to exactly this list, removing anything else","tags":["Roles"]}},"/api/v1/permissions":{"get":{"operationId":"PermissionController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PermissionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get the permissions available to you. Tenants see only the modules they have enabled.","tags":["Permissions"]}},"/api/v1/categories":{"post":{"operationId":"CategoryController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCategoryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CategoryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new category","tags":["Categories"]},"get":{"operationId":"CategoryController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CategoryEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all categories (paginated)","tags":["Categories"]}},"/api/v1/categories/tree":{"get":{"operationId":"CategoryController_findTree_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CategoryEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get category tree (nested children)","tags":["Categories"]}},"/api/v1/categories/{id}":{"get":{"operationId":"CategoryController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CategoryEntity"}}}]}}}},"404":{"description":"Category not found."}},"security":[{"bearer":[]}],"summary":"Get a category by ID","tags":["Categories"]},"patch":{"operationId":"CategoryController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCategoryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CategoryEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a category","tags":["Categories"]},"delete":{"operationId":"CategoryController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CategoryEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a category","tags":["Categories"]}},"/api/v1/uom-classes":{"post":{"operationId":"UomClassController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUomClassDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomClassEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UomClassEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new UOM class","tags":["UOM Classes"]},"get":{"operationId":"UomClassController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UomClassEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all UOM classes","tags":["UOM Classes"]}},"/api/v1/uom-classes/{id}":{"get":{"operationId":"UomClassController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomClassEntity"}}}]}}}},"404":{"description":"UOM class not found."}},"security":[{"bearer":[]}],"summary":"Get a UOM class by ID","tags":["UOM Classes"]},"patch":{"operationId":"UomClassController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUomClassDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomClassEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a UOM class","tags":["UOM Classes"]},"delete":{"operationId":"UomClassController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomClassEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a UOM class","tags":["UOM Classes"]}},"/api/v1/uoms":{"post":{"operationId":"UomController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUomDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UomEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new UOM","tags":["UOMs"]},"get":{"operationId":"UomController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"classId","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UomEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all UOMs","tags":["UOMs"]}},"/api/v1/uoms/{id}":{"get":{"operationId":"UomController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomEntity"}}}]}}}},"404":{"description":"UOM not found."}},"security":[{"bearer":[]}],"summary":"Get a UOM by ID","tags":["UOMs"]},"patch":{"operationId":"UomController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUomDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a UOM","tags":["UOMs"]},"delete":{"operationId":"UomController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UomEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a UOM","tags":["UOMs"]}},"/api/v1/products":{"post":{"operationId":"ProductController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProductDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new product","tags":["Products"]},"get":{"operationId":"ProductController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"categoryId","required":false,"in":"query","description":"Filter by category ID","schema":{"format":"uuid","type":"string"}},{"name":"trackingType","required":false,"in":"query","description":"Filter by tracking type (e.g. STANDARD, SERIALIZED)","schema":{"type":"string"}},{"name":"inStockOnly","required":false,"in":"query","description":"If true, return only products whose total on-hand stock is greater than 0","schema":{"type":"boolean"}},{"name":"locationId","required":false,"in":"query","description":"Scope stock computation to this location (applies to inStockOnly filter and totalOnHand enrichment)","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProductEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all products","tags":["Products"]}},"/api/v1/products/{id}":{"get":{"operationId":"ProductController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductEntity"}}}]}}}},"404":{"description":"Product not found."}},"security":[{"bearer":[]}],"summary":"Get a product by ID","tags":["Products"]},"patch":{"operationId":"ProductController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProductDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a product","tags":["Products"]},"delete":{"operationId":"ProductController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a product","tags":["Products"]}},"/api/v1/products/{productId}/variants":{"post":{"operationId":"ProductVariantController_create_v1","parameters":[{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProductVariantDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductVariantEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductVariantEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new product variant","tags":["Product Variants"]},"get":{"operationId":"ProductVariantController_findAll_v1","parameters":[{"name":"productId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProductVariantEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all variants for a product","tags":["Product Variants"]}},"/api/v1/products/{productId}/variants/{id}":{"get":{"operationId":"ProductVariantController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductVariantEntity"}}}]}}}},"404":{"description":"Product variant not found."}},"security":[{"bearer":[]}],"summary":"Get a product variant by ID","tags":["Product Variants"]},"patch":{"operationId":"ProductVariantController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProductVariantDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductVariantEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a product variant","tags":["Product Variants"]},"delete":{"operationId":"ProductVariantController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ProductVariantEntity"}}}]}}}},"400":{"description":"Cannot delete the last variant of a product."},"404":{"description":"Product variant not found."}},"security":[{"bearer":[]}],"summary":"Delete a product variant","tags":["Product Variants"]}},"/api/v1/locations":{"post":{"operationId":"LocationController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLocationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LocationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new location","tags":["Locations"]},"get":{"operationId":"LocationController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LocationEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all locations (paginated)","tags":["Locations"]}},"/api/v1/locations/tree":{"get":{"operationId":"LocationController_findTree_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get location tree (nested subLocations)","tags":["Locations"]}},"/api/v1/locations/{id}":{"get":{"operationId":"LocationController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LocationEntity"}}}]}}}},"404":{"description":"Location not found."}},"security":[{"bearer":[]}],"summary":"Get a location by ID","tags":["Locations"]},"patch":{"operationId":"LocationController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLocationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a location","tags":["Locations"]},"delete":{"operationId":"LocationController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a location","tags":["Locations"]}},"/api/v1/vendors":{"post":{"operationId":"VendorController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVendorDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new vendor","tags":["Vendors"]},"get":{"operationId":"VendorController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VendorEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all vendors","tags":["Vendors"]}},"/api/v1/vendors/{id}":{"get":{"operationId":"VendorController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorEntity"}}}]}}}},"404":{"description":"Vendor not found."}},"security":[{"bearer":[]}],"summary":"Get a vendor by ID","tags":["Vendors"]},"patch":{"operationId":"VendorController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVendorDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a vendor","tags":["Vendors"]},"delete":{"operationId":"VendorController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a vendor","tags":["Vendors"]}},"/api/v1/transfer-orders":{"post":{"operationId":"TransferOrderController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransferOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new transfer order","tags":["Transfer Orders"]},"get":{"operationId":"TransferOrderController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TransferOrderEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all transfer orders","tags":["Transfer Orders"]}},"/api/v1/transfer-orders/{id}":{"get":{"operationId":"TransferOrderController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderEntity"}}}]}}}},"404":{"description":"Transfer order not found."}},"security":[{"bearer":[]}],"summary":"Get a transfer order by ID","tags":["Transfer Orders"]},"patch":{"operationId":"TransferOrderController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTransferOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a transfer order","tags":["Transfer Orders"]},"delete":{"operationId":"TransferOrderController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a transfer order","tags":["Transfer Orders"]}},"/api/v1/transfer-orders/{transferOrderId}/lines":{"post":{"operationId":"TransferOrderLineController_create_v1","parameters":[{"name":"transferOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransferOrderLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOrderLineEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new transfer order line","tags":["Transfer Order Lines"]},"get":{"operationId":"TransferOrderLineController_findAll_v1","parameters":[{"name":"transferOrderId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TransferOrderLineEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all lines for a transfer order","tags":["Transfer Order Lines"]}},"/api/v1/transfer-orders/{transferOrderId}/lines/{id}":{"get":{"operationId":"TransferOrderLineController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"transferOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderLineEntity"}}}]}}}},"404":{"description":"Transfer order line not found."}},"security":[{"bearer":[]}],"summary":"Get a transfer order line by ID","tags":["Transfer Order Lines"]},"patch":{"operationId":"TransferOrderLineController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"transferOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTransferOrderLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a transfer order line","tags":["Transfer Order Lines"]},"delete":{"operationId":"TransferOrderLineController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"transferOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TransferOrderLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a transfer order line","tags":["Transfer Order Lines"]}},"/api/v1/purchase-requisitions":{"post":{"operationId":"PurchaseRequisitionController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePurchaseRequisitionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseRequisitionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseRequisitionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new purchase requisition","tags":["Purchase Requisitions"]},"get":{"operationId":"PurchaseRequisitionController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseRequisitionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all purchase requisitions","tags":["Purchase Requisitions"]}},"/api/v1/purchase-requisitions/{id}":{"get":{"operationId":"PurchaseRequisitionController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseRequisitionEntity"}}}]}}}},"404":{"description":"Purchase requisition not found."}},"security":[{"bearer":[]}],"summary":"Get a purchase requisition by ID","tags":["Purchase Requisitions"]},"patch":{"operationId":"PurchaseRequisitionController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePurchaseRequisitionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseRequisitionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a purchase requisition","tags":["Purchase Requisitions"]},"delete":{"operationId":"PurchaseRequisitionController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseRequisitionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a purchase requisition","tags":["Purchase Requisitions"]}},"/api/v1/purchase-orders":{"post":{"operationId":"PurchaseOrderController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePurchaseOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseOrderEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new purchase order","tags":["Purchase Orders"]},"get":{"operationId":"PurchaseOrderController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrderEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all purchase orders","tags":["Purchase Orders"]}},"/api/v1/purchase-orders/{id}":{"get":{"operationId":"PurchaseOrderController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseOrderEntity"}}}]}}}},"404":{"description":"Purchase order not found."}},"security":[{"bearer":[]}],"summary":"Get a purchase order by ID","tags":["Purchase Orders"]},"patch":{"operationId":"PurchaseOrderController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePurchaseOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseOrderEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a purchase order","tags":["Purchase Orders"]},"delete":{"operationId":"PurchaseOrderController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PurchaseOrderEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a purchase order","tags":["Purchase Orders"]}},"/api/v1/goods-received-notes":{"post":{"operationId":"GoodsReceivedNoteController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGoodsReceivedNoteDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GoodsReceivedNoteEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceivedNoteEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new goods received note","tags":["Goods Received Notes"]},"get":{"operationId":"GoodsReceivedNoteController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GoodsReceivedNoteEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all goods received notes","tags":["Goods Received Notes"]}},"/api/v1/goods-received-notes/{id}":{"get":{"operationId":"GoodsReceivedNoteController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GoodsReceivedNoteEntity"}}}]}}}},"404":{"description":"Goods received note not found."}},"security":[{"bearer":[]}],"summary":"Get a goods received note by ID","tags":["Goods Received Notes"]},"patch":{"operationId":"GoodsReceivedNoteController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGoodsReceivedNoteDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GoodsReceivedNoteEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a goods received note","tags":["Goods Received Notes"]},"delete":{"operationId":"GoodsReceivedNoteController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GoodsReceivedNoteEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a goods received note","tags":["Goods Received Notes"]}},"/api/v1/goods-received-notes/{grnId}/lines":{"post":{"operationId":"GrnLineController_create_v1","parameters":[{"name":"grnId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGrnLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GrnLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrnLineEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new GRN line","tags":["GRN Lines"]},"get":{"operationId":"GrnLineController_findAll_v1","parameters":[{"name":"grnId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GrnLineEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all lines for a GRN","tags":["GRN Lines"]}},"/api/v1/goods-received-notes/{grnId}/lines/{id}":{"get":{"operationId":"GrnLineController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"grnId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GrnLineEntity"}}}]}}}},"404":{"description":"GRN line not found."}},"security":[{"bearer":[]}],"summary":"Get a GRN line by ID","tags":["GRN Lines"]},"patch":{"operationId":"GrnLineController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"grnId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGrnLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GrnLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a GRN line","tags":["GRN Lines"]},"delete":{"operationId":"GrnLineController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"grnId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GrnLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a GRN line","tags":["GRN Lines"]}},"/api/v1/vendor-invoices":{"post":{"operationId":"VendorInvoiceController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVendorInvoiceDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorInvoiceEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorInvoiceEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new vendor invoice","tags":["Vendor Invoices"]},"get":{"operationId":"VendorInvoiceController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VendorInvoiceEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all vendor invoices","tags":["Vendor Invoices"]}},"/api/v1/vendor-invoices/{id}":{"get":{"operationId":"VendorInvoiceController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorInvoiceEntity"}}}]}}}},"404":{"description":"Vendor invoice not found."}},"security":[{"bearer":[]}],"summary":"Get a vendor invoice by ID","tags":["Vendor Invoices"]},"patch":{"operationId":"VendorInvoiceController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVendorInvoiceDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorInvoiceEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a vendor invoice","tags":["Vendor Invoices"]},"delete":{"operationId":"VendorInvoiceController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VendorInvoiceEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a vendor invoice","tags":["Vendor Invoices"]}},"/api/v1/landed-cost-allocations":{"post":{"operationId":"LandedCostAllocationController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLandedCostAllocationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LandedCostAllocationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LandedCostAllocationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new landed cost allocation","tags":["Landed Cost Allocations"]},"get":{"operationId":"LandedCostAllocationController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LandedCostAllocationEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all landed cost allocations","tags":["Landed Cost Allocations"]}},"/api/v1/landed-cost-allocations/{id}":{"get":{"operationId":"LandedCostAllocationController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LandedCostAllocationEntity"}}}]}}}},"404":{"description":"Landed cost allocation not found."}},"security":[{"bearer":[]}],"summary":"Get a landed cost allocation by ID","tags":["Landed Cost Allocations"]},"patch":{"operationId":"LandedCostAllocationController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLandedCostAllocationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LandedCostAllocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a landed cost allocation","tags":["Landed Cost Allocations"]},"delete":{"operationId":"LandedCostAllocationController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LandedCostAllocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a landed cost allocation","tags":["Landed Cost Allocations"]}},"/api/v1/customers":{"post":{"operationId":"CustomerController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new customer","tags":["Customers"]},"get":{"operationId":"CustomerController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomerEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Search and list customers (search by phone, name, or email)","tags":["Customers"]}},"/api/v1/customers/{id}":{"get":{"operationId":"CustomerController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerEntity"}}}]}}}},"404":{"description":"Customer not found."}},"security":[{"bearer":[]}],"summary":"Get a customer by ID","tags":["Customers"]},"patch":{"operationId":"CustomerController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a customer","tags":["Customers"]},"delete":{"operationId":"CustomerController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a customer","tags":["Customers"]}},"/api/v1/loyalty-ledger":{"get":{"operationId":"LoyaltyLedgerGlobalController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"customerId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"transactionType","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all loyalty ledger entries (tenant-scoped, filterable)","tags":["Loyalty Ledger"]}},"/api/v1/loyalty-ledger/{id}":{"get":{"operationId":"LoyaltyLedgerGlobalController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}}}]}}}},"404":{"description":"Loyalty ledger entry not found."}},"security":[{"bearer":[]}],"summary":"Get a loyalty ledger entry by ID (tenant-scoped)","tags":["Loyalty Ledger"]}},"/api/v1/customers/{customerId}/loyalty-ledger":{"post":{"operationId":"LoyaltyLedgerController_create_v1","parameters":[{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLoyaltyLedgerDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new loyalty ledger entry","tags":["Loyalty Ledger"]},"get":{"operationId":"LoyaltyLedgerController_findAll_v1","parameters":[{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all loyalty ledger entries for a customer","tags":["Loyalty Ledger"]}},"/api/v1/customers/{customerId}/loyalty-ledger/{id}":{"get":{"operationId":"LoyaltyLedgerController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}}}]}}}},"404":{"description":"Loyalty ledger entry not found."}},"security":[{"bearer":[]}],"summary":"Get a loyalty ledger entry by ID","tags":["Loyalty Ledger"]},"patch":{"operationId":"LoyaltyLedgerController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLoyaltyLedgerDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a loyalty ledger entry","tags":["Loyalty Ledger"]},"delete":{"operationId":"LoyaltyLedgerController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoyaltyLedgerEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a loyalty ledger entry","tags":["Loyalty Ledger"]}},"/api/v1/customer-interactions":{"get":{"operationId":"CustomerInteractionGlobalController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"customerId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"interactionType","required":false,"in":"query","schema":{"type":"string"}},{"name":"interactionChannel","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomerInteractionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all customer interactions (tenant-scoped, filterable)","tags":["Customer Interactions"]}},"/api/v1/customer-interactions/{id}":{"get":{"operationId":"CustomerInteractionGlobalController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerInteractionEntity"}}}]}}}},"404":{"description":"Customer interaction not found."}},"security":[{"bearer":[]}],"summary":"Get a customer interaction by ID (tenant-scoped)","tags":["Customer Interactions"]}},"/api/v1/customers/{customerId}/interactions":{"post":{"operationId":"CustomerInteractionController_create_v1","parameters":[{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerInteractionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerInteractionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerInteractionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new customer interaction","tags":["Customer Interactions"]},"get":{"operationId":"CustomerInteractionController_findAll_v1","parameters":[{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomerInteractionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all interactions for a customer","tags":["Customer Interactions"]}},"/api/v1/customers/{customerId}/interactions/{id}":{"get":{"operationId":"CustomerInteractionController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerInteractionEntity"}}}]}}}},"404":{"description":"Customer interaction not found."}},"security":[{"bearer":[]}],"summary":"Get a customer interaction by ID","tags":["Customer Interactions"]},"patch":{"operationId":"CustomerInteractionController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerInteractionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerInteractionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a customer interaction","tags":["Customer Interactions"]},"delete":{"operationId":"CustomerInteractionController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"customerId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CustomerInteractionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a customer interaction","tags":["Customer Interactions"]}},"/api/v1/sales-orders":{"post":{"operationId":"SalesOrderController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSalesOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new sales order","tags":["Sales Orders"]},"get":{"description":"Drives the order tabs. `serviceType` narrows to one channel - TAKEAWAY for the take-away list. `waitingPickup=true` is the \"Waiting Pickup\" tab: orders with nothing left to prepare that nobody has collected yet, which is the same condition the pickup endpoint enforces, so every order listed can actually be picked up. Note this is separate from a line being PENDING, which means the opposite - the kitchen has not started it.","operationId":"SalesOrderController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"status","required":false,"in":"query","description":"Filter by order status (e.g. DRAFT, CONFIRMED, COMPLETED)","schema":{"type":"string"}},{"name":"customerId","required":false,"in":"query","description":"Filter by customer ID","schema":{"format":"uuid","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter orders from this date (ISO 8601)","schema":{"format":"date-time","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter orders until this date (ISO 8601)","schema":{"format":"date-time","type":"string"}},{"name":"serviceType","required":false,"in":"query","description":"Filter by how the order is served: DINE_IN, TAKEAWAY, DELIVERY, COUNTER.","schema":{"type":"string","enum":["DINE_IN","TAKEAWAY","DELIVERY","COUNTER"]}},{"name":"waitingPickup","required":false,"in":"query","description":"Only orders sitting on the counter waiting to be collected: nothing left to prepare and not yet picked up. Narrows to TAKEAWAY and COUNTER unless `serviceType` says otherwise. This is the same condition the pickup endpoint enforces, so anything listed here can actually be picked up.","schema":{"example":"true","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalesOrderEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all sales orders","tags":["Sales Orders"]}},"/api/v1/sales-orders/{id}/settle":{"post":{"description":"Settles an order that already exists, for the shape checkout cannot handle: a KTV room or a dining table, where the order is opened when the party sits down and lines land on it for hours. Prices the order from its lines as they stand, checks the payments cover it, takes the money and marks it COMPLETED. Same tender rules as checkout, guest cards included - a card tender may omit its amount and is charged the remainder.","operationId":"SalesOrderController_settle_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SettleOrderResponseDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleOrderResponseDto"}}}},"400":{"description":"Payments do not cover the bill, a credit limit is exceeded, or there is nothing on the order to pay for."},"409":{"description":"The order has already been paid, or is not a draft."}},"security":[{"bearer":[]}],"summary":"Pay a bill that was built up over time","tags":["Sales Orders"]}},"/api/v1/sales-orders/{id}":{"get":{"operationId":"SalesOrderController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderEntity"}}}]}}}},"404":{"description":"Sales order not found."}},"security":[{"bearer":[]}],"summary":"Get a sales order by ID","tags":["Sales Orders"]},"patch":{"operationId":"SalesOrderController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSalesOrderDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a sales order","tags":["Sales Orders"]},"delete":{"operationId":"SalesOrderController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a sales order","tags":["Sales Orders"]}},"/api/v1/sales-orders/{salesOrderId}/lines":{"post":{"operationId":"SalesOrderLineController_create_v1","parameters":[{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSalesOrderLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new sales order line","tags":["Sales Order Lines"]},"get":{"operationId":"SalesOrderLineController_findAll_v1","parameters":[{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SalesOrderLineEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all lines for a sales order","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/lines/{id}":{"get":{"operationId":"SalesOrderLineController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"404":{"description":"Sales order line not found."}},"security":[{"bearer":[]}],"summary":"Get a sales order line by ID","tags":["Sales Order Lines"]},"patch":{"operationId":"SalesOrderLineController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSalesOrderLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a sales order line","tags":["Sales Order Lines"]},"delete":{"operationId":"SalesOrderLineController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a sales order line","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/lines/{id}/fire":{"post":{"operationId":"SalesOrderLineController_fire_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}},"400":{"description":"Line is not in PENDING state."}},"security":[{"bearer":[]}],"summary":"Fire a line (PENDING → FIRED)","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/lines/{id}/ready":{"post":{"operationId":"SalesOrderLineController_ready_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}},"400":{"description":"Line is not in FIRED state."}},"security":[{"bearer":[]}],"summary":"Mark a line ready (FIRED → READY)","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/lines/{id}/serve":{"post":{"operationId":"SalesOrderLineController_serve_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}},"400":{"description":"Line is not in READY state."}},"security":[{"bearer":[]}],"summary":"Mark a line served (READY → SERVED)","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/lines/{id}/void":{"post":{"operationId":"SalesOrderLineController_voidLine_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}},"400":{"description":"Line is in a terminal state."}},"security":[{"bearer":[]}],"summary":"Void a line with a reason","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/lines/{id}/comp":{"post":{"operationId":"SalesOrderLineController_compLine_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesOrderLineEntity"}}}},"400":{"description":"Line is in a terminal state."}},"security":[{"bearer":[]}],"summary":"Comp a line with a discount reason","tags":["Sales Order Lines"]}},"/api/v1/sales-orders/{salesOrderId}/payments":{"post":{"operationId":"OrderPaymentController_create_v1","parameters":[{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderPaymentDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/OrderPaymentEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderPaymentEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new order payment","tags":["Order Payments"]},"get":{"operationId":"OrderPaymentController_findAll_v1","parameters":[{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OrderPaymentEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all payments for a sales order","tags":["Order Payments"]}},"/api/v1/sales-orders/{salesOrderId}/payments/{id}":{"get":{"operationId":"OrderPaymentController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/OrderPaymentEntity"}}}]}}}},"404":{"description":"Order payment not found."}},"security":[{"bearer":[]}],"summary":"Get an order payment by ID","tags":["Order Payments"]},"patch":{"operationId":"OrderPaymentController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrderPaymentDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/OrderPaymentEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update an order payment","tags":["Order Payments"]},"delete":{"operationId":"OrderPaymentController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/OrderPaymentEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete an order payment","tags":["Order Payments"]}},"/api/v1/promotion-rules":{"post":{"operationId":"PromotionRuleController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePromotionRuleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PromotionRuleEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionRuleEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new promotion rule","tags":["Promotion Rules"]},"get":{"operationId":"PromotionRuleController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PromotionRuleEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all promotion rules","tags":["Promotion Rules"]}},"/api/v1/promotion-rules/{id}":{"get":{"operationId":"PromotionRuleController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PromotionRuleEntity"}}}]}}}},"404":{"description":"Promotion rule not found."}},"security":[{"bearer":[]}],"summary":"Get a promotion rule by ID","tags":["Promotion Rules"]},"patch":{"operationId":"PromotionRuleController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePromotionRuleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PromotionRuleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a promotion rule","tags":["Promotion Rules"]},"delete":{"operationId":"PromotionRuleController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PromotionRuleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a promotion rule","tags":["Promotion Rules"]}},"/api/v1/checkout":{"post":{"description":"Creates the order and settles it in one call. Several entries in `payments` are a split tender. For a guest card, send the tapped card as `guestCardId` and leave `amount` out: only the server knows the tier discount, so the card covers whatever the bill comes to. At most one card tender may omit its amount. Paying on account is a payment method whose kind is CUSTOMER_CREDIT, plus `customerId` on the order. Reuse `idempotencyKey` when retrying after a network error and the original sale is returned rather than a second charge.","operationId":"CheckoutController_checkout_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CheckoutResponseDto"}}}]}}}},"400":{"description":"Payments do not cover the bill, a credit limit is exceeded, stock is short, or a card tender omitted its amount alongside another that also did."},"404":{"description":"A variant, customer, payment method or guest card was not found."},"409":{"description":"The wallet behind the card is busy - being settled, or charged by another till. Safe to retry with the same idempotency key."},"422":{"description":"The card cannot pay: not active, expired, or short of the amount. Only a postpaid card may go negative."}},"security":[{"bearer":[]}],"summary":"Ring up a sale and take payment","tags":["Checkout"]}},"/api/v1/checkout/{id}/void":{"post":{"description":"Reverses the whole sale: stock goes back, loyalty points are taken back, and anything paid by guest card is credited to the wallet. Only a COMPLETED order can be voided - once any part has been refunded it has a history to keep, and a return is the way to undo it.","operationId":"CheckoutController_voidSale_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CheckoutResponseDto"}}}]}}}},"404":{"description":"No COMPLETED order with that id in your tenant."}},"security":[{"bearer":[]}],"summary":"Void a completed sale","tags":["Checkout"]}},"/api/v1/receipts/{salesOrderId}":{"get":{"operationId":"ReceiptController_getReceipt_v1","parameters":[{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReceiptResponseDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get receipt for a completed sale","tags":["Receipts"]}},"/api/v1/refunds":{"post":{"operationId":"RefundController_processReturn_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessReturnDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReturnResponseDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Process a return/refund","tags":["Refunds"]}},"/api/v1/refunds/{id}":{"get":{"operationId":"RefundController_getReturn_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReturnResponseDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get return details by ID","tags":["Refunds"]}},"/api/v1/refunds/order/{salesOrderId}":{"get":{"operationId":"RefundController_getReturnsByOrder_v1","parameters":[{"name":"salesOrderId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReturnResponseDto"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List all returns for a sales order","tags":["Refunds"]}},"/api/v1/card-tiers":{"post":{"description":"Tiers are the hotel’s to define and change at any time. Editing one never affects cards already issued.","operationId":"CardTierController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCardTierDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CardTierEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CardTierEntity"}}}},"409":{"description":"A tier with that name already exists"}},"security":[{"bearer":[]}],"summary":"Create a card tier","tags":["Card Tiers"]},"get":{"operationId":"CardTierController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CardTierEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List card tiers","tags":["Card Tiers"]}},"/api/v1/card-tiers/{id}":{"get":{"operationId":"CardTierController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CardTierEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get a card tier","tags":["Card Tiers"]},"patch":{"description":"Affects cards issued from now on. Balances and terms on existing cards are untouched, because a wallet keeps the terms it was sold on.","operationId":"CardTierController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCardTierDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CardTierEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a card tier","tags":["Card Tiers"]},"delete":{"description":"Cards already issued against it keep working.","operationId":"CardTierController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CardTierEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Retire a card tier","tags":["Card Tiers"]}},"/api/v1/guest-wallets":{"post":{"description":"Creates the wallet, links every card supplied, applies the tier preload and records the cash, all in one transaction. The tier’s terms are copied onto the wallet, so later edits to the tier leave this guest alone.","operationId":"GuestWalletController_issue_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueWalletDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestWalletEntity"}}}},"409":{"description":"One of those cards is already in use"}},"security":[{"bearer":[]}],"summary":"Issue a wallet and its cards","tags":["Guest Wallets"]},"get":{"description":"Filter by `customerId` for every card a customer has ever been issued.","operationId":"GuestWalletController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GuestWalletEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List guest wallets","tags":["Guest Wallets"]}},"/api/v1/guest-wallets/{id}":{"get":{"operationId":"GuestWalletController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get a guest wallet","tags":["Guest Wallets"]}},"/api/v1/guest-wallets/{id}/cards":{"get":{"description":"A KTV room may hand out several, all spending one balance.","operationId":"GuestWalletController_findCards_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Cards drawing on this wallet","tags":["Guest Wallets"]}},"/api/v1/guest-wallets/{id}/ledger":{"get":{"description":"Every movement, newest first. Append-only: nothing here is ever edited.","operationId":"GuestWalletController_findLedger_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WalletLedgerEntryEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Wallet statement","tags":["Guest Wallets"]}},"/api/v1/guest-wallets/{id}/audit":{"get":{"description":"Replays every entry and compares the result with the stored balance. Reports drift; never repairs it, because a silent correction would destroy the evidence that something wrote a wrong number.","operationId":"GuestWalletController_audit_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Check a wallet against its ledger","tags":["Guest Wallets"]}},"/api/v1/guest-wallets/{id}/top-up":{"post":{"description":"Works on every tier. A mobile wallet transfer is refused without a reference.","operationId":"GuestWalletController_topUp_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopUpWalletDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WalletLedgerEntryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletLedgerEntryEntity"}}}},"409":{"description":"The wallet is being settled"}},"security":[{"bearer":[]}],"summary":"Add value to a wallet","tags":["Guest Wallets"]}},"/api/v1/guest-wallets/{id}/settlement-quote":{"get":{"description":"Read-only and safe to poll. Drive the checkout screen off `action` and `blockers` rather than re-deriving them from the balance.","operationId":"WalletSettlementController_quote_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SettlementQuoteDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"What closing this wallet would take","tags":["Guest Wallet Settlement"]}},"/api/v1/guest-wallets/{id}/begin-settlement":{"post":{"description":"Stops the card being spent while the desk counts the guest out. Without this their friend could buy a round at the bar mid-count, and the refund would be paid against a balance that had already moved.","operationId":"WalletSettlementController_begin_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestWalletEntity"}}}}},"security":[{"bearer":[]}],"summary":"Begin settling a wallet","tags":["Guest Wallet Settlement"]}},"/api/v1/guest-wallets/{id}/cancel-settlement":{"post":{"description":"For a guest who decides to stay after all.","operationId":"WalletSettlementController_cancel_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestWalletEntity"}}}}},"security":[{"bearer":[]}],"summary":"Return a wallet to spendable","tags":["Guest Wallet Settlement"]}},"/api/v1/guest-wallets/{id}/settle":{"post":{"description":"Forfeits promotional value, refunds the guest’s own money, collects what a postpaid card owes, retires the cards and closes the account - all at once. A wallet holding anything cannot close; the database refuses it outright.","operationId":"WalletSettlementController_settle_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-approver-authorization","in":"header","description":"The approving manager’s own bearer token, obtained by signing in on this terminal. Must be a different person from the one making the request.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleWalletDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestWalletEntity"}}}},"409":{"description":"The guest still has an open bill"},"422":{"description":"A postpaid card owes money that has not been collected"}},"security":[{"bearer":[]}],"summary":"Settle and close a wallet","tags":["Guest Wallet Settlement"]}},"/api/v1/guest-wallets/{id}/refund":{"post":{"description":"For a guest who wants cash back mid-stay and carries on spending. Only their own money can be returned - promotional value is never paid out.","operationId":"WalletSettlementController_refund_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-approver-authorization","in":"header","description":"The approving manager’s own bearer token, obtained by signing in on this terminal. Must be a different person from the one making the request.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundWalletDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestWalletEntity"}}}},"422":{"description":"More was asked for than the guest actually put in"}},"security":[{"bearer":[]}],"summary":"Hand back part of a balance without closing","tags":["Guest Wallet Settlement"]}},"/api/v1/guest-wallets/{id}/void":{"post":{"description":"Only while it is untouched. Anything else is a real history that has to be settled rather than erased.","operationId":"WalletSettlementController_voidWallet_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-approver-authorization","in":"header","description":"The approving manager’s own bearer token, obtained by signing in on this terminal. Must be a different person from the one making the request.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestWalletEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestWalletEntity"}}}}},"security":[{"bearer":[]}],"summary":"Void a wallet issued in error","tags":["Guest Wallet Settlement"]}},"/api/v1/guest-cards/lookup":{"get":{"description":"What a till calls when a card is tapped. Returns the card and the wallet it draws on, for display. Never decide affordability from this: the balance can change between the lookup and the tender, and the server rechecks under a lock.","operationId":"GuestCardController_lookup_v1","parameters":[{"name":"cardUid","required":true,"in":"query","schema":{"example":"04A3B2C1","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}},"404":{"description":"No active card with that UID"}},"security":[{"bearer":[]}],"summary":"Look up a card by its UID","tags":["Guest Cards"]}},"/api/v1/guest-cards":{"post":{"description":"For a room where several guests each carry a card on one balance.","operationId":"GuestCardController_link_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkCardDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCardEntity"}}}},"409":{"description":"That card is already active elsewhere"}},"security":[{"bearer":[]}],"summary":"Link another card to a wallet","tags":["Guest Cards"]},"get":{"operationId":"GuestCardController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GuestCardEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List guest cards","tags":["Guest Cards"]}},"/api/v1/guest-cards/{id}":{"get":{"operationId":"GuestCardController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get a guest card","tags":["Guest Cards"]},"delete":{"description":"Used at checkout. Frees the UID for the next guest.","operationId":"GuestCardController_deactivate_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Take a card out of use","tags":["Guest Cards"]}},"/api/v1/guest-cards/{id}/report-lost":{"post":{"description":"Stops the card paying immediately. It does NOT cancel the room key - the door lock is a separate system and must be cancelled there too, or the card still opens the room.","operationId":"GuestCardController_reportLost_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCardEntity"}}}}},"security":[{"bearer":[]}],"summary":"Report a card lost","tags":["Guest Cards"]}},"/api/v1/guest-cards/{id}/replace":{"post":{"description":"Issues a new card on the same wallet. The balance is untouched and no ledger entry is written, because the money was never on the card.","operationId":"GuestCardController_replace_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceCardDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/GuestCardEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCardEntity"}}}}},"security":[{"bearer":[]}],"summary":"Replace a lost card","tags":["Guest Cards"]}},"/api/v1/reports/guest-card/daily-cash":{"get":{"description":"Deposits and sales are reported side by side and never summed. A top-up is money held for a guest, not money earned; adding them together tells a property it made revenue it has merely been handed.","operationId":"GuestCardReportController_dailyCash_v1","parameters":[{"name":"locationId","required":false,"in":"query","schema":{}},{"name":"businessDate","required":false,"in":"query","schema":{"example":"2026-09-12"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Cash in and out for a day","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/revenue":{"get":{"description":"Recognised when a guest spends, not when they pay in. Top-ups cannot appear here: they have no sales order to be counted against.","operationId":"GuestCardReportController_revenue_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Revenue by outlet","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/liability":{"get":{"description":"The balance-sheet number, split by funding. Purchased value is a real debt that leaves in cash at checkout; granted value is a marketing cost that is mostly forfeited.","operationId":"GuestCardReportController_liability_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Unspent guest money","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/open-wallets":{"get":{"description":"With ages. A wallet open a month is not a guest still here - it is an account somebody forgot to close.","operationId":"GuestCardReportController_openWallets_v1","parameters":[{"name":"olderThanDays","required":false,"in":"query","schema":{"example":7}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Wallets still open","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/negative-balances":{"get":{"description":"Must be empty before those guests leave, which is why a negative wallet cannot be closed.","operationId":"GuestCardReportController_negativeBalances_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Postpaid cards in debt","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/refunds":{"get":{"description":"Grouped by both. One cashier’s refunds are a workload; the same cashier and the same approver together, repeatedly, is a pattern worth looking at.","operationId":"GuestCardReportController_refunds_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Refunds by staff and approver","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/tier-usage":{"get":{"operationId":"GuestCardReportController_tierUsage_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Spending by tier, as the cards were sold","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/lost-cards":{"get":{"operationId":"GuestCardReportController_lostCards_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Lost cards and their replacements","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/shift-reconciliation":{"get":{"description":"Expected cash counts top-ups and refunds as well as sales, because those notes are in the same drawer. Flags any closed session whose variance was never approved.","operationId":"GuestCardReportController_shiftReconciliation_v1","parameters":[{"name":"businessDate","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Shift reconciliation","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/audit":{"get":{"description":"Every ledger entry summed must equal every wallet balance summed, each wallet must replay to its cached balance with a gap-free sequence, and each entry must follow from the one before. Records what does not add up and never repairs it - a silent correction destroys the evidence. A system admin gets one result per tenant, because the equation has to hold in each hotel on its own.","operationId":"GuestCardReportController_runAudit_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Run the audit equation","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/discrepancies":{"get":{"operationId":"GuestCardReportController_discrepancies_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"security":[{"bearer":[]}],"summary":"Discrepancies nobody has dealt with yet","tags":["Guest Card Reports"]}},"/api/v1/reports/guest-card/discrepancies/{id}/resolve":{"post":{"description":"Records that somebody understood it. Correcting the balance itself is a separate adjustment entry needing a manager’s approval.","operationId":"GuestCardReportController_resolve_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearer":[]}],"summary":"Mark a discrepancy dealt with","tags":["Guest Card Reports"]}},"/api/v1/pos-registers":{"post":{"operationId":"PosRegisterController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePosRegisterDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosRegisterEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosRegisterEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new POS register","tags":["POS Registers"]},"get":{"operationId":"PosRegisterController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PosRegisterEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all POS registers","tags":["POS Registers"]}},"/api/v1/pos-registers/{id}":{"get":{"operationId":"PosRegisterController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosRegisterEntity"}}}]}}}},"404":{"description":"POS register not found."}},"security":[{"bearer":[]}],"summary":"Get a POS register by ID","tags":["POS Registers"]},"patch":{"operationId":"PosRegisterController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePosRegisterDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosRegisterEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a POS register","tags":["POS Registers"]},"delete":{"operationId":"PosRegisterController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosRegisterEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a POS register","tags":["POS Registers"]}},"/api/v1/pos-sessions":{"post":{"operationId":"PosSessionController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePosSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSessionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new POS session","tags":["POS Sessions"]},"get":{"operationId":"PosSessionController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PosSessionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all POS sessions","tags":["POS Sessions"]}},"/api/v1/pos-sessions/{id}":{"get":{"operationId":"PosSessionController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosSessionEntity"}}}]}}}},"404":{"description":"POS session not found."}},"security":[{"bearer":[]}],"summary":"Get a POS session by ID","tags":["POS Sessions"]},"patch":{"operationId":"PosSessionController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePosSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosSessionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a POS session","tags":["POS Sessions"]},"delete":{"operationId":"PosSessionController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PosSessionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a POS session","tags":["POS Sessions"]}},"/api/v1/pos-sessions/{id}/close":{"post":{"description":"Expected cash counts guest-card top-ups and refunds as well as sales, since those notes are in the drawer too. A drawer that does not balance needs a manager to sign the difference off, and who signed it is recorded.","operationId":"PosSessionController_closeSession_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-approver-authorization","in":"header","description":"A manager’s own bearer token. Required only when the counted cash differs from the expected figure.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClosePosSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/EndOfDaySummaryDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndOfDaySummaryDto"}}}},"422":{"description":"The till is out and nobody has approved the difference"}},"security":[{"bearer":[]}],"summary":"Close a POS session with cash count (End of Day)","tags":["POS Sessions"]}},"/api/v1/pos-sessions/{id}/summary":{"get":{"operationId":"PosSessionController_getSessionSummary_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/EndOfDaySummaryDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get POS session summary (sales, refunds, payment breakdown)","tags":["POS Sessions"]}},"/api/v1/payment-methods":{"post":{"operationId":"PaymentMethodController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePaymentMethodDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethodEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new payment method","tags":["Payment Methods"]},"get":{"operationId":"PaymentMethodController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethodEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all payment methods","tags":["Payment Methods"]}},"/api/v1/payment-methods/{id}":{"get":{"operationId":"PaymentMethodController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethodEntity"}}}]}}}},"404":{"description":"Payment method not found."}},"security":[{"bearer":[]}],"summary":"Get a payment method by ID","tags":["Payment Methods"]},"patch":{"operationId":"PaymentMethodController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePaymentMethodDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethodEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a payment method","tags":["Payment Methods"]},"delete":{"operationId":"PaymentMethodController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethodEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a payment method","tags":["Payment Methods"]}},"/api/v1/cash-movements":{"post":{"description":"Paid-ins, paid-outs, drops and float corrections. These count towards the expected cash at shift close but never towards sales, because they are not trade.","operationId":"CashMovementController_record_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordCashMovementDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CashMovementEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashMovementEntity"}}}}},"security":[{"bearer":[]}],"summary":"Record money in or out of a till","tags":["Cash Movements"]},"get":{"operationId":"CashMovementController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CashMovementEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List cash movements","tags":["Cash Movements"]}},"/api/v1/cash-movements/{id}":{"get":{"operationId":"CashMovementController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/CashMovementEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get a cash movement","tags":["Cash Movements"]}},"/api/v1/outlet-settings":{"get":{"operationId":"OutletSettingController_findAll_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"security":[{"bearer":[]}],"summary":"List outlet settings","tags":["Outlet Settings"]}},"/api/v1/outlet-settings/{locationId}":{"get":{"operationId":"OutletSettingController_findOne_v1","parameters":[{"name":"locationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get one outlet’s settings","tags":["Outlet Settings"]},"put":{"description":"Creating a row makes the server authoritative for that outlet’s service charge, which until now has been an unvalidated number sent by the till. Outlets with no row keep behaving exactly as they do today.","operationId":"OutletSettingController_upsert_v1","parameters":[{"name":"locationId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertOutletSettingDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Set an outlet’s commercial configuration","tags":["Outlet Settings"]},"delete":{"description":"Hands the service charge back to whatever the till sends. Rarely what you want; set the rate to zero instead.","operationId":"OutletSettingController_remove_v1","parameters":[{"name":"locationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Remove an outlet’s settings","tags":["Outlet Settings"]}},"/api/v1/inventory-ledger":{"post":{"operationId":"InventoryLedgerController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInventoryLedgerDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/InventoryLedgerEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryLedgerEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new inventory ledger entry","tags":["Inventory Ledger"]},"get":{"operationId":"InventoryLedgerController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InventoryLedgerEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all inventory ledger entries","tags":["Inventory Ledger"]}},"/api/v1/inventory-ledger/expiring":{"get":{"operationId":"InventoryLedgerController_findExpiring_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"days","required":false,"in":"query","description":"Number of days to look ahead for expiring stock","schema":{"minimum":1,"default":30,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InventoryLedgerEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get stock expiring within N days","tags":["Inventory Ledger"]}},"/api/v1/inventory-ledger/write-off":{"post":{"operationId":"InventoryLedgerController_writeOff_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteOffInventoryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/InventoryLedgerEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryLedgerEntity"}}}}},"security":[{"bearer":[]}],"summary":"Write off expired or damaged stock","tags":["Inventory Ledger"]}},"/api/v1/inventory-ledger/balance/{variantId}/{locationId}":{"get":{"operationId":"InventoryLedgerController_getBalance_v1","parameters":[{"name":"variantId","required":true,"in":"path","schema":{"type":"string"}},{"name":"locationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns the inventory balance."}},"security":[{"bearer":[]}],"summary":"Get inventory balance for a variant at a location","tags":["Inventory Ledger"]}},"/api/v1/inventory-ledger/{id}":{"get":{"operationId":"InventoryLedgerController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/InventoryLedgerEntity"}}}]}}}},"404":{"description":"Inventory ledger entry not found."}},"security":[{"bearer":[]}],"summary":"Get an inventory ledger entry by ID","tags":["Inventory Ledger"]},"delete":{"operationId":"InventoryLedgerController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/InventoryLedgerEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete an inventory ledger entry","tags":["Inventory Ledger"]}},"/api/v1/exchange-rates":{"post":{"operationId":"ExchangeRateController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExchangeRateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ExchangeRateEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeRateEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new exchange rate","tags":["Exchange Rates"]},"get":{"operationId":"ExchangeRateController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExchangeRateEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all exchange rates","tags":["Exchange Rates"]}},"/api/v1/exchange-rates/{id}":{"get":{"operationId":"ExchangeRateController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ExchangeRateEntity"}}}]}}}},"404":{"description":"Exchange rate not found."}},"security":[{"bearer":[]}],"summary":"Get an exchange rate by ID","tags":["Exchange Rates"]},"patch":{"operationId":"ExchangeRateController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExchangeRateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ExchangeRateEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update an exchange rate","tags":["Exchange Rates"]},"delete":{"operationId":"ExchangeRateController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ExchangeRateEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete an exchange rate","tags":["Exchange Rates"]}},"/api/v1/tax-rates":{"post":{"operationId":"TaxRateController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTaxRateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TaxRateEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new tax rate","tags":["Tax Rates"]},"get":{"operationId":"TaxRateController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaxRateEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all tax rates","tags":["Tax Rates"]}},"/api/v1/tax-rates/{id}":{"get":{"operationId":"TaxRateController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TaxRateEntity"}}}]}}}},"404":{"description":"Tax rate not found."}},"security":[{"bearer":[]}],"summary":"Get a tax rate by ID","tags":["Tax Rates"]},"patch":{"operationId":"TaxRateController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTaxRateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TaxRateEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a tax rate","tags":["Tax Rates"]},"delete":{"operationId":"TaxRateController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TaxRateEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a tax rate","tags":["Tax Rates"]}},"/api/v1/accounting-periods":{"post":{"operationId":"AccountingPeriodController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccountingPeriodDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/AccountingPeriodEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingPeriodEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new accounting period","tags":["Accounting Periods"]},"get":{"operationId":"AccountingPeriodController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AccountingPeriodEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all accounting periods","tags":["Accounting Periods"]}},"/api/v1/accounting-periods/{id}":{"get":{"operationId":"AccountingPeriodController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/AccountingPeriodEntity"}}}]}}}},"404":{"description":"Accounting period not found."}},"security":[{"bearer":[]}],"summary":"Get an accounting period by ID","tags":["Accounting Periods"]},"patch":{"operationId":"AccountingPeriodController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountingPeriodDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/AccountingPeriodEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update an accounting period","tags":["Accounting Periods"]},"delete":{"operationId":"AccountingPeriodController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/AccountingPeriodEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete an accounting period","tags":["Accounting Periods"]}},"/api/v1/chart-of-accounts":{"post":{"operationId":"ChartOfAccountController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChartOfAccountDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ChartOfAccountEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartOfAccountEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new chart of account","tags":["Chart of Accounts"]},"get":{"operationId":"ChartOfAccountController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChartOfAccountEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all chart of accounts","tags":["Chart of Accounts"]}},"/api/v1/chart-of-accounts/{id}":{"get":{"operationId":"ChartOfAccountController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ChartOfAccountEntity"}}}]}}}},"404":{"description":"Chart of account not found."}},"security":[{"bearer":[]}],"summary":"Get a chart of account by ID","tags":["Chart of Accounts"]},"patch":{"operationId":"ChartOfAccountController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateChartOfAccountDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ChartOfAccountEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a chart of account","tags":["Chart of Accounts"]},"delete":{"operationId":"ChartOfAccountController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ChartOfAccountEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a chart of account","tags":["Chart of Accounts"]}},"/api/v1/journal-entries":{"post":{"operationId":"JournalEntryController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJournalEntryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalEntryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalEntryEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new journal entry","tags":["Journal Entries"]},"get":{"operationId":"JournalEntryController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/JournalEntryEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all journal entries","tags":["Journal Entries"]}},"/api/v1/journal-entries/{id}":{"get":{"operationId":"JournalEntryController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalEntryEntity"}}}]}}}},"404":{"description":"Journal entry not found."}},"security":[{"bearer":[]}],"summary":"Get a journal entry by ID","tags":["Journal Entries"]},"patch":{"operationId":"JournalEntryController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJournalEntryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalEntryEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a journal entry","tags":["Journal Entries"]},"delete":{"operationId":"JournalEntryController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalEntryEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a journal entry","tags":["Journal Entries"]}},"/api/v1/journal-entries/{journalEntryId}/lines":{"post":{"operationId":"JournalLineController_create_v1","parameters":[{"name":"journalEntryId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJournalLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalLineEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new journal line","tags":["Journal Lines"]},"get":{"operationId":"JournalLineController_findAll_v1","parameters":[{"name":"journalEntryId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/JournalLineEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all lines for a journal entry","tags":["Journal Lines"]}},"/api/v1/journal-entries/{journalEntryId}/lines/{id}":{"get":{"operationId":"JournalLineController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"journalEntryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalLineEntity"}}}]}}}},"404":{"description":"Journal line not found."}},"security":[{"bearer":[]}],"summary":"Get a journal line by ID","tags":["Journal Lines"]},"patch":{"operationId":"JournalLineController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"journalEntryId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJournalLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a journal line","tags":["Journal Lines"]},"delete":{"operationId":"JournalLineController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"journalEntryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/JournalLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a journal line","tags":["Journal Lines"]}},"/api/v1/bank-statements":{"post":{"operationId":"BankStatementController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBankStatementDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankStatementEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new bank statement","tags":["Bank Statements"]},"get":{"operationId":"BankStatementController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BankStatementEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all bank statements","tags":["Bank Statements"]}},"/api/v1/bank-statements/{id}":{"get":{"operationId":"BankStatementController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementEntity"}}}]}}}},"404":{"description":"Bank statement not found."}},"security":[{"bearer":[]}],"summary":"Get a bank statement by ID","tags":["Bank Statements"]},"patch":{"operationId":"BankStatementController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBankStatementDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a bank statement","tags":["Bank Statements"]},"delete":{"operationId":"BankStatementController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a bank statement","tags":["Bank Statements"]}},"/api/v1/bank-statements/{bankStatementId}/lines":{"post":{"operationId":"BankStatementLineController_create_v1","parameters":[{"name":"bankStatementId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBankStatementLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankStatementLineEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new bank statement line","tags":["Bank Statement Lines"]},"get":{"operationId":"BankStatementLineController_findAll_v1","parameters":[{"name":"bankStatementId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BankStatementLineEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all lines for a bank statement","tags":["Bank Statement Lines"]}},"/api/v1/bank-statements/{bankStatementId}/lines/{id}":{"get":{"operationId":"BankStatementLineController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"bankStatementId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementLineEntity"}}}]}}}},"404":{"description":"Bank statement line not found."}},"security":[{"bearer":[]}],"summary":"Get a bank statement line by ID","tags":["Bank Statement Lines"]},"patch":{"operationId":"BankStatementLineController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"bankStatementId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBankStatementLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a bank statement line","tags":["Bank Statement Lines"]},"delete":{"operationId":"BankStatementLineController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"bankStatementId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BankStatementLineEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a bank statement line","tags":["Bank Statement Lines"]}},"/api/v1/reconciliation-matches":{"post":{"operationId":"ReconciliationMatchController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReconciliationMatchDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReconciliationMatchEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconciliationMatchEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new reconciliation match","tags":["Reconciliation Matches"]},"get":{"operationId":"ReconciliationMatchController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReconciliationMatchEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all reconciliation matches","tags":["Reconciliation Matches"]}},"/api/v1/reconciliation-matches/{id}":{"get":{"operationId":"ReconciliationMatchController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReconciliationMatchEntity"}}}]}}}},"404":{"description":"Reconciliation match not found."}},"security":[{"bearer":[]}],"summary":"Get a reconciliation match by ID","tags":["Reconciliation Matches"]},"patch":{"operationId":"ReconciliationMatchController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReconciliationMatchDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReconciliationMatchEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a reconciliation match","tags":["Reconciliation Matches"]},"delete":{"operationId":"ReconciliationMatchController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReconciliationMatchEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a reconciliation match","tags":["Reconciliation Matches"]}},"/api/v1/fixed-assets":{"post":{"operationId":"FixedAssetController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFixedAssetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/FixedAssetEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FixedAssetEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new fixed asset","tags":["Fixed Assets"]},"get":{"operationId":"FixedAssetController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FixedAssetEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all fixed assets","tags":["Fixed Assets"]}},"/api/v1/fixed-assets/{id}":{"get":{"operationId":"FixedAssetController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/FixedAssetEntity"}}}]}}}},"404":{"description":"Fixed asset not found."}},"security":[{"bearer":[]}],"summary":"Get a fixed asset by ID","tags":["Fixed Assets"]},"patch":{"operationId":"FixedAssetController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFixedAssetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/FixedAssetEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a fixed asset","tags":["Fixed Assets"]},"delete":{"operationId":"FixedAssetController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/FixedAssetEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a fixed asset","tags":["Fixed Assets"]}},"/api/v1/fixed-assets/{fixedAssetId}/depreciation-schedules":{"post":{"operationId":"DepreciationScheduleController_create_v1","parameters":[{"name":"fixedAssetId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDepreciationScheduleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DepreciationScheduleEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepreciationScheduleEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a new depreciation schedule","tags":["Depreciation Schedules"]},"get":{"operationId":"DepreciationScheduleController_findAll_v1","parameters":[{"name":"fixedAssetId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DepreciationScheduleEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all depreciation schedules for a fixed asset","tags":["Depreciation Schedules"]}},"/api/v1/fixed-assets/{fixedAssetId}/depreciation-schedules/{id}":{"get":{"operationId":"DepreciationScheduleController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"fixedAssetId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DepreciationScheduleEntity"}}}]}}}},"404":{"description":"Depreciation schedule not found."}},"security":[{"bearer":[]}],"summary":"Get a depreciation schedule by ID","tags":["Depreciation Schedules"]},"patch":{"operationId":"DepreciationScheduleController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"fixedAssetId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDepreciationScheduleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DepreciationScheduleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a depreciation schedule","tags":["Depreciation Schedules"]},"delete":{"operationId":"DepreciationScheduleController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"fixedAssetId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DepreciationScheduleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a depreciation schedule","tags":["Depreciation Schedules"]}},"/api/v1/uploads":{"get":{"operationId":"UploadController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"folder","required":false,"in":"query","description":"Filter by folder","schema":{"type":"string"}},{"name":"branchId","required":false,"in":"query","description":"Filter by branch ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UploadResponseDto"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get all uploaded files with pagination","tags":["Uploads"]},"post":{"operationId":"UploadController_uploadFile_v1","parameters":[{"name":"folder","required":false,"in":"query","description":"Subfolder to store the file","schema":{"example":"products","type":"string"}},{"name":"branchId","required":false,"in":"query","description":"Branch ID (defaults to user branch)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UploadResponseDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Upload a single file","tags":["Uploads"]}},"/api/v1/uploads/multiple":{"post":{"operationId":"UploadController_uploadFiles_v1","parameters":[{"name":"folder","required":false,"in":"query","schema":{"type":"string"}},{"name":"branchId","required":false,"in":"query","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"string","format":"binary"}}},"required":["files"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/UploadResponseDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UploadResponseDto"}}}}}},"security":[{"bearer":[]}],"summary":"Upload multiple files (max 10)","tags":["Uploads"]}},"/api/v1/uploads/{id}":{"delete":{"operationId":"UploadController_deleteFile_v1","parameters":[{"name":"id","required":true,"in":"path","description":"Upload record ID","schema":{"type":"string"}}],"responses":{"200":{"description":"File deleted successfully.","content":{"application/json":{"schema":{"properties":{"message":{"type":"string","example":"File deleted successfully"}}}}}}},"security":[{"bearer":[]}],"summary":"Delete an uploaded file by ID","tags":["Uploads"]}},"/api/v1/modifier-groups":{"post":{"operationId":"ModifierGroupController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateModifierGroupDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierGroupEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifierGroupEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a modifier group","tags":["Modifier Groups"]},"get":{"operationId":"ModifierGroupController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ModifierGroupEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List modifier groups (paginated)","tags":["Modifier Groups"]}},"/api/v1/modifier-groups/{id}":{"get":{"operationId":"ModifierGroupController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierGroupEntity"}}}]}}}},"404":{"description":"Modifier group not found."}},"security":[{"bearer":[]}],"summary":"Get a modifier group by ID","tags":["Modifier Groups"]},"patch":{"operationId":"ModifierGroupController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateModifierGroupDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierGroupEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a modifier group","tags":["Modifier Groups"]},"delete":{"operationId":"ModifierGroupController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierGroupEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a modifier group","tags":["Modifier Groups"]}},"/api/v1/modifier-groups/{id}/products":{"post":{"operationId":"ModifierGroupController_attachToProduct_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachModifierGroupDto"}}}},"responses":{"204":{"description":"Attached."}},"security":[{"bearer":[]}],"summary":"Attach a modifier group to a product","tags":["Modifier Groups"]}},"/api/v1/modifier-groups/{id}/products/{productId}":{"delete":{"operationId":"ModifierGroupController_detachFromProduct_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Detached."}},"security":[{"bearer":[]}],"summary":"Detach a modifier group from a product","tags":["Modifier Groups"]}},"/api/v1/modifier-groups/{groupId}/modifiers":{"post":{"operationId":"ModifierController_create_v1","parameters":[{"name":"groupId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateModifierDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifierEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a modifier within a group","tags":["Modifiers"]},"get":{"operationId":"ModifierController_findAll_v1","parameters":[{"name":"groupId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ModifierEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List modifiers in a group","tags":["Modifiers"]}},"/api/v1/modifier-groups/{groupId}/modifiers/{id}":{"get":{"operationId":"ModifierController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierEntity"}}}]}}}},"404":{"description":"Modifier not found."}},"security":[{"bearer":[]}],"summary":"Get a modifier by ID","tags":["Modifiers"]},"patch":{"operationId":"ModifierController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateModifierDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a modifier","tags":["Modifiers"]},"delete":{"operationId":"ModifierController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ModifierEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a modifier","tags":["Modifiers"]}},"/api/v1/recipes":{"post":{"operationId":"RecipeController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRecipeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RecipeEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a recipe (with ingredients)","tags":["Recipes"]},"get":{"operationId":"RecipeController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RecipeEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List recipes (paginated)","tags":["Recipes"]}},"/api/v1/recipes/by-variant/{variantId}":{"get":{"operationId":"RecipeController_findByVariant_v1","parameters":[{"name":"variantId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RecipeEntity"}}}]}}}},"404":{"description":"Recipe not found."}},"security":[{"bearer":[]}],"summary":"Get the recipe for a specific variant","tags":["Recipes"]}},"/api/v1/recipes/{id}":{"get":{"operationId":"RecipeController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RecipeEntity"}}}]}}}},"404":{"description":"Recipe not found."}},"security":[{"bearer":[]}],"summary":"Get a recipe by ID","tags":["Recipes"]},"patch":{"operationId":"RecipeController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRecipeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RecipeEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a recipe (and optionally replace ingredients)","tags":["Recipes"]},"delete":{"operationId":"RecipeController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RecipeEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a recipe","tags":["Recipes"]}},"/api/v1/bundles":{"post":{"operationId":"BundleController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBundleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BundleEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BundleEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a bundle (combo) with components","tags":["Bundles"]},"get":{"operationId":"BundleController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BundleEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List bundles (paginated)","tags":["Bundles"]}},"/api/v1/bundles/{id}":{"get":{"operationId":"BundleController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BundleEntity"}}}]}}}},"404":{"description":"Bundle not found."}},"security":[{"bearer":[]}],"summary":"Get a bundle by ID","tags":["Bundles"]},"patch":{"operationId":"BundleController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBundleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BundleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a bundle (and optionally replace components)","tags":["Bundles"]},"delete":{"operationId":"BundleController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/BundleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a bundle","tags":["Bundles"]}},"/api/v1/pricing-schedules":{"post":{"operationId":"PricingScheduleController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePricingScheduleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PricingScheduleEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingScheduleEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a pricing schedule (with rules)","tags":["Pricing Schedules"]},"get":{"operationId":"PricingScheduleController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PricingScheduleEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List pricing schedules (paginated)","tags":["Pricing Schedules"]}},"/api/v1/pricing-schedules/{id}":{"get":{"operationId":"PricingScheduleController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PricingScheduleEntity"}}}]}}}},"404":{"description":"Pricing schedule not found."}},"security":[{"bearer":[]}],"summary":"Get a pricing schedule by ID","tags":["Pricing Schedules"]},"patch":{"operationId":"PricingScheduleController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePricingScheduleDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PricingScheduleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a pricing schedule (and optionally replace rules)","tags":["Pricing Schedules"]},"delete":{"operationId":"PricingScheduleController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/PricingScheduleEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a pricing schedule","tags":["Pricing Schedules"]}},"/api/v1/dining-zones":{"post":{"operationId":"DiningZoneController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDiningZoneDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningZoneEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiningZoneEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a dining zone","tags":["Dining Zones"]},"get":{"operationId":"DiningZoneController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DiningZoneEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List dining zones (paginated)","tags":["Dining Zones"]}},"/api/v1/dining-zones/{id}":{"get":{"operationId":"DiningZoneController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningZoneEntity"}}}]}}}},"404":{"description":"Dining zone not found."}},"security":[{"bearer":[]}],"summary":"Get a dining zone by ID","tags":["Dining Zones"]},"patch":{"operationId":"DiningZoneController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDiningZoneDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningZoneEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a dining zone","tags":["Dining Zones"]},"delete":{"operationId":"DiningZoneController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningZoneEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a dining zone","tags":["Dining Zones"]}},"/api/v1/dining-tables":{"post":{"operationId":"DiningTableController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDiningTableDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningTableEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiningTableEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a dining table","tags":["Dining Tables"]},"get":{"description":"Drives the floor plan: every table with its layout, plus `activeSession` carrying the guest count, units ordered and seated duration for the ones in service. `activeSession` is null when nobody is seated. `itemCount` is units, not lines - voided lines are left out, comped lines counted. Tick a live duration badge from `openedAt`; `seatedSeconds` is only the value at the moment the response was built.","operationId":"DiningTableController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"zoneId","required":false,"in":"query","description":"Filter by zone","schema":{"format":"uuid","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["AVAILABLE","OCCUPIED","DIRTY","RESERVED"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DiningTableEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List dining tables (paginated)","tags":["Dining Tables"]}},"/api/v1/dining-tables/{id}":{"get":{"description":"Returns the same card shape as the list, `activeSession` included, so a single table can be refreshed without re-reading the whole floor.","operationId":"DiningTableController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningTableEntity"}}}]}}}},"404":{"description":"Dining table not found."}},"security":[{"bearer":[]}],"summary":"Get a dining table by ID","tags":["Dining Tables"]},"patch":{"operationId":"DiningTableController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDiningTableDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningTableEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a dining table","tags":["Dining Tables"]},"delete":{"operationId":"DiningTableController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningTableEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a dining table","tags":["Dining Tables"]}},"/api/v1/dining-tables/{id}/status":{"patch":{"operationId":"DiningTableController_updateStatus_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDiningTableStatusDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiningTableEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Change a dining table status","tags":["Dining Tables"]}},"/api/v1/sections":{"post":{"operationId":"SectionController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSectionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a section","tags":["Sections"]},"get":{"operationId":"SectionController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SectionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List sections (paginated)","tags":["Sections"]}},"/api/v1/sections/{id}":{"get":{"operationId":"SectionController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionEntity"}}}]}}}},"404":{"description":"Section not found."}},"security":[{"bearer":[]}],"summary":"Get a section by ID","tags":["Sections"]},"patch":{"operationId":"SectionController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSectionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a section","tags":["Sections"]},"delete":{"operationId":"SectionController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a section","tags":["Sections"]}},"/api/v1/sections/{id}/tables":{"post":{"operationId":"SectionController_attachTable_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachTableDto"}}}},"responses":{"204":{"description":"Attached."}},"security":[{"bearer":[]}],"summary":"Attach a dining table to this section","tags":["Sections"]}},"/api/v1/sections/{id}/tables/{tableId}":{"delete":{"operationId":"SectionController_detachTable_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"tableId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Detached."}},"security":[{"bearer":[]}],"summary":"Detach a dining table from this section","tags":["Sections"]}},"/api/v1/sections/{id}/assignments":{"post":{"operationId":"SectionController_createAssignment_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSectionAssignmentDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionAssignmentEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionAssignmentEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a waiter assignment to this section","tags":["Sections"]},"get":{"operationId":"SectionController_listAssignments_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SectionAssignmentEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List assignments for this section","tags":["Sections"]}},"/api/v1/sections/assignments/{assignmentId}":{"patch":{"operationId":"SectionController_updateAssignment_v1","parameters":[{"name":"assignmentId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSectionAssignmentDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionAssignmentEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update an assignment (notes / endsAt)","tags":["Sections"]}},"/api/v1/sections/assignments/{assignmentId}/end":{"post":{"operationId":"SectionController_endAssignment_v1","parameters":[{"name":"assignmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SectionAssignmentEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionAssignmentEntity"}}}}},"security":[{"bearer":[]}],"summary":"End an assignment (sets endsAt to now)","tags":["Sections"]}},"/api/v1/kitchen-printers":{"post":{"operationId":"KitchenPrinterController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKitchenPrinterDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KitchenPrinterEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KitchenPrinterEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a kitchen printer","tags":["Kitchen Printers"]},"get":{"operationId":"KitchenPrinterController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KitchenPrinterEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List kitchen printers (paginated)","tags":["Kitchen Printers"]}},"/api/v1/kitchen-printers/{id}":{"get":{"operationId":"KitchenPrinterController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KitchenPrinterEntity"}}}]}}}},"404":{"description":"Kitchen printer not found."}},"security":[{"bearer":[]}],"summary":"Get a kitchen printer by ID","tags":["Kitchen Printers"]},"patch":{"operationId":"KitchenPrinterController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKitchenPrinterDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KitchenPrinterEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a kitchen printer","tags":["Kitchen Printers"]},"delete":{"operationId":"KitchenPrinterController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KitchenPrinterEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a kitchen printer","tags":["Kitchen Printers"]}},"/api/v1/kitchen-printers/{id}/categories":{"post":{"operationId":"KitchenPrinterController_attachCategory_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachCategoryDto"}}}},"responses":{"204":{"description":"Attached."}},"security":[{"bearer":[]}],"summary":"Route a category to this printer","tags":["Kitchen Printers"]}},"/api/v1/kitchen-printers/{id}/categories/{categoryId}":{"delete":{"operationId":"KitchenPrinterController_detachCategory_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"categoryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Detached."}},"security":[{"bearer":[]}],"summary":"Stop routing a category to this printer","tags":["Kitchen Printers"]}},"/api/v1/discount-reasons":{"post":{"operationId":"DiscountReasonController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDiscountReasonDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiscountReasonEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscountReasonEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a discount reason","tags":["Discount Reasons"]},"get":{"operationId":"DiscountReasonController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"activeOnly","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DiscountReasonEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List discount reasons (paginated)","tags":["Discount Reasons"]}},"/api/v1/discount-reasons/{id}":{"get":{"operationId":"DiscountReasonController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiscountReasonEntity"}}}]}}}},"404":{"description":"Discount reason not found."}},"security":[{"bearer":[]}],"summary":"Get a discount reason by ID","tags":["Discount Reasons"]},"patch":{"operationId":"DiscountReasonController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDiscountReasonDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiscountReasonEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a discount reason","tags":["Discount Reasons"]},"delete":{"operationId":"DiscountReasonController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DiscountReasonEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a discount reason","tags":["Discount Reasons"]}},"/api/v1/void-reasons":{"post":{"operationId":"VoidReasonController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVoidReasonDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VoidReasonEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidReasonEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a void reason","tags":["Void Reasons"]},"get":{"operationId":"VoidReasonController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"activeOnly","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VoidReasonEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List void reasons (paginated)","tags":["Void Reasons"]}},"/api/v1/void-reasons/{id}":{"get":{"operationId":"VoidReasonController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VoidReasonEntity"}}}]}}}},"404":{"description":"Void reason not found."}},"security":[{"bearer":[]}],"summary":"Get a void reason by ID","tags":["Void Reasons"]},"patch":{"operationId":"VoidReasonController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVoidReasonDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VoidReasonEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a void reason","tags":["Void Reasons"]},"delete":{"operationId":"VoidReasonController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/VoidReasonEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a void reason","tags":["Void Reasons"]}},"/api/v1/table-sessions":{"post":{"operationId":"TableSessionController_open_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenTableSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TableSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TableSessionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Open a new table session (seat guests)","tags":["Table Sessions"]},"get":{"operationId":"TableSessionController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"example":10,"type":"number"}},{"name":"tableId","required":false,"in":"query","description":"Filter by table","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"waiterId","required":false,"in":"query","description":"Filter by waiter","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"sessionState","required":false,"in":"query","schema":{"type":"string","enum":["SEATED","ORDERING","SERVED","PAYMENT_PENDING","CLOSED"]}},{"name":"openOnly","required":false,"in":"query","description":"Only sessions that are still open (no closedAt)","schema":{"example":"true","type":"boolean"}},{"name":"sortBy","required":false,"in":"query","schema":{"example":"openedAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","schema":{"example":"desc","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TableSessionEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List table sessions (paginated)","tags":["Table Sessions"]}},"/api/v1/table-sessions/{id}":{"get":{"operationId":"TableSessionController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TableSessionEntity"}}}]}}}},"404":{"description":"Table session not found."}},"security":[{"bearer":[]}],"summary":"Get a table session by ID with order + seat allocations","tags":["Table Sessions"]},"patch":{"operationId":"TableSessionController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTableSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TableSessionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update waiter or guest count","tags":["Table Sessions"]}},"/api/v1/table-sessions/{id}/state":{"post":{"operationId":"TableSessionController_transitionState_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionStateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TableSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TableSessionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Transition session state","tags":["Table Sessions"]}},"/api/v1/table-sessions/{id}/lines":{"post":{"operationId":"TableSessionController_addLine_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSessionLineDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TableSessionLineResultDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearer":[]}],"summary":"Add an order line to the session","tags":["Table Sessions"]}},"/api/v1/table-sessions/{id}/seats":{"post":{"operationId":"TableSessionController_allocateSeat_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllocateSeatDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SessionSeatAllocationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSeatAllocationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Allocate an order line to a seat","tags":["Table Sessions"]}},"/api/v1/table-sessions/{id}/seats/{allocationId}":{"delete":{"operationId":"TableSessionController_removeAllocation_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"allocationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SessionSeatAllocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Remove a seat allocation","tags":["Table Sessions"]}},"/api/v1/table-sessions/{id}/checkout":{"post":{"operationId":"TableSessionController_checkout_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TableSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TableSessionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Checkout the session (close + capture payments + free table)","tags":["Table Sessions"]}},"/api/v1/kds/stations":{"post":{"operationId":"KdsStationController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKdsStationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsStationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KdsStationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a KDS station","tags":["KDS Stations"]},"get":{"operationId":"KdsStationController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"example":10,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"example":"Hot","type":"string"}},{"name":"locationId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"example":"name","type":"string"}},{"name":"sortOrder","required":false,"in":"query","schema":{"example":"asc","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KdsStationEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List KDS stations (paginated)","tags":["KDS Stations"]}},"/api/v1/kds/stations/{id}":{"get":{"operationId":"KdsStationController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsStationEntity"}}}]}}}},"404":{"description":"KDS station not found."}},"security":[{"bearer":[]}],"summary":"Get a KDS station by ID","tags":["KDS Stations"]},"patch":{"operationId":"KdsStationController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKdsStationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsStationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a KDS station","tags":["KDS Stations"]},"delete":{"operationId":"KdsStationController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsStationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a KDS station","tags":["KDS Stations"]}},"/api/v1/kds/fire":{"post":{"operationId":"KdsTicketController_fire_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FireTicketsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/FireTicketsResultDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearer":[]}],"summary":"Fire pending lines to KDS — pass sessionId (dine-in) or salesOrderId (counter/QSR)","tags":["KDS Tickets"]}},"/api/v1/kds/tickets":{"get":{"operationId":"KdsTicketController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"example":50,"type":"number"}},{"name":"stationId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"sessionId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","PREPARING","READY","EXPEDITED"]}},{"name":"activeOnly","required":false,"in":"query","description":"Only active tickets (not READY)","schema":{"example":"true","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KdsTicketEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List KDS tickets (paginated)","tags":["KDS Tickets"]}},"/api/v1/kds/tickets/{id}":{"get":{"operationId":"KdsTicketController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsTicketEntity"}}}]}}}},"404":{"description":"KDS ticket not found."}},"security":[{"bearer":[]}],"summary":"Get a KDS ticket by ID","tags":["KDS Tickets"]}},"/api/v1/kds/tickets/{id}/start":{"post":{"operationId":"KdsTicketController_start_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsTicketEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KdsTicketEntity"}}}}},"security":[{"bearer":[]}],"summary":"Start preparing (PENDING -> PREPARING)","tags":["KDS Tickets"]}},"/api/v1/kds/tickets/{id}/ready":{"post":{"operationId":"KdsTicketController_markReady_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsTicketEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KdsTicketEntity"}}}}},"security":[{"bearer":[]}],"summary":"Bump entire ticket (-> READY, marks all lines + sales lines READY)","tags":["KDS Tickets"]}},"/api/v1/kds/tickets/{id}/recall":{"post":{"operationId":"KdsTicketController_recall_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsTicketEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KdsTicketEntity"}}}}},"security":[{"bearer":[]}],"summary":"Recall a bumped ticket (READY -> PREPARING)","tags":["KDS Tickets"]}},"/api/v1/kds/tickets/{id}/expedite":{"post":{"operationId":"KdsTicketController_expedite_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsTicketEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KdsTicketEntity"}}}}},"security":[{"bearer":[]}],"summary":"Mark ticket as EXPEDITED","tags":["KDS Tickets"]}},"/api/v1/kds/tickets/lines/{lineId}/ready":{"post":{"operationId":"KdsTicketController_bumpLine_v1","parameters":[{"name":"lineId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KdsTicketLineEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KdsTicketLineEntity"}}}}},"security":[{"bearer":[]}],"summary":"Bump a single ticket line — auto-promotes ticket if all lines READY","tags":["KDS Tickets"]}},"/api/v1/reservations":{"post":{"operationId":"ReservationController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReservationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReservationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReservationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a reservation","tags":["Reservations"]},"get":{"operationId":"ReservationController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"example":10,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"example":"Jane","type":"string"}},{"name":"locationId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"customerId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","CONFIRMED","SEATED","NO_SHOW","CANCELED","COMPLETED"]}},{"name":"fromDate","required":false,"in":"query","schema":{"example":"2026-05-10T00:00:00Z","type":"string"}},{"name":"toDate","required":false,"in":"query","schema":{"example":"2026-05-11T00:00:00Z","type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"example":"reservedAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","schema":{"example":"asc","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReservationEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List reservations (paginated)","tags":["Reservations"]}},"/api/v1/reservations/{id}":{"get":{"operationId":"ReservationController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReservationEntity"}}}]}}}},"404":{"description":"Reservation not found."}},"security":[{"bearer":[]}],"summary":"Get a reservation by ID","tags":["Reservations"]},"patch":{"operationId":"ReservationController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReservationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReservationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a reservation","tags":["Reservations"]},"delete":{"operationId":"ReservationController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReservationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Soft-delete a reservation","tags":["Reservations"]}},"/api/v1/reservations/{id}/confirm":{"post":{"operationId":"ReservationController_confirm_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Confirm a reservation (PENDING -> CONFIRMED, returns conflict warnings)","tags":["Reservations"]}},"/api/v1/reservations/{id}/seat":{"post":{"operationId":"ReservationController_seat_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeatReservationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SeatReservationResultDto"}}}]}}}},"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Seat the reservation — opens a TableSession and links it","tags":["Reservations"]}},"/api/v1/reservations/{id}/cancel":{"post":{"operationId":"ReservationController_cancel_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReservationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReservationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Cancel a reservation","tags":["Reservations"]}},"/api/v1/reservations/{id}/no-show":{"post":{"operationId":"ReservationController_noShow_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ReservationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReservationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Mark a reservation as no-show","tags":["Reservations"]}},"/api/v1/waitlist":{"post":{"operationId":"WaitlistController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWaitlistEntryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}}},"security":[{"bearer":[]}],"summary":"Add a walk-in party to the waitlist","tags":["Waitlist"]},"get":{"operationId":"WaitlistController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"example":20,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"example":"John","type":"string"}},{"name":"locationId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["WAITING","NOTIFIED","SEATED","CANCELED","NO_SHOW"]}},{"name":"activeOnly","required":false,"in":"query","description":"Only active (WAITING / NOTIFIED)","schema":{"example":"true","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WaitlistEntryEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List waitlist entries (paginated)","tags":["Waitlist"]}},"/api/v1/waitlist/{id}":{"get":{"operationId":"WaitlistController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}]}}}},"404":{"description":"Waitlist entry not found."}},"security":[{"bearer":[]}],"summary":"Get a waitlist entry by ID","tags":["Waitlist"]},"patch":{"operationId":"WaitlistController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWaitlistEntryDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a waitlist entry","tags":["Waitlist"]}},"/api/v1/waitlist/{id}/notify":{"post":{"operationId":"WaitlistController_notify_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}}},"security":[{"bearer":[]}],"summary":"Notify the party (WAITING -> NOTIFIED)","tags":["Waitlist"]}},"/api/v1/waitlist/{id}/seat":{"post":{"operationId":"WaitlistController_seat_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeatWaitlistDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Seat the party — opens a TableSession and links it","tags":["Waitlist"]}},"/api/v1/waitlist/{id}/cancel":{"post":{"operationId":"WaitlistController_cancel_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}}},"security":[{"bearer":[]}],"summary":"Cancel a waitlist entry","tags":["Waitlist"]}},"/api/v1/waitlist/{id}/no-show":{"post":{"operationId":"WaitlistController_noShow_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistEntryEntity"}}}}},"security":[{"bearer":[]}],"summary":"Mark waitlist as no-show","tags":["Waitlist"]}},"/api/v1/tip-pools":{"post":{"operationId":"TipPoolController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTipPoolDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TipPoolEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a tip pool — auto-snapshots tips/serviceCharge from sales in window","tags":["Tip Pools"]},"get":{"operationId":"TipPoolController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"example":10,"type":"number"}},{"name":"locationId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["OPEN","SETTLED"]}},{"name":"fromDate","required":false,"in":"query","schema":{"example":"2026-05-01T00:00:00Z","type":"string"}},{"name":"toDate","required":false,"in":"query","schema":{"example":"2026-05-31T23:59:59Z","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TipPoolEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List tip pools (paginated)","tags":["Tip Pools"]}},"/api/v1/tip-pools/{id}":{"get":{"operationId":"TipPoolController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolEntity"}}}]}}}},"404":{"description":"Tip pool not found."}},"security":[{"bearer":[]}],"summary":"Get a tip pool with allocations","tags":["Tip Pools"]},"patch":{"operationId":"TipPoolController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTipPoolDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a tip pool (re-snapshots totals if period changed)","tags":["Tip Pools"]},"delete":{"operationId":"TipPoolController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Soft-delete a tip pool (only OPEN)","tags":["Tip Pools"]}},"/api/v1/tip-pools/{id}/allocations":{"get":{"operationId":"TipPoolController_listAllocations_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TipPoolAllocationEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List allocations for a tip pool","tags":["Tip Pools"]},"post":{"operationId":"TipPoolController_addAllocation_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAllocationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolAllocationEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TipPoolAllocationEntity"}}}}},"security":[{"bearer":[]}],"summary":"Add an allocation to a tip pool","tags":["Tip Pools"]}},"/api/v1/tip-pools/{id}/allocations/{allocationId}":{"patch":{"operationId":"TipPoolController_updateAllocation_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"allocationId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAllocationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolAllocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update an allocation","tags":["Tip Pools"]},"delete":{"operationId":"TipPoolController_removeAllocation_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"allocationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolAllocationEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Remove an allocation","tags":["Tip Pools"]}},"/api/v1/tip-pools/{id}/distribute":{"post":{"operationId":"TipPoolController_distribute_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TipPoolEntity"}}}}},"security":[{"bearer":[]}],"summary":"Auto-fill allocation amounts using the pool distribution method","tags":["Tip Pools"]}},"/api/v1/tip-pools/{id}/settle":{"post":{"operationId":"TipPoolController_settle_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TipPoolEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TipPoolEntity"}}}}},"security":[{"bearer":[]}],"summary":"Settle the pool — finalizes (immutable)","tags":["Tip Pools"]}},"/api/v1/shift-templates":{"post":{"description":"An end time at or before the start means the shift runs past midnight.","operationId":"ShiftTemplateController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateShiftTemplateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftTemplateEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShiftTemplateEntity"}}}}},"security":[{"bearer":[]}],"summary":"Create a shift template, e.g. Evening 17:00-02:00","tags":["Shift Templates"]},"get":{"operationId":"ShiftTemplateController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ShiftTemplateEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List shift templates","tags":["Shift Templates"]}},"/api/v1/shift-templates/{id}":{"get":{"operationId":"ShiftTemplateController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftTemplateEntity"}}}]}}}},"404":{"description":"Shift template not found."}},"security":[{"bearer":[]}],"summary":"Get a shift template","tags":["Shift Templates"]},"patch":{"operationId":"ShiftTemplateController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateShiftTemplateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftTemplateEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a shift template","tags":["Shift Templates"]},"delete":{"description":"Soft delete. Shifts already rostered from it keep their scheduled times.","operationId":"ShiftTemplateController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftTemplateEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Delete a shift template","tags":["Shift Templates"]}},"/api/v1/shift-rosters":{"post":{"operationId":"ShiftRosterController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateShiftRosterDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}},"409":{"description":"That person is already rostered on an overlapping shift."}},"security":[{"bearer":[]}],"summary":"Roster one person onto one shift","tags":["Shift Roster"]},"get":{"operationId":"ShiftRosterController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"locationId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"userId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","schema":{"example":"2026-08-25","type":"string"}},{"name":"to","required":false,"in":"query","schema":{"example":"2026-08-31","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PUBLISHED","SWAP_REQUESTED","COMPLETED","ABSENT"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ShiftRosterEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List rostered shifts","tags":["Shift Roster"]}},"/api/v1/shift-rosters/run":{"post":{"description":"How a week is planned. Days someone is already booked are skipped and listed in the response rather than failing the run.","operationId":"ShiftRosterController_createRun_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateShiftRosterRunDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterRunResultDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShiftRosterRunResultDto"}}}}},"security":[{"bearer":[]}],"summary":"Roster several people onto a template across a date range","tags":["Shift Roster"]}},"/api/v1/shift-rosters/{id}":{"get":{"operationId":"ShiftRosterController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}]}}}},"404":{"description":"Shift roster not found."}},"security":[{"bearer":[]}],"summary":"Get a rostered shift","tags":["Shift Roster"]},"patch":{"operationId":"ShiftRosterController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateShiftRosterDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Reassign, re-time or mark a shift, e.g. status ABSENT","tags":["Shift Roster"]},"delete":{"operationId":"ShiftRosterController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Remove a rostered shift","tags":["Shift Roster"]}},"/api/v1/shift-rosters/{id}/swap-request":{"post":{"description":"The shift stays with its current holder until the swap is approved.","operationId":"ShiftRosterController_requestSwap_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestShiftSwapDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}}},"security":[{"bearer":[]}],"summary":"Ask a colleague to take this shift","tags":["Shift Roster"]}},"/api/v1/shift-rosters/{id}/swap-approve":{"post":{"operationId":"ShiftRosterController_approveSwap_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShiftRosterEntity"}}}}},"security":[{"bearer":[]}],"summary":"Approve the pending swap, handing the shift over","tags":["Shift Roster"]}},"/api/v1/timesheets/clock-in":{"post":{"description":"Starts a shift. Pass shiftRosterId to attach it to a rostered shift, which is what makes lateness measurable. Omit userId to clock yourself in.","operationId":"TimesheetController_clockIn_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClockInDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TimesheetEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimesheetEntity"}}}},"409":{"description":"Already clocked in."}},"security":[{"bearer":[]}],"summary":"Clock in","tags":["Timesheets"]}},"/api/v1/timesheets/{id}/clock-out":{"post":{"description":"Ends the shift and derives worked, late and overtime minutes. Marks the rostered shift COMPLETED.","operationId":"TimesheetController_clockOut_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClockOutDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TimesheetEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimesheetEntity"}}}}},"security":[{"bearer":[]}],"summary":"Clock out","tags":["Timesheets"]}},"/api/v1/timesheets":{"get":{"operationId":"TimesheetController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"userId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","schema":{"example":"2026-08-25","type":"string"}},{"name":"to","required":false,"in":"query","schema":{"example":"2026-08-31","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING_APPROVAL","APPROVED","REJECTED"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TimesheetEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List timesheets","tags":["Timesheets"]}},"/api/v1/timesheets/worked-hours":{"get":{"description":"The hours a tip pool distributing BY_HOURS should use. Only approved timesheets count.","operationId":"TimesheetController_workedHours_v1","parameters":[{"name":"from","required":true,"in":"query","schema":{"example":"2026-08-25","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"example":"2026-08-31","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkedHoursDto"}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Approved worked hours per person over a period","tags":["Timesheets"]}},"/api/v1/timesheets/{id}":{"get":{"operationId":"TimesheetController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TimesheetEntity"}}}]}}}},"404":{"description":"Timesheet not found."}},"security":[{"bearer":[]}],"summary":"Get a timesheet","tags":["Timesheets"]}},"/api/v1/timesheets/{id}/decision":{"patch":{"operationId":"TimesheetController_decide_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideTimesheetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/TimesheetEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Approve or reject a timesheet","tags":["Timesheets"]}},"/api/v1/ktv-rooms":{"post":{"operationId":"KtvRoomController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKtvRoomDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KtvRoomEntity"}}}},"400":{"description":"The rate product is stock-tracked rather than a service"}},"security":[{"bearer":[]}],"summary":"Create a KTV room","tags":["KTV Rooms"]},"get":{"operationId":"KtvRoomController_findAll_v1","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search keyword","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KtvRoomEntity"}},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}}}]}}}}},"security":[{"bearer":[]}],"summary":"List KTV rooms","tags":["KTV Rooms"]}},"/api/v1/ktv-rooms/board":{"get":{"description":"Every room with whatever is happening in it - in use, free, being cleaned - and how long the current party has been in. This is the staff panel from requirement 6.1.","operationId":"KtvRoomController_board_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"security":[{"bearer":[]}],"summary":"The room board","tags":["KTV Rooms"]}},"/api/v1/ktv-rooms/{id}":{"get":{"operationId":"KtvRoomController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Get a KTV room","tags":["KTV Rooms"]},"patch":{"description":"Billing changes apply to the next party only. A let copies the terms when it opens, so a party already singing keeps the price they were quoted.","operationId":"KtvRoomController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKtvRoomDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Update a KTV room","tags":["KTV Rooms"]},"delete":{"operationId":"KtvRoomController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Retire a KTV room","tags":["KTV Rooms"]}},"/api/v1/ktv-rooms/{id}/ready":{"post":{"description":"Moves it from CLEANING back to AVAILABLE.","operationId":"KtvRoomController_markReady_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KtvRoomEntity"}}}}},"security":[{"bearer":[]}],"summary":"Mark a cleaned room ready","tags":["KTV Rooms"]}},"/api/v1/ktv-sessions":{"post":{"description":"Opens the let and starts a bill. Food and drink ordered to the room land on the same order as the room charge, so the party settles once.","operationId":"KtvSessionController_open_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenKtvSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}},"409":{"description":"That room is already in use"}},"security":[{"bearer":[]}],"summary":"Take a room","tags":["KTV Sessions"]}},"/api/v1/ktv-sessions/{id}/quote":{"get":{"description":"Read-only and safe to poll, which is how a room panel shows a live figure. Uses the same arithmetic as the close, so the quoted number is the charged one.","operationId":"KtvSessionController_quote_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvSessionQuoteDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"The running bill","tags":["KTV Sessions"]}},"/api/v1/ktv-sessions/{id}/planned-minutes":{"patch":{"description":"Records the time a party asked for, or changes it when they extend. Informational only - the bill is metered off the clock, so this never changes what they are charged. The value is the total length from when the room opened, not an amount to add. Null clears it.","operationId":"KtvSessionController_setPlannedMinutes_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPlannedMinutesDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Set how long the party wants the room for","tags":["KTV Sessions"]}},"/api/v1/ktv-sessions/{id}/pause":{"post":{"description":"For a fault or a dispute. Paused minutes are not charged for.","operationId":"KtvSessionController_pause_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Stop the clock","tags":["KTV Sessions"]}},"/api/v1/ktv-sessions/{id}/resume":{"post":{"operationId":"KtvSessionController_resume_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KtvRoomSessionEntity"}}}}},"security":[{"bearer":[]}],"summary":"Restart the clock","tags":["KTV Sessions"]}},"/api/v1/ktv-sessions/{id}/close":{"post":{"description":"Writes the room charge onto the bill, one line per rate window, and sends the room for cleaning. The order stays open: paying is checkout’s job, which is what gives a room bill split tender, guest cards, tax and refunds for free.","operationId":"KtvSessionController_close_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloseKtvSessionDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/KtvSessionQuoteDto"}}}]}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KtvSessionQuoteDto"}}}}},"security":[{"bearer":[]}],"summary":"End the let","tags":["KTV Sessions"]}},"/api/v1/reports/sales-summary":{"get":{"description":"Sales filed under each business date in the range, with refunds on the day they were made. Totals are built from order lines, so gross, discounts and net add up to the grand total whether a sale closed at the counter or at a table. Guest-card top-ups are deposits and never appear here.","operationId":"ReportController_salesSummary_v1","parameters":[{"name":"from","required":true,"in":"query","description":"First business date, YYYY-MM-DD, in the property’s timezone.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-01","type":"string"}},{"name":"to","required":false,"in":"query","description":"Last business date, included. Defaults to `from`.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-14","type":"string"}},{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/SalesSummaryReportDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Sales summary tab","tags":["Reports"]}},"/api/v1/reports/item-sales":{"get":{"description":"Every item sold in the range. Bill-level discounts are spread across the lines they applied to, so the item net sales total equals the sales summary net sales. Returns are counted on the day they were made.","operationId":"ReportController_itemSales_v1","parameters":[{"name":"from","required":true,"in":"query","description":"First business date, YYYY-MM-DD, in the property’s timezone.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-01","type":"string"}},{"name":"to","required":false,"in":"query","description":"Last business date, included. Defaults to `from`.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-14","type":"string"}},{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":500,"default":50,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Product name or SKU contains","schema":{"type":"string"}},{"name":"categoryId","required":false,"in":"query","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"default":"netSales","type":"string","enum":["netSales","grossSales","quantitySold","refundAmount","productName","categoryName"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ItemSalesReportDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Item sales tab","tags":["Reports"]}},"/api/v1/reports/other-income-expenses":{"get":{"description":"Paid-ins and paid-outs recorded against a till. Drops, float corrections and guest-card money are left out: none of them earns or spends anything.","operationId":"ReportController_otherIncomeExpenses_v1","parameters":[{"name":"from","required":true,"in":"query","description":"First business date, YYYY-MM-DD, in the property’s timezone.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-01","type":"string"}},{"name":"to","required":false,"in":"query","description":"Last business date, included. Defaults to `from`.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-14","type":"string"}},{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/OtherIncomeExpenseReportDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Other expenses / income tab","tags":["Reports"]}},"/api/v1/reports/member-cards":{"get":{"description":"Cards issued and closed, money paid in and spent, refunds and forfeits in the range, and what is still owed to guests now. Top-ups are deposits, not sales.","operationId":"ReportController_memberCards_v1","parameters":[{"name":"from","required":true,"in":"query","description":"First business date, YYYY-MM-DD, in the property’s timezone.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-01","type":"string"}},{"name":"to","required":false,"in":"query","description":"Last business date, included. Defaults to `from`.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-14","type":"string"}},{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/MemberCardReportDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Member card tab: guest cards","tags":["Reports"]}},"/api/v1/reports/loyalty-points":{"get":{"description":"Points earned and reversed in the range, and the balance members hold now. Points cannot yet be redeemed or expire, so those figures are always zero.","operationId":"ReportController_loyaltyPoints_v1","parameters":[{"name":"from","required":true,"in":"query","description":"First business date, YYYY-MM-DD, in the property’s timezone.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-01","type":"string"}},{"name":"to","required":false,"in":"query","description":"Last business date, included. Defaults to `from`.","schema":{"pattern":"BUSINESS_DATE","example":"2026-09-14","type":"string"}},{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"top","required":false,"in":"query","description":"How many top members to list","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/LoyaltyPointsReportDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Member card tab: loyalty points","tags":["Reports"]}},"/api/v1/reports/daily-sales":{"get":{"operationId":"ReportController_dailySales_v1","parameters":[{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"date","required":true,"in":"query","description":"Business date, YYYY-MM-DD, in the property’s timezone.","schema":{"example":"2026-05-06","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/DailySalesSummaryDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Daily sales summary (orders, revenue, tax, tips, payment breakdown)","tags":["Reports"]}},"/api/v1/reports/sales-by-category":{"get":{"operationId":"ReportController_salesByCategory_v1","parameters":[{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"fromDate","required":true,"in":"query","description":"First business date. Only the date part is used; a time is ignored.","schema":{"example":"2026-05-01","type":"string"}},{"name":"toDate","required":true,"in":"query","description":"Last business date, included. Only the date part is used; a time is ignored.","schema":{"example":"2026-05-31","type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CategorySalesRowDto"}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Sales by category over a date range","tags":["Reports"]}},"/api/v1/reports/sales-by-item":{"get":{"operationId":"ReportController_salesByItem_v1","parameters":[{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"fromDate","required":true,"in":"query","description":"First business date. Only the date part is used; a time is ignored.","schema":{"example":"2026-05-01","type":"string"}},{"name":"toDate","required":true,"in":"query","description":"Last business date, included. Only the date part is used; a time is ignored.","schema":{"example":"2026-05-31","type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ItemSalesRowDto"}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Top items by revenue over a date range","tags":["Reports"]}},"/api/v1/reports/sales-by-hour":{"get":{"operationId":"ReportController_salesByHour_v1","parameters":[{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"date","required":true,"in":"query","description":"Business date, YYYY-MM-DD, in the property’s timezone.","schema":{"example":"2026-05-06","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HourlySalesRowDto"}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Sales distribution by hour for a given day","tags":["Reports"]}},"/api/v1/reports/server-performance":{"get":{"operationId":"ReportController_serverPerformance_v1","parameters":[{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"fromDate","required":true,"in":"query","description":"First business date. Only the date part is used; a time is ignored.","schema":{"example":"2026-05-01","type":"string"}},{"name":"toDate","required":true,"in":"query","description":"Last business date, included. Only the date part is used; a time is ignored.","schema":{"example":"2026-05-31","type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ServerPerformanceRowDto"}}}}]}}}}},"security":[{"bearer":[]}],"summary":"Per-server performance over a date range","tags":["Reports"]}},"/api/v1/reports/z-report":{"get":{"operationId":"ReportController_zReport_v1","parameters":[{"name":"locationId","required":false,"in":"query","description":"One outlet. Omit for every outlet you can see.","schema":{"format":"uuid","example":"uuid","type":"string"}},{"name":"date","required":true,"in":"query","description":"Business date, YYYY-MM-DD, in the property’s timezone.","schema":{"example":"2026-05-06","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/ZReportDto"}}}]}}}}},"security":[{"bearer":[]}],"summary":"Z-Report — consolidated end-of-day rollup for accounting","tags":["Reports"]}},"/api/v1/counter-orders/{id}":{"get":{"operationId":"CounterOrderController_findOne_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"404":{"description":"Order not found."}},"security":[{"bearer":[]}],"summary":"Get a counter/takeaway order with lines + KDS tickets","tags":["Counter Orders"]}},"/api/v1/counter-orders/{id}/pickup":{"post":{"operationId":"CounterOrderController_markPickedUp_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Mark order picked up — moves READY lines to SERVED and stamps pickedUpAt","tags":["Counter Orders"]}},"/api/v1/room-tablet/menu":{"get":{"description":"Guest-facing: names, prices and pictures only. Cost, stock and supplier data are deliberately absent. Prices are list prices - a card tier discount is applied when the bill is settled, not shown here, because the card is not known until then.","operationId":"RoomTabletController_menu_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RoomMenuDto"}}}]}}}},"403":{"description":"The device is not assigned to a room, or nobody is seated in it."}},"security":[{"bearer":[]}],"summary":"The menu this room can order from","tags":["Room Tablet"]}},"/api/v1/room-tablet/session":{"get":{"description":"What the party has ordered so far, what it comes to, what is left on their card, and when the time they asked for runs out. The room charge is not included: it is worked out when they leave.","operationId":"RoomTabletController_session_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GlobalResponseDto"},{"properties":{"data":{"$ref":"#/components/schemas/RoomSessionViewDto"}}}]}}}},"403":{"description":"The device is not assigned to a room, or nobody is seated in it."}},"security":[{"bearer":[]}],"summary":"This room’s tab, balance and countdown","tags":["Room Tablet"]}}},"info":{"title":"VISION POS","description":"The VISION POS Backend API description","version":"1.0","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"GlobalResponseDto":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Request successful"},"meta":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}}}},"required":["success","message"]},"TenantEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Grand Hotel Group"},"legalName":{"type":"string","nullable":true,"example":"Grand Hotel Group LLC"},"domain":{"type":"string","nullable":true,"example":"grandhotel.com"},"website":{"type":"string","nullable":true,"example":"https://grandhotel.com"},"logoUrl":{"type":"string","nullable":true,"example":"https://logo.url/logo.png"},"primaryContactName":{"type":"string","nullable":true,"example":"John Doe"},"primaryContactEmail":{"type":"string","nullable":true,"example":"john@grandhotel.com"},"primaryContactPhone":{"type":"string","nullable":true,"example":"+1234567890"},"address":{"type":"string","nullable":true,"example":"123 Main St"},"city":{"type":"string","nullable":true,"example":"New York"},"state":{"type":"string","nullable":true,"example":"NY"},"country":{"type":"string","nullable":true,"example":"USA"},"timezone":{"type":"string","nullable":true,"example":"Asia/Bangkok","description":"Null for a tenant created before timezones; filled in from the first sign-in."},"zipCode":{"type":"string","nullable":true,"example":"10001"},"status":{"type":"string","enum":["ACTIVE","INACTIVE","SUSPENDED","TRIAL"],"example":"ACTIVE"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.448Z"}},"required":["id","name","status","createdAt"]},"UpdateTenantDto":{"type":"object","properties":{"timezone":{"type":"string","example":"Asia/Bangkok","description":"IANA timezone the business day is counted in: order numbers roll over at its midnight and reports file sales under its calendar. An outlet can override it. Changing it moves which day new sales are filed under; past sales keep theirs."},"name":{"type":"string","minLength":1,"maxLength":255,"example":"KFC","description":"The name of the tenant"},"legalName":{"type":"string","minLength":1,"maxLength":255,"example":"KFC Corporation","description":"The legal name"},"domain":{"type":"string","minLength":1,"maxLength":255,"example":"kfc.com","description":"The domain"},"website":{"type":"string","minLength":1,"maxLength":255,"example":"https://kfc.com","description":"The website"},"logoUrl":{"type":"string","minLength":1,"maxLength":255,"example":"https://logo.url","description":"The logo URL"},"primaryContactName":{"type":"string","minLength":1,"maxLength":255,"example":"Colonel Sanders","description":"Primary contact name"},"primaryContactEmail":{"type":"string","minLength":1,"maxLength":255,"example":"colonel@kfc.com","description":"Primary contact email"},"primaryContactPhone":{"type":"string","minLength":1,"maxLength":255,"example":"+1234567890","description":"Primary contact phone"},"address":{"type":"string","minLength":1,"maxLength":255,"example":"123 Fried Chicken St","description":"Address"},"city":{"type":"string","minLength":1,"maxLength":255,"example":"Louisville","description":"City"},"state":{"type":"string","minLength":1,"maxLength":255,"example":"Kentucky","description":"State"},"country":{"type":"string","minLength":1,"maxLength":255,"example":"USA","description":"Country"},"zipCode":{"type":"string","minLength":1,"maxLength":255,"example":"40213","description":"Zip code"}}},"UserEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid","description":"The tenant this user belongs to. A user belongs to exactly one."},"email":{"type":"string","example":"john@example.com"},"username":{"type":"string","nullable":true,"example":"john_doe"},"fullName":{"type":"string","nullable":true,"example":"John Doe"},"phoneNumber":{"type":"string","nullable":true,"example":"+1234567890"},"avatarUrl":{"type":"string","nullable":true,"example":"https://avatar.url"},"jobTitle":{"type":"string","nullable":true,"example":"Manager"},"status":{"type":"string","enum":["ACTIVE","INACTIVE","LOCKED","PENDING_VERIFICATION"],"example":"ACTIVE"},"lastLoginAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-09-21T21:31:21.544Z"},"loginAttempts":{"type":"number","example":0},"lockoutUntil":{"format":"date-time","type":"string","nullable":true,"example":null},"preferredLanguage":{"type":"string","example":"EN"},"metadata":{"type":"object","additionalProperties":true,"properties":{}},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.544Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.544Z"}},"required":["id","tenantId","email","status","loginAttempts","preferredLanguage","createdAt","updatedAt"]},"CreateUserDto":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"john@example.com"},"password":{"type":"string","minLength":8,"maxLength":20,"example":"password123"},"username":{"type":"string","minLength":1,"maxLength":255,"example":"john_doe"},"fullName":{"type":"string","minLength":1,"maxLength":255,"example":"John Doe"},"phoneNumber":{"type":"string","nullable":true,"example":"+1234567890"},"avatarUrl":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"example":"https://avatar.url"},"jobTitle":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"example":"Manager"},"roleId":{"type":"string","format":"uuid","example":"uuid"},"branchId":{"type":"string","format":"uuid","example":"uuid"},"preferredLanguage":{"type":"string","minLength":1,"maxLength":255,"example":"EN"}},"required":["email","password","username","fullName"]},"UpdateUserDto":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"john@example.com"},"password":{"type":"string","minLength":8,"maxLength":20,"example":"password123"},"username":{"type":"string","minLength":1,"maxLength":255,"example":"john_doe"},"fullName":{"type":"string","minLength":1,"maxLength":255,"example":"John Doe"},"phoneNumber":{"type":"string","nullable":true,"example":"+1234567890"},"avatarUrl":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"example":"https://avatar.url"},"jobTitle":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"example":"Manager"},"preferredLanguage":{"type":"string","minLength":1,"maxLength":255,"example":"en"}}},"UserInfo":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"email":{"type":"string","example":"john@example.com"},"fullName":{"type":"string","example":"John Doe"},"type":{"enum":["user","system_admin"],"type":"string","example":"user"},"tenantId":{"type":"string","example":"uuid","description":"The tenant this user belongs to. Absent for a system_admin sign-in."}},"required":["id","email","fullName","type"]},"BranchAccess":{"type":"object","properties":{"branchId":{"type":"string","nullable":true,"example":"uuid","description":"Null means tenant-wide access rather than one branch."},"roles":{"example":["admin"],"type":"array","items":{"type":"string"}},"permissions":{"example":["inventory:product:read"],"description":"Permission strings in module:subject:action form.","type":"array","items":{"type":"string"}}},"required":["branchId","roles","permissions"]},"LoginResponseDto":{"type":"object","properties":{"access_token":{"type":"string","example":"jwt_token_here"},"user":{"$ref":"#/components/schemas/UserInfo"},"activeBranch":{"type":"string","nullable":true,"example":"uuid"},"access":{"type":"array","items":{"$ref":"#/components/schemas/BranchAccess"}}},"required":["access_token","user","activeBranch","access"]},"SignInDto":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"user@example.com","description":"The email of the user"},"password":{"type":"string","example":"password123","description":"The password of the user"},"type":{"default":"user","enum":["user","system_admin"],"type":"string","description":"The type of authentication. ( user, system_admin )"},"branchId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174001","description":"The branch ID for context switching"},"timezone":{"type":"string","maxLength":64,"example":"Asia/Bangkok","description":"The device timezone: Intl.DateTimeFormat().resolvedOptions().timeZone. Send it on every sign-in. It is saved as the tenant timezone only when the tenant has none yet, so it fills in an existing tenant once and never overrides a setting."}},"required":["email","password"]},"SetActiveBranchDto":{"type":"object","properties":{"branchId":{"type":"string","nullable":true,"description":"The ID of the branch to set as active. Use null for tenant-wide access.","example":"branch-uuid-here"}},"required":["branchId"]},"OnboardedTenantDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"name":{"type":"string","example":"FreshMart"},"domain":{"type":"string","nullable":true,"example":"freshmart.com"}},"required":["id","name"]},"OnboardedBranchDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"name":{"type":"string","example":"FreshMart Downtown"},"branchCode":{"type":"string","nullable":true,"example":"FM-DT"}},"required":["id","name"]},"OnboardedRoleDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Owner"}},"required":["id","name"]},"OnboardedOwnerDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"email":{"type":"string","example":"owner@freshmart.com"},"fullName":{"type":"string","nullable":true,"example":"Aung Kyaw"}},"required":["id","email"]},"OnboardTenantResponseDto":{"type":"object","properties":{"tenant":{"$ref":"#/components/schemas/OnboardedTenantDto"},"branch":{"$ref":"#/components/schemas/OnboardedBranchDto"},"roles":{"description":"The starter roles created for this tenant.","type":"array","items":{"$ref":"#/components/schemas/OnboardedRoleDto"}},"modules":{"example":["common","iam","inventory","pos","sales"],"description":"The modules enabled for this tenant.","type":"array","items":{"type":"string"}},"owner":{"$ref":"#/components/schemas/OnboardedOwnerDto"}},"required":["tenant","branch","roles","modules","owner"]},"OnboardTenantInfoDto":{"type":"object","properties":{"name":{"type":"string","example":"Acme Corporation"},"timezone":{"type":"string","example":"Asia/Bangkok","description":"IANA timezone the business day is counted in: order numbers roll over at its midnight and reports file sales under its calendar. An outlet can override it. A browser can supply it: Intl.DateTimeFormat().resolvedOptions().timeZone."},"legalName":{"type":"string","example":"Acme Corp Ltd."},"domain":{"type":"string","example":"acme.com"},"website":{"type":"string","example":"https://acme.com"},"address":{"type":"string","example":"123 Main St"},"city":{"type":"string","example":"New York"},"state":{"type":"string","example":"NY"},"country":{"type":"string","example":"USA"},"zipCode":{"type":"string","example":"10001"}},"required":["name","timezone"]},"OnboardBranchInfoDto":{"type":"object","properties":{"name":{"type":"string","example":"Main Branch"},"branchCode":{"type":"string","example":"MB001"},"address":{"type":"string","example":"123 Main St"},"city":{"type":"string","example":"New York"},"phone":{"type":"string","example":"+1234567890"}},"required":["name"]},"OnboardOwnerInfoDto":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"owner@acme.com"},"password":{"type":"string","minLength":8,"maxLength":20,"example":"password123"},"username":{"type":"string","example":"owner_acme"},"fullName":{"type":"string","example":"John Owner"},"phoneNumber":{"type":"string","example":"+1234567890"},"jobTitle":{"type":"string","example":"CEO"}},"required":["email","password","username","fullName"]},"OnboardTenantDto":{"type":"object","properties":{"tenant":{"$ref":"#/components/schemas/OnboardTenantInfoDto"},"branch":{"$ref":"#/components/schemas/OnboardBranchInfoDto"},"owner":{"$ref":"#/components/schemas/OnboardOwnerInfoDto"},"modules":{"example":["inventory","sales","pos","finance","reports"],"description":"Which optional modules this tenant may build roles from. Omit to enable all. The iam and common modules are always on.","type":"array","items":{"type":"string"}}},"required":["tenant","branch","owner"]},"TenantModulesDto":{"type":"object","properties":{"modules":{"example":["common","finance","iam","inventory","pos","reports","sales"],"description":"Every module this tenant may build roles from, including the always-on iam and common.","type":"array","items":{"type":"string"}}},"required":["modules"]},"SetTenantModulesResultDto":{"type":"object","properties":{"modules":{"example":["common","finance","iam","inventory","pos","reports","sales"],"description":"Every module this tenant may build roles from, including the always-on iam and common.","type":"array","items":{"type":"string"}},"removedRolePermissions":{"type":"number","example":27,"description":"Role-permission links removed because their module was switched off."},"removedOverrides":{"type":"number","example":0,"description":"User permission overrides removed because their module was switched off."},"grantedRolePermissions":{"type":"number","example":9,"description":"Permissions added to the tenant’s starter roles for newly enabled modules, so the module is actually usable."}},"required":["modules","removedRolePermissions","removedOverrides","grantedRolePermissions"]},"SetTenantModulesDto":{"type":"object","properties":{"modules":{"example":["inventory","sales","pos","finance","reports"],"description":"The optional modules this tenant may build roles from. The iam and common modules are always on and do not need to be listed. Modules left out are disabled, and permissions from them are removed from the tenant’s roles.","type":"array","items":{"type":"string"}}},"required":["modules"]},"CreateUserAsAdminDto":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"john@example.com"},"password":{"type":"string","minLength":8,"maxLength":20,"example":"password123"},"username":{"type":"string","minLength":1,"maxLength":255,"example":"john_doe"},"fullName":{"type":"string","minLength":1,"maxLength":255,"example":"John Doe"},"phoneNumber":{"type":"string","nullable":true,"example":"+1234567890"},"avatarUrl":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"example":"https://avatar.url"},"jobTitle":{"type":"string","nullable":true,"minLength":1,"maxLength":255,"example":"Manager"},"roleId":{"type":"string","format":"uuid","example":"uuid"},"branchId":{"type":"string","format":"uuid","example":"uuid"},"preferredLanguage":{"type":"string","minLength":1,"maxLength":255,"example":"EN"},"tenantId":{"type":"string","format":"uuid","example":"uuid"}},"required":["email","password","username","fullName","tenantId"]},"AssignPermissionToRoleDto":{"type":"object","properties":{"roleId":{"type":"string","format":"uuid","example":"uuid"},"permissionIds":{"example":["uuid1","uuid2"],"type":"array","items":{"type":"string","format":"uuid"}}},"required":["roleId","permissionIds"]},"AssignRoleToUserDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"uuid"},"roleId":{"type":"string","format":"uuid","example":"uuid"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"branchId":{"type":"string","format":"uuid","example":"uuid"}},"required":["userId","roleId","tenantId"]},"BranchEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Main Street Branch"},"branchCode":{"type":"string","nullable":true,"example":"BR-001"},"type":{"type":"string","enum":["RETAIL","WAREHOUSE","OFFICE","CLINIC","HOTEL","RESTAURANT"],"example":"RETAIL"},"address":{"type":"string","nullable":true,"example":"456 Main St"},"city":{"type":"string","nullable":true,"example":"San Francisco"},"state":{"type":"string","nullable":true,"example":"CA"},"country":{"type":"string","nullable":true,"example":"USA"},"zipCode":{"type":"string","nullable":true,"example":"94101"},"phone":{"type":"string","nullable":true,"example":"+1987654321"},"email":{"type":"string","nullable":true,"example":"main@branch.com"},"latitude":{"type":"string","nullable":true,"example":"37.7749"},"longitude":{"type":"string","nullable":true,"example":"-122.4194"},"status":{"type":"string","enum":["ACTIVE","INACTIVE","TEMPORARILY_CLOSED","MAINTENANCE"],"example":"ACTIVE"},"openingHours":{"type":"object","example":{"mon":"08:00-18:00"}},"managerId":{"type":"string","nullable":true,"example":"uuid"},"locationId":{"type":"string","nullable":true,"example":null,"description":"The operational outlet this branch corresponds to. Branch is the permission hierarchy; Location is what transactions key off. Null until a tenant maps them."},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.779Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.779Z"}},"required":["id","tenantId","name","type","status","createdAt","updatedAt"]},"CreateBranchDto":{"type":"object","properties":{"name":{"type":"string","example":"Main Branch"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"branchCode":{"type":"string","example":"BR001"},"type":{"type":"string","enum":["RETAIL","WAREHOUSE","OFFICE","CLINIC","HOTEL","RESTAURANT"],"default":"RESTAURANT"},"address":{"type":"string","example":"123 Main St"},"city":{"type":"string","example":"New York"},"state":{"type":"string","example":"NY"},"country":{"type":"string","example":"USA"},"zipCode":{"type":"string","example":"10001"},"phone":{"type":"string","example":"+1234567890"},"email":{"type":"string","example":"branch@example.com"},"latitude":{"type":"string","example":40.7128},"longitude":{"type":"string","example":-74.006},"openingHours":{"type":"object","example":{"mon":"09:00-17:00"}}},"required":["name","tenantId"]},"UpdateBranchDto":{"type":"object","properties":{"name":{"type":"string","example":"Main Branch"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"branchCode":{"type":"string","example":"BR001"},"type":{"type":"string","enum":["RETAIL","WAREHOUSE","OFFICE","CLINIC","HOTEL","RESTAURANT"],"default":"RESTAURANT"},"address":{"type":"string","example":"123 Main St"},"city":{"type":"string","example":"New York"},"state":{"type":"string","example":"NY"},"country":{"type":"string","example":"USA"},"zipCode":{"type":"string","example":"10001"},"phone":{"type":"string","example":"+1234567890"},"email":{"type":"string","example":"branch@example.com"},"latitude":{"type":"string","example":40.7128},"longitude":{"type":"string","example":-74.006},"openingHours":{"type":"object","example":{"mon":"09:00-17:00"}}}},"RoleEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"parentId":{"type":"string","nullable":true,"example":"uuid"},"name":{"type":"string","example":"Store Manager"},"isSystemDefault":{"type":"boolean","example":false}},"required":["id","tenantId","name","isSystemDefault"]},"CreateRoleDto":{"type":"object","properties":{"name":{"type":"string","example":"Admin"},"tenantId":{"type":"string","format":"uuid","example":"uuid","description":"System admins only. Tenant users always create roles in their own tenant."},"parentId":{"type":"string","format":"uuid","example":"uuid"},"isSystemDefault":{"type":"boolean","default":false,"example":false}},"required":["name"]},"PermissionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"module":{"type":"string","example":"INVENTORY"},"subject":{"type":"string","example":"PRODUCT"},"action":{"type":"string","example":"READ"},"description":{"type":"string","nullable":true,"example":"Can read products"}},"required":["id","module","subject","action"]},"UpdateRoleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"Night Shift Cashier"},"parentId":{"type":"string","format":"uuid","example":"uuid","nullable":true}}},"RolePermissionsResultDto":{"type":"object","properties":{"count":{"type":"number","example":12,"description":"How many permissions the role holds as a result of the call."}},"required":["count"]},"SetRolePermissionsDto":{"type":"object","properties":{"permissionIds":{"uniqueItems":true,"example":["uuid-1","uuid-2"],"description":"The complete set of permissions this role should hold. Anything not listed is removed.","type":"array","items":{"type":"string","format":"uuid"}}},"required":["permissionIds"]},"CategoryEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"parentId":{"type":"string","nullable":true,"example":"uuid"},"name":{"type":"string","example":"Electronics"},"description":{"type":"string","nullable":true,"example":"Electronic devices and accessories"},"sortOrder":{"type":"number","example":0},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.898Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.898Z"}},"required":["id","tenantId","name","sortOrder","createdAt","updatedAt"]},"CreateCategoryDto":{"type":"object","properties":{"name":{"type":"string","example":"Electronics"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"parentId":{"type":"string","format":"uuid","example":"uuid"},"description":{"type":"string","example":"Electronic devices and accessories"},"sortOrder":{"type":"number","minimum":0,"example":0}},"required":["name","tenantId"]},"UpdateCategoryDto":{"type":"object","properties":{"name":{"type":"string","example":"Electronics"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"parentId":{"type":"string","format":"uuid","example":"uuid"},"description":{"type":"string","example":"Electronic devices and accessories"},"sortOrder":{"type":"number","minimum":0,"example":0}}},"UomClassEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Weight"}},"required":["id","tenantId","name"]},"CreateUomClassDto":{"type":"object","properties":{"name":{"type":"string","example":"Weight"},"tenantId":{"type":"string","format":"uuid","example":"uuid"}},"required":["name","tenantId"]},"UpdateUomClassDto":{"type":"object","properties":{"name":{"type":"string","example":"Weight"},"tenantId":{"type":"string","format":"uuid","example":"uuid"}}},"UomEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"classId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Kilogram"},"abbreviation":{"type":"string","example":"kg"},"conversionRateToBase":{"type":"string","example":"1.000000"}},"required":["id","classId","name","abbreviation","conversionRateToBase"]},"CreateUomDto":{"type":"object","properties":{"name":{"type":"string","example":"Kilogram"},"classId":{"type":"string","format":"uuid","example":"uuid"},"abbreviation":{"type":"string","example":"kg"},"conversionRateToBase":{"type":"string","example":"1.000000"}},"required":["name","classId","abbreviation","conversionRateToBase"]},"UpdateUomDto":{"type":"object","properties":{"name":{"type":"string","example":"Kilogram"},"classId":{"type":"string","format":"uuid","example":"uuid"},"abbreviation":{"type":"string","example":"kg"},"conversionRateToBase":{"type":"string","example":"1.000000"}}},"ProductEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"categoryId":{"type":"string","nullable":true,"example":"uuid"},"baseSku":{"type":"string","example":"SKU-IP15"},"name":{"type":"string","example":"iPhone 15"},"basePrice":{"type":"string","example":"999.0000"},"baseUomId":{"type":"string","example":"uuid"},"globalAttributes":{"type":"object","additionalProperties":true,"properties":{}},"imageUrl":{"type":"string","nullable":true,"example":"/uploads/products/iphone15.jpg"},"trackingType":{"type":"string","nullable":true,"example":"STANDARD"},"isTaxable":{"type":"boolean","nullable":true,"example":true},"taxRateId":{"type":"string","nullable":true,"example":"uuid"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.969Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:21.969Z"},"totalOnHand":{"type":"string","example":"250.0000","description":"Computed on-hand stock across active variants (scoped by locationId when provided). Only populated by list endpoints."}},"required":["id","tenantId","baseSku","name","basePrice","baseUomId","isTaxable","createdAt","updatedAt"]},"CreateProductDto":{"type":"object","properties":{"name":{"type":"string","example":"iPhone 15"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"baseSku":{"type":"string","example":"SKU-IP15"},"basePrice":{"type":"string","example":"999.0000"},"baseUomId":{"type":"string","format":"uuid","example":"uuid"},"categoryId":{"type":"string","format":"uuid","example":"uuid"},"globalAttributes":{"type":"object","example":{}},"imageUrl":{"type":"string","example":"/uploads/products/iphone15.jpg"},"trackingType":{"type":"string","example":"STANDARD"},"isTaxable":{"type":"boolean","example":true},"taxRateId":{"type":"string","format":"uuid","example":"uuid"}},"required":["name","tenantId","baseSku","basePrice","baseUomId"]},"UpdateProductDto":{"type":"object","properties":{"name":{"type":"string","example":"iPhone 15"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"baseSku":{"type":"string","example":"SKU-IP15"},"basePrice":{"type":"string","example":"999.0000"},"baseUomId":{"type":"string","format":"uuid","example":"uuid"},"categoryId":{"type":"string","format":"uuid","example":"uuid"},"globalAttributes":{"type":"object","example":{}},"imageUrl":{"type":"string","example":"/uploads/products/iphone15.jpg"},"trackingType":{"type":"string","example":"STANDARD"},"isTaxable":{"type":"boolean","example":true},"taxRateId":{"type":"string","format":"uuid","example":"uuid"}}},"ProductVariantEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"productId":{"type":"string","example":"uuid"},"variantSku":{"type":"string","example":"SKU-IP15-BLK-128"},"barcode":{"type":"string","nullable":true,"example":"1234567890123"},"matrixOptions":{"type":"object","additionalProperties":true,"example":{"color":"Black","storage":"128GB"}},"priceModifier":{"type":"string","nullable":true,"example":"50.0000"},"imageUrl":{"type":"string","nullable":true,"example":"/uploads/products/iphone15-black.jpg"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.007Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.007Z"}},"required":["id","productId","variantSku","matrixOptions","createdAt","updatedAt"]},"CreateProductVariantDto":{"type":"object","properties":{"variantSku":{"type":"string","example":"SKU-IP15-BLK-128"},"matrixOptions":{"type":"object","example":{"color":"Black","storage":"128GB"}},"barcode":{"type":"string","example":"1234567890123"},"priceModifier":{"type":"string","example":"50.0000"},"imageUrl":{"type":"string","example":"/uploads/products/iphone15-black.jpg"}},"required":["variantSku","matrixOptions"]},"UpdateProductVariantDto":{"type":"object","properties":{"variantSku":{"type":"string","example":"SKU-IP15-BLK-128"},"matrixOptions":{"type":"object","example":{"color":"Black","storage":"128GB"}},"barcode":{"type":"string","example":"1234567890123"},"priceModifier":{"type":"string","example":"50.0000"},"imageUrl":{"type":"string","example":"/uploads/products/iphone15-black.jpg"}}},"LocationEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"parentLocationId":{"type":"string","nullable":true,"example":"uuid"},"name":{"type":"string","example":"Main Warehouse"},"type":{"type":"string","example":"warehouse"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.068Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.068Z"}},"required":["id","tenantId","name","type","createdAt","updatedAt"]},"CreateLocationDto":{"type":"object","properties":{"name":{"type":"string","example":"Main Warehouse"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"parentLocationId":{"type":"string","format":"uuid","example":"uuid"},"type":{"type":"string","example":"warehouse"}},"required":["name","tenantId","type"]},"UpdateLocationDto":{"type":"object","properties":{"name":{"type":"string","example":"Main Warehouse"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"parentLocationId":{"type":"string","format":"uuid","example":"uuid"},"type":{"type":"string","example":"warehouse"}}},"VendorEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Acme Supplies"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","name","createdAt","updatedAt"]},"CreateVendorDto":{"type":"object","properties":{"name":{"type":"string","example":"Acme Supplies"},"tenantId":{"type":"string","format":"uuid","example":"uuid"}},"required":["name","tenantId"]},"UpdateVendorDto":{"type":"object","properties":{"name":{"type":"string","example":"Acme Supplies"},"tenantId":{"type":"string","format":"uuid","example":"uuid"}}},"TransferOrderEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"sourceLocationId":{"type":"string","example":"uuid"},"transitLocationId":{"type":"string","example":"uuid"},"destinationLocationId":{"type":"string","example":"uuid"},"transferNumber":{"type":"string","example":"TO-2026-0001"},"status":{"type":"string","nullable":true,"example":"DRAFT","enum":["DRAFT","SHIPPED","PARTIALLY_RECEIVED","COMPLETED"]},"shippedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"receivedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdBy":{"type":"string","nullable":true,"example":"uuid"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.115Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.115Z"}},"required":["id","tenantId","sourceLocationId","transitLocationId","destinationLocationId","transferNumber","createdAt","updatedAt"]},"CreateTransferOrderDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"sourceLocationId":{"type":"string","format":"uuid","example":"uuid"},"transitLocationId":{"type":"string","format":"uuid","example":"uuid"},"destinationLocationId":{"type":"string","format":"uuid","example":"uuid"},"transferNumber":{"type":"string","example":"TO-2026-0001"},"createdBy":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","sourceLocationId","transitLocationId","destinationLocationId","transferNumber"]},"UpdateTransferOrderDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"sourceLocationId":{"type":"string","format":"uuid","example":"uuid"},"transitLocationId":{"type":"string","format":"uuid","example":"uuid"},"destinationLocationId":{"type":"string","format":"uuid","example":"uuid"},"transferNumber":{"type":"string","example":"TO-2026-0001"},"createdBy":{"type":"string","format":"uuid","example":"uuid"}}},"TransferOrderLineEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"transferOrderId":{"type":"string","example":"uuid"},"productId":{"type":"string","example":"uuid"},"requestedQuantity":{"type":"string","example":"10.0000"},"shippedQuantity":{"type":"string","nullable":true,"example":"0.0000"},"receivedQuantity":{"type":"string","nullable":true,"example":"0.0000"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.125Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.125Z"}},"required":["id","transferOrderId","productId","requestedQuantity","createdAt","updatedAt"]},"CreateTransferOrderLineDto":{"type":"object","properties":{"productId":{"type":"string","format":"uuid","example":"uuid"},"requestedQuantity":{"type":"string","example":"10.0000"},"shippedQuantity":{"type":"string","example":"0.0000"},"receivedQuantity":{"type":"string","example":"0.0000"}},"required":["productId","requestedQuantity"]},"UpdateTransferOrderLineDto":{"type":"object","properties":{"productId":{"type":"string","format":"uuid","example":"uuid"},"requestedQuantity":{"type":"string","example":"10.0000"},"shippedQuantity":{"type":"string","example":"0.0000"},"receivedQuantity":{"type":"string","example":"0.0000"}}},"PurchaseRequisitionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"requestedBy":{"type":"string","example":"uuid"},"department":{"type":"string","nullable":true,"example":"Engineering"},"justification":{"type":"string","nullable":true,"example":"Urgent restock of office supplies"},"status":{"type":"string","nullable":true,"example":"PENDING_APPROVAL","enum":["PENDING_APPROVAL","APPROVED","REJECTED"]},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.168Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.168Z"}},"required":["id","tenantId","requestedBy","createdAt","updatedAt"]},"CreatePurchaseRequisitionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"requestedBy":{"type":"string","format":"uuid","example":"uuid"},"department":{"type":"string","example":"Engineering"},"justification":{"type":"string","example":"Urgent restock of office supplies"}},"required":["tenantId","requestedBy"]},"UpdatePurchaseRequisitionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"requestedBy":{"type":"string","format":"uuid","example":"uuid"},"department":{"type":"string","example":"Engineering"},"justification":{"type":"string","example":"Urgent restock of office supplies"}}},"PurchaseOrderEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"requisitionId":{"type":"string","nullable":true,"example":"uuid"},"vendorId":{"type":"string","example":"uuid"},"poNumber":{"type":"string","example":"PO-2026-0001"},"currency":{"type":"string","example":"USD"},"expectedDeliveryDate":{"format":"date-time","type":"string","nullable":true,"example":"2026-04-15"},"status":{"type":"string","nullable":true,"example":"DRAFT","enum":["DRAFT","ISSUED","PARTIAL_RECEIPT","FULFILLED","CLOSED"]},"totalAmount":{"type":"string","example":"15000.00"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.184Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.184Z"}},"required":["id","tenantId","vendorId","poNumber","currency","totalAmount","createdAt","updatedAt"]},"CreatePurchaseOrderDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"vendorId":{"type":"string","format":"uuid","example":"uuid"},"poNumber":{"type":"string","example":"PO-2026-0001"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"totalAmount":{"type":"string","example":"15000.00"},"requisitionId":{"type":"string","format":"uuid","example":"uuid"},"expectedDeliveryDate":{"type":"string","example":"2026-04-15"}},"required":["tenantId","vendorId","poNumber","currency","totalAmount"]},"UpdatePurchaseOrderDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"vendorId":{"type":"string","format":"uuid","example":"uuid"},"poNumber":{"type":"string","example":"PO-2026-0001"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"totalAmount":{"type":"string","example":"15000.00"},"requisitionId":{"type":"string","format":"uuid","example":"uuid"},"expectedDeliveryDate":{"type":"string","example":"2026-04-15"}}},"GoodsReceivedNoteEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"purchaseOrderId":{"type":"string","example":"uuid"},"receivingLocationId":{"type":"string","example":"uuid"},"grnNumber":{"type":"string","example":"GRN-2026-0001"},"receivedBy":{"type":"string","nullable":true,"example":"uuid"},"receivedAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-09-21T21:31:22.193Z"},"status":{"type":"string","nullable":true,"example":"INSPECTING","enum":["INSPECTING","ACCEPTED","REJECTED"]},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.193Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.194Z"}},"required":["id","tenantId","purchaseOrderId","receivingLocationId","grnNumber","createdAt","updatedAt"]},"CreateGoodsReceivedNoteDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"purchaseOrderId":{"type":"string","format":"uuid","example":"uuid"},"receivingLocationId":{"type":"string","format":"uuid","example":"uuid"},"grnNumber":{"type":"string","example":"GRN-2026-0001"},"receivedBy":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","purchaseOrderId","receivingLocationId","grnNumber"]},"UpdateGoodsReceivedNoteDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"purchaseOrderId":{"type":"string","format":"uuid","example":"uuid"},"receivingLocationId":{"type":"string","format":"uuid","example":"uuid"},"grnNumber":{"type":"string","example":"GRN-2026-0001"},"receivedBy":{"type":"string","format":"uuid","example":"uuid"}}},"GrnLineEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"grnId":{"type":"string","example":"uuid"},"poLineId":{"type":"string","example":"uuid"},"productId":{"type":"string","example":"uuid"},"receivedQuantity":{"type":"string","example":"100.0000"},"acceptedQuantity":{"type":"string","nullable":true,"example":"95.0000"},"rejectedQuantity":{"type":"string","nullable":true,"example":"5.0000"},"inventoryLedgerPosted":{"type":"boolean","nullable":true,"example":false},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.205Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.205Z"}},"required":["id","grnId","poLineId","productId","receivedQuantity","createdAt","updatedAt"]},"CreateGrnLineDto":{"type":"object","properties":{"poLineId":{"type":"string","format":"uuid","example":"uuid"},"productId":{"type":"string","format":"uuid","example":"uuid"},"receivedQuantity":{"type":"string","example":"100.0000"},"acceptedQuantity":{"type":"string","example":"95.0000"},"rejectedQuantity":{"type":"string","example":"5.0000"},"inventoryLedgerPosted":{"type":"boolean","example":false}},"required":["poLineId","productId","receivedQuantity"]},"UpdateGrnLineDto":{"type":"object","properties":{"poLineId":{"type":"string","format":"uuid","example":"uuid"},"productId":{"type":"string","format":"uuid","example":"uuid"},"receivedQuantity":{"type":"string","example":"100.0000"},"acceptedQuantity":{"type":"string","example":"95.0000"},"rejectedQuantity":{"type":"string","example":"5.0000"},"inventoryLedgerPosted":{"type":"boolean","example":false}}},"VendorInvoiceEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"vendorId":{"type":"string","example":"uuid"},"invoiceNumber":{"type":"string","example":"INV-2026-0001"},"invoiceType":{"type":"string","example":"STANDARD"},"matchedPoId":{"type":"string","nullable":true,"example":"uuid"},"matchedGrnId":{"type":"string","nullable":true,"example":"uuid"},"totalAmount":{"type":"string","example":"15000.00"},"status":{"type":"string","nullable":true,"example":"UNPAID","enum":["UNPAID","PARTIALLY_PAID","PAID"]},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.216Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.216Z"}},"required":["id","tenantId","vendorId","invoiceNumber","invoiceType","totalAmount","createdAt","updatedAt"]},"CreateVendorInvoiceDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"vendorId":{"type":"string","format":"uuid","example":"uuid"},"invoiceNumber":{"type":"string","example":"INV-2026-0001"},"invoiceType":{"type":"string","example":"STANDARD"},"totalAmount":{"type":"string","example":"15000.00"},"matchedPoId":{"type":"string","format":"uuid","example":"uuid"},"matchedGrnId":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","vendorId","invoiceNumber","invoiceType","totalAmount"]},"UpdateVendorInvoiceDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"vendorId":{"type":"string","format":"uuid","example":"uuid"},"invoiceNumber":{"type":"string","example":"INV-2026-0001"},"invoiceType":{"type":"string","example":"STANDARD"},"totalAmount":{"type":"string","example":"15000.00"},"matchedPoId":{"type":"string","format":"uuid","example":"uuid"},"matchedGrnId":{"type":"string","format":"uuid","example":"uuid"}}},"LandedCostAllocationEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"sourceInvoiceId":{"type":"string","example":"uuid"},"targetGrnId":{"type":"string","example":"uuid"},"targetGrnLineId":{"type":"string","example":"uuid"},"allocationMethod":{"type":"string","example":"BY_VALUE"},"allocatedAmount":{"type":"string","example":"500.00"},"glJournalPosted":{"type":"boolean","nullable":true,"example":false},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.227Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.227Z"}},"required":["id","tenantId","sourceInvoiceId","targetGrnId","targetGrnLineId","allocationMethod","allocatedAmount","createdAt","updatedAt"]},"CreateLandedCostAllocationDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"sourceInvoiceId":{"type":"string","format":"uuid","example":"uuid"},"targetGrnId":{"type":"string","format":"uuid","example":"uuid"},"targetGrnLineId":{"type":"string","format":"uuid","example":"uuid"},"allocationMethod":{"type":"string","example":"BY_VALUE"},"allocatedAmount":{"type":"string","example":"500.00"},"glJournalPosted":{"type":"boolean","example":false}},"required":["tenantId","sourceInvoiceId","targetGrnId","targetGrnLineId","allocationMethod","allocatedAmount"]},"UpdateLandedCostAllocationDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"sourceInvoiceId":{"type":"string","format":"uuid","example":"uuid"},"targetGrnId":{"type":"string","format":"uuid","example":"uuid"},"targetGrnLineId":{"type":"string","format":"uuid","example":"uuid"},"allocationMethod":{"type":"string","example":"BY_VALUE"},"allocatedAmount":{"type":"string","example":"500.00"},"glJournalPosted":{"type":"boolean","example":false}}},"CustomerEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"accountType":{"type":"string","nullable":true,"example":"RETAIL"},"name":{"type":"string","example":"Walk-In Customer"},"phone":{"type":"string","nullable":true,"example":"09123456789"},"email":{"type":"string","nullable":true,"example":"customer@example.com"},"hasCreditAccount":{"type":"boolean","nullable":true,"example":false},"maxCreditLimit":{"type":"string","nullable":true,"example":"0.0000"},"currentCreditBalance":{"type":"string","nullable":true,"example":"0.0000"},"paymentTermsDays":{"type":"number","nullable":true,"example":0},"loyaltyTier":{"type":"string","nullable":true,"example":"BRONZE"},"lifetimePointsEarned":{"type":"number","nullable":true,"example":0},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","name","createdAt","updatedAt"]},"CreateCustomerDto":{"type":"object","properties":{"name":{"type":"string","example":"Walk-In Customer"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"phone":{"type":"string","example":"09123456789"},"email":{"type":"string","format":"email","example":"customer@example.com"},"accountType":{"type":"string","example":"RETAIL"},"hasCreditAccount":{"type":"boolean","example":false},"maxCreditLimit":{"type":"string","example":"5000.0000"},"paymentTermsDays":{"type":"number","minimum":0,"example":30},"loyaltyTier":{"type":"string","example":"BRONZE"}},"required":["name","tenantId"]},"UpdateCustomerDto":{"type":"object","properties":{"name":{"type":"string","example":"Walk-In Customer"},"tenantId":{"type":"string","format":"uuid","example":"uuid"},"phone":{"type":"string","example":"09123456789"},"email":{"type":"string","format":"email","example":"customer@example.com"},"accountType":{"type":"string","example":"RETAIL"},"hasCreditAccount":{"type":"boolean","example":false},"maxCreditLimit":{"type":"string","example":"5000.0000"},"paymentTermsDays":{"type":"number","minimum":0,"example":30},"loyaltyTier":{"type":"string","example":"BRONZE"}}},"LoyaltyLedgerEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"customerId":{"type":"string","example":"uuid"},"transactionType":{"type":"string","example":"EARN"},"points":{"type":"number","example":100},"referenceOrderId":{"type":"string","nullable":true,"example":"uuid"},"expiryDate":{"format":"date-time","type":"string","nullable":true,"example":"2026-12-31"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","customerId","transactionType","points","createdAt","updatedAt"]},"CreateLoyaltyLedgerDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"transactionType":{"type":"string","example":"EARN"},"points":{"type":"number","example":100},"referenceOrderId":{"type":"string","format":"uuid","example":"uuid"},"expiryDate":{"format":"date-time","type":"string","example":"2026-12-31"}},"required":["tenantId","transactionType","points"]},"UpdateLoyaltyLedgerDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"transactionType":{"type":"string","example":"EARN"},"points":{"type":"number","example":100},"referenceOrderId":{"type":"string","format":"uuid","example":"uuid"},"expiryDate":{"format":"date-time","type":"string","example":"2026-12-31"}}},"CustomerInteractionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"customerId":{"type":"string","example":"uuid"},"agentId":{"type":"string","nullable":true,"example":"uuid"},"interactionChannel":{"type":"string","example":"EMAIL"},"interactionType":{"type":"string","example":"INQUIRY"},"summary":{"type":"string","example":"Customer asked about product availability"},"detailedNotes":{"type":"string","nullable":true,"example":"Detailed notes here..."},"externalReferenceId":{"type":"string","nullable":true,"example":"EXT-REF-001"},"interactionDate":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","customerId","interactionChannel","interactionType","summary","interactionDate","updatedAt"]},"CreateCustomerInteractionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"agentId":{"type":"string","format":"uuid","example":"uuid"},"interactionChannel":{"type":"string","example":"EMAIL"},"interactionType":{"type":"string","example":"INQUIRY"},"summary":{"type":"string","example":"Customer asked about product availability"},"detailedNotes":{"type":"string","example":"Detailed notes here..."},"externalReferenceId":{"type":"string","example":"EXT-REF-001"}},"required":["tenantId","interactionChannel","interactionType","summary"]},"UpdateCustomerInteractionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"agentId":{"type":"string","format":"uuid","example":"uuid"},"interactionChannel":{"type":"string","example":"EMAIL"},"interactionType":{"type":"string","example":"INQUIRY"},"summary":{"type":"string","example":"Customer asked about product availability"},"detailedNotes":{"type":"string","example":"Detailed notes here..."},"externalReferenceId":{"type":"string","example":"EXT-REF-001"}}},"SalesOrderEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"customerId":{"type":"string","nullable":true,"example":"uuid"},"locationId":{"type":"string","nullable":true,"example":"uuid"},"orderNumber":{"type":"string","example":"SO-R01-20260728-0001"},"businessDate":{"type":"string","example":"2026-07-28"},"salesChannel":{"type":"string","example":"POS"},"serviceType":{"type":"string","nullable":true,"enum":["DINE_IN","TAKEAWAY","DELIVERY","COUNTER"],"example":"DINE_IN"},"idempotencyKey":{"type":"string","nullable":true,"example":"idem-key-001"},"subtotal":{"type":"string","example":"100.0000"},"totalDiscount":{"type":"string","nullable":true,"example":"10.0000"},"discountReasonId":{"type":"string","nullable":true,"example":"uuid"},"totalTax":{"type":"string","nullable":true,"example":"5.0000"},"tipAmount":{"type":"string","example":"5.0000"},"serviceCharge":{"type":"string","example":"3.0000"},"grandTotal":{"type":"string","example":"95.0000"},"status":{"type":"string","nullable":true,"example":"DRAFT","enum":["DRAFT","COMPLETED","ON_HOLD_CREDIT","VOIDED","PARTIALLY_REFUNDED","REFUNDED"]},"pickupNumber":{"type":"string","nullable":true,"example":"A47","description":"Display number for counter pickup"},"pickedUpAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","orderNumber","businessDate","salesChannel","subtotal","tipAmount","serviceCharge","grandTotal","createdAt","updatedAt"]},"CreateSalesOrderDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"customerId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"orderNumber":{"type":"string","example":"SO-WEB-20260728-0001","description":"Auto-generated when omitted. Supplying one risks colliding with the tenant-scoped uniqueness constraint."},"salesChannel":{"type":"string","example":"POS"},"idempotencyKey":{"type":"string","example":"idem-key-001"},"subtotal":{"type":"string","example":"100.0000"},"totalDiscount":{"type":"string","example":"10.0000"},"totalTax":{"type":"string","example":"5.0000"},"grandTotal":{"type":"string","example":"95.0000"},"status":{"type":"string","example":"DRAFT","enum":["DRAFT","COMPLETED","ON_HOLD_CREDIT","VOIDED","PARTIALLY_REFUNDED","REFUNDED"]}},"required":["tenantId","salesChannel","subtotal","grandTotal"]},"SettleOrderResponseDto":{"type":"object","properties":{"orderId":{"type":"string","example":"uuid"},"orderNumber":{"type":"string","example":"SO-R02-20260921-0001"},"grandTotal":{"type":"string","example":"100000.0000","description":"Recomputed from the lines as they stand, plus tip and service."},"totalPaid":{"type":"string","example":"100000.0000"},"change":{"type":"string","example":"0.0000"},"status":{"type":"string","example":"COMPLETED"}},"required":["orderId","orderNumber","grandTotal","totalPaid","change","status"]},"CheckoutPaymentDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","format":"uuid","example":"uuid","description":"Payment method ID"},"amount":{"type":"string","example":"100.0000","description":"Payment amount (includes any tip). May be omitted for a guest-card tender, which then covers whatever the rest of the bill comes to - the server knows the tier discount and the client does not have to compute it."},"guestCardId":{"type":"string","format":"uuid","example":"uuid","description":"The card that was tapped. Required when the payment method is a guest card, and meaningless otherwise. The wallet behind it is charged as part of the same transaction that closes the order."},"tipAmount":{"type":"string","example":"5.0000","description":"Tip amount included in this payment"},"transactionReference":{"type":"string","example":"TXN-12345","description":"External transaction reference (card, mobile, etc.)"}},"required":["paymentMethodId"]},"SettleOrderDto":{"type":"object","properties":{"payments":{"minItems":1,"description":"How the bill is being paid. Same shape as checkout, so a split between cash and a guest card works the same way. A guest-card tender may leave its amount out and will be charged whatever the rest of the bill comes to.","type":"array","items":{"$ref":"#/components/schemas/CheckoutPaymentDto"}},"customerId":{"type":"string","format":"uuid","example":"uuid","description":"Customer the bill is being put on. Required for a CUSTOMER_CREDIT tender, and what loyalty points are awarded against."},"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"tipAmount":{"type":"string","example":"5.0000","description":"Tip on the whole bill, added to the total being settled."},"serviceCharge":{"type":"string","example":"3.0000","description":"Service charge on the whole bill, added to the total."},"idempotencyKey":{"type":"string","maxLength":255,"example":"settle-order-001","description":"Reuse when retrying after a network error and the settled order is returned rather than the bill being paid twice."}},"required":["payments"]},"UpdateSalesOrderDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"customerId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"orderNumber":{"type":"string","example":"SO-WEB-20260728-0001","description":"Auto-generated when omitted. Supplying one risks colliding with the tenant-scoped uniqueness constraint."},"salesChannel":{"type":"string","example":"POS"},"idempotencyKey":{"type":"string","example":"idem-key-001"},"subtotal":{"type":"string","example":"100.0000"},"totalDiscount":{"type":"string","example":"10.0000"},"totalTax":{"type":"string","example":"5.0000"},"grandTotal":{"type":"string","example":"95.0000"},"status":{"type":"string","example":"DRAFT","enum":["DRAFT","COMPLETED","ON_HOLD_CREDIT","VOIDED","PARTIALLY_REFUNDED","REFUNDED"]}}},"SalesOrderLineEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"salesOrderId":{"type":"string","example":"uuid"},"variantId":{"type":"string","example":"uuid"},"quantity":{"type":"string","example":"2.0000"},"unitPrice":{"type":"string","example":"49.9900"},"lineDiscount":{"type":"string","nullable":true,"example":"0.0000"},"taxRateId":{"type":"string","nullable":true,"example":"uuid"},"taxAmount":{"type":"string","nullable":true,"example":"5.0000"},"appliedPromotionId":{"type":"string","nullable":true,"example":"uuid"},"status":{"type":"string","nullable":true,"enum":["PENDING","FIRED","READY","SERVED","VOIDED","COMPED"],"example":"PENDING"},"firedAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-01-01T00:00:00.000Z"},"voidedAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-01-01T00:00:00.000Z"},"voidReasonId":{"type":"string","nullable":true,"example":"uuid"},"compReasonId":{"type":"string","nullable":true,"example":"uuid"},"courseType":{"type":"string","nullable":true,"example":"MAIN"},"selectedModifiers":{"type":"object","additionalProperties":true,"properties":{},"description":"JSONB array of selected modifiers"},"seatNumber":{"type":"number","nullable":true,"example":1},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","salesOrderId","variantId","quantity","unitPrice","selectedModifiers","createdAt","updatedAt"]},"SelectedModifierDto":{"type":"object","properties":{"modifierId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Bacon"},"priceDelta":{"type":"string","example":"2.0000"}},"required":["modifierId","name","priceDelta"]},"CreateSalesOrderLineDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid","example":"uuid"},"quantity":{"type":"string","example":"2.0000"},"unitPrice":{"type":"string","example":"49.9900"},"lineDiscount":{"type":"string","example":"0.0000"},"taxRateId":{"type":"string","format":"uuid","example":"uuid"},"taxAmount":{"type":"string","example":"0.0000"},"appliedPromotionId":{"type":"string","format":"uuid","example":"uuid"},"courseType":{"type":"string","example":"MAIN","description":"Course (APPETIZER, MAIN, DESSERT, etc.)"},"selectedModifiers":{"description":"Snapshot of modifier choices made for this line","type":"array","items":{"$ref":"#/components/schemas/SelectedModifierDto"}},"seatNumber":{"type":"number","minimum":1,"example":1}},"required":["variantId","quantity","unitPrice"]},"UpdateSalesOrderLineDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid","example":"uuid"},"quantity":{"type":"string","example":"2.0000"},"unitPrice":{"type":"string","example":"49.9900"},"lineDiscount":{"type":"string","example":"0.0000"},"taxRateId":{"type":"string","format":"uuid","example":"uuid"},"taxAmount":{"type":"string","example":"0.0000"},"appliedPromotionId":{"type":"string","format":"uuid","example":"uuid"},"courseType":{"type":"string","example":"MAIN","description":"Course (APPETIZER, MAIN, DESSERT, etc.)"},"selectedModifiers":{"description":"Snapshot of modifier choices made for this line","type":"array","items":{"$ref":"#/components/schemas/SelectedModifierDto"}},"seatNumber":{"type":"number","minimum":1,"example":1}}},"VoidLineDto":{"type":"object","properties":{"voidReasonId":{"type":"string","format":"uuid","example":"uuid"},"notes":{"type":"string","example":"Customer changed their mind after firing"}},"required":["voidReasonId"]},"CompLineDto":{"type":"object","properties":{"compReasonId":{"type":"string","format":"uuid","example":"uuid"},"notes":{"type":"string","example":"Birthday on the house"}},"required":["compReasonId"]},"OrderPaymentEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"salesOrderId":{"type":"string","example":"uuid"},"paymentMethodId":{"type":"string","example":"uuid"},"posSessionId":{"type":"string","nullable":true,"example":"uuid"},"amount":{"type":"string","example":"100.0000"},"tipAmount":{"type":"string","example":"5.0000"},"transactionReference":{"type":"string","nullable":true,"example":"TXN-12345"},"paymentDate":{"format":"date-time","type":"string","nullable":true,"example":"2026-01-01T00:00:00.000Z"},"walletLedgerEntryId":{"type":"string","nullable":true,"example":null,"description":"The wallet debit that funded this payment, for a guest-card tender. Unique, so one ledger entry can never fund two payments."},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","salesOrderId","paymentMethodId","amount","tipAmount","updatedAt"]},"CreateOrderPaymentDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"amount":{"type":"string","example":"100.0000"},"tipAmount":{"type":"string","example":"5.0000"},"transactionReference":{"type":"string","example":"TXN-12345"}},"required":["tenantId","paymentMethodId","amount"]},"UpdateOrderPaymentDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"amount":{"type":"string","example":"100.0000"},"tipAmount":{"type":"string","example":"5.0000"},"transactionReference":{"type":"string","example":"TXN-12345"}}},"PromotionRuleEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"10% Off Electronics"},"eligibilityCriteria":{"type":"object","example":{"category":"Electronics"}},"rewardAction":{"type":"object","example":{"type":"PERCENTAGE_DISCOUNT","value":10}},"priorityLevel":{"type":"number","nullable":true,"example":0},"isStackable":{"type":"boolean","nullable":true,"example":false},"startDate":{"format":"date-time","type":"string","nullable":true,"example":"2026-01-01T00:00:00.000Z"},"endDate":{"format":"date-time","type":"string","nullable":true,"example":"2026-12-31T00:00:00.000Z"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","name","eligibilityCriteria","rewardAction","createdAt","updatedAt"]},"CreatePromotionRuleDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"10% Off Electronics"},"eligibilityCriteria":{"type":"object","example":{"category":"Electronics"}},"rewardAction":{"type":"object","example":{"type":"PERCENTAGE_DISCOUNT","value":10}},"priorityLevel":{"type":"number","minimum":0,"example":0},"isStackable":{"type":"boolean","example":false},"startDate":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"endDate":{"format":"date-time","type":"string","example":"2026-12-31T00:00:00.000Z"}},"required":["tenantId","name","eligibilityCriteria","rewardAction"]},"UpdatePromotionRuleDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"10% Off Electronics"},"eligibilityCriteria":{"type":"object","example":{"category":"Electronics"}},"rewardAction":{"type":"object","example":{"type":"PERCENTAGE_DISCOUNT","value":10}},"priorityLevel":{"type":"number","minimum":0,"example":0},"isStackable":{"type":"boolean","example":false},"startDate":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"endDate":{"format":"date-time","type":"string","example":"2026-12-31T00:00:00.000Z"}}},"CheckoutResponseDto":{"type":"object","properties":{"orderId":{"type":"string","example":"uuid"},"orderNumber":{"type":"string","example":"SO-20260402-0001"},"grandTotal":{"type":"string","example":"95.0000"},"totalPaid":{"type":"string","example":"100.0000"},"change":{"type":"string","example":"5.0000","description":"Change to return (cash overpayment)"},"status":{"type":"string","example":"COMPLETED"},"lines":{"description":"Order line items","type":"array","items":{"$ref":"#/components/schemas/SalesOrderLineEntity"}},"payments":{"description":"What was recorded against each tender. A cash row holds what was handed over, so it can exceed the bill by the change given back.","type":"array","items":{"$ref":"#/components/schemas/OrderPaymentEntity"}}},"required":["orderId","orderNumber","grandTotal","totalPaid","change","status","lines","payments"]},"CheckoutItemDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid","example":"uuid","description":"Product variant ID"},"quantity":{"type":"string","example":"1.0000","description":"Quantity to purchase"},"lineDiscount":{"type":"string","example":"5.0000","description":"Per-line discount amount"}},"required":["variantId","quantity"]},"CheckoutDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid","description":"Location/store ID"},"salesChannel":{"type":"string","example":"POS","description":"Sales channel (POS, ONLINE)"},"customerId":{"type":"string","format":"uuid","example":"uuid","description":"Customer ID"},"posSessionId":{"type":"string","format":"uuid","example":"uuid","description":"POS session ID"},"serviceType":{"type":"string","enum":["DINE_IN","TAKEAWAY","DELIVERY","COUNTER"],"description":"DINE_IN, TAKEAWAY, DELIVERY, COUNTER"},"lineStatus":{"type":"string","enum":["PENDING","FIRED","READY","SERVED","VOIDED","COMPED"],"description":"Initial line status. Defaults to SERVED (instant retail). Use PENDING for counter/QSR orders that need kitchen prep — fire to KDS afterwards."},"tipAmount":{"type":"string","example":"5.0000","description":"Total tip amount on this order"},"serviceCharge":{"type":"string","example":"3.0000","description":"Service charge added to this order"},"discountReasonId":{"type":"string","format":"uuid","example":"uuid","description":"Discount reason for any order-level discount"},"idempotencyKey":{"type":"string","example":"idem-key-001","description":"Idempotency key to prevent duplicate orders"},"items":{"minItems":1,"description":"Cart items","type":"array","items":{"$ref":"#/components/schemas/CheckoutItemDto"}},"payments":{"minItems":1,"description":"Payments","type":"array","items":{"$ref":"#/components/schemas/CheckoutPaymentDto"}}},"required":["locationId","salesChannel","items","payments"]},"ReceiptHeaderDto":{"type":"object","properties":{"businessName":{"type":"string","example":"Acme Corp"},"legalName":{"type":"string","nullable":true,"example":"Acme Corporation Ltd."},"logoUrl":{"type":"string","nullable":true,"example":"https://example.com/logo.png"},"address":{"type":"string","nullable":true,"example":"123 Main Street"},"city":{"type":"string","nullable":true,"example":"New York"},"state":{"type":"string","nullable":true,"example":"NY"},"country":{"type":"string","nullable":true,"example":"US"},"zipCode":{"type":"string","nullable":true,"example":"10001"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"email":{"type":"string","nullable":true,"example":"info@acme.com"},"website":{"type":"string","nullable":true,"example":"https://acme.com"}},"required":["businessName"]},"ReceiptOrderInfoDto":{"type":"object","properties":{"receiptNumber":{"type":"string","example":"RCP-20260402-0001"},"orderNumber":{"type":"string","example":"SO-20260402-0001"},"dateTime":{"format":"date-time","type":"string","example":"2026-04-02T10:30:00.000Z"},"salesChannel":{"type":"string","example":"POS"},"locationName":{"type":"string","nullable":true,"example":"Main Store"}},"required":["receiptNumber","orderNumber","dateTime","salesChannel"]},"ReceiptCustomerDto":{"type":"object","properties":{"name":{"type":"string","example":"John Doe"},"phone":{"type":"string","nullable":true,"example":"+1-555-0199"},"email":{"type":"string","nullable":true,"example":"john@example.com"},"loyaltyTier":{"type":"string","nullable":true,"example":"GOLD"},"pointsEarned":{"type":"number","example":95,"description":"Loyalty points earned from this order"}},"required":["name","pointsEarned"]},"ReceiptLineItemDto":{"type":"object","properties":{"productName":{"type":"string","example":"Wireless Mouse"},"variantSku":{"type":"string","example":"WM-BLK-001"},"barcode":{"type":"string","nullable":true,"example":"4901234567890"},"variantOptions":{"type":"object","example":{"color":"Black","size":"Standard"},"description":"Variant options (color, size, etc.)"},"quantity":{"type":"string","example":"2.0000"},"unitPrice":{"type":"string","example":"29.9900"},"lineDiscount":{"type":"string","example":"0.0000"},"taxAmount":{"type":"string","example":"4.2000"},"lineTotal":{"type":"string","example":"64.1800"}},"required":["productName","variantSku","quantity","unitPrice","lineDiscount","taxAmount","lineTotal"]},"ReceiptTaxSummaryLineDto":{"type":"object","properties":{"taxName":{"type":"string","example":"VAT 7%"},"ratePercentage":{"type":"string","example":"0.0700"},"taxableAmount":{"type":"string","example":"59.9800"},"taxAmount":{"type":"string","example":"4.2000"}},"required":["taxName","ratePercentage","taxableAmount","taxAmount"]},"ReceiptTotalsDto":{"type":"object","properties":{"subtotal":{"type":"string","example":"59.9800"},"totalDiscount":{"type":"string","example":"0.0000"},"totalTax":{"type":"string","example":"4.2000"},"grandTotal":{"type":"string","example":"64.1800"}},"required":["subtotal","totalDiscount","totalTax","grandTotal"]},"ReceiptPaymentDto":{"type":"object","properties":{"methodName":{"type":"string","example":"CASH"},"amount":{"type":"string","example":"70.0000"},"transactionReference":{"type":"string","nullable":true,"example":"TXN-12345"},"paymentDate":{"format":"date-time","type":"string","nullable":true,"example":"2026-04-02T10:30:00.000Z"}},"required":["methodName","amount"]},"ReceiptPaymentSummaryDto":{"type":"object","properties":{"payments":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptPaymentDto"}},"totalPaid":{"type":"string","example":"70.0000"},"changeDue":{"type":"string","example":"5.8200"}},"required":["payments","totalPaid","changeDue"]},"ReceiptFooterDto":{"type":"object","properties":{"message":{"type":"string","example":"Thank you for your purchase!"},"returnPolicy":{"type":"string","nullable":true,"example":"Returns accepted within 30 days with receipt."}},"required":["message"]},"ReceiptResponseDto":{"type":"object","properties":{"header":{"$ref":"#/components/schemas/ReceiptHeaderDto"},"orderInfo":{"$ref":"#/components/schemas/ReceiptOrderInfoDto"},"customer":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/ReceiptCustomerDto"}]},"lineItems":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptLineItemDto"}},"taxSummary":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptTaxSummaryLineDto"}},"totals":{"$ref":"#/components/schemas/ReceiptTotalsDto"},"paymentSummary":{"$ref":"#/components/schemas/ReceiptPaymentSummaryDto"},"footer":{"$ref":"#/components/schemas/ReceiptFooterDto"}},"required":["header","orderInfo","lineItems","taxSummary","totals","paymentSummary","footer"]},"ReturnLineResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"salesOrderLineId":{"type":"string","example":"uuid"},"variantId":{"type":"string","example":"uuid"},"returnedQuantity":{"type":"string","example":"1.0000"},"unitPrice":{"type":"string","example":"29.9900"},"lineDiscount":{"type":"string","example":"0.0000"},"taxAmount":{"type":"string","example":"2.1000"},"lineRefund":{"type":"string","example":"32.0900"}},"required":["id","salesOrderLineId","variantId","returnedQuantity","unitPrice","lineDiscount","taxAmount","lineRefund"]},"ReturnResponseDto":{"type":"object","properties":{"returnId":{"type":"string","example":"uuid"},"returnNumber":{"type":"string","example":"RET-20260403-0001"},"salesOrderId":{"type":"string","example":"uuid"},"reason":{"type":"string","example":"Defective product"},"refundMethod":{"type":"string","example":"CASH","enum":["ORIGINAL_PAYMENT","STORE_CREDIT","CASH"]},"subtotalRefund":{"type":"string","example":"29.9900"},"taxRefund":{"type":"string","example":"2.1000"},"totalRefund":{"type":"string","example":"32.0900"},"orderStatus":{"type":"string","example":"PARTIALLY_REFUNDED"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ReturnLineResponseDto"}},"createdAt":{"format":"date-time","type":"string","example":"2026-04-03T10:30:00.000Z"}},"required":["returnId","returnNumber","salesOrderId","reason","refundMethod","subtotalRefund","taxRefund","totalRefund","orderStatus","lines","createdAt"]},"ReturnItemDto":{"type":"object","properties":{"salesOrderLineId":{"type":"string","format":"uuid","example":"uuid","description":"Original sales order line ID"},"returnedQuantity":{"type":"string","example":"1.0000","description":"Quantity to return"}},"required":["salesOrderLineId","returnedQuantity"]},"ProcessReturnDto":{"type":"object","properties":{"salesOrderId":{"type":"string","format":"uuid","example":"uuid","description":"Sales order ID to return against"},"reason":{"type":"string","maxLength":500,"example":"Defective product","description":"Reason for return"},"refundMethod":{"type":"string","example":"CASH","enum":["ORIGINAL_PAYMENT","STORE_CREDIT","CASH"],"description":"How to issue the refund"},"posSessionId":{"type":"string","format":"uuid","example":"uuid","description":"POS session ID"},"items":{"minItems":1,"description":"Items to return","type":"array","items":{"$ref":"#/components/schemas/ReturnItemDto"}},"tenantId":{"type":"string"}},"required":["salesOrderId","reason","refundMethod","items","tenantId"]},"Decimal2":{"type":"object","properties":{}},"CardTierEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Silver"},"rank":{"type":"number","example":2,"description":"Display order, low to high."},"preloadAmount":{"example":"100000.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"preloadFunding":{"type":"string","enum":["PURCHASED","GRANTED"],"example":"PURCHASED"},"discountBps":{"type":"number","example":500,"description":"Basis points. 500 = 5.00%."},"isPostpaid":{"type":"boolean","example":false},"customerRequirement":{"type":"string","enum":["NONE","OPTIONAL","REQUIRED"],"example":"NONE","description":"What a card of this tier needs to know about the guest. NONE: handed over with no details. OPTIONAL: linked when the desk recognises a returning guest. REQUIRED: a card cannot be issued without a customer. A postpaid tier left at NONE is allowed, and means a debt with nobody to bill."},"validityDays":{"type":"number","nullable":true,"example":30},"isActive":{"type":"boolean","example":true},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","name","rank","preloadAmount","preloadFunding","discountBps","isPostpaid","customerRequirement","isActive","createdAt","updatedAt"]},"CreateCardTierDto":{"type":"object","properties":{"name":{"type":"string","maxLength":50,"example":"Silver"},"rank":{"type":"number","example":2,"description":"Display order, low to high."},"preloadAmount":{"type":"string","example":"100000.0000","description":"Value attached when a card of this tier is issued."},"preloadFunding":{"type":"string","enum":["PURCHASED","GRANTED"],"default":"PURCHASED","description":"PURCHASED: the guest pays for the preload and gets the unspent part back. GRANTED: the hotel gives it, and the remainder is forfeited at checkout."},"discountBps":{"type":"number","minimum":0,"maximum":10000,"example":500,"description":"Basis points, so 500 is 5.00%."},"isPostpaid":{"type":"boolean","example":false,"description":"Postpaid tiers may go negative and must be settled before checkout. Every other tier is hard-stopped at a zero balance."},"customerRequirement":{"type":"string","enum":["NONE","OPTIONAL","REQUIRED"],"default":"NONE","description":"What a card of this tier needs to know about the guest. NONE: handed over with no details. OPTIONAL: linked when the desk recognises a returning guest. REQUIRED: a card cannot be issued without a customer. A postpaid tier left at NONE is allowed, and means a debt with nobody to bill."},"validityDays":{"type":"number","minimum":1,"example":30,"description":"Null means no expiry."},"isActive":{"type":"boolean","example":true}},"required":["name"]},"UpdateCardTierDto":{"type":"object","properties":{"name":{"type":"string","maxLength":50,"example":"Silver"},"rank":{"type":"number","example":2},"preloadAmount":{"type":"string","example":"120000.0000"},"preloadFunding":{"type":"string","enum":["PURCHASED","GRANTED"]},"discountBps":{"type":"number","minimum":0,"maximum":10000,"example":700},"isPostpaid":{"type":"boolean","example":false},"customerRequirement":{"type":"string","enum":["NONE","OPTIONAL","REQUIRED"],"default":"NONE","description":"What a card of this tier needs to know about the guest. NONE: handed over with no details. OPTIONAL: linked when the desk recognises a returning guest. REQUIRED: a card cannot be issued without a customer. A postpaid tier left at NONE is allowed, and means a debt with nobody to bill."},"validityDays":{"type":"number","minimum":1,"example":30},"isActive":{"type":"boolean","example":true}}},"GuestWalletEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"walletNumber":{"type":"string","example":"W-000041"},"guestName":{"type":"string","example":"Ko Aung"},"guestPhone":{"type":"string","nullable":true,"example":"09xxxxxxxxx"},"guestIdNumber":{"type":"string","nullable":true,"example":null},"customerId":{"type":"string","nullable":true,"example":"uuid","description":"The customer this wallet belongs to, when the tier asks for one. Null for a walk-in card issued without taking details."},"tierId":{"type":"string","example":"uuid","description":"Reporting only. Behaviour reads the snapshot fields, never this tier."},"tierNameSnapshot":{"type":"string","example":"Silver"},"discountBpsSnapshot":{"type":"number","example":500},"isPostpaidSnapshot":{"type":"boolean","example":false},"preloadAmountSnapshot":{"example":"100000.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"preloadFundingSnapshot":{"type":"string","enum":["PURCHASED","GRANTED"],"example":"PURCHASED"},"expiresAt":{"format":"date-time","type":"string","nullable":true,"example":null},"balance":{"example":"88600.0000","description":"Derived from the ledger.","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"purchasedBalance":{"example":"88600.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"grantedBalance":{"example":"0.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"sequenceNo":{"type":"number","example":4},"status":{"type":"string","enum":["ACTIVE","SUSPENDED","SETTLING","CLOSED","VOID"],"example":"ACTIVE"},"issuedAtLocationId":{"type":"string","example":"uuid"},"issuedByUserId":{"type":"string","example":"uuid"},"openedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"},"closedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"closedByUserId":{"type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"}},"required":["id","tenantId","walletNumber","guestName","tierId","tierNameSnapshot","discountBpsSnapshot","isPostpaidSnapshot","preloadAmountSnapshot","preloadFundingSnapshot","balance","purchasedBalance","grantedBalance","sequenceNo","status","issuedAtLocationId","issuedByUserId","openedAt","createdAt","updatedAt"]},"IssueWalletCustomerDto":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"example":"U Mg Mg"},"phone":{"type":"string","maxLength":50,"example":"09770011223","description":"Matched against existing customers: the same number is the same person, so a returning guest is linked rather than duplicated."},"email":{"type":"string","maxLength":255,"example":"guest@example.com"}},"required":["name"]},"IssueWalletCardDto":{"type":"object","properties":{"cardUid":{"type":"string","maxLength":100,"example":"04A3B2C1"},"label":{"type":"string","maxLength":50,"example":"Guest 1"},"roomNumber":{"type":"string","maxLength":20,"example":"304"}},"required":["cardUid"]},"WalletPaymentDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"amount":{"type":"string","example":"100000.0000"},"reference":{"type":"string","maxLength":255,"example":"KBZ-99182736","description":"Required when the payment method is a mobile wallet."}},"required":["paymentMethodId","amount"]},"IssueWalletDto":{"type":"object","properties":{"tierId":{"type":"string","format":"uuid","example":"uuid"},"guestName":{"type":"string","maxLength":255,"example":"Ko Aung","description":"The name on the card. Optional: a tier that takes no details can be issued without one, and a linked customer lends theirs."},"guestPhone":{"type":"string","maxLength":50,"example":"09xxxxxxxxx"},"guestIdNumber":{"type":"string","maxLength":100,"example":"NRC / passport number"},"customerId":{"type":"string","format":"uuid","example":"uuid","description":"An existing customer to issue this card to. Use it or `customer`, not both."},"customer":{"description":"Details for a guest who is not on file yet. Matched on phone where one is given, so issuing a second card to the same number reuses the customer rather than making another.","allOf":[{"$ref":"#/components/schemas/IssueWalletCustomerDto"}]},"locationId":{"type":"string","format":"uuid","example":"uuid","description":"The outlet issuing the card."},"posSessionId":{"type":"string","format":"uuid","example":"uuid","description":"Required whenever money changes hands, so it reaches shift close."},"cards":{"minItems":1,"description":"One or more cards, all drawing on this single wallet.","type":"array","items":{"$ref":"#/components/schemas/IssueWalletCardDto"}},"payment":{"description":"How the guest paid for a purchased preload. Not needed for a granted one.","allOf":[{"$ref":"#/components/schemas/WalletPaymentDto"}]},"idempotencyKey":{"type":"string","maxLength":255,"example":"uuid","description":"Generate once per action and reuse it on every retry. Replaying the same key returns the original result rather than issuing twice."}},"required":["tierId","locationId","cards"]},"GuestCardEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"walletId":{"type":"string","example":"uuid"},"cardUid":{"type":"string","example":"04A3B2C1","description":"The card’s permanent serial, read from the reader."},"label":{"type":"string","nullable":true,"example":"Guest 2"},"roomNumber":{"type":"string","nullable":true,"example":"304","description":"The room this card was encoded for on the door-lock system. Display only."},"status":{"type":"string","enum":["ACTIVE","LOST","DAMAGED","RETURNED","DEACTIVATED"],"example":"ACTIVE"},"issuedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"},"issuedByUserId":{"type":"string","example":"uuid"},"deactivatedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"replacedByCardId":{"type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"}},"required":["id","tenantId","walletId","cardUid","status","issuedAt","issuedByUserId","createdAt","updatedAt"]},"WalletLedgerEntryEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"walletId":{"type":"string","example":"uuid"},"sequenceNo":{"type":"number","example":4,"description":"Gap-free per wallet."},"entryType":{"type":"string","enum":["TOP_UP","PRELOAD_GRANT","SPEND","SPEND_REVERSAL","REFUND_OUT","SETTLEMENT_COLLECTION","GRANT_FORFEIT","ADJUSTMENT_CREDIT","ADJUSTMENT_DEBIT"],"example":"TOP_UP"},"amount":{"example":"-11400.0000","description":"Signed: credits positive, debits negative.","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"purchasedDelta":{"example":"-11400.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"grantedDelta":{"example":"0.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"balanceAfter":{"example":"88600.0000","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"guestCardId":{"type":"string","nullable":true,"example":"uuid"},"locationId":{"type":"string","example":"uuid"},"posSessionId":{"type":"string","nullable":true,"example":"uuid"},"staffUserId":{"type":"string","example":"uuid"},"approvedByUserId":{"type":"string","nullable":true,"example":null},"sourceModule":{"type":"string","nullable":true,"example":"GUEST_CARD"},"sourceRecordId":{"type":"string","nullable":true,"example":null},"correctsEntryId":{"type":"string","nullable":true,"example":null},"reference":{"type":"string","nullable":true,"example":"KBZ-99182736"},"idempotencyKey":{"type":"string","nullable":true,"example":"uuid"},"businessDate":{"type":"string","example":"2026-09-12"},"notes":{"type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-12T22:00:00.000Z"}},"required":["id","tenantId","walletId","sequenceNo","entryType","amount","purchasedDelta","grantedDelta","balanceAfter","locationId","staffUserId","businessDate","createdAt"]},"TopUpWalletDto":{"type":"object","properties":{"amount":{"type":"string","example":"60000.0000"},"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"reference":{"type":"string","maxLength":255,"example":"KBZ-99182736","description":"Mandatory for a mobile wallet transfer; the save is refused without it."},"guestCardId":{"type":"string","format":"uuid","example":"uuid"},"idempotencyKey":{"type":"string","maxLength":255,"example":"uuid"},"notes":{"type":"string","example":"Topped up at the cash desk"}},"required":["amount","paymentMethodId","posSessionId","locationId"]},"SettlementBlockerDto":{"type":"object","properties":{"type":{"type":"string","example":"OPEN_ORDER"},"id":{"type":"string","example":"uuid"},"label":{"type":"string","example":"order SO-R01-20260912-0042"}},"required":["type","id","label"]},"SettlementQuoteDto":{"type":"object","properties":{"walletId":{"type":"string","example":"uuid"},"walletNumber":{"type":"string","example":"W-000041"},"guestName":{"type":"string","example":"Ko Aung"},"status":{"type":"string","enum":["ACTIVE","SUSPENDED","SETTLING","CLOSED","VOID"]},"balance":{"type":"string","example":"15000.0000"},"purchasedBalance":{"type":"string","example":"15000.0000"},"grantedBalance":{"type":"string","example":"0.0000"},"action":{"type":"string","example":"REFUND_DUE","enum":["REFUND_DUE","COLLECT_DUE","READY_TO_CLOSE"],"description":"Drive the settlement screen off this rather than the balance: a positive balance may be entirely promotional value, which looks refundable and is not."},"refundable":{"type":"string","example":"15000.0000","description":"The guest’s own money, to be handed back."},"forfeitable":{"type":"string","example":"0.0000","description":"Promotional value, written off rather than paid out."},"collectable":{"type":"string","example":"0.0000","description":"Owed by the guest on a postpaid card."},"blockers":{"description":"Business still open. Must be empty before the wallet can close.","type":"array","items":{"$ref":"#/components/schemas/SettlementBlockerDto"}}},"required":["walletId","walletNumber","guestName","status","balance","purchasedBalance","grantedBalance","action","refundable","forfeitable","collectable","blockers"]},"SettlementTenderDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"reference":{"type":"string","maxLength":255,"example":"KBZ-99182736","description":"Required for a mobile wallet transfer."}},"required":["paymentMethodId"]},"SettlementCollectionDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"reference":{"type":"string","maxLength":255,"example":"KBZ-99182736","description":"Required for a mobile wallet transfer."},"amount":{"type":"string","example":"45000.0000","description":"Must match the outstanding amount exactly. Part payment does not close an account: the requirement is that a guest cannot check out until it is clear."}},"required":["paymentMethodId","amount"]},"SettleWalletDto":{"type":"object","properties":{"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"refund":{"description":"How unspent money is being handed back. Required when the quote says REFUND_DUE with a refundable amount, and needs a manager’s approval.","allOf":[{"$ref":"#/components/schemas/SettlementTenderDto"}]},"collect":{"description":"Money taken to clear a postpaid card. Required when the quote says COLLECT_DUE.","allOf":[{"$ref":"#/components/schemas/SettlementCollectionDto"}]},"idempotencyKey":{"type":"string","maxLength":255,"example":"uuid"},"notes":{"type":"string","example":"Checked out at 01:15"}},"required":["posSessionId","locationId"]},"RefundWalletDto":{"type":"object","properties":{"amount":{"type":"string","example":"20000.0000","description":"How much to hand back. Cannot exceed the guest’s own money - promotional value is never paid out in cash."},"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"reference":{"type":"string","maxLength":255,"example":"KBZ-99182736"},"idempotencyKey":{"type":"string","maxLength":255,"example":"uuid"},"notes":{"type":"string","example":"Guest asked for cash back"}},"required":["amount","paymentMethodId","posSessionId","locationId"]},"LinkCardDto":{"type":"object","properties":{"walletId":{"type":"string","format":"uuid","example":"uuid"},"cardUid":{"type":"string","maxLength":100,"example":"04A3B2C1","description":"The card’s serial as read by the reader. We never write to a card."},"label":{"type":"string","maxLength":50,"example":"Guest 2"},"roomNumber":{"type":"string","maxLength":20,"example":"304","description":"The room this card was encoded for on the door-lock system. Recorded for the desk’s benefit only; it grants nothing."}},"required":["walletId","cardUid"]},"ReplaceCardDto":{"type":"object","properties":{"newCardUid":{"type":"string","maxLength":100,"example":"04A3B2C9"},"label":{"type":"string","maxLength":50,"example":"Guest 2"},"roomNumber":{"type":"string","maxLength":20,"example":"304"}},"required":["newCardUid"]},"PosRegisterEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"code":{"type":"string","example":"R01"},"name":{"type":"string","example":"Register 1"},"macAddress":{"type":"string","nullable":true,"example":"AA:BB:CC:DD:EE:FF"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","locationId","code","name","createdAt","updatedAt"]},"CreatePosRegisterDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"code":{"type":"string","example":"R01","description":"Short code unique within the tenant, embedded in every document number this register issues. Auto-assigned (R01, R02, ...) when omitted."},"name":{"type":"string","example":"Register 1"},"macAddress":{"type":"string","example":"AA:BB:CC:DD:EE:FF"}},"required":["tenantId","locationId","name"]},"UpdatePosRegisterDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"code":{"type":"string","example":"R01","description":"Short code unique within the tenant, embedded in every document number this register issues. Auto-assigned (R01, R02, ...) when omitted."},"name":{"type":"string","example":"Register 1"},"macAddress":{"type":"string","example":"AA:BB:CC:DD:EE:FF"}}},"PosSessionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"registerId":{"type":"string","example":"uuid"},"cashierId":{"type":"string","example":"uuid"},"openedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"closedAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-01-01T23:59:59.000Z"},"openingCashFloat":{"type":"string","example":"500.0000"},"expectedClosingCash":{"type":"string","nullable":true,"example":"1500.0000"},"actualClosingCash":{"type":"string","nullable":true,"example":"1490.0000"},"cashVariance":{"type":"string","nullable":true,"example":"-10.0000"},"status":{"type":"string","nullable":true,"example":"OPEN","enum":["OPEN","CLOSED","AUDITED"]},"varianceApprovedByUserId":{"type":"string","nullable":true,"example":"2026-01-01T00:00:00.000Z","description":"Manager who signed off a drawer that did not balance."},"varianceApprovedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","tenantId","registerId","cashierId","openedAt","openingCashFloat","updatedAt"]},"CreatePosSessionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"registerId":{"type":"string","format":"uuid","example":"uuid"},"cashierId":{"type":"string","format":"uuid","example":"uuid"},"openingCashFloat":{"type":"string","example":"500.0000"},"expectedClosingCash":{"type":"string","example":"1500.0000"},"actualClosingCash":{"type":"string","example":"1490.0000"},"cashVariance":{"type":"string","example":"-10.0000"},"closedAt":{"format":"date-time","type":"string","example":"2026-01-01T23:59:59.000Z"},"status":{"type":"string","example":"OPEN","enum":["OPEN","CLOSED","AUDITED"]}},"required":["tenantId","registerId","cashierId","openingCashFloat"]},"UpdatePosSessionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"registerId":{"type":"string","format":"uuid","example":"uuid"},"cashierId":{"type":"string","format":"uuid","example":"uuid"},"openingCashFloat":{"type":"string","example":"500.0000"},"expectedClosingCash":{"type":"string","example":"1500.0000"},"actualClosingCash":{"type":"string","example":"1490.0000"},"cashVariance":{"type":"string","example":"-10.0000"},"closedAt":{"format":"date-time","type":"string","example":"2026-01-01T23:59:59.000Z"},"status":{"type":"string","example":"OPEN","enum":["OPEN","CLOSED","AUDITED"]}}},"PaymentMethodSummaryDto":{"type":"object","properties":{"methodName":{"type":"string","example":"CASH"},"transactionCount":{"type":"number","example":5},"totalAmount":{"type":"string","example":"750.0000"}},"required":["methodName","transactionCount","totalAmount"]},"EndOfDaySummaryDto":{"type":"object","properties":{"sessionId":{"type":"string","example":"uuid"},"registerName":{"type":"string","example":"Register 1"},"cashierName":{"type":"string","nullable":true,"example":"John Doe"},"openedAt":{"format":"date-time","type":"string","example":"2026-04-03T08:00:00.000Z"},"closedAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-04-03T20:00:00.000Z"},"openingCashFloat":{"type":"string","example":"500.0000"},"expectedClosingCash":{"type":"string","example":"1480.0000"},"actualClosingCash":{"type":"string","nullable":true,"example":"1500.0000"},"cashVariance":{"type":"string","nullable":true,"example":"20.0000"},"totalSales":{"type":"string","example":"2500.0000"},"totalRefunds":{"type":"string","example":"120.0000"},"netTotal":{"type":"string","example":"2380.0000"},"salesCount":{"type":"number","example":15},"refundCount":{"type":"number","example":2},"nonSalesCashIn":{"example":"1450000.0000","description":"Cash into the drawer that was not a sale - guest-card top-ups, paid-ins. Included in the expected count but deliberately absent from totalSales, because a deposit is money owed back, not revenue.","type":"array","items":{"$ref":"#/components/schemas/PaymentMethodSummaryDto"}},"nonSalesCashOut":{"type":"string","example":"85000.0000","description":"Cash out of the drawer that was not a refund of a sale - card refunds, paid-outs."},"status":{"type":"string","example":"CLOSED"},"paymentBreakdown":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethodSummaryDto"}}},"required":["sessionId","registerName","openedAt","openingCashFloat","expectedClosingCash","totalSales","totalRefunds","netTotal","salesCount","refundCount","nonSalesCashIn","nonSalesCashOut","status","paymentBreakdown"]},"ClosePosSessionDto":{"type":"object","properties":{"actualClosingCash":{"type":"string","example":"1500.0000","description":"Physical cash count at end of day"}},"required":["actualClosingCash"]},"PaymentMethodEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Cash"},"kind":{"type":"string","enum":["CASH","CARD","MOBILE_WALLET","BANK_TRANSFER","CUSTOMER_CREDIT","GUEST_CARD","VOUCHER","OTHER"],"example":"CASH","description":"What this tender is. Behaviour keys off this, never off the name."},"isActive":{"type":"boolean","example":true},"glAccountId":{"type":"string","nullable":true,"example":"uuid"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","name","kind","isActive","createdAt","updatedAt"]},"CreatePaymentMethodDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Cash","description":"The tenant’s own label. Unique within a tenant."},"kind":{"type":"string","enum":["CASH","CARD","MOBILE_WALLET","BANK_TRANSFER","CUSTOMER_CREDIT","GUEST_CARD","VOUCHER","OTHER"],"default":"OTHER","description":"What this tender is. Drives behaviour: CASH counts towards the drawer at shift close, CUSTOMER_CREDIT runs the credit-limit check, GUEST_CARD debits a wallet. Defaults to OTHER, which records the payment and nothing more."},"isActive":{"type":"boolean","example":true,"default":true},"glAccountId":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","name"]},"UpdatePaymentMethodDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Cash","description":"The tenant’s own label. Unique within a tenant."},"kind":{"type":"string","enum":["CASH","CARD","MOBILE_WALLET","BANK_TRANSFER","CUSTOMER_CREDIT","GUEST_CARD","VOUCHER","OTHER"],"default":"OTHER","description":"What this tender is. Drives behaviour: CASH counts towards the drawer at shift close, CUSTOMER_CREDIT runs the credit-limit check, GUEST_CARD debits a wallet. Defaults to OTHER, which records the payment and nothing more."},"isActive":{"type":"boolean","example":true,"default":true},"glAccountId":{"type":"string","format":"uuid","example":"uuid"}}},"CashMovementEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"posSessionId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"businessDate":{"type":"string","example":"2026-09-12"},"direction":{"type":"string","enum":["IN","OUT"],"example":"IN"},"reason":{"type":"string","enum":["WALLET_TOP_UP","WALLET_REFUND","WALLET_SETTLEMENT","PAID_IN","PAID_OUT","DROP","FLOAT_ADJUSTMENT"],"example":"WALLET_TOP_UP"},"paymentMethodId":{"type":"string","example":"uuid"},"amount":{"example":"100000.0000","description":"Always positive; direction carries the sign.","allOf":[{"$ref":"#/components/schemas/Decimal2"}]},"reference":{"type":"string","nullable":true,"example":"KBZ-99182736"},"sourceModule":{"type":"string","nullable":true,"example":"GUEST_CARD"},"sourceRecordId":{"type":"string","nullable":true,"example":"uuid"},"staffUserId":{"type":"string","example":"uuid"},"approvedByUserId":{"type":"string","nullable":true,"example":null},"notes":{"type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"}},"required":["id","tenantId","posSessionId","locationId","businessDate","direction","reason","paymentMethodId","amount","staffUserId","createdAt"]},"RecordCashMovementDto":{"type":"object","properties":{"posSessionId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"direction":{"type":"string","enum":["IN","OUT"],"example":"OUT"},"reason":{"type":"string","enum":["WALLET_TOP_UP","WALLET_REFUND","WALLET_SETTLEMENT","PAID_IN","PAID_OUT","DROP","FLOAT_ADJUSTMENT"],"example":"PAID_OUT","description":"Wallet reasons are written by the guest-card flows themselves; record PAID_IN, PAID_OUT, DROP and FLOAT_ADJUSTMENT here."},"paymentMethodId":{"type":"string","format":"uuid","example":"uuid"},"amount":{"type":"string","example":"25000.0000","description":"Always positive; direction says which way it went."},"reference":{"type":"string","maxLength":255,"example":"KBZ-99182736"},"notes":{"type":"string","example":"Paid the laundry supplier"}},"required":["posSessionId","locationId","direction","reason","paymentMethodId","amount"]},"UpsertOutletSettingDto":{"type":"object","properties":{"serviceChargeBps":{"type":"number","minimum":0,"maximum":10000,"example":1000,"description":"Basis points, so 1000 is 10.00%. Once set, the server computes the service charge and ignores whatever the till sends."},"serviceChargeAppliesTo":{"type":"string","enum":["ALL","FNB_ONLY","ROOM_ONLY","NONE"],"default":"ALL","description":"Properties differ on whether a spa treatment attracts the same charge as a bottle of whisky."},"defaultTaxRateId":{"type":"string","format":"uuid","example":"uuid"},"timezone":{"type":"string","example":"Asia/Bangkok","description":"Only for an outlet in a different timezone from the rest of its tenant. Leave it out to use the tenant’s timezone, which is right for almost every outlet."},"currencyCode":{"type":"string","minLength":3,"maxLength":3,"example":"MMK"}}},"InventoryLedgerEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"variantId":{"type":"string","example":"uuid"},"transactionType":{"type":"string","example":"GRN_RECEIPT"},"referenceId":{"type":"string","example":"uuid"},"quantity":{"type":"string","example":"100.0000"},"unitCost":{"type":"string","example":"25.5000"},"serialNumber":{"type":"string","nullable":true,"example":"SN-001"},"batchNumber":{"type":"string","nullable":true,"example":"BATCH-001"},"manufacturingDate":{"format":"date-time","type":"string","nullable":true,"example":"2025-01-01"},"expiryDate":{"format":"date-time","type":"string","nullable":true,"example":"2027-01-01"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"createdBy":{"type":"string","nullable":true,"example":"uuid"}},"required":["id","tenantId","locationId","variantId","transactionType","referenceId","quantity","unitCost","createdAt"]},"CreateInventoryLedgerDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"variantId":{"type":"string","format":"uuid","example":"uuid"},"transactionType":{"type":"string","example":"GRN_RECEIPT"},"referenceId":{"type":"string","format":"uuid","example":"uuid"},"quantity":{"type":"string","example":"100.0000"},"unitCost":{"type":"string","example":"25.5000"},"serialNumber":{"type":"string","example":"SN-001"},"batchNumber":{"type":"string","example":"BATCH-001"},"manufacturingDate":{"format":"date-time","type":"string","example":"2025-01-01"},"expiryDate":{"format":"date-time","type":"string","example":"2027-01-01"},"createdBy":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","locationId","variantId","transactionType","referenceId","quantity","unitCost"]},"WriteOffInventoryDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"variantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"quantity":{"type":"string","example":"5.0000","description":"Quantity to write off (positive number, will be deducted)"},"reason":{"type":"string","example":"Expired batch BATCH-001"},"batchNumber":{"type":"string","example":"BATCH-001"},"unitCost":{"type":"string","example":"25.5000"}},"required":["tenantId","variantId","locationId","quantity","reason"]},"ExchangeRateEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"baseCurrency":{"type":"string","example":"USD"},"targetCurrency":{"type":"string","example":"EUR"},"rate":{"type":"string","example":"1.0850"},"effectiveFrom":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"effectiveTo":{"format":"date-time","type":"string","nullable":true,"example":"2026-12-31T00:00:00.000Z"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","baseCurrency","targetCurrency","rate","effectiveFrom","createdAt","updatedAt"]},"CreateExchangeRateDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"baseCurrency":{"type":"string","example":"USD"},"targetCurrency":{"type":"string","example":"EUR"},"rate":{"type":"string","example":"1.0850"},"effectiveFrom":{"format":"date-time","type":"string","example":"2026-01-01"},"effectiveTo":{"format":"date-time","type":"string","example":"2026-12-31"}},"required":["tenantId","baseCurrency","targetCurrency","rate","effectiveFrom"]},"UpdateExchangeRateDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"baseCurrency":{"type":"string","example":"USD"},"targetCurrency":{"type":"string","example":"EUR"},"rate":{"type":"string","example":"1.0850"},"effectiveFrom":{"format":"date-time","type":"string","example":"2026-01-01"},"effectiveTo":{"format":"date-time","type":"string","example":"2026-12-31"}}},"TaxRateEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"VAT Standard"},"ratePercentage":{"type":"string","example":"15.0000"},"isPriceInclusive":{"type":"boolean","nullable":true,"example":true},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"glLiabilityAccountId":{"type":"string","nullable":true,"example":"uuid"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.714Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:22.714Z"}},"required":["id","tenantId","name","ratePercentage","createdAt","updatedAt"]},"CreateTaxRateDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"VAT Standard"},"ratePercentage":{"type":"string","example":"15.0000"},"isPriceInclusive":{"type":"boolean","example":true},"glLiabilityAccountId":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","name","ratePercentage"]},"UpdateTaxRateDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"VAT Standard"},"ratePercentage":{"type":"string","example":"15.0000"},"isPriceInclusive":{"type":"boolean","example":true},"glLiabilityAccountId":{"type":"string","format":"uuid","example":"uuid"}}},"AccountingPeriodEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"periodName":{"type":"string","example":"Q1 2026"},"startDate":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"endDate":{"format":"date-time","type":"string","example":"2026-03-31T00:00:00.000Z"},"status":{"type":"string","nullable":true,"example":"OPEN","enum":["OPEN","CLOSED","LOCKED_FOR_AUDIT"]},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","periodName","startDate","endDate","createdAt","updatedAt"]},"CreateAccountingPeriodDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"periodName":{"type":"string","example":"Q1 2026"},"startDate":{"format":"date-time","type":"string","example":"2026-01-01"},"endDate":{"format":"date-time","type":"string","example":"2026-03-31"},"status":{"type":"string","example":"OPEN","enum":["OPEN","CLOSED","LOCKED_FOR_AUDIT"]}},"required":["tenantId","periodName","startDate","endDate"]},"UpdateAccountingPeriodDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"periodName":{"type":"string","example":"Q1 2026"},"startDate":{"format":"date-time","type":"string","example":"2026-01-01"},"endDate":{"format":"date-time","type":"string","example":"2026-03-31"},"status":{"type":"string","example":"OPEN","enum":["OPEN","CLOSED","LOCKED_FOR_AUDIT"]}}},"ChartOfAccountEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"parentAccountId":{"type":"string","nullable":true,"example":"uuid"},"accountCode":{"type":"string","example":"1000"},"accountName":{"type":"string","example":"Cash and Cash Equivalents"},"accountType":{"type":"string","example":"ASSET"},"isReconcilable":{"type":"boolean","nullable":true,"example":true},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","accountCode","accountName","accountType","createdAt","updatedAt"]},"CreateChartOfAccountDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"parentAccountId":{"type":"string","format":"uuid","example":"uuid"},"accountCode":{"type":"string","example":"1000"},"accountName":{"type":"string","example":"Cash and Cash Equivalents"},"accountType":{"type":"string","example":"ASSET"},"isReconcilable":{"type":"boolean","example":true}},"required":["tenantId","accountCode","accountName","accountType"]},"UpdateChartOfAccountDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"parentAccountId":{"type":"string","format":"uuid","example":"uuid"},"accountCode":{"type":"string","example":"1000"},"accountName":{"type":"string","example":"Cash and Cash Equivalents"},"accountType":{"type":"string","example":"ASSET"},"isReconcilable":{"type":"boolean","example":true}}},"JournalEntryEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"periodId":{"type":"string","example":"uuid"},"entryDate":{"format":"date-time","type":"string","example":"2026-01-15T00:00:00.000Z"},"description":{"type":"string","nullable":true,"example":"Monthly payroll entry"},"sourceModule":{"type":"string","nullable":true,"example":"payroll"},"sourceRecordId":{"type":"string","nullable":true,"example":"uuid"},"status":{"type":"string","nullable":true,"example":"DRAFT","enum":["DRAFT","POSTED","VOIDED"]},"postedAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-01-15T00:00:00.000Z"},"postedBy":{"type":"string","nullable":true,"example":"uuid"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","periodId","entryDate","createdAt","updatedAt"]},"CreateJournalEntryDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"periodId":{"type":"string","format":"uuid","example":"uuid"},"description":{"type":"string","example":"Monthly payroll entry"},"sourceModule":{"type":"string","example":"payroll"},"sourceRecordId":{"type":"string","format":"uuid","example":"uuid"},"status":{"type":"string","example":"DRAFT","enum":["DRAFT","POSTED","VOIDED"]},"postedBy":{"type":"string","format":"uuid","example":"uuid"}},"required":["tenantId","periodId"]},"UpdateJournalEntryDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"periodId":{"type":"string","format":"uuid","example":"uuid"},"description":{"type":"string","example":"Monthly payroll entry"},"sourceModule":{"type":"string","example":"payroll"},"sourceRecordId":{"type":"string","format":"uuid","example":"uuid"},"status":{"type":"string","example":"DRAFT","enum":["DRAFT","POSTED","VOIDED"]},"postedBy":{"type":"string","format":"uuid","example":"uuid"}}},"JournalLineEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"journalEntryId":{"type":"string","example":"uuid"},"accountId":{"type":"string","example":"uuid"},"transactionCurrency":{"type":"string","example":"USD"},"transactionDebit":{"type":"string","nullable":true,"example":"1000.0000"},"transactionCredit":{"type":"string","nullable":true,"example":"0.0000"},"exchangeRate":{"type":"string","nullable":true,"example":"1.0000"},"baseDebit":{"type":"string","nullable":true,"example":"1000.0000"},"baseCredit":{"type":"string","nullable":true,"example":"0.0000"}},"required":["id","journalEntryId","accountId","transactionCurrency"]},"CreateJournalLineDto":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid","example":"uuid"},"transactionCurrency":{"type":"string","example":"USD"},"transactionDebit":{"type":"string","example":"1000.0000"},"transactionCredit":{"type":"string","example":"0.0000"},"exchangeRate":{"type":"string","example":"1.0000"},"baseDebit":{"type":"string","example":"1000.0000"},"baseCredit":{"type":"string","example":"0.0000"}},"required":["accountId","transactionCurrency"]},"UpdateJournalLineDto":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid","example":"uuid"},"transactionCurrency":{"type":"string","example":"USD"},"transactionDebit":{"type":"string","example":"1000.0000"},"transactionCredit":{"type":"string","example":"0.0000"},"exchangeRate":{"type":"string","example":"1.0000"},"baseDebit":{"type":"string","example":"1000.0000"},"baseCredit":{"type":"string","example":"0.0000"}}},"BankStatementEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"glAccountId":{"type":"string","example":"uuid"},"statementDate":{"format":"date-time","type":"string","example":"2026-01-31T00:00:00.000Z"},"openingBalance":{"type":"string","nullable":true,"example":"10000.0000"},"closingBalance":{"type":"string","nullable":true,"example":"12500.0000"},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","glAccountId","statementDate","createdAt","updatedAt"]},"CreateBankStatementDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"glAccountId":{"type":"string","format":"uuid","example":"uuid"},"statementDate":{"format":"date-time","type":"string","example":"2026-01-31"},"openingBalance":{"type":"string","example":"10000.0000"},"closingBalance":{"type":"string","example":"12500.0000"}},"required":["tenantId","glAccountId","statementDate"]},"UpdateBankStatementDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"glAccountId":{"type":"string","format":"uuid","example":"uuid"},"statementDate":{"format":"date-time","type":"string","example":"2026-01-31"},"openingBalance":{"type":"string","example":"10000.0000"},"closingBalance":{"type":"string","example":"12500.0000"}}},"BankStatementLineEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"statementId":{"type":"string","example":"uuid"},"transactionDate":{"format":"date-time","type":"string","example":"2026-01-15T00:00:00.000Z"},"description":{"type":"string","example":"Wire transfer from client"},"referenceNumber":{"type":"string","nullable":true,"example":"REF-001"},"amount":{"type":"string","example":"500.0000"},"status":{"type":"string","nullable":true,"example":"UNMATCHED","enum":["UNMATCHED","MATCHED"]}},"required":["id","statementId","transactionDate","description","amount"]},"CreateBankStatementLineDto":{"type":"object","properties":{"transactionDate":{"format":"date-time","type":"string","example":"2026-01-15"},"description":{"type":"string","example":"Wire transfer from client"},"referenceNumber":{"type":"string","example":"REF-001"},"amount":{"type":"string","example":"500.0000"},"status":{"type":"string","example":"UNMATCHED","enum":["UNMATCHED","MATCHED"]}},"required":["transactionDate","description","amount"]},"UpdateBankStatementLineDto":{"type":"object","properties":{"transactionDate":{"format":"date-time","type":"string","example":"2026-01-15"},"description":{"type":"string","example":"Wire transfer from client"},"referenceNumber":{"type":"string","example":"REF-001"},"amount":{"type":"string","example":"500.0000"},"status":{"type":"string","example":"UNMATCHED","enum":["UNMATCHED","MATCHED"]}}},"ReconciliationMatchEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"statementLineId":{"type":"string","example":"uuid"},"journalLineId":{"type":"string","example":"uuid"},"matchedBy":{"type":"string","nullable":true,"example":"uuid"},"matchedAt":{"format":"date-time","type":"string","example":"2026-01-15T00:00:00.000Z"}},"required":["id","statementLineId","journalLineId","matchedAt"]},"CreateReconciliationMatchDto":{"type":"object","properties":{"statementLineId":{"type":"string","format":"uuid","example":"uuid"},"journalLineId":{"type":"string","format":"uuid","example":"uuid"},"matchedBy":{"type":"string","format":"uuid","example":"uuid"}},"required":["statementLineId","journalLineId"]},"UpdateReconciliationMatchDto":{"type":"object","properties":{"statementLineId":{"type":"string","format":"uuid","example":"uuid"},"journalLineId":{"type":"string","format":"uuid","example":"uuid"},"matchedBy":{"type":"string","format":"uuid","example":"uuid"}}},"FixedAssetEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"assetName":{"type":"string","example":"Office Laptop"},"serialNumber":{"type":"string","nullable":true,"example":"SN-12345"},"assetAccountId":{"type":"string","nullable":true,"example":"uuid"},"depreciationExpenseAccountId":{"type":"string","nullable":true,"example":"uuid"},"accumulatedDepreciationAccountId":{"type":"string","nullable":true,"example":"uuid"},"purchaseDate":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"purchaseCost":{"type":"string","example":"1500.0000"},"salvageValue":{"type":"string","nullable":true,"example":"200.0000"},"usefulLifeMonths":{"type":"number","example":60},"depreciationMethod":{"type":"string","nullable":true,"example":"STRAIGHT_LINE"},"status":{"type":"string","nullable":true,"example":"ACTIVE","enum":["ACTIVE","FULLY_DEPRECIATED","DISPOSED"]},"createdAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-01-01T00:00:00.000Z"}},"required":["id","tenantId","assetName","purchaseDate","purchaseCost","usefulLifeMonths","createdAt","updatedAt"]},"CreateFixedAssetDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"assetName":{"type":"string","example":"Office Laptop"},"serialNumber":{"type":"string","example":"SN-12345"},"assetAccountId":{"type":"string","format":"uuid","example":"uuid"},"depreciationExpenseAccountId":{"type":"string","format":"uuid","example":"uuid"},"accumulatedDepreciationAccountId":{"type":"string","format":"uuid","example":"uuid"},"purchaseDate":{"format":"date-time","type":"string","example":"2026-01-01"},"purchaseCost":{"type":"string","example":"1500.0000"},"salvageValue":{"type":"string","example":"200.0000"},"usefulLifeMonths":{"type":"number","example":60},"depreciationMethod":{"type":"string","example":"STRAIGHT_LINE"},"status":{"type":"string","example":"ACTIVE","enum":["ACTIVE","FULLY_DEPRECIATED","DISPOSED"]}},"required":["tenantId","assetName","purchaseDate","purchaseCost","usefulLifeMonths"]},"UpdateFixedAssetDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"assetName":{"type":"string","example":"Office Laptop"},"serialNumber":{"type":"string","example":"SN-12345"},"assetAccountId":{"type":"string","format":"uuid","example":"uuid"},"depreciationExpenseAccountId":{"type":"string","format":"uuid","example":"uuid"},"accumulatedDepreciationAccountId":{"type":"string","format":"uuid","example":"uuid"},"purchaseDate":{"format":"date-time","type":"string","example":"2026-01-01"},"purchaseCost":{"type":"string","example":"1500.0000"},"salvageValue":{"type":"string","example":"200.0000"},"usefulLifeMonths":{"type":"number","example":60},"depreciationMethod":{"type":"string","example":"STRAIGHT_LINE"},"status":{"type":"string","example":"ACTIVE","enum":["ACTIVE","FULLY_DEPRECIATED","DISPOSED"]}}},"DepreciationScheduleEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"assetId":{"type":"string","example":"uuid"},"scheduledDate":{"format":"date-time","type":"string","example":"2026-02-01T00:00:00.000Z"},"depreciationAmount":{"type":"string","example":"21.67"},"isPosted":{"type":"boolean","nullable":true,"example":false},"postedJournalEntryId":{"type":"string","nullable":true,"example":"uuid"}},"required":["id","assetId","scheduledDate","depreciationAmount"]},"CreateDepreciationScheduleDto":{"type":"object","properties":{"scheduledDate":{"format":"date-time","type":"string","example":"2026-02-01"},"depreciationAmount":{"type":"string","example":"21.67"},"isPosted":{"type":"boolean","example":false},"postedJournalEntryId":{"type":"string","format":"uuid","example":"uuid"}},"required":["scheduledDate","depreciationAmount"]},"UpdateDepreciationScheduleDto":{"type":"object","properties":{"scheduledDate":{"format":"date-time","type":"string","example":"2026-02-01"},"depreciationAmount":{"type":"string","example":"21.67"},"isPosted":{"type":"boolean","example":false},"postedJournalEntryId":{"type":"string","format":"uuid","example":"uuid"}}},"UploadResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"url":{"type":"string","example":"/uploads/tenant-uuid/branch-uuid/products/iphone15-1712345678000-123456789.jpg"},"originalName":{"type":"string","example":"iphone15.jpg"},"filename":{"type":"string","example":"iphone15-1712345678000-123456789.jpg"},"folder":{"type":"string","example":"products"},"mimeType":{"type":"string","example":"image/jpeg"},"size":{"type":"number","example":204800,"description":"File size in bytes"},"createdAt":{"format":"date-time","type":"string","example":"2026-04-06T12:00:00.000Z"}},"required":["id","url","originalName","filename","folder","mimeType","size","createdAt"]},"ModifierGroupEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Choose protein"},"minSelection":{"type":"number","example":0},"maxSelection":{"type":"number","nullable":true,"example":1},"isRequired":{"type":"boolean","example":false},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.266Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.266Z"}},"required":["id","tenantId","name","minSelection","isRequired","createdAt","updatedAt"]},"CreateModifierGroupDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Choose protein"},"minSelection":{"type":"number","minimum":0,"example":0},"maxSelection":{"type":"number","minimum":1,"example":1},"isRequired":{"type":"boolean","example":false}},"required":["tenantId","name"]},"UpdateModifierGroupDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Choose protein"},"minSelection":{"type":"number","minimum":0,"example":0},"maxSelection":{"type":"number","minimum":1,"example":1},"isRequired":{"type":"boolean","example":false}}},"AttachModifierGroupDto":{"type":"object","properties":{"productId":{"type":"string","format":"uuid","example":"uuid"},"sortOrder":{"type":"number","minimum":0,"example":0}},"required":["productId"]},"ModifierEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"modifierGroupId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Bacon"},"priceDelta":{"type":"string","example":"2.0000"},"sortOrder":{"type":"number","example":0},"isDefault":{"type":"boolean","example":false},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.278Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.278Z"}},"required":["id","modifierGroupId","name","priceDelta","sortOrder","isDefault","createdAt","updatedAt"]},"CreateModifierDto":{"type":"object","properties":{"name":{"type":"string","example":"Bacon"},"priceDelta":{"type":"number","example":2},"sortOrder":{"type":"number","minimum":0,"example":0},"isDefault":{"type":"boolean","example":false}},"required":["name"]},"UpdateModifierDto":{"type":"object","properties":{"name":{"type":"string","example":"Bacon"},"priceDelta":{"type":"number","example":2},"sortOrder":{"type":"number","minimum":0,"example":0},"isDefault":{"type":"boolean","example":false}}},"RecipeEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"variantId":{"type":"string","example":"uuid"},"yield":{"type":"string","example":"1.0000"},"notes":{"type":"string","nullable":true,"example":"Mix dry, then wet, then bake."},"isActive":{"type":"boolean","example":true},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.302Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.302Z"}},"required":["id","tenantId","variantId","yield","isActive","createdAt","updatedAt"]},"CreateRecipeIngredientDto":{"type":"object","properties":{"ingredientVariantId":{"type":"string","format":"uuid","example":"uuid"},"quantity":{"type":"number","minimum":0,"example":1.5},"uomId":{"type":"string","format":"uuid","example":"uuid"},"isOptional":{"type":"boolean","example":false},"notes":{"type":"string","example":"Use room-temperature butter"}},"required":["ingredientVariantId","quantity","uomId"]},"CreateRecipeDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"variantId":{"type":"string","format":"uuid","example":"uuid"},"yield":{"type":"number","minimum":0,"example":1},"notes":{"type":"string","example":"Mix everything and bake."},"isActive":{"type":"boolean","example":true},"ingredients":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/CreateRecipeIngredientDto"}}},"required":["tenantId","variantId","ingredients"]},"UpdateRecipeDto":{"type":"object","properties":{"yield":{"type":"number","minimum":0,"example":1},"notes":{"type":"string","example":"Updated notes."},"isActive":{"type":"boolean","example":true},"ingredients":{"description":"When provided, replaces the entire ingredient list with this set.","type":"array","items":{"$ref":"#/components/schemas/CreateRecipeIngredientDto"}}}},"BundleEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"productId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Burger Combo"},"description":{"type":"string","nullable":true,"example":"Burger + fries + drink"},"isActive":{"type":"boolean","example":true},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.323Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.323Z"}},"required":["id","tenantId","productId","name","isActive","createdAt","updatedAt"]},"CreateBundleComponentDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid","example":"uuid"},"quantity":{"type":"number","minimum":0,"example":1},"swapGroupId":{"type":"string","example":"side","description":"Components sharing a swapGroupId can be substituted at order time"}},"required":["variantId"]},"CreateBundleDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"productId":{"type":"string","format":"uuid","example":"uuid","description":"The parent product representing this combo SKU"},"name":{"type":"string","example":"Burger Combo"},"description":{"type":"string","example":"Burger + fries + drink"},"isActive":{"type":"boolean","example":true},"components":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/CreateBundleComponentDto"}}},"required":["tenantId","productId","name","components"]},"UpdateBundleDto":{"type":"object","properties":{"name":{"type":"string","example":"Burger Combo"},"description":{"type":"string","example":"Updated description"},"isActive":{"type":"boolean","example":true},"components":{"description":"When provided, replaces the entire component list with this set.","type":"array","items":{"$ref":"#/components/schemas/CreateBundleComponentDto"}}}},"PricingScheduleEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Happy Hour"},"startsAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-09-21T21:31:23.350Z"},"endsAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-09-21T21:31:23.350Z"},"daysOfWeek":{"example":[1,2,3,4,5],"description":"0=Sun … 6=Sat","type":"array","items":{"type":"number"}},"startTime":{"type":"string","nullable":true,"example":"17:00"},"endTime":{"type":"string","nullable":true,"example":"19:00"},"priority":{"type":"number","example":0},"isActive":{"type":"boolean","example":true},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.350Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.350Z"}},"required":["id","tenantId","name","daysOfWeek","priority","isActive","createdAt","updatedAt"]},"CreatePricingRuleDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid","example":"uuid"},"categoryId":{"type":"string","format":"uuid","example":"uuid"},"adjustmentType":{"enum":["PERCENT_OFF","AMOUNT_OFF","FIXED_PRICE"],"type":"string"},"adjustmentValue":{"type":"number","example":10}},"required":["adjustmentType","adjustmentValue"]},"CreatePricingScheduleDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Happy Hour"},"startsAt":{"type":"string","example":"2026-01-01T00:00:00Z"},"endsAt":{"type":"string","example":"2026-12-31T23:59:59Z"},"daysOfWeek":{"uniqueItems":true,"example":[1,2,3,4,5],"description":"Days of week, 0=Sun … 6=Sat","type":"array","items":{"type":"number","maximum":6,"minimum":0}},"startTime":{"type":"string","pattern":"/^([01]\\d|2[0-3]):[0-5]\\d$/","example":"17:00","description":"24h HH:MM"},"endTime":{"type":"string","pattern":"/^([01]\\d|2[0-3]):[0-5]\\d$/","example":"19:00","description":"24h HH:MM"},"priority":{"type":"number","example":0},"isActive":{"type":"boolean","example":true},"rules":{"type":"array","items":{"$ref":"#/components/schemas/CreatePricingRuleDto"}}},"required":["tenantId","name"]},"UpdatePricingScheduleDto":{"type":"object","properties":{"name":{"type":"string","example":"Happy Hour"},"startsAt":{"type":"string","example":"2026-01-01T00:00:00Z"},"endsAt":{"type":"string","example":"2026-12-31T23:59:59Z"},"daysOfWeek":{"uniqueItems":true,"example":[1,2,3,4,5],"description":"Days of week, 0=Sun … 6=Sat","type":"array","items":{"type":"number","maximum":6,"minimum":0}},"startTime":{"type":"string","pattern":"/^([01]\\d|2[0-3]):[0-5]\\d$/","example":"17:00","description":"24h HH:MM"},"endTime":{"type":"string","pattern":"/^([01]\\d|2[0-3]):[0-5]\\d$/","example":"19:00","description":"24h HH:MM"},"priority":{"type":"number","example":0},"isActive":{"type":"boolean","example":true},"rules":{"type":"array","items":{"$ref":"#/components/schemas/CreatePricingRuleDto"}}}},"DiningZoneEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Patio"},"layoutSvg":{"type":"string","nullable":true,"example":"<svg>...</svg>"},"sortOrder":{"type":"number","example":0},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.372Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.372Z"}},"required":["id","tenantId","name","sortOrder","createdAt","updatedAt"]},"CreateDiningZoneDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Patio"},"layoutSvg":{"type":"string","example":"<svg>...</svg>"},"sortOrder":{"type":"number","minimum":0,"example":0}},"required":["tenantId","name"]},"UpdateDiningZoneDto":{"type":"object","properties":{"name":{"type":"string","example":"Patio"},"layoutSvg":{"type":"string","example":"<svg>...</svg>"},"sortOrder":{"type":"number","minimum":0,"example":0}}},"ActiveTableSessionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"salesOrderId":{"type":"string","nullable":true,"example":"uuid"},"guestCount":{"type":"number","example":4},"sessionState":{"type":"string","nullable":true,"enum":["SEATED","ORDERING","SERVED","PAYMENT_PENDING","CLOSED"],"example":"SEATED"},"openedAt":{"format":"date-time","type":"string","example":"2026-09-19T06:32:00.000Z","description":"When the party was seated, in UTC. Render the clock time in the tenant timezone."},"seatedSeconds":{"type":"number","example":59280,"description":"Seconds since openedAt, measured on the server as the response was built. A badge that ticks should count up from openedAt itself rather than reuse this snapshot, which ages the moment it is sent."},"itemCount":{"type":"number","example":12,"description":"Units ordered: the sum of line quantities, not the number of lines. Voided lines are excluded; comped lines are counted."}},"required":["id","guestCount","openedAt","seatedSeconds","itemCount"]},"DiningTableEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"zoneId":{"type":"string","example":"uuid"},"tableNumber":{"type":"string","example":"T-12"},"maxSeats":{"type":"number","example":4},"posX":{"type":"string","nullable":true,"example":"120.50"},"posY":{"type":"string","nullable":true,"example":"85.00"},"shape":{"type":"string","nullable":true,"example":"RECTANGLE"},"status":{"type":"string","nullable":true,"enum":["AVAILABLE","OCCUPIED","DIRTY","RESERVED"],"example":"AVAILABLE"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.401Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.401Z"},"activeSession":{"nullable":true,"description":"The open session on this table, or null when nobody is seated. Carries the guest count, item count and seated duration the floor-plan card shows.","allOf":[{"$ref":"#/components/schemas/ActiveTableSessionEntity"}]}},"required":["id","tenantId","zoneId","tableNumber","maxSeats","createdAt","updatedAt"]},"CreateDiningTableDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"zoneId":{"type":"string","format":"uuid","example":"uuid"},"tableNumber":{"type":"string","example":"T-12"},"maxSeats":{"type":"number","minimum":1,"maximum":50,"example":4},"posX":{"type":"number","example":120.5},"posY":{"type":"number","example":85},"shape":{"type":"string","example":"RECTANGLE"},"status":{"type":"string","enum":["AVAILABLE","OCCUPIED","DIRTY","RESERVED"]}},"required":["tenantId","zoneId","tableNumber","maxSeats"]},"UpdateDiningTableDto":{"type":"object","properties":{"zoneId":{"type":"string","format":"uuid","example":"uuid"},"tableNumber":{"type":"string","example":"T-12"},"maxSeats":{"type":"number","minimum":1,"maximum":50,"example":4},"posX":{"type":"number","example":120.5},"posY":{"type":"number","example":85},"shape":{"type":"string","example":"RECTANGLE"},"status":{"type":"string","enum":["AVAILABLE","OCCUPIED","DIRTY","RESERVED"]}}},"UpdateDiningTableStatusDto":{"type":"object","properties":{"status":{"type":"string","enum":["AVAILABLE","OCCUPIED","DIRTY","RESERVED"]}},"required":["status"]},"SectionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Section A"},"color":{"type":"string","nullable":true,"example":"#FF5733"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.426Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.426Z"}},"required":["id","tenantId","locationId","name","createdAt","updatedAt"]},"CreateSectionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Section A"},"color":{"type":"string","example":"#FF5733"}},"required":["tenantId","locationId","name"]},"UpdateSectionDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Section A"},"color":{"type":"string","example":"#FF5733"}}},"AttachTableDto":{"type":"object","properties":{"tableId":{"type":"string","format":"uuid","example":"uuid"}},"required":["tableId"]},"SectionAssignmentEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"sectionId":{"type":"string","example":"uuid"},"userId":{"type":"string","example":"uuid"},"startsAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.428Z"},"endsAt":{"format":"date-time","type":"string","nullable":true,"example":null,"description":"When null, this assignment is currently active"},"notes":{"type":"string","nullable":true,"example":"Lunch shift coverage"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.428Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.428Z"}},"required":["id","sectionId","userId","startsAt","createdAt","updatedAt"]},"CreateSectionAssignmentDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"uuid"},"startsAt":{"type":"string","example":"2026-05-05T11:00:00Z"},"endsAt":{"type":"string","example":"2026-05-05T15:00:00Z","description":"When omitted, the assignment is open-ended (currently active)"},"notes":{"type":"string","example":"Lunch shift coverage"}},"required":["userId","startsAt"]},"UpdateSectionAssignmentDto":{"type":"object","properties":{"endsAt":{"type":"string","example":"2026-05-05T15:00:00Z"},"notes":{"type":"string","example":"Updated notes"}}},"KitchenPrinterEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Hot Line Printer"},"ipAddress":{"type":"string","nullable":true,"example":"192.168.1.50"},"port":{"type":"number","nullable":true,"example":9100},"isActive":{"type":"boolean","example":true},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.451Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.451Z"}},"required":["id","tenantId","locationId","name","isActive","createdAt","updatedAt"]},"CreateKitchenPrinterDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Hot Line Printer"},"ipAddress":{"type":"string","example":"192.168.1.50"},"port":{"type":"number","minimum":1,"maximum":65535,"example":9100},"isActive":{"type":"boolean","example":true}},"required":["tenantId","locationId","name"]},"UpdateKitchenPrinterDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Hot Line Printer"},"ipAddress":{"type":"string","example":"192.168.1.50"},"port":{"type":"number","minimum":1,"maximum":65535,"example":9100},"isActive":{"type":"boolean","example":true}}},"AttachCategoryDto":{"type":"object","properties":{"categoryId":{"type":"string","format":"uuid","example":"uuid"}},"required":["categoryId"]},"DiscountReasonEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"code":{"type":"string","example":"SENIOR_15"},"name":{"type":"string","example":"Senior citizen 15% off"},"description":{"type":"string","nullable":true,"example":"Applies to customers 65 and older"},"isActive":{"type":"boolean","example":true},"requiresManagerOverride":{"type":"boolean","example":false},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.473Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.473Z"}},"required":["id","tenantId","code","name","isActive","requiresManagerOverride","createdAt","updatedAt"]},"CreateDiscountReasonDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"code":{"type":"string","maxLength":50,"pattern":"/^[A-Z0-9_]+$/","example":"SENIOR_15"},"name":{"type":"string","example":"Senior citizen 15% off"},"description":{"type":"string","example":"Applies to customers 65 and older"},"isActive":{"type":"boolean","example":true},"requiresManagerOverride":{"type":"boolean","example":false}},"required":["tenantId","code","name"]},"UpdateDiscountReasonDto":{"type":"object","properties":{"name":{"type":"string","example":"Senior citizen 15% off"},"description":{"type":"string","example":"Applies to customers 65 and older"},"isActive":{"type":"boolean","example":true},"requiresManagerOverride":{"type":"boolean","example":false}}},"VoidReasonEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"code":{"type":"string","example":"CUSTOMER_CHANGED_MIND"},"name":{"type":"string","example":"Customer changed their mind"},"description":{"type":"string","nullable":true,"example":"Used when the customer modifies their order before service"},"isActive":{"type":"boolean","example":true},"requiresManagerOverride":{"type":"boolean","example":false},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.499Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.500Z"}},"required":["id","tenantId","code","name","isActive","requiresManagerOverride","createdAt","updatedAt"]},"CreateVoidReasonDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"code":{"type":"string","maxLength":50,"pattern":"/^[A-Z0-9_]+$/","example":"CUSTOMER_CHANGED_MIND"},"name":{"type":"string","example":"Customer changed their mind"},"description":{"type":"string","example":"Used when the customer modifies their order before service"},"isActive":{"type":"boolean","example":true},"requiresManagerOverride":{"type":"boolean","example":false}},"required":["tenantId","code","name"]},"UpdateVoidReasonDto":{"type":"object","properties":{"name":{"type":"string","example":"Customer changed their mind"},"description":{"type":"string","example":"Used when the customer modifies their order before service"},"isActive":{"type":"boolean","example":true},"requiresManagerOverride":{"type":"boolean","example":false}}},"TableSessionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"tableId":{"type":"string","example":"uuid"},"waiterId":{"type":"string","nullable":true,"example":"uuid"},"guestCount":{"type":"number","example":4},"openedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.519Z"},"closedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"salesOrderId":{"type":"string","nullable":true,"example":"uuid"},"sessionState":{"type":"string","nullable":true,"enum":["SEATED","ORDERING","SERVED","PAYMENT_PENDING","CLOSED"],"example":"SEATED"},"posRegisterId":{"type":"string","nullable":true,"example":"uuid"},"openedByPosSessionId":{"type":"string","nullable":true,"example":"uuid"}},"required":["id","tenantId","tableId","guestCount","openedAt"]},"OpenTableSessionDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid","description":"Tenant ID"},"tableId":{"type":"string","format":"uuid","example":"uuid","description":"Dining table to seat at"},"locationId":{"type":"string","format":"uuid","example":"uuid","description":"Location for the underlying SalesOrder (typically the restaurant location)"},"guestCount":{"type":"number","minimum":1,"example":4},"waiterId":{"type":"string","format":"uuid","example":"uuid","description":"Assigned waiter"},"posRegisterId":{"type":"string","format":"uuid","example":"uuid","description":"POS terminal opening this session"},"openedByPosSessionId":{"type":"string","format":"uuid","example":"uuid","description":"Cashier shift (PosSession) under which this is opened"},"salesChannel":{"type":"string","example":"POS","description":"Sales channel for the underlying order (default: POS)"}},"required":["tenantId","tableId","locationId","guestCount"]},"UpdateTableSessionDto":{"type":"object","properties":{"guestCount":{"type":"number","minimum":1,"example":4},"waiterId":{"type":"string","format":"uuid","example":"uuid"}}},"UpdateSessionStateDto":{"type":"object","properties":{"sessionState":{"type":"string","enum":["SEATED","ORDERING","SERVED","PAYMENT_PENDING","CLOSED"]}}},"TableSessionLineResultDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"salesOrderId":{"type":"string","example":"uuid"},"variantId":{"type":"string","example":"uuid"},"quantity":{"type":"string","example":"2.0000"},"unitPrice":{"type":"string","example":"5.0000"},"status":{"type":"string","nullable":true,"example":"PENDING"},"seatNumber":{"type":"number","nullable":true,"example":3}},"required":["id","salesOrderId","variantId","quantity","unitPrice"]},"AddSessionLineDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid","example":"uuid","description":"Product variant to add"},"quantity":{"type":"number","minimum":0.0001,"example":1},"unitPrice":{"type":"number","example":9.5,"description":"Unit price at time of order"},"lineDiscount":{"type":"number","example":0},"taxRateId":{"type":"string","format":"uuid","example":"uuid"},"taxAmount":{"type":"number","example":0},"courseType":{"type":"string","example":"STARTER","description":"Course type (STARTER, MAIN, DESSERT, etc.)"},"seatNumber":{"type":"number","minimum":1,"example":1,"description":"Seat number to allocate this line to"},"selectedModifiers":{"description":"Selected modifiers (JSON)","example":[{"modifierId":"uuid","name":"Extra cheese","priceDelta":1.5}],"type":"array","items":{"type":"object"}}},"required":["variantId","quantity","unitPrice"]},"SessionSeatAllocationEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"sessionId":{"type":"string","example":"uuid"},"salesOrderLineId":{"type":"string","example":"uuid"},"seatNumber":{"type":"number","example":1}},"required":["id","sessionId","salesOrderLineId","seatNumber"]},"AllocateSeatDto":{"type":"object","properties":{"salesOrderLineId":{"type":"string","format":"uuid","example":"uuid","description":"Sales order line to allocate"},"seatNumber":{"type":"number","minimum":1,"example":1,"description":"Seat number within the session"}},"required":["salesOrderLineId","seatNumber"]},"CheckoutSessionDto":{"type":"object","properties":{"payments":{"type":"array","items":{"$ref":"#/components/schemas/CheckoutPaymentDto"}},"tipAmount":{"type":"number","example":5,"description":"Total tip amount"},"serviceCharge":{"type":"number","example":2.5,"description":"Service charge"},"discountReasonId":{"type":"string","format":"uuid","example":"uuid","description":"Discount reason if discount applied"},"totalDiscount":{"type":"number","example":0,"description":"Order-level discount amount"}},"required":["payments"]},"KdsStationEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","nullable":true,"example":"uuid"},"name":{"type":"string","example":"Hot line"},"displayColor":{"type":"string","nullable":true,"example":"#FF5733"},"printerId":{"type":"string","nullable":true,"example":"uuid","description":"The printer at this station, if it has one."},"routingRules":{"type":"object","description":"Routing rules: { categoryIds: string[] }","example":{"categoryIds":["uuid-1","uuid-2"]}},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.557Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.558Z"}},"required":["id","tenantId","name","routingRules","createdAt","updatedAt"]},"KdsRoutingRulesDto":{"type":"object","properties":{"categoryIds":{"example":["uuid-cat-1","uuid-cat-2"],"description":"Category IDs that route to this station","type":"array","items":{"type":"string","format":"uuid"}}}},"CreateKdsStationDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Hot line"},"displayColor":{"type":"string","example":"#FF5733"},"printerId":{"type":"string","format":"uuid","example":"uuid","description":"The printer standing at this station. Tickets grouped here print there. Leave it out for a screen-only station that needs no paper."},"routingRules":{"$ref":"#/components/schemas/KdsRoutingRulesDto"}},"required":["tenantId","name"]},"UpdateKdsStationDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Hot line"},"displayColor":{"type":"string","example":"#FF5733"},"printerId":{"type":"string","format":"uuid","example":"uuid","description":"The printer standing at this station. Tickets grouped here print there. Leave it out for a screen-only station that needs no paper."},"routingRules":{"$ref":"#/components/schemas/KdsRoutingRulesDto"}}},"KdsTicketEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"sessionId":{"type":"string","nullable":true,"example":"uuid","description":"Set for dine-in tickets"},"salesOrderId":{"type":"string","nullable":true,"example":"uuid","description":"Set for counter/QSR tickets (no table session)"},"stationId":{"type":"string","example":"uuid"},"ticketNumber":{"type":"string","example":"KDS-20260506-0001"},"courseType":{"type":"string","nullable":true,"example":"MAIN"},"firedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.596Z"},"startedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"bumpedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"status":{"type":"string","nullable":true,"enum":["PENDING","PREPARING","READY","EXPEDITED"],"example":"PENDING"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.596Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.596Z"}},"required":["id","tenantId","stationId","ticketNumber","firedAt","createdAt","updatedAt"]},"FireTicketsResultDto":{"type":"object","properties":{"tickets":{"type":"array","items":{"$ref":"#/components/schemas/KdsTicketEntity"}},"unroutedLineIds":{"example":["uuid"],"description":"Order lines that matched no station routing rule.","type":"array","items":{"type":"string"}}},"required":["tickets","unroutedLineIds"]},"FireTicketsDto":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid","example":"uuid","description":"Table session to fire (dine-in flow). Either sessionId or salesOrderId is required."},"salesOrderId":{"type":"string","format":"uuid","example":"uuid","description":"Sales order to fire (counter/QSR flow). Either sessionId or salesOrderId is required."}}},"KdsTicketLineEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"ticketId":{"type":"string","example":"uuid"},"salesOrderLineId":{"type":"string","example":"uuid"},"productName":{"type":"string","example":"Cheeseburger"},"quantity":{"type":"string","example":"1.0000"},"seatNumber":{"type":"number","nullable":true,"example":1},"kitchenModifiers":{"type":"string","nullable":true,"example":"No onions"},"status":{"type":"string","nullable":true,"enum":["PENDING","PREPARING","READY"],"example":"PENDING"},"bumpedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.600Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.600Z"}},"required":["id","ticketId","salesOrderLineId","productName","quantity","createdAt","updatedAt"]},"ReservationEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"customerId":{"type":"string","nullable":true,"example":"uuid"},"guestName":{"type":"string","example":"Jane Doe"},"guestPhone":{"type":"string","nullable":true,"example":"+1-555-0100"},"guestEmail":{"type":"string","nullable":true,"example":"jane@example.com"},"partySize":{"type":"number","example":4},"reservedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.625Z"},"estimatedDurationMins":{"type":"number","example":90},"preferredZoneId":{"type":"string","nullable":true,"example":"uuid"},"assignedTableId":{"type":"string","nullable":true,"example":"uuid"},"tableSessionId":{"type":"string","nullable":true,"example":"uuid"},"specialRequests":{"type":"string","nullable":true,"example":"High chair needed"},"notes":{"type":"string","nullable":true,"example":null},"status":{"type":"string","nullable":true,"enum":["PENDING","CONFIRMED","SEATED","NO_SHOW","CANCELED","COMPLETED"],"example":"PENDING"},"seatedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"canceledAt":{"format":"date-time","type":"string","nullable":true,"example":null},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.625Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.625Z"}},"required":["id","tenantId","locationId","guestName","partySize","reservedAt","estimatedDurationMins","createdAt","updatedAt"]},"CreateReservationDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"customerId":{"type":"string","format":"uuid","example":"uuid"},"guestName":{"type":"string","example":"Jane Doe"},"guestPhone":{"type":"string","example":"+1-555-0100"},"guestEmail":{"type":"string","format":"email","example":"jane@example.com"},"partySize":{"type":"number","minimum":1,"example":4},"reservedAt":{"type":"string","example":"2026-05-10T19:00:00Z"},"estimatedDurationMins":{"type":"number","minimum":15,"example":90,"description":"Default 90 minutes"},"preferredZoneId":{"type":"string","format":"uuid","example":"uuid"},"assignedTableId":{"type":"string","format":"uuid","example":"uuid"},"specialRequests":{"type":"string","example":"High chair, window seat"},"notes":{"type":"string","example":"Birthday celebration"}},"required":["tenantId","locationId","guestName","partySize","reservedAt"]},"UpdateReservationDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"customerId":{"type":"string","format":"uuid","example":"uuid"},"guestName":{"type":"string","example":"Jane Doe"},"guestPhone":{"type":"string","example":"+1-555-0100"},"guestEmail":{"type":"string","format":"email","example":"jane@example.com"},"partySize":{"type":"number","minimum":1,"example":4},"reservedAt":{"type":"string","example":"2026-05-10T19:00:00Z"},"estimatedDurationMins":{"type":"number","minimum":15,"example":90,"description":"Default 90 minutes"},"preferredZoneId":{"type":"string","format":"uuid","example":"uuid"},"assignedTableId":{"type":"string","format":"uuid","example":"uuid"},"specialRequests":{"type":"string","example":"High chair, window seat"},"notes":{"type":"string","example":"Birthday celebration"}}},"SeatReservationResultDto":{"type":"object","properties":{"reservation":{"$ref":"#/components/schemas/ReservationEntity"},"tableSession":{"$ref":"#/components/schemas/TableSessionEntity"}},"required":["reservation","tableSession"]},"SeatReservationDto":{"type":"object","properties":{"tableId":{"type":"string","format":"uuid","example":"uuid","description":"Table to seat the party at"},"waiterId":{"type":"string","format":"uuid","example":"uuid"},"guestCount":{"type":"number","minimum":1,"example":4,"description":"Override partySize on session (defaults to reservation party size)"},"posRegisterId":{"type":"string","format":"uuid","example":"uuid"},"openedByPosSessionId":{"type":"string","format":"uuid","example":"uuid"}},"required":["tableId"]},"WaitlistEntryEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"customerId":{"type":"string","nullable":true,"example":"uuid"},"guestName":{"type":"string","example":"John Smith"},"guestPhone":{"type":"string","nullable":true,"example":"+1-555-0100"},"partySize":{"type":"number","example":2},"joinedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.654Z"},"estimatedWaitMins":{"type":"number","nullable":true,"example":25},"preferredZoneId":{"type":"string","nullable":true,"example":"uuid"},"assignedTableId":{"type":"string","nullable":true,"example":"uuid"},"tableSessionId":{"type":"string","nullable":true,"example":"uuid"},"notifiedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"seatedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"canceledAt":{"format":"date-time","type":"string","nullable":true,"example":null},"notes":{"type":"string","nullable":true,"example":null},"status":{"type":"string","nullable":true,"enum":["WAITING","NOTIFIED","SEATED","CANCELED","NO_SHOW"],"example":"WAITING"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.654Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.654Z"}},"required":["id","tenantId","locationId","guestName","partySize","joinedAt","createdAt","updatedAt"]},"CreateWaitlistEntryDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"customerId":{"type":"string","format":"uuid","example":"uuid"},"guestName":{"type":"string","example":"John Smith"},"guestPhone":{"type":"string","example":"+1-555-0100"},"partySize":{"type":"number","minimum":1,"example":2},"estimatedWaitMins":{"type":"number","minimum":0,"example":25},"preferredZoneId":{"type":"string","format":"uuid","example":"uuid"},"notes":{"type":"string","example":"Window seat preferred"}},"required":["tenantId","locationId","guestName","partySize"]},"UpdateWaitlistEntryDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"customerId":{"type":"string","format":"uuid","example":"uuid"},"guestName":{"type":"string","example":"John Smith"},"guestPhone":{"type":"string","example":"+1-555-0100"},"partySize":{"type":"number","minimum":1,"example":2},"estimatedWaitMins":{"type":"number","minimum":0,"example":25},"preferredZoneId":{"type":"string","format":"uuid","example":"uuid"},"notes":{"type":"string","example":"Window seat preferred"}}},"SeatWaitlistDto":{"type":"object","properties":{"tableId":{"type":"string","format":"uuid","example":"uuid"},"waiterId":{"type":"string","format":"uuid","example":"uuid"},"guestCount":{"type":"number","minimum":1,"example":2},"posRegisterId":{"type":"string","format":"uuid","example":"uuid"},"openedByPosSessionId":{"type":"string","format":"uuid","example":"uuid"}},"required":["tableId"]},"TipPoolEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Friday Dinner Pool"},"periodStart":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.680Z"},"periodEnd":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.680Z"},"distributionMethod":{"type":"string","enum":["EQUAL","BY_HOURS","MANUAL"],"example":"BY_HOURS"},"totalTips":{"type":"string","example":"500.0000"},"totalServiceCharge":{"type":"string","example":"120.0000"},"includeServiceCharge":{"type":"boolean","example":false},"serviceChargeShareBps":{"type":"number","example":0},"totalDistributable":{"type":"string","example":"500.0000"},"status":{"type":"string","nullable":true,"enum":["OPEN","SETTLED"],"example":"OPEN"},"settledAt":{"format":"date-time","type":"string","nullable":true,"example":null},"settledBy":{"type":"string","nullable":true,"example":"uuid"},"notes":{"type":"string","nullable":true,"example":null},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.681Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.681Z"}},"required":["id","tenantId","locationId","name","periodStart","periodEnd","distributionMethod","totalTips","totalServiceCharge","includeServiceCharge","serviceChargeShareBps","totalDistributable","createdAt","updatedAt"]},"CreateTipPoolDto":{"type":"object","properties":{"tenantId":{"type":"string","format":"uuid","example":"uuid"},"locationId":{"type":"string","format":"uuid","example":"uuid"},"name":{"type":"string","example":"Friday Dinner Pool"},"periodStart":{"type":"string","example":"2026-05-06T17:00:00Z"},"periodEnd":{"type":"string","example":"2026-05-06T23:00:00Z"},"distributionMethod":{"type":"string","enum":["EQUAL","BY_HOURS","MANUAL"],"example":"BY_HOURS"},"includeServiceCharge":{"type":"boolean","example":false},"serviceChargeShareBps":{"type":"number","minimum":0,"maximum":10000,"example":5000,"description":"Basis points (5000 = 50%) of service charge that feeds the pool"},"notes":{"type":"string","example":"Closing manager: Alice"}},"required":["tenantId","locationId","name","periodStart","periodEnd","distributionMethod"]},"UpdateTipPoolDto":{"type":"object","properties":{"name":{"type":"string","example":"Friday Dinner Pool"},"periodStart":{"type":"string","example":"2026-05-06T17:00:00Z"},"periodEnd":{"type":"string","example":"2026-05-06T23:00:00Z"},"distributionMethod":{"type":"string","enum":["EQUAL","BY_HOURS","MANUAL"],"example":"BY_HOURS"},"includeServiceCharge":{"type":"boolean","example":false},"serviceChargeShareBps":{"type":"number","minimum":0,"maximum":10000,"example":5000,"description":"Basis points (5000 = 50%) of service charge that feeds the pool"},"notes":{"type":"string","example":"Closing manager: Alice"}}},"TipPoolAllocationEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"poolId":{"type":"string","example":"uuid"},"userId":{"type":"string","example":"uuid"},"role":{"type":"string","nullable":true,"example":"SERVER"},"hoursWorked":{"type":"string","nullable":true,"example":"8.00"},"weight":{"type":"string","example":"1.0000"},"amount":{"type":"string","example":"125.0000"},"notes":{"type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.683Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.683Z"}},"required":["id","poolId","userId","weight","amount","createdAt","updatedAt"]},"CreateAllocationDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"uuid"},"role":{"type":"string","example":"SERVER"},"hoursWorked":{"type":"number","minimum":0,"example":8},"weight":{"type":"number","minimum":0,"example":1},"amount":{"type":"number","minimum":0,"example":0,"description":"Manual amount (used when distributionMethod = MANUAL)"},"notes":{"type":"string","example":null}},"required":["userId"]},"UpdateAllocationDto":{"type":"object","properties":{"role":{"type":"string","example":"SERVER"},"hoursWorked":{"type":"number","minimum":0,"example":8},"weight":{"type":"number","minimum":0,"example":1},"amount":{"type":"number","minimum":0,"example":0},"notes":{"type":"string","example":null}}},"ShiftTemplateEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Evening"},"startTime":{"format":"date-time","type":"string","example":"1970-01-01T17:00:00.000Z","description":"Time of day only; the date part is not meaningful."},"endTime":{"format":"date-time","type":"string","example":"1970-01-01T02:00:00.000Z","description":"Time of day only. An end at or before the start means the shift runs past midnight."},"unpaidBreakMinutes":{"type":"number","example":30},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.721Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.721Z"}},"required":["id","tenantId","name","startTime","endTime","unpaidBreakMinutes","createdAt","updatedAt"]},"CreateShiftTemplateDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"Evening"},"startTime":{"type":"string","example":"17:00","description":"24-hour HH:MM. An end at or before the start runs past midnight."},"endTime":{"type":"string","example":"02:00","description":"24-hour HH:MM."},"unpaidBreakMinutes":{"type":"number","minimum":0,"example":30,"default":0}},"required":["name","startTime","endTime"]},"UpdateShiftTemplateDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"Evening"},"startTime":{"type":"string","example":"17:00"},"endTime":{"type":"string","example":"02:00"},"unpaidBreakMinutes":{"type":"number","minimum":0,"example":30}}},"ShiftRosterEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"userId":{"type":"string","example":"uuid"},"shiftTemplateId":{"type":"string","nullable":true,"example":"uuid"},"shiftDate":{"format":"date-time","type":"string","example":"2026-08-25"},"scheduledStart":{"format":"date-time","type":"string","example":"2026-08-25T17:00:00.000Z"},"scheduledEnd":{"format":"date-time","type":"string","example":"2026-08-26T02:00:00.000Z","description":"Absolute timestamp, so a shift past midnight needs no special case."},"status":{"type":"string","enum":["PUBLISHED","SWAP_REQUESTED","COMPLETED","ABSENT"],"example":"PUBLISHED"},"swapRequestedWithUserId":{"type":"string","nullable":true,"example":null},"swapApprovedBy":{"type":"string","nullable":true,"example":null},"notes":{"type":"string","nullable":true,"example":null},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.735Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.735Z"}},"required":["id","tenantId","locationId","userId","shiftDate","scheduledStart","scheduledEnd","status","createdAt","updatedAt"]},"CreateShiftRosterDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"userId":{"type":"string","format":"uuid","example":"uuid"},"shiftDate":{"type":"string","example":"2026-08-25","description":"Calendar date, YYYY-MM-DD."},"shiftTemplateId":{"type":"string","format":"uuid","example":"uuid","description":"Take the times from this template. Omit only if supplying scheduledStart and scheduledEnd."},"scheduledStart":{"type":"string","example":"2026-08-25T17:00:00.000Z","description":"Overrides the template. Required when no template is given."},"scheduledEnd":{"type":"string","example":"2026-08-26T02:00:00.000Z"},"notes":{"type":"string","example":"Covering for Zaw"}},"required":["locationId","userId","shiftDate"]},"SkippedShiftDto":{"type":"object","properties":{"userId":{"type":"string","example":"uuid"},"shiftDate":{"type":"string","example":"2026-08-26"},"reason":{"type":"string","example":"already rostered on an overlapping shift"}},"required":["userId","shiftDate","reason"]},"ShiftRosterRunResultDto":{"type":"object","properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/ShiftRosterEntity"}},"skipped":{"description":"Days that were not rostered, and why.","type":"array","items":{"$ref":"#/components/schemas/SkippedShiftDto"}}},"required":["created","skipped"]},"CreateShiftRosterRunDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"shiftTemplateId":{"type":"string","format":"uuid","example":"uuid"},"userIds":{"example":["uuid-a","uuid-b"],"type":"array","items":{"type":"string","format":"uuid"}},"fromDate":{"type":"string","example":"2026-08-25"},"toDate":{"type":"string","example":"2026-08-31"},"weekdays":{"example":[1,2,3,4,5],"description":"Days of the week to roster, 0 = Sunday. Omit to roster every day in the range.","type":"array","items":{"type":"number","maximum":6,"minimum":0}}},"required":["locationId","shiftTemplateId","userIds","fromDate","toDate"]},"UpdateShiftRosterDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"uuid"},"scheduledStart":{"type":"string","example":"2026-08-25T17:00:00.000Z"},"scheduledEnd":{"type":"string","example":"2026-08-26T02:00:00.000Z"},"status":{"type":"string","enum":["PUBLISHED","SWAP_REQUESTED","COMPLETED","ABSENT"]},"notes":{"type":"string","example":"Called in sick"}}},"RequestShiftSwapDto":{"type":"object","properties":{"swapWithUserId":{"type":"string","format":"uuid","example":"uuid","description":"The colleague asked to take the shift."}},"required":["swapWithUserId"]},"TimesheetEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"userId":{"type":"string","example":"uuid"},"shiftRosterId":{"type":"string","nullable":true,"example":"uuid"},"workDate":{"format":"date-time","type":"string","example":"2026-08-25"},"actualStart":{"format":"date-time","type":"string","nullable":true,"example":"2026-08-25T17:04:00.000Z"},"actualEnd":{"format":"date-time","type":"string","nullable":true,"example":null,"description":"Null while the shift is still in progress."},"totalWorkedMinutes":{"type":"number","example":540,"description":"Excludes the unpaid break."},"lateMinutes":{"type":"number","example":4},"overtimeMinutes":{"type":"number","example":30},"status":{"type":"string","enum":["PENDING_APPROVAL","APPROVED","REJECTED"],"example":"PENDING_APPROVAL"},"approvedBy":{"type":"string","nullable":true,"example":null},"notes":{"type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.765Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-21T21:31:23.765Z"}},"required":["id","tenantId","userId","workDate","totalWorkedMinutes","lateMinutes","overtimeMinutes","status","createdAt","updatedAt"]},"ClockInDto":{"type":"object","properties":{"shiftRosterId":{"type":"string","format":"uuid","example":"uuid","description":"The rostered shift being started. Omit for unscheduled work; lateness is then zero."},"userId":{"type":"string","format":"uuid","example":"uuid","description":"Whose attendance this is. Defaults to the caller."},"at":{"type":"string","example":"2026-08-25T17:04:00.000Z","description":"Defaults to now. Supply to record a punch after the fact."}}},"ClockOutDto":{"type":"object","properties":{"at":{"type":"string","example":"2026-08-26T02:30:00.000Z","description":"Defaults to now."},"notes":{"type":"string","example":"Stayed to close the till"}}},"WorkedHoursDto":{"type":"object","properties":{"userId":{"type":"string","example":"uuid"},"totalWorkedMinutes":{"type":"number","example":2460},"hours":{"type":"number","example":41}},"required":["userId","totalWorkedMinutes","hours"]},"DecideTimesheetDto":{"type":"object","properties":{"status":{"type":"string","enum":["APPROVED","REJECTED"],"example":"APPROVED","description":"Only approved hours count towards tip distribution by hours."}},"required":["status"]},"KtvRoomEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"locationId":{"type":"string","example":"uuid"},"roomNumber":{"type":"string","example":"A1"},"name":{"type":"string","nullable":true,"example":"Grand Room"},"capacity":{"type":"number","example":12},"rateVariantId":{"type":"string","example":"uuid","description":"The variant whose price is the hourly rate. Billing emits ordinary order lines against it, so tax, discounts and reporting need no knowledge of rooms."},"minimumMinutes":{"type":"number","example":60},"incrementMinutes":{"type":"number","example":30},"graceMinutes":{"type":"number","example":5,"description":"Minutes past a block boundary that are not charged for."},"roundingMode":{"type":"string","enum":["UP","NEAREST","DOWN"],"example":"UP"},"status":{"type":"string","enum":["AVAILABLE","OCCUPIED","CLEANING","OUT_OF_SERVICE"],"example":"AVAILABLE"},"deletedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"createdAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:00:00.000Z"}},"required":["id","tenantId","locationId","roomNumber","capacity","rateVariantId","minimumMinutes","incrementMinutes","graceMinutes","roundingMode","status","createdAt","updatedAt"]},"CreateKtvRoomDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid","description":"The outlet the room belongs to."},"roomNumber":{"type":"string","maxLength":50,"example":"A1"},"name":{"type":"string","maxLength":100,"example":"Grand Room"},"capacity":{"type":"number","minimum":1,"example":12},"rateVariantId":{"type":"string","format":"uuid","example":"uuid","description":"Variant whose price is the hourly rate. Must be a SERVICE product - a stocked one would have its stock checked, and there are no hours in stock."},"minimumMinutes":{"type":"number","minimum":0,"example":60,"description":"Shortest let that can be charged."},"incrementMinutes":{"type":"number","minimum":1,"example":30,"description":"Time is sold in blocks of this size beyond the minimum."},"graceMinutes":{"type":"number","minimum":0,"example":5,"description":"Minutes past a block boundary that are forgiven. Must be shorter than the increment, or no overrun is ever chargeable."},"roundingMode":{"type":"string","enum":["UP","NEAREST","DOWN"],"default":"UP"}},"required":["locationId","roomNumber","capacity","rateVariantId"]},"UpdateKtvRoomDto":{"type":"object","properties":{"locationId":{"type":"string","format":"uuid","example":"uuid"},"roomNumber":{"type":"string","maxLength":50,"example":"A1"},"name":{"type":"string","maxLength":100,"example":"Grand Room"},"capacity":{"type":"number","minimum":1,"example":12},"rateVariantId":{"type":"string","format":"uuid","example":"uuid"},"minimumMinutes":{"type":"number","minimum":0,"example":60},"incrementMinutes":{"type":"number","minimum":1,"example":30},"graceMinutes":{"type":"number","minimum":0,"example":5},"roundingMode":{"type":"string","enum":["UP","NEAREST","DOWN"]},"status":{"type":"string","enum":["AVAILABLE","OCCUPIED","CLEANING","OUT_OF_SERVICE"],"description":"Use CLEANING and OUT_OF_SERVICE here; OCCUPIED is set by a let."}}},"KtvRoomSessionEntity":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"tenantId":{"type":"string","example":"uuid"},"roomId":{"type":"string","example":"uuid"},"guestWalletId":{"type":"string","nullable":true,"example":"uuid","description":"The wallet the party is drawing on, if they are using cards."},"hostUserId":{"type":"string","nullable":true,"example":"uuid"},"guestCount":{"type":"number","example":5},"openedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:05:00.000Z"},"closedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"pausedMinutes":{"type":"number","example":0,"description":"Minutes the clock was stopped, deducted from the bill."},"pausedAt":{"format":"date-time","type":"string","nullable":true,"example":null},"plannedMinutes":{"type":"number","nullable":true,"example":180,"description":"How long the party said they wanted, in minutes. Informational: the bill is still metered off the clock, so leaving early costs less and staying late costs more. Null on sessions opened before anyone was asked."},"salesOrderId":{"type":"string","nullable":true,"example":"uuid"},"sessionState":{"type":"string","enum":["OPEN","PAUSED","PAYMENT_PENDING","CLOSED"],"example":"OPEN"},"posRegisterId":{"type":"string","nullable":true,"example":"uuid"},"openedByPosSessionId":{"type":"string","nullable":true,"example":"uuid"},"minimumMinutesSnapshot":{"type":"number","example":60},"incrementMinutesSnapshot":{"type":"number","example":30},"graceMinutesSnapshot":{"type":"number","example":5},"roundingModeSnapshot":{"type":"string","enum":["UP","NEAREST","DOWN"]},"createdAt":{"format":"date-time","type":"string","example":"2026-09-12T20:05:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:05:00.000Z"}},"required":["id","tenantId","roomId","guestCount","openedAt","pausedMinutes","sessionState","minimumMinutesSnapshot","incrementMinutesSnapshot","graceMinutesSnapshot","roundingModeSnapshot","createdAt","updatedAt"]},"OpenKtvSessionDto":{"type":"object","properties":{"roomId":{"type":"string","format":"uuid","example":"uuid"},"guestCount":{"type":"number","minimum":1,"example":5},"guestWalletId":{"type":"string","format":"uuid","example":"uuid","description":"The wallet the party will pay from. Several cards may draw on it, which is the usual arrangement for a room."},"hostUserId":{"type":"string","format":"uuid","example":"uuid","description":"Staff member hosting."},"plannedMinutes":{"type":"number","minimum":1,"example":180,"description":"How long the party asked for, in minutes. Informational only - the bill is metered off the clock, so this never changes what they are charged. It is what the board counts down to, and what tells the desk when to go and ask."},"posRegisterId":{"type":"string","format":"uuid","example":"uuid"},"openedByPosSessionId":{"type":"string","format":"uuid","example":"uuid"},"salesChannel":{"type":"string","example":"POS"}},"required":["roomId","guestCount"]},"QuotedSegmentDto":{"type":"object","properties":{"label":{"type":"string","example":"Peak"},"from":{"format":"date-time","type":"string","example":"2026-09-12T22:00:00.000Z"},"to":{"format":"date-time","type":"string","example":"2026-09-13T01:00:00.000Z"},"minutes":{"type":"number","example":180,"description":"Wall-clock minutes in this window."},"billableMinutes":{"type":"number","example":180,"description":"Minutes actually charged for."},"hours":{"type":"string","example":"3.0000"},"rate":{"type":"string","example":"30000.0000"},"amount":{"type":"string","example":"90000.0000"}},"required":["label","from","to","minutes","billableMinutes","hours","rate","amount"]},"KtvSessionQuoteDto":{"type":"object","properties":{"sessionId":{"type":"string","example":"uuid"},"roomId":{"type":"string","example":"uuid"},"roomNumber":{"type":"string","example":"A1"},"state":{"type":"string","enum":["OPEN","PAUSED","PAYMENT_PENDING","CLOSED"]},"openedAt":{"format":"date-time","type":"string","example":"2026-09-12T20:05:00.000Z"},"asOf":{"format":"date-time","type":"string","example":"2026-09-13T01:00:00.000Z"},"elapsedMinutes":{"type":"number","example":295},"pausedMinutes":{"type":"number","example":0},"segments":{"description":"One entry per rate window, so a receipt shows both rates rather than an average the guest cannot check.","type":"array","items":{"$ref":"#/components/schemas/QuotedSegmentDto"}},"roomCharge":{"type":"string","example":"130000.0000"},"fnbCharge":{"type":"string","example":"15000.0000"},"runningTotal":{"type":"string","example":"145000.0000"}},"required":["sessionId","roomId","roomNumber","state","openedAt","asOf","elapsedMinutes","pausedMinutes","segments","roomCharge","fnbCharge","runningTotal"]},"SetPlannedMinutesDto":{"type":"object","properties":{"plannedMinutes":{"type":"number","nullable":true,"minimum":1,"example":240,"description":"The new planned length in minutes, measured from when the room opened - not an amount to add. Null clears it and the board stops counting down."}},"required":["plannedMinutes"]},"CloseKtvSessionDto":{"type":"object","properties":{"closedAt":{"type":"string","example":"2026-09-13T01:00:00.000Z","description":"Defaults to now. Cannot be before the room was taken."}}},"CountAmountDto":{"type":"object","properties":{"count":{"type":"number","example":3},"amount":{"type":"string","example":"45000.0000"}},"required":["count","amount"]},"SummaryOrdersDto":{"type":"object","properties":{"count":{"type":"number","example":120,"description":"Orders sold, refunded ones included"},"averageNetSales":{"type":"string","example":"38500.0000"},"averageGrandTotal":{"type":"string","example":"42350.0000"},"voided":{"$ref":"#/components/schemas/CountAmountDto"}},"required":["count","averageNetSales","averageGrandTotal","voided"]},"SummarySalesDto":{"type":"object","properties":{"grossSales":{"type":"string","example":"4800000.0000","description":"Quantity x price"},"lineDiscounts":{"type":"string","example":"120000.0000"},"orderDiscounts":{"type":"string","example":"60000.0000","description":"Discounts on the whole bill"},"totalDiscounts":{"type":"string","example":"180000.0000"},"netSales":{"type":"string","example":"4620000.0000","description":"After discounts, before tax"},"serviceCharge":{"type":"string","example":"231000.0000"},"tax":{"type":"string","example":"231000.0000"},"tips":{"type":"string","example":"12000.0000"},"grandTotal":{"type":"string","example":"5094000.0000"}},"required":["grossSales","lineDiscounts","orderDiscounts","totalDiscounts","netSales","serviceCharge","tax","tips","grandTotal"]},"RefundMethodRowDto":{"type":"object","properties":{"refundMethod":{"type":"string","example":"CASH"},"count":{"type":"number","example":2},"amount":{"type":"string","example":"15000.0000"}},"required":["refundMethod","count","amount"]},"SummaryRefundsDto":{"type":"object","properties":{"count":{"type":"number","example":2},"subtotal":{"type":"string","example":"14285.7143"},"tax":{"type":"string","example":"714.2857"},"total":{"type":"string","example":"15000.0000"},"byMethod":{"type":"array","items":{"$ref":"#/components/schemas/RefundMethodRowDto"}}},"required":["count","subtotal","tax","total","byMethod"]},"PaymentMethodRowDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Cash"},"kind":{"type":"string","example":"CASH"},"count":{"type":"number","example":80},"amount":{"type":"string","example":"3200000.0000"}},"required":["paymentMethodId","name","kind","count","amount"]},"SummaryPaymentsDto":{"type":"object","properties":{"byMethod":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethodRowDto"}},"tendered":{"type":"string","example":"5140000.0000","description":"Everything handed over"},"changeGiven":{"type":"string","example":"46000.0000","description":"Handed back as change. Tendered less change is the grand total."}},"required":["byMethod","tendered","changeGiven"]},"SummaryDayRowDto":{"type":"object","properties":{"businessDate":{"type":"string","example":"2026-09-13"},"orderCount":{"type":"number","example":14},"netSales":{"type":"string","example":"540000.0000"},"grandTotal":{"type":"string","example":"594000.0000"},"refunds":{"type":"string","example":"0.0000","description":"Refunds made that day"}},"required":["businessDate","orderCount","netSales","grandTotal","refunds"]},"SummaryHourRowDto":{"type":"object","properties":{"hour":{"type":"number","example":21,"description":"Local hour, 0-23, of the payment"},"orderCount":{"type":"number","example":9},"netSales":{"type":"string","example":"310000.0000"},"grandTotal":{"type":"string","example":"341000.0000"}},"required":["hour","orderCount","netSales","grandTotal"]},"SummaryOutletRowDto":{"type":"object","properties":{"locationId":{"type":"string","nullable":true,"example":"uuid"},"locationName":{"type":"string","example":"KTV"},"orderCount":{"type":"number","example":40},"netSales":{"type":"string","example":"1800000.0000"},"grandTotal":{"type":"string","example":"1980000.0000"}},"required":["locationId","locationName","orderCount","netSales","grandTotal"]},"SummaryServiceTypeRowDto":{"type":"object","properties":{"serviceType":{"type":"string","example":"DINE_IN"},"orderCount":{"type":"number","example":60},"netSales":{"type":"string","example":"2400000.0000"},"grandTotal":{"type":"string","example":"2640000.0000"}},"required":["serviceType","orderCount","netSales","grandTotal"]},"SalesSummaryReportDto":{"type":"object","properties":{"from":{"type":"string","example":"2026-09-01"},"to":{"type":"string","example":"2026-09-14"},"locationIds":{"nullable":true,"description":"Outlets covered; null means every outlet you can see.","type":"array","items":{"type":"string"}},"orders":{"$ref":"#/components/schemas/SummaryOrdersDto"},"sales":{"$ref":"#/components/schemas/SummarySalesDto"},"refunds":{"$ref":"#/components/schemas/SummaryRefundsDto"},"netAfterRefunds":{"type":"string","example":"5079000.0000","description":"Grand total less refunds"},"voidedLines":{"description":"Lines voided on sold bills","allOf":[{"$ref":"#/components/schemas/CountAmountDto"}]},"compedLines":{"description":"Lines given away","allOf":[{"$ref":"#/components/schemas/CountAmountDto"}]},"payments":{"$ref":"#/components/schemas/SummaryPaymentsDto"},"byDay":{"type":"array","items":{"$ref":"#/components/schemas/SummaryDayRowDto"}},"byHour":{"type":"array","items":{"$ref":"#/components/schemas/SummaryHourRowDto"}},"byOutlet":{"type":"array","items":{"$ref":"#/components/schemas/SummaryOutletRowDto"}},"byServiceType":{"type":"array","items":{"$ref":"#/components/schemas/SummaryServiceTypeRowDto"}}},"required":["from","to","locationIds","orders","sales","refunds","netAfterRefunds","voidedLines","compedLines","payments","byDay","byHour","byOutlet","byServiceType"]},"ItemTotalsDto":{"type":"object","properties":{"itemCount":{"type":"number","example":42},"quantitySold":{"type":"string","example":"860.0000"},"grossSales":{"type":"string","example":"4800000.0000"},"lineDiscounts":{"type":"string","example":"120000.0000"},"orderDiscounts":{"type":"string","example":"60000.0000"},"netSales":{"type":"string","example":"4620000.0000"},"quantityReturned":{"type":"string","example":"3.0000"},"refundAmount":{"type":"string","example":"14285.7143","description":"Before tax"},"netAfterRefunds":{"type":"string","example":"4605714.2857"},"quantityVoided":{"type":"string","example":"4.0000"},"voidedValue":{"type":"string","example":"20000.0000"},"quantityComped":{"type":"string","example":"1.0000"},"compedValue":{"type":"string","example":"8000.0000"}},"required":["itemCount","quantitySold","grossSales","lineDiscounts","orderDiscounts","netSales","quantityReturned","refundAmount","netAfterRefunds","quantityVoided","voidedValue","quantityComped","compedValue"]},"ItemCategoryRowDto":{"type":"object","properties":{"categoryId":{"type":"string","nullable":true,"example":"uuid"},"categoryName":{"type":"string","example":"Beer"},"orderCount":{"type":"number","example":55},"quantitySold":{"type":"string","example":"310.0000"},"netSales":{"type":"string","example":"1550000.0000"},"shareOfNetSales":{"type":"string","example":"33.55","description":"Percent of net sales"},"refundAmount":{"type":"string","example":"0.0000"}},"required":["categoryId","categoryName","orderCount","quantitySold","netSales","shareOfNetSales","refundAmount"]},"ItemRowDto":{"type":"object","properties":{"variantId":{"type":"string","example":"uuid"},"productId":{"type":"string","nullable":true,"example":"uuid"},"productName":{"type":"string","example":"Myanmar Beer"},"variantSku":{"type":"string","nullable":true,"example":"BEER-MM-640"},"categoryId":{"type":"string","nullable":true,"example":"uuid"},"categoryName":{"type":"string","example":"Beer"},"orderCount":{"type":"number","example":40},"quantitySold":{"type":"string","example":"120.0000"},"averagePrice":{"type":"string","example":"4750.0000","description":"Net sales per unit"},"grossSales":{"type":"string","example":"600000.0000"},"lineDiscounts":{"type":"string","example":"12000.0000"},"orderDiscounts":{"type":"string","example":"18000.0000","description":"Share of bill discounts"},"netSales":{"type":"string","example":"570000.0000"},"shareOfNetSales":{"type":"string","example":"12.34"},"quantityReturned":{"type":"string","example":"1.0000"},"refundAmount":{"type":"string","example":"4750.0000"},"netQuantity":{"type":"string","example":"119.0000"},"netAfterRefunds":{"type":"string","example":"565250.0000"},"quantityVoided":{"type":"string","example":"2.0000"},"voidedValue":{"type":"string","example":"10000.0000"},"quantityComped":{"type":"string","example":"0.0000"},"compedValue":{"type":"string","example":"0.0000"}},"required":["variantId","productId","productName","variantSku","categoryId","categoryName","orderCount","quantitySold","averagePrice","grossSales","lineDiscounts","orderDiscounts","netSales","shareOfNetSales","quantityReturned","refundAmount","netQuantity","netAfterRefunds","quantityVoided","voidedValue","quantityComped","compedValue"]},"PageMetaDto":{"type":"object","properties":{"total":{"type":"number","example":42},"page":{"type":"number","example":1},"limit":{"type":"number","example":50},"totalPages":{"type":"number","example":1}},"required":["total","page","limit","totalPages"]},"ItemSalesReportDto":{"type":"object","properties":{"from":{"type":"string","example":"2026-09-01"},"to":{"type":"string","example":"2026-09-14"},"locationIds":{"nullable":true,"description":"Outlets covered; null means every outlet you can see.","type":"array","items":{"type":"string"}},"totals":{"description":"Across every item matching the filters, not just this page","allOf":[{"$ref":"#/components/schemas/ItemTotalsDto"}]},"categories":{"type":"array","items":{"$ref":"#/components/schemas/ItemCategoryRowDto"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/ItemRowDto"}},"meta":{"$ref":"#/components/schemas/PageMetaDto"}},"required":["from","to","locationIds","totals","categories","items","meta"]},"IncomeExpenseTotalsDto":{"type":"object","properties":{"incomeCount":{"type":"number","example":2},"income":{"type":"string","example":"30000.0000"},"expenseCount":{"type":"number","example":5},"expense":{"type":"string","example":"85000.0000"},"net":{"type":"string","example":"-55000.0000"}},"required":["incomeCount","income","expenseCount","expense","net"]},"IncomeExpenseDayRowDto":{"type":"object","properties":{"businessDate":{"type":"string","example":"2026-09-13"},"income":{"type":"string","example":"0.0000"},"expense":{"type":"string","example":"25000.0000"},"net":{"type":"string","example":"-25000.0000"}},"required":["businessDate","income","expense","net"]},"IncomeExpenseMethodRowDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"Cash"},"kind":{"type":"string","example":"CASH"},"income":{"type":"string","example":"30000.0000"},"expense":{"type":"string","example":"85000.0000"}},"required":["paymentMethodId","name","kind","income","expense"]},"IncomeExpenseOutletRowDto":{"type":"object","properties":{"locationId":{"type":"string","example":"uuid"},"locationName":{"type":"string","example":"Restaurant"},"income":{"type":"string","example":"30000.0000"},"expense":{"type":"string","example":"85000.0000"},"net":{"type":"string","example":"-55000.0000"}},"required":["locationId","locationName","income","expense","net"]},"IncomeExpenseEntryDto":{"type":"object","properties":{"id":{"type":"string","example":"uuid"},"businessDate":{"type":"string","example":"2026-09-13"},"createdAt":{"format":"date-time","type":"string","example":"2026-09-13T08:15:00.000Z"},"type":{"type":"string","enum":["INCOME","EXPENSE"]},"reason":{"type":"string","example":"PAID_OUT"},"amount":{"type":"string","example":"25000.0000"},"locationId":{"type":"string","example":"uuid"},"locationName":{"type":"string","example":"Restaurant"},"paymentMethodId":{"type":"string","example":"uuid"},"paymentMethodName":{"type":"string","example":"Cash"},"reference":{"type":"string","nullable":true,"example":"INV-2231"},"notes":{"type":"string","nullable":true,"example":"Ice delivery"},"posSessionId":{"type":"string","example":"uuid"},"staffName":{"type":"string","nullable":true,"example":"Ma Thida"},"approverName":{"type":"string","nullable":true,"example":"U Kyaw"}},"required":["id","businessDate","createdAt","type","reason","amount","locationId","locationName","paymentMethodId","paymentMethodName","reference","notes","posSessionId","staffName","approverName"]},"OtherIncomeExpenseReportDto":{"type":"object","properties":{"from":{"type":"string","example":"2026-09-01"},"to":{"type":"string","example":"2026-09-14"},"locationIds":{"nullable":true,"description":"Outlets covered; null means every outlet you can see.","type":"array","items":{"type":"string"}},"totals":{"$ref":"#/components/schemas/IncomeExpenseTotalsDto"},"byDay":{"type":"array","items":{"$ref":"#/components/schemas/IncomeExpenseDayRowDto"}},"byPaymentMethod":{"type":"array","items":{"$ref":"#/components/schemas/IncomeExpenseMethodRowDto"}},"byOutlet":{"type":"array","items":{"$ref":"#/components/schemas/IncomeExpenseOutletRowDto"}},"entries":{"type":"array","items":{"$ref":"#/components/schemas/IncomeExpenseEntryDto"}}},"required":["from","to","locationIds","totals","byDay","byPaymentMethod","byOutlet","entries"]},"IssuedTierRowDto":{"type":"object","properties":{"tier":{"type":"string","example":"Gold"},"count":{"type":"number","example":4},"preloadValue":{"type":"string","example":"200000.0000"}},"required":["tier","count","preloadValue"]},"IssuedDto":{"type":"object","properties":{"count":{"type":"number","example":9},"linkedToCustomer":{"type":"number","example":4,"description":"Of those, issued to a named customer rather than a walk-in"},"byTier":{"type":"array","items":{"$ref":"#/components/schemas/IssuedTierRowDto"}}},"required":["count","linkedToCustomer","byTier"]},"ClosedDto":{"type":"object","properties":{"count":{"type":"number","example":6},"settled":{"type":"number","example":5},"voided":{"type":"number","example":1}},"required":["count","settled","voided"]},"TopUpsDto":{"type":"object","properties":{"count":{"type":"number","example":12},"amount":{"type":"string","example":"1250000.0000"},"byPaymentMethod":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethodRowDto"}}},"required":["count","amount","byPaymentMethod"]},"SpendDto":{"type":"object","properties":{"count":{"type":"number","example":48},"reversals":{"type":"number","example":1},"amount":{"type":"string","example":"980000.0000","description":"Net of reversals"}},"required":["count","reversals","amount"]},"LedgerDto":{"type":"object","properties":{"topUps":{"$ref":"#/components/schemas/CountAmountDto"},"preloadGranted":{"$ref":"#/components/schemas/CountAmountDto"},"spend":{"$ref":"#/components/schemas/SpendDto"},"refunds":{"$ref":"#/components/schemas/CountAmountDto"},"settlementsCollected":{"$ref":"#/components/schemas/CountAmountDto"},"forfeited":{"description":"Promotional value written off","allOf":[{"$ref":"#/components/schemas/CountAmountDto"}]},"adjustmentsCredit":{"$ref":"#/components/schemas/CountAmountDto"},"adjustmentsDebit":{"$ref":"#/components/schemas/CountAmountDto"},"netChange":{"type":"string","example":"270000.0000","description":"Change in what guests hold"}},"required":["topUps","preloadGranted","spend","refunds","settlementsCollected","forfeited","adjustmentsCredit","adjustmentsDebit","netChange"]},"SpendOutletRowDto":{"type":"object","properties":{"locationId":{"type":"string","example":"uuid"},"locationName":{"type":"string","example":"KTV"},"count":{"type":"number","example":30},"amount":{"type":"string","example":"640000.0000"}},"required":["locationId","locationName","count","amount"]},"SpendTierRowDto":{"type":"object","properties":{"tier":{"type":"string","example":"Gold"},"amount":{"type":"string","example":"400000.0000"}},"required":["tier","amount"]},"OutstandingCardsDto":{"type":"object","properties":{"activeCards":{"type":"number","example":10},"walletsInCredit":{"type":"number","example":4},"owedToGuests":{"type":"string","example":"381250.0000","description":"Owed to guests. Matches /reports/guest-card/liability total."},"purchased":{"type":"string","example":"361250.0000","description":"Refundable in cash"},"granted":{"type":"string","example":"20000.0000","description":"Promotional"},"walletsInDebt":{"type":"number","example":1},"owedByGuests":{"type":"string","example":"96500.0000","description":"Owed by postpaid guests, as a positive amount"}},"required":["activeCards","walletsInCredit","owedToGuests","purchased","granted","walletsInDebt","owedByGuests"]},"MemberCardReportDto":{"type":"object","properties":{"from":{"type":"string","example":"2026-09-01"},"to":{"type":"string","example":"2026-09-14"},"locationIds":{"nullable":true,"description":"Outlets covered; null means every outlet you can see.","type":"array","items":{"type":"string"}},"issued":{"$ref":"#/components/schemas/IssuedDto"},"closed":{"$ref":"#/components/schemas/ClosedDto"},"topUps":{"$ref":"#/components/schemas/TopUpsDto"},"ledger":{"$ref":"#/components/schemas/LedgerDto"},"spendByOutlet":{"type":"array","items":{"$ref":"#/components/schemas/SpendOutletRowDto"}},"spendByTier":{"type":"array","items":{"$ref":"#/components/schemas/SpendTierRowDto"}},"outstanding":{"description":"As of now","allOf":[{"$ref":"#/components/schemas/OutstandingCardsDto"}]}},"required":["from","to","locationIds","issued","closed","topUps","ledger","spendByOutlet","spendByTier","outstanding"]},"PointsTypeRowDto":{"type":"object","properties":{"transactionType":{"type":"string","example":"EARN"},"entries":{"type":"number","example":60},"points":{"type":"number","example":2400000}},"required":["transactionType","entries","points"]},"PointsPeriodDto":{"type":"object","properties":{"pointsEarned":{"type":"number","example":2400000},"pointsReversed":{"type":"number","example":15000},"netPoints":{"type":"number","example":2385000},"activeMembers":{"type":"number","example":38},"newMembers":{"type":"number","example":6},"byTransactionType":{"type":"array","items":{"$ref":"#/components/schemas/PointsTypeRowDto"}}},"required":["pointsEarned","pointsReversed","netPoints","activeMembers","newMembers","byTransactionType"]},"PointsOutstandingDto":{"type":"object","properties":{"members":{"type":"number","example":120},"points":{"type":"number","example":9800000},"pointsRedeemed":{"type":"number","example":0,"description":"Always 0: redemption does not exist yet"},"pointsExpired":{"type":"number","example":0,"description":"Always 0: nothing expires points yet"}},"required":["members","points","pointsRedeemed","pointsExpired"]},"LoyaltyTierRowDto":{"type":"object","properties":{"loyaltyTier":{"type":"string","example":"BRONZE"},"members":{"type":"number","example":100}},"required":["loyaltyTier","members"]},"TopMemberRowDto":{"type":"object","properties":{"customerId":{"type":"string","example":"uuid"},"name":{"type":"string","nullable":true,"example":"U Mg Mg"},"phone":{"type":"string","nullable":true,"example":"09 7700 11223"},"loyaltyTier":{"type":"string","nullable":true,"example":"GOLD"},"pointsEarned":{"type":"number","example":180000},"pointsBalance":{"type":"number","example":420000}},"required":["customerId","name","phone","loyaltyTier","pointsEarned","pointsBalance"]},"LoyaltyPointsReportDto":{"type":"object","properties":{"from":{"type":"string","example":"2026-09-01"},"to":{"type":"string","example":"2026-09-14"},"locationIds":{"nullable":true,"description":"Outlets covered; null means every outlet you can see.","type":"array","items":{"type":"string"}},"period":{"$ref":"#/components/schemas/PointsPeriodDto"},"outstanding":{"description":"As of now","allOf":[{"$ref":"#/components/schemas/PointsOutstandingDto"}]},"byLoyaltyTier":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyTierRowDto"}},"topMembers":{"type":"array","items":{"$ref":"#/components/schemas/TopMemberRowDto"}}},"required":["from","to","locationIds","period","outstanding","byLoyaltyTier","topMembers"]},"PaymentBreakdownRowDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","example":"uuid"},"method":{"type":"string","example":"CASH"},"total":{"type":"string","example":"150.0000"}},"required":["paymentMethodId","method","total"]},"DailySalesSummaryDto":{"type":"object","properties":{"locationId":{"type":"string","nullable":true,"example":"uuid","description":"The outlet asked for; null when the report covers several"},"date":{"type":"string","example":"2026-07-02"},"orderCount":{"type":"number","example":42},"subtotal":{"type":"string","example":"1000.0000"},"totalTax":{"type":"string","example":"70.0000"},"totalDiscount":{"type":"string","example":"25.0000"},"tipAmount":{"type":"string","example":"30.0000"},"serviceCharge":{"type":"string","example":"15.0000"},"grandTotal":{"type":"string","example":"1090.0000"},"averageTicket":{"type":"string","example":"25.9500"},"paymentBreakdown":{"type":"array","items":{"$ref":"#/components/schemas/PaymentBreakdownRowDto"}}},"required":["locationId","date","orderCount","subtotal","totalTax","totalDiscount","tipAmount","serviceCharge","grandTotal","averageTicket","paymentBreakdown"]},"CategorySalesRowDto":{"type":"object","properties":{"categoryId":{"type":"string","nullable":true,"example":"uuid"},"categoryName":{"type":"string","example":"Beverages"},"orderCount":{"type":"number","example":12},"totalRevenue":{"type":"string","example":"350.0000"}},"required":["categoryId","categoryName","orderCount","totalRevenue"]},"ItemSalesRowDto":{"type":"object","properties":{"variantId":{"type":"string","example":"uuid"},"productName":{"type":"string","example":"Iced Latte"},"variantSku":{"type":"string","example":"SKU-001"},"quantitySold":{"type":"string","example":"48.0000"},"totalRevenue":{"type":"string","example":"240.0000"}},"required":["variantId","productName","variantSku","quantitySold","totalRevenue"]},"HourlySalesRowDto":{"type":"object","properties":{"hour":{"type":"number","example":14},"orderCount":{"type":"number","example":8},"totalRevenue":{"type":"string","example":"180.0000"}},"required":["hour","orderCount","totalRevenue"]},"ServerPerformanceRowDto":{"type":"object","properties":{"waiterId":{"type":"string","nullable":true,"example":"uuid"},"waiterName":{"type":"string","nullable":true,"example":"Ko Aung"},"orderCount":{"type":"number","example":15},"totalRevenue":{"type":"string","example":"420.0000"},"totalTips":{"type":"string","example":"35.0000"},"averageTicket":{"type":"string","example":"28.0000"}},"required":["waiterId","waiterName","orderCount","totalRevenue","totalTips","averageTicket"]},"ZReportOrdersDto":{"type":"object","properties":{"completed":{"type":"number","example":40},"voided":{"type":"number","example":2},"refunded":{"type":"number","example":1}},"required":["completed","voided","refunded"]},"ZReportTotalsDto":{"type":"object","properties":{"subtotal":{"type":"string","example":"1000.0000"},"totalDiscount":{"type":"string","example":"25.0000"},"totalTax":{"type":"string","example":"70.0000"},"tipAmount":{"type":"string","example":"30.0000"},"serviceCharge":{"type":"string","example":"15.0000"},"grandTotal":{"type":"string","example":"1090.0000"}},"required":["subtotal","totalDiscount","totalTax","tipAmount","serviceCharge","grandTotal"]},"ZReportPaymentRowDto":{"type":"object","properties":{"paymentMethodId":{"type":"string","example":"uuid"},"method":{"type":"string","example":"CASH"},"total":{"type":"string","example":"600.0000"},"tip":{"type":"string","example":"20.0000"}},"required":["paymentMethodId","method","total","tip"]},"ZReportDto":{"type":"object","properties":{"locationId":{"type":"string","nullable":true,"example":"uuid","description":"The outlet asked for; null when the report covers several"},"date":{"type":"string","example":"2026-07-02"},"orders":{"$ref":"#/components/schemas/ZReportOrdersDto"},"totals":{"$ref":"#/components/schemas/ZReportTotalsDto"},"payments":{"type":"array","items":{"$ref":"#/components/schemas/ZReportPaymentRowDto"}},"topItems":{"type":"array","items":{"$ref":"#/components/schemas/ItemSalesRowDto"}},"byCategory":{"type":"array","items":{"$ref":"#/components/schemas/CategorySalesRowDto"}}},"required":["locationId","date","orders","totals","payments","topItems","byCategory"]},"MenuItemDto":{"type":"object","properties":{"variantId":{"type":"string","example":"uuid","description":"Send this as variantId when ordering."},"name":{"type":"string","example":"Myanmar Beer"},"price":{"type":"string","example":"3500.0000"},"imageUrl":{"type":"string","nullable":true,"example":"/uploads/..."}},"required":["variantId","name","price"]},"MenuCategoryDto":{"type":"object","properties":{"categoryId":{"type":"string","example":"uuid"},"name":{"type":"string","example":"KTV Snacks"},"items":{"type":"array","items":{"$ref":"#/components/schemas/MenuItemDto"}}},"required":["categoryId","name","items"]},"RoomMenuDto":{"type":"object","properties":{"roomNumber":{"type":"string","example":"VIP1"},"categories":{"type":"array","items":{"$ref":"#/components/schemas/MenuCategoryDto"}}},"required":["roomNumber","categories"]},"RoomTabLineDto":{"type":"object","properties":{"name":{"type":"string","example":"Myanmar Beer"},"quantity":{"type":"string","example":"6.0000"},"unitPrice":{"type":"string","example":"3500.0000"},"lineTotal":{"type":"string","example":"21000.0000"},"status":{"type":"string","example":"PENDING","description":"PENDING and FIRED are still coming; SERVED has arrived."}},"required":["name","quantity","unitPrice","lineTotal","status"]},"RoomSessionViewDto":{"type":"object","properties":{"roomNumber":{"type":"string","example":"VIP1"},"guestCount":{"type":"number","example":6},"openedAt":{"format":"date-time","type":"string","example":"2026-09-22T20:00:00.000Z"},"endsAt":{"format":"date-time","type":"string","nullable":true,"example":"2026-09-22T23:00:00.000Z","description":"When the time the party asked for runs out. Null if they did not say. Paused time pushes it back."},"sessionState":{"type":"string","example":"OPEN"},"lines":{"description":"What is on the tab so far.","type":"array","items":{"$ref":"#/components/schemas/RoomTabLineDto"}},"fnbTotal":{"type":"string","example":"21000.0000","description":"Food and drink only. The room charge is added when they leave."},"walletBalance":{"type":"string","nullable":true,"example":"150000.0000","description":"What is left on the card the party is drawing on, or null if they are not using one. A postpaid card may be negative."}},"required":["roomNumber","guestCount","openedAt","sessionState","lines","fnbTotal"]}}}}