Saltar al contenido principal

Product Attributes Module

Overview​

The product-attributes module manages the many-to-many association between products and attribute definitions. Each record stores a value linking a specific product to an attribute (e.g., "Color: Red", "Material: Cotton").

Product attributes are business-scoped: every entry belongs to a specific business and is isolated from other businesses.


Architecture​

The module follows Hexagonal Architecture with strict layer boundaries.

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

Layer responsibilities​

LayerResponsibility
domain/Repository port (IProductAttributesRepository) and PRODUCT_ATTRIBUTES_REPOSITORY injection token.
application/ProductAttributesService — orchestrates CRUD operations and pagination.
infrastructure/ProductAttributesRepository — Kysely queries against the product_attribute table. Implements IProductAttributesRepository.
interfaces/ProductAttributesController — maps HTTP requests to service calls. Thin layer with no business logic.

Dependency rule​

interfaces → application → domain ← infrastructure

Domain Concepts​

Product Attribute​

An association record that assigns a value from an attribute definition to a specific product.

FieldTypeDescription
idUUIDPrimary key (auto-generated)
productIdUUIDFK to product
attributeIdUUIDFK to attribute
valuestringThe attribute value (e.g., "Red", "Large")
businessIdUUIDFK to business
isActivebooleanDefaults to true
createdByUUIDUser who created
updatedByUUIDUser who last updated (nullable)
createdAttimestamptzAuto-set on creation
updatedAttimestamptzSet on update

Access Control​

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

ActionPermission
CreatePolicyAction.Create
ListPolicyAction.Read
Get by IDPolicyAction.Read
UpdatePolicyAction.Update
DeletePolicyAction.Delete

API Endpoints​

POST /product-attributes​

Create a new product attribute.

Body:

{
"productId": "<uuid>",
"attributeId": "<uuid>",
"value": "Red",
"businessId": "<uuid>",
"isActive": true,
"createdBy": "<uuid>"
}

Responses: 201 Created | 400 Invalid body | 401 Unauthorized

GET /product-attributes​

List product attributes with pagination, search, and sorting.

Query parameters:

ParamRequiredDescription
businessIdNoUUID filter by business
productIdNoUUID filter by product
pageNoPage number (default: 1)
sizeNoPage size (default: 10; 0 = no limit)
searchNoCase-insensitive search on value, product name, attribute name
orderByNoSort field (value)
orderNoasc or desc

Responses: 200 Paginated list | 401 Unauthorized

GET /product-attributes/:id​

Get a single product attribute by UUID.

Query parameters: businessId (required)

Responses: 200 Found | 404 Not found | 401 Unauthorized

PATCH /product-attributes/:id​

Partially update a product attribute.

Body:

{
"value": "Blue",
"businessId": "<uuid>",
"updatedBy": "<uuid>"
}

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

DELETE /product-attributes/:id​

Delete a product attribute.

Query parameters: businessId (required)

Responses: 200 Deleted | 404 Not found | 401 Unauthorized


  • Products — products own product attribute records via productId FK
  • Attributes — attribute definitions referenced via attributeId FK
  • Product Variants — variant option types/values are a separate system; product attributes store additional metadata