package models import ( "apskel-pos-be/internal/constants" "time" "github.com/google/uuid" ) type Product struct { ID uuid.UUID OrganizationID uuid.UUID CategoryID uuid.UUID SKU *string Name string Description *string Price float64 Cost float64 BusinessType constants.BusinessType ImageURL *string PrinterType string UnitID *uuid.UUID HasIngredients bool Metadata map[string]interface{} IsActive bool CreatedAt time.Time UpdatedAt time.Time } type ProductVariant struct { ID uuid.UUID ProductID uuid.UUID Name string PriceModifier float64 Cost float64 Metadata map[string]interface{} CreatedAt time.Time UpdatedAt time.Time } type CreateProductRequest struct { OrganizationID uuid.UUID `validate:"required"` CategoryID uuid.UUID `validate:"required"` SKU *string `validate:"omitempty,max=100"` Name string `validate:"required,min=1,max=255"` Description *string `validate:"omitempty,max=1000"` Price float64 `validate:"required,min=0"` Cost float64 `validate:"min=0"` BusinessType constants.BusinessType `validate:"required"` ImageURL *string `validate:"omitempty,max=500"` PrinterType *string `validate:"omitempty,max=50"` UnitID *uuid.UUID `validate:"omitempty"` HasIngredients bool `validate:"omitempty"` Metadata map[string]interface{} Variants []CreateProductVariantRequest `validate:"omitempty,dive"` // Stock management fields InitialStock *int `validate:"omitempty,min=0"` // Initial stock quantity for all outlets ReorderLevel *int `validate:"omitempty,min=0"` // Reorder level for all outlets CreateInventory bool `validate:"omitempty"` // Whether to create inventory records for all outlets } type UpdateProductRequest struct { CategoryID *uuid.UUID `validate:"omitempty"` SKU *string `validate:"omitempty,max=100"` Name *string `validate:"omitempty,min=1,max=255"` Description *string `validate:"omitempty,max=1000"` Price *float64 `validate:"omitempty,min=0"` Cost *float64 `validate:"omitempty,min=0"` ImageURL *string `validate:"omitempty,max=500"` PrinterType *string `validate:"omitempty,max=50"` UnitID *uuid.UUID `validate:"omitempty"` HasIngredients *bool `validate:"omitempty"` Metadata map[string]interface{} IsActive *bool // Stock management fields ReorderLevel *int `validate:"omitempty,min=0"` // Update reorder level for all existing inventory records } type CreateProductVariantRequest struct { ProductID uuid.UUID `validate:"required"` Name string `validate:"required,min=1,max=255"` PriceModifier float64 `validate:"required"` Cost float64 `validate:"min=0"` Metadata map[string]interface{} } type UpdateProductVariantRequest struct { Name *string `validate:"omitempty,min=1,max=255"` PriceModifier *float64 Cost *float64 `validate:"omitempty,min=0"` Metadata map[string]interface{} } type ProductResponse struct { ID uuid.UUID OrganizationID uuid.UUID CategoryID uuid.UUID SKU *string Name string Description *string Price float64 Cost float64 BusinessType constants.BusinessType ImageURL *string PrinterType string UnitID *uuid.UUID HasIngredients bool Metadata map[string]interface{} IsActive bool CreatedAt time.Time UpdatedAt time.Time Variants []ProductVariantResponse } type ProductVariantResponse struct { ID uuid.UUID ProductID uuid.UUID Name string PriceModifier float64 Cost float64 Metadata map[string]interface{} CreatedAt time.Time UpdatedAt time.Time } func (p *Product) GetFinalPrice(variant *ProductVariant) float64 { if variant == nil { return p.Price } return p.Price + variant.PriceModifier } func (p *Product) GetProfitMargin() float64 { if p.Price == 0 { return 0 } return ((p.Price - p.Cost) / p.Price) * 100 } func (p *Product) IsValidPrice() bool { return p.Price > 0 && p.Cost >= 0 && p.Price > p.Cost }