package service import ( "context" "fmt" "strings" "time" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gorm.io/gorm" ) const ( purchaseInFunctionCode = "PURCHASE_IN" purchaseStockableLane = "STOCKABLE" purchaseSourceTable = "purchase_items" ) func reflowPurchaseScope( ctx context.Context, fifoStockV2Svc commonSvc.FifoStockV2Service, tx *gorm.DB, productWarehouseID uint, asOf *time.Time, ) error { if fifoStockV2Svc == nil { return fmt.Errorf("FIFO v2 service is not available") } if productWarehouseID == 0 { return fmt.Errorf("product warehouse id is required") } flagGroupCode, err := resolvePurchaseFlagGroupByProductWarehouse(ctx, tx, productWarehouseID) if err != nil { return err } if strings.TrimSpace(flagGroupCode) == "" { return fmt.Errorf("flag group code is not found for product warehouse %d", productWarehouseID) } _, err = fifoStockV2Svc.Reflow(ctx, commonSvc.FifoStockV2ReflowRequest{ FlagGroupCode: flagGroupCode, ProductWarehouseID: productWarehouseID, AsOf: asOf, Tx: tx, }) return err } func resolvePurchaseFlagGroupByProductWarehouse(ctx context.Context, tx *gorm.DB, productWarehouseID uint) (string, error) { type row struct { FlagGroupCode string `gorm:"column:flag_group_code"` } var selected row err := tx.WithContext(ctx). Table("fifo_stock_v2_route_rules rr"). Select("rr.flag_group_code"). Joins("JOIN fifo_stock_v2_flag_groups fg ON fg.code = rr.flag_group_code AND fg.is_active = TRUE"). Where("rr.is_active = TRUE"). Where("rr.lane = ?", purchaseStockableLane). Where("rr.function_code = ?", purchaseInFunctionCode). Where("rr.source_table = ?", purchaseSourceTable). Where(` EXISTS ( SELECT 1 FROM product_warehouses pw JOIN flags f ON f.flagable_id = pw.product_id JOIN fifo_stock_v2_flag_members fm ON fm.flag_name = f.name AND fm.is_active = TRUE WHERE pw.id = ? AND f.flagable_type = ? AND fm.flag_group_code = rr.flag_group_code ) `, productWarehouseID, entity.FlagableTypeProduct). Order("rr.id ASC"). Limit(1). Take(&selected).Error if err != nil { return "", err } return strings.TrimSpace(selected.FlagGroupCode), nil } func assignEarliestAsOf(m map[uint]time.Time, productWarehouseID uint, asOf time.Time) { if productWarehouseID == 0 { return } if current, ok := m[productWarehouseID]; !ok || asOf.Before(current) { m[productWarehouseID] = asOf } }