mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
149 lines
4.1 KiB
Go
149 lines
4.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
|
"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,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = fifoStockV2Svc.Recalculate(ctx, commonSvc.FifoStockV2RecalculateRequest{
|
|
ProductWarehouseIDs: []uint{productWarehouseID},
|
|
FlagGroupCodes: []string{flagGroupCode},
|
|
AsOf: asOf,
|
|
FixDrift: true,
|
|
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 strings.TrimSpace(selected.FlagGroupCode), nil
|
|
}
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return "", err
|
|
}
|
|
|
|
type categoryRow struct {
|
|
CategoryCode string `gorm:"column:category_code"`
|
|
}
|
|
|
|
var category categoryRow
|
|
err = tx.WithContext(ctx).
|
|
Table("product_warehouses pw").
|
|
Select("pc.code AS category_code").
|
|
Joins("JOIN products p ON p.id = pw.product_id").
|
|
Joins("JOIN product_categories pc ON pc.id = p.product_category_id").
|
|
Where("pw.id = ?", productWarehouseID).
|
|
Limit(1).
|
|
Take(&category).Error
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
flagGroupCode := utils.LegacyFlagGroupCodeByProductCategoryCode(category.CategoryCode)
|
|
if flagGroupCode == "" {
|
|
return "", gorm.ErrRecordNotFound
|
|
}
|
|
|
|
var matched int64
|
|
err = tx.WithContext(ctx).
|
|
Table("fifo_stock_v2_route_rules rr").
|
|
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("rr.flag_group_code = ?", flagGroupCode).
|
|
Count(&matched).Error
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if matched == 0 {
|
|
return "", gorm.ErrRecordNotFound
|
|
}
|
|
|
|
return 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
|
|
}
|
|
}
|