package recording import ( "fmt" "strings" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/validations" ) func MapStocks(recordingID uint, ownerProjectFlockKandangID *uint, items []validation.Stock) []entity.RecordingStock { if len(items) == 0 { return nil } result := make([]entity.RecordingStock, 0, len(items)) for _, item := range items { usagePtr := new(float64) *usagePtr = item.Qty result = append(result, entity.RecordingStock{ RecordingId: recordingID, ProductWarehouseId: item.ProductWarehouseId, ProjectFlockKandangId: ownerProjectFlockKandangID, UsageQty: usagePtr, }) } return result } func MapDepletions(recordingID uint, items []validation.Depletion) []entity.RecordingDepletion { if len(items) == 0 { return nil } type depletionKey struct { ProductWarehouseID uint SourceProductWarehouseID uint } aggregate := make(map[depletionKey]float64, len(items)) for _, item := range items { if item.ProductWarehouseId == 0 || item.Qty == 0 { continue } key := depletionKey{ProductWarehouseID: item.ProductWarehouseId} if item.SourceProductWarehouseId != nil { key.SourceProductWarehouseID = *item.SourceProductWarehouseId } aggregate[key] += item.Qty } if len(aggregate) == 0 { return nil } result := make([]entity.RecordingDepletion, 0, len(aggregate)) for key, qty := range aggregate { if qty == 0 { continue } var sourceWarehouseID *uint if key.SourceProductWarehouseID != 0 { sourceWarehouseID = new(uint) *sourceWarehouseID = key.SourceProductWarehouseID } result = append(result, entity.RecordingDepletion{ RecordingId: recordingID, ProductWarehouseId: key.ProductWarehouseID, SourceProductWarehouseId: sourceWarehouseID, Qty: qty, }) } return result } func MapEggs(recordingID uint, projectFlockKandangID uint, createdBy uint, items []validation.Egg) []entity.RecordingEgg { if len(items) == 0 { return nil } result := make([]entity.RecordingEgg, 0, len(items)) for _, item := range items { var sourceProjectFlockKandangID *uint if projectFlockKandangID != 0 { sourceProjectFlockKandangID = new(uint) *sourceProjectFlockKandangID = projectFlockKandangID } result = append(result, entity.RecordingEgg{ RecordingId: recordingID, ProductWarehouseId: item.ProductWarehouseId, ProjectFlockKandangId: sourceProjectFlockKandangID, Qty: item.Qty, Weight: item.Weight, CreatedBy: createdBy, }) } return result } type EggTotals struct { Qty int Weight float64 } type DepletionRoute struct { ProductWarehouseId uint SourceProductWarehouseId uint } func StockUsageByWarehouse(items []entity.RecordingStock) map[uint]float64 { return TotalsByWarehouse(items, func(stock entity.RecordingStock) (uint, float64) { var usage float64 if stock.UsageQty != nil { usage = *stock.UsageQty } return stock.ProductWarehouseId, usage }) } func StockUsageByWarehouseReq(items []validation.Stock) map[uint]float64 { return TotalsByWarehouse(items, func(item validation.Stock) (uint, float64) { return item.ProductWarehouseId, item.Qty }) } func FloatMapsEqual(a, b map[uint]float64) bool { if len(a) != len(b) { return false } for key, value := range a { other, ok := b[key] if !ok || !floatNearlyEqual(value, other) { return false } } return true } func EggTotalsEqual(a, b map[uint]EggTotals) bool { if len(a) != len(b) { return false } for key, value := range a { other, ok := b[key] if !ok || value.Qty != other.Qty || !floatNearlyEqual(value.Weight, other.Weight) { return false } } return true } func DepletionRouteMapsEqual(a, b map[DepletionRoute]float64) bool { if len(a) != len(b) { return false } for key, value := range a { other, ok := b[key] if !ok || !floatNearlyEqual(value, other) { return false } } return true } func floatNearlyEqual(a, b float64) bool { return a-b <= 0.000001 && b-a <= 0.000001 } func TotalsByWarehouse[T any](items []T, get func(T) (uint, float64)) map[uint]float64 { result := make(map[uint]float64) for _, item := range items { warehouseID, qty := get(item) result[warehouseID] += qty } return result } func DepletionTotalsByRoute[T any](items []T, get func(T) (uint, *uint, float64)) map[DepletionRoute]float64 { result := make(map[DepletionRoute]float64) for _, item := range items { productWarehouseID, sourceProductWarehouseID, qty := get(item) key := DepletionRoute{ProductWarehouseId: productWarehouseID} if sourceProductWarehouseID != nil { key.SourceProductWarehouseId = *sourceProductWarehouseID } result[key] += qty } return result } func EggTotalsByWarehouse[T any](items []T, get func(T) (uint, int, *float64)) map[uint]EggTotals { result := make(map[uint]EggTotals) for _, item := range items { warehouseID, qty, weightPtr := get(item) weight := 0.0 if weightPtr != nil { weight = *weightPtr } current := result[warehouseID] current.Qty += qty current.Weight += weight result[warehouseID] = current } return result } func RecordingNote(action string, id uint) string { action = strings.TrimSpace(action) if action == "" { return fmt.Sprintf("Recording#%d", id) } return fmt.Sprintf("Recording-%s#%d", action, id) }