Saltar al contenido principal

Brands Module

Overview

The brands module manages product brands within FlowPOS. Brands are used to classify products by manufacturer or label, supporting filtering, reporting, and catalog organization.

Brands are business-scoped: every brand belongs to a specific business and is isolated from other businesses.


Architecture

The module follows Hexagonal Architecture with strict layer boundaries.

brands/
├── brands.module.ts # NestJS module wiring
├── domain/
│ └── brands-repository.domain.ts # IBrandsRepository port + injection token
├── application/
│ └── brands.service.ts # Use cases (CRUD)
├── infrastructure/
│ └── brands.repository.ts # Kysely DB adapter (implements port)
└── interfaces/
├── brands.controller.ts # HTTP adapter
├── dtos/
│ ├── create-brand.dto.ts
│ └── update-brand.dto.ts
└── query/
└── paginate-brands.query.ts

Layer responsibilities

LayerResponsibility
domain/Repository port (IBrandsRepository) and BRANDS_REPOSITORY injection token.
application/BrandsService — orchestrates CRUD operations and pagination.
infrastructure/BrandsRepository — Kysely queries against the brand table. Implements IBrandsRepository.
interfaces/BrandsController — maps HTTP requests to service calls. Thin layer with no business logic.

Dependency rule

interfaces → application → domain ← infrastructure

Domain Concepts

Brand

A named label used to classify products by manufacturer or product line.

FieldTypeDescription
idUUIDPrimary key (auto-generated)
namestringDisplay name (required)
businessIdUUIDFK to business
isActivebooleanDefaults to true
createdByUUIDFK to user
updatedByUUIDFK to user (nullable)
createdAttimestamptzAuto-set on creation
updatedAttimestamptzSet on update

API Endpoints

All endpoints require Bearer token authentication and are scoped to PolicyResource.Brand for RBAC.

POST /brands

Create a new brand.

Body:

{
"name": "Nike",
"businessId": "<uuid>",
"isActive": true,
"createdBy": "<uuid>"
}

Responses: 201 Created | 400 Invalid body | 401 Unauthorized

GET /brands

List brands with pagination, search, and sorting.

Query parameters:

ParamRequiredDescription
businessIdNoUUID of the business (filter)
pageNoPage number (default: 1)
sizeNoPage size (default: 10)
searchNoCase-insensitive name search
orderByNoSort field (name)
orderNoasc or desc

Responses: 200 Paginated list | 401 Unauthorized

GET /brands/:id

Get a single brand by UUID.

Query parameters: businessId (required)

Responses: 200 Found | 404 Not found | 401 Unauthorized

PATCH /brands/:id

Partially update a brand.

Body:

{
"name": "Updated Name",
"businessId": "<uuid>",
"updatedBy": "<uuid>"
}

Responses: 200 Updated | 400 Invalid body | 404 Not found | 401 Unauthorized

DELETE /brands/:id

Delete a brand.

Query parameters: businessId (required)

Responses: 200 Deleted | 404 Not found | 401 Unauthorized


Data Import

Brands can be bulk-imported via the data-import module. The BrandImportHandler supports:

  • Required field: name
  • Upsert behavior: matches by name within the business; updates if the brand exists, creates a new one otherwise.

  • Products — products reference brandId as a FK
  • Collections — merchandising collections can filter by brand
  • MarkdownMarkdownScopeType.Brand enables brand-level price markdowns