package dto import ( "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" productCategoryDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/product-categories/dto" uomDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/dto" userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" ) // === DTO Structs === type ProductStockRelationDTO struct { Id uint `json:"id"` Name string `json:"name"` } type ProductStockListDTO struct { Id uint `json:"id"` Name string `json:"name"` Brand string `json:"brand"` Sku *string `json:"sku,omitempty"` ProductPrice float64 `json:"product_price"` SellingPrice *float64 `json:"selling_price,omitempty"` Tax *float64 `json:"tax,omitempty"` ExpiryPeriod *int `json:"expiry_period,omitempty"` Flags []string `json:"flags"` Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"` ProductCategory *productCategoryDTO.ProductCategoryRelationDTO `json:"product_category,omitempty"` CreatedUser *userDTO.UserRelationDTO `json:"created_user"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` Suppliers []SupplierDTO `json:"suppliers,omitempty"` ProductWarehouses []ProductWarehouseDTO `json:"product_warehouses,omitempty"` TotalStock float64 `json:"total_stock"` } type ProductStockDetailDTO struct { ProductStockListDTO } type SupplierDTO struct { Id uint `json:"id"` Name string `json:"name"` Alias string `json:"alias"` Category string `json:"category"` } type ProductWarehouseDTO struct { Id uint `json:"id"` ProductId uint `json:"product_id"` WarehouseId uint `json:"warehouse_id"` WarehouseName string `json:"warehouse_name"` Location *locationDTO.LocationRelationDTO `json:"location"` CurrentStock float64 `json:"current_stock"` StockLogs []StockLogDetailDTO `json:"stock_logs"` } type StockLogDetailDTO struct { Id uint `json:"id"` Increase float64 `json:"increase"` Decrease float64 `json:"decrease"` LoggableType string `json:"loggable_type"` LoggableId uint `json:"loggable_id"` Notes *string `json:"notes"` ProductWarehouseId uint `json:"product_warehouse_id"` CreatedBy uint `json:"created_by"` CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"` CreatedAt time.Time `json:"created_at"` } // === Mapper Functions === func ToProductStockListDTO(e entity.Product) ProductStockListDTO { var createdUser *userDTO.UserRelationDTO if e.CreatedUser.Id != 0 { mapped := userDTO.ToUserRelationDTO(e.CreatedUser) createdUser = &mapped } var categoryRef *productCategoryDTO.ProductCategoryRelationDTO if e.ProductCategory.Id != 0 { mapped := productCategoryDTO.ToProductCategoryRelationDTO(e.ProductCategory) categoryRef = &mapped } flags := make([]string, len(e.Flags)) for i, f := range e.Flags { flags[i] = f.Name } var uomRef *uomDTO.UomRelationDTO if e.Uom.Id != 0 { mapped := uomDTO.ToUomRelationDTO(e.Uom) uomRef = &mapped } return ProductStockListDTO{ Id: e.Id, Name: e.Name, Flags: flags, Uom: uomRef, Brand: e.Brand, Sku: e.Sku, ProductPrice: e.ProductPrice, SellingPrice: e.SellingPrice, Tax: e.Tax, ExpiryPeriod: e.ExpiryPeriod, CreatedAt: e.CreatedAt, UpdatedAt: e.UpdatedAt, CreatedUser: createdUser, ProductCategory: categoryRef, Suppliers: mapSupplierDTOs(e.ProductSuppliers), TotalStock: calculateTotalStock(e.ProductWarehouses), } } func ToProductStockListDTOs(e []entity.Product) []ProductStockListDTO { result := make([]ProductStockListDTO, len(e)) for i, r := range e { result[i] = ToProductStockListDTO(r) } return result } func ToProductStockDetailDTO(e entity.Product) ProductStockDetailDTO { base := ToProductStockListDTO(e) base.ProductWarehouses = mapProductWarehouseDTOs(e.ProductWarehouses) return ProductStockDetailDTO{ ProductStockListDTO: base, } } // --- helpers --- func mapSupplierDTOs(src []entity.ProductSupplier) []SupplierDTO { if len(src) == 0 { return nil } result := make([]SupplierDTO, 0, len(src)) for _, ps := range src { if ps.Supplier.Id == 0 { continue } result = append(result, SupplierDTO{ Id: ps.Supplier.Id, Name: ps.Supplier.Name, Alias: ps.Supplier.Alias, Category: ps.Supplier.Category, }) } return result } func mapProductWarehouseDTOs(src []entity.ProductWarehouse) []ProductWarehouseDTO { if len(src) == 0 { return []ProductWarehouseDTO{} } result := make([]ProductWarehouseDTO, 0, len(src)) for _, pw := range src { dto := ProductWarehouseDTO{ Id: pw.Id, ProductId: pw.ProductId, WarehouseId: pw.WarehouseId, CurrentStock: pw.Quantity, StockLogs: mapStockLogs(pw.StockLogs), } if pw.Warehouse.Id != 0 { dto.WarehouseName = pw.Warehouse.Name if pw.Warehouse.Location != nil { mapped := locationDTO.ToLocationRelationDTO(*pw.Warehouse.Location) dto.Location = &mapped } } result = append(result, dto) } return result } func mapStockLogs(src []entity.StockLog) []StockLogDetailDTO { if len(src) == 0 { return []StockLogDetailDTO{} } result := make([]StockLogDetailDTO, 0, len(src)) for _, log := range src { var notes *string if log.Notes != "" { n := log.Notes notes = &n } result = append(result, StockLogDetailDTO{ Id: log.Id, Increase: log.Increase, Decrease: log.Decrease, LoggableType: log.LoggableType, LoggableId: log.LoggableId, Notes: notes, ProductWarehouseId: log.ProductWarehouseId, CreatedBy: log.CreatedBy, CreatedUser: mapCreatedUser(log.CreatedUser), CreatedAt: log.CreatedAt, }) } return result } func mapCreatedUser(user *entity.User) *userDTO.UserRelationDTO { if user == nil || user.Id == 0 { return nil } mapped := userDTO.ToUserRelationDTO(*user) return &mapped } func calculateTotalStock(productWarehouses []entity.ProductWarehouse) float64 { var total float64 for _, pw := range productWarehouses { total += pw.Quantity } return total }