143 lines
4.4 KiB
Go
143 lines
4.4 KiB
Go
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
|
|
}
|