mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 07:15:43 +00:00
Merge branch 'codex/sales-at-farm-level' into 'development'
codex/fix: recheck and fix purchase receive failed and farm stock not shown on recording See merge request mbugroup/lti-api!383
This commit is contained in:
+1
@@ -29,6 +29,7 @@ func (u *ProductWarehouseController) GetAll(c *fiber.Ctx) error {
|
|||||||
Limit: c.QueryInt("limit", 10),
|
Limit: c.QueryInt("limit", 10),
|
||||||
ProductId: uint(c.QueryInt("product_id", 0)),
|
ProductId: uint(c.QueryInt("product_id", 0)),
|
||||||
WarehouseId: uint(c.QueryInt("warehouse_id", 0)),
|
WarehouseId: uint(c.QueryInt("warehouse_id", 0)),
|
||||||
|
LocationId: uint(c.QueryInt("location_id", 0)),
|
||||||
Flags: c.Query("flags", ""),
|
Flags: c.Query("flags", ""),
|
||||||
KandangId: uint(c.QueryInt("kandang_id", 0)),
|
KandangId: uint(c.QueryInt("kandang_id", 0)),
|
||||||
TransferContext: c.Query(utils.TransferContextKey, ""),
|
TransferContext: c.Query(utils.TransferContextKey, ""),
|
||||||
|
|||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
service "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/services"
|
||||||
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/validations"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stubProductWarehouseService struct {
|
||||||
|
lastQuery *validation.Query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubProductWarehouseService) GetAll(_ *fiber.Ctx, params *validation.Query) ([]entity.ProductWarehouse, int64, error) {
|
||||||
|
s.lastQuery = params
|
||||||
|
return []entity.ProductWarehouse{}, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubProductWarehouseService) GetOne(_ *fiber.Ctx, _ uint) (*entity.ProductWarehouse, error) {
|
||||||
|
return nil, gorm.ErrRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ service.ProductWarehouseService = (*stubProductWarehouseService)(nil)
|
||||||
|
|
||||||
|
func TestGetAllParsesLocationID(t *testing.T) {
|
||||||
|
app := fiber.New()
|
||||||
|
stub := &stubProductWarehouseService{}
|
||||||
|
ctrl := NewProductWarehouseController(stub)
|
||||||
|
app.Get("/product-warehouses", ctrl.GetAll)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "/product-warehouses?location_id=16&kandang_id=59&limit=25", nil)
|
||||||
|
resp, err := app.Test(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != fiber.StatusOK {
|
||||||
|
t.Fatalf("expected status 200, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
if stub.lastQuery == nil {
|
||||||
|
t.Fatalf("expected service to receive query")
|
||||||
|
}
|
||||||
|
if stub.lastQuery.LocationId != 16 {
|
||||||
|
t.Fatalf("expected location_id 16, got %d", stub.lastQuery.LocationId)
|
||||||
|
}
|
||||||
|
if stub.lastQuery.KandangId != 59 {
|
||||||
|
t.Fatalf("expected kandang_id 59, got %d", stub.lastQuery.KandangId)
|
||||||
|
}
|
||||||
|
if stub.lastQuery.Limit != 25 {
|
||||||
|
t.Fatalf("expected limit 25, got %d", stub.lastQuery.Limit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStubImplementsServiceContract(t *testing.T) {
|
||||||
|
validate := validator.New()
|
||||||
|
if validate == nil {
|
||||||
|
t.Fatal(errors.New("validator should not be nil"))
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
-3
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -164,10 +165,42 @@ func (r *ProductWarehouseRepositoryImpl) ApplyFlagsFilter(db *gorm.DB, flags []s
|
|||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.
|
fallbackCategoryCodes := utils.LegacyProductCategoryCodesForFlags(flags)
|
||||||
|
|
||||||
|
db = db.
|
||||||
Joins("JOIN products p_flag ON p_flag.id = product_warehouses.product_id").
|
Joins("JOIN products p_flag ON p_flag.id = product_warehouses.product_id").
|
||||||
Joins("JOIN flags f_flag ON f_flag.flagable_id = p_flag.id AND f_flag.flagable_type = ?", "products").
|
Joins("LEFT JOIN product_categories pc_flag ON pc_flag.id = p_flag.product_category_id")
|
||||||
Where("f_flag.name IN ?", flags).
|
|
||||||
|
actualFlagFilter := `
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM flags f_flag
|
||||||
|
WHERE f_flag.flagable_id = p_flag.id
|
||||||
|
AND f_flag.flagable_type = ?
|
||||||
|
AND f_flag.name IN ?
|
||||||
|
)
|
||||||
|
`
|
||||||
|
|
||||||
|
if len(fallbackCategoryCodes) == 0 {
|
||||||
|
return db.Where(actualFlagFilter, entity.FlagableTypeProduct, flags).Distinct()
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.
|
||||||
|
Where(
|
||||||
|
`(`+actualFlagFilter+`) OR (
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM flags f_any
|
||||||
|
WHERE f_any.flagable_id = p_flag.id
|
||||||
|
AND f_any.flagable_type = ?
|
||||||
|
)
|
||||||
|
AND pc_flag.code IN ?
|
||||||
|
)`,
|
||||||
|
entity.FlagableTypeProduct,
|
||||||
|
flags,
|
||||||
|
entity.FlagableTypeProduct,
|
||||||
|
fallbackCategoryCodes,
|
||||||
|
).
|
||||||
Distinct()
|
Distinct()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+73
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/glebarez/sqlite"
|
"github.com/glebarez/sqlite"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -115,3 +116,75 @@ func insertProductWarehouseTestFixtures(t *testing.T, db *gorm.DB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyFlagsFilterIncludesLegacyCategoryFallback(t *testing.T) {
|
||||||
|
db := setupProductWarehouseFlagFilterTestDB(t)
|
||||||
|
repo := NewProductWarehouseRepository(db)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var ids []uint
|
||||||
|
err := repo.ApplyFlagsFilter(
|
||||||
|
db.WithContext(ctx).Model(&entity.ProductWarehouse{}),
|
||||||
|
[]string{"PAKAN"},
|
||||||
|
).Order("product_warehouses.id").Pluck("product_warehouses.id", &ids).Error
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ids) != 2 || ids[0] != 1 || ids[1] != 2 {
|
||||||
|
t.Fatalf("expected flagged and legacy RAW rows to match, got %v", ids)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyFlagsFilterDoesNotFallbackWhenProductAlreadyHasDifferentFlags(t *testing.T) {
|
||||||
|
db := setupProductWarehouseFlagFilterTestDB(t)
|
||||||
|
repo := NewProductWarehouseRepository(db)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var ids []uint
|
||||||
|
err := repo.ApplyFlagsFilter(
|
||||||
|
db.WithContext(ctx).Model(&entity.ProductWarehouse{}),
|
||||||
|
[]string{"PAKAN"},
|
||||||
|
).Where("product_warehouses.id = ?", 3).Pluck("product_warehouses.id", &ids).Error
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ids) != 0 {
|
||||||
|
t.Fatalf("expected OVK-flagged product not to match PAKAN fallback, got %v", ids)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupProductWarehouseFlagFilterTestDB(t *testing.T) *gorm.DB {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=private"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed opening sqlite db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
statements := []string{
|
||||||
|
`CREATE TABLE product_categories (id INTEGER PRIMARY KEY, code TEXT NOT NULL)`,
|
||||||
|
`CREATE TABLE products (id INTEGER PRIMARY KEY, product_category_id INTEGER NOT NULL)`,
|
||||||
|
`CREATE TABLE flags (id INTEGER PRIMARY KEY, flagable_id INTEGER NOT NULL, flagable_type TEXT NOT NULL, name TEXT NOT NULL)`,
|
||||||
|
`CREATE TABLE product_warehouses (id INTEGER PRIMARY KEY, product_id INTEGER NOT NULL, warehouse_id INTEGER NOT NULL, project_flock_kandang_id INTEGER NULL, qty NUMERIC(15,3) NOT NULL DEFAULT 0)`,
|
||||||
|
`INSERT INTO product_categories (id, code) VALUES (1, 'STR'), (2, 'RAW'), (3, 'OBT')`,
|
||||||
|
`INSERT INTO products (id, product_category_id) VALUES (10, 1), (20, 2), (30, 2), (40, 3)`,
|
||||||
|
`INSERT INTO flags (id, flagable_id, flagable_type, name) VALUES
|
||||||
|
(1, 10, 'products', 'PAKAN'),
|
||||||
|
(2, 10, 'products', 'STARTER'),
|
||||||
|
(3, 40, 'products', 'OVK'),
|
||||||
|
(4, 40, 'products', 'OBAT')`,
|
||||||
|
`INSERT INTO product_warehouses (id, product_id, warehouse_id, project_flock_kandang_id, qty) VALUES
|
||||||
|
(1, 10, 1, NULL, 10),
|
||||||
|
(2, 20, 1, NULL, 20),
|
||||||
|
(3, 40, 1, NULL, 30)`,
|
||||||
|
}
|
||||||
|
for _, stmt := range statements {
|
||||||
|
if err := db.Exec(stmt).Error; err != nil {
|
||||||
|
t.Fatalf("failed preparing schema: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -76,11 +78,53 @@ func resolvePurchaseFlagGroupByProductWarehouse(ctx context.Context, tx *gorm.DB
|
|||||||
Order("rr.id ASC").
|
Order("rr.id ASC").
|
||||||
Limit(1).
|
Limit(1).
|
||||||
Take(&selected).Error
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.TrimSpace(selected.FlagGroupCode), nil
|
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) {
|
func assignEarliestAsOf(m map[uint]time.Time, productWarehouseID uint, asOf time.Time) {
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResolvePurchaseFlagGroupByProductWarehouseFallsBackToProductCategory(t *testing.T) {
|
||||||
|
db := setupPurchaseFifoHelperTestDB(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
flagGroupCode, err := resolvePurchaseFlagGroupByProductWarehouse(ctx, db, 1115)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if flagGroupCode != "PAKAN" {
|
||||||
|
t.Fatalf("expected PAKAN, got %s", flagGroupCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolvePurchaseFlagGroupByProductWarehouseUsesProductFlagsWhenPresent(t *testing.T) {
|
||||||
|
db := setupPurchaseFifoHelperTestDB(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
flagGroupCode, err := resolvePurchaseFlagGroupByProductWarehouse(ctx, db, 2222)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if flagGroupCode != "OVK" {
|
||||||
|
t.Fatalf("expected OVK, got %s", flagGroupCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupPurchaseFifoHelperTestDB(t *testing.T) *gorm.DB {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=private"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed opening sqlite db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
statements := []string{
|
||||||
|
`CREATE TABLE fifo_stock_v2_flag_groups (code TEXT PRIMARY KEY, is_active BOOLEAN NOT NULL)`,
|
||||||
|
`CREATE TABLE fifo_stock_v2_flag_members (flag_name TEXT NOT NULL, flag_group_code TEXT NOT NULL, is_active BOOLEAN NOT NULL)`,
|
||||||
|
`CREATE TABLE fifo_stock_v2_route_rules (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
flag_group_code TEXT NOT NULL,
|
||||||
|
lane TEXT NOT NULL,
|
||||||
|
function_code TEXT NOT NULL,
|
||||||
|
source_table TEXT NOT NULL,
|
||||||
|
is_active BOOLEAN NOT NULL
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE product_categories (id INTEGER PRIMARY KEY, code TEXT NOT NULL)`,
|
||||||
|
`CREATE TABLE products (id INTEGER PRIMARY KEY, product_category_id INTEGER NOT NULL)`,
|
||||||
|
`CREATE TABLE flags (id INTEGER PRIMARY KEY, flagable_id INTEGER NOT NULL, flagable_type TEXT NOT NULL, name TEXT NOT NULL)`,
|
||||||
|
`CREATE TABLE product_warehouses (id INTEGER PRIMARY KEY, product_id INTEGER NOT NULL)`,
|
||||||
|
`INSERT INTO fifo_stock_v2_flag_groups (code, is_active) VALUES ('PAKAN', TRUE), ('OVK', TRUE)`,
|
||||||
|
`INSERT INTO fifo_stock_v2_flag_members (flag_name, flag_group_code, is_active) VALUES ('PAKAN', 'PAKAN', TRUE), ('OVK', 'OVK', TRUE), ('OBAT', 'OVK', TRUE)`,
|
||||||
|
`INSERT INTO fifo_stock_v2_route_rules (id, flag_group_code, lane, function_code, source_table, is_active) VALUES
|
||||||
|
(1, 'PAKAN', 'STOCKABLE', 'PURCHASE_IN', 'purchase_items', TRUE),
|
||||||
|
(2, 'OVK', 'STOCKABLE', 'PURCHASE_IN', 'purchase_items', TRUE)`,
|
||||||
|
`INSERT INTO product_categories (id, code) VALUES (1, 'RAW'), (2, 'OBT')`,
|
||||||
|
`INSERT INTO products (id, product_category_id) VALUES (37, 1), (112, 2)`,
|
||||||
|
`INSERT INTO flags (id, flagable_id, flagable_type, name) VALUES
|
||||||
|
(1, 112, 'products', 'OVK'),
|
||||||
|
(2, 112, 'products', 'OBAT')`,
|
||||||
|
`INSERT INTO product_warehouses (id, product_id) VALUES (1115, 37), (2222, 112)`,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, stmt := range statements {
|
||||||
|
if err := db.Exec(stmt).Error; err != nil {
|
||||||
|
t.Fatalf("failed preparing schema: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
||||||
@@ -129,10 +130,23 @@ var productSubFlagToFlag = func() map[FlagType]FlagType {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var productAllowWithoutSubFlagByFlag = map[FlagType]bool{
|
var productAllowWithoutSubFlagByFlag = map[FlagType]bool{
|
||||||
FlagAyam: true,
|
FlagAyam: true,
|
||||||
FlagPakan: false,
|
FlagPakan: false,
|
||||||
FlagOVK: false,
|
FlagOVK: false,
|
||||||
FlagTelur: false,
|
FlagTelur: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
var legacyProductCategoryFlagsByCode = map[string][]FlagType{
|
||||||
|
"DOC": {FlagAyam, FlagDOC},
|
||||||
|
"PLT": {FlagAyam, FlagPullet},
|
||||||
|
"EGG": {FlagTelur},
|
||||||
|
"RAW": {FlagPakan},
|
||||||
|
"PST": {FlagPakan, FlagPreStarter},
|
||||||
|
"STR": {FlagPakan, FlagStarter},
|
||||||
|
"FSR": {FlagPakan, FlagFinisher},
|
||||||
|
"OBT": {FlagOVK, FlagObat},
|
||||||
|
"VTM": {FlagOVK, FlagVitamin},
|
||||||
|
"KMA": {FlagOVK, FlagKimia},
|
||||||
}
|
}
|
||||||
|
|
||||||
var legacyFlagTypeAliases = map[FlagType]FlagType{
|
var legacyFlagTypeAliases = map[FlagType]FlagType{
|
||||||
@@ -228,6 +242,52 @@ func ProductFlagAllowWithoutSubFlag(flag FlagType) bool {
|
|||||||
return allow
|
return allow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LegacyProductCategoryCodesForFlags(flags []string) []string {
|
||||||
|
if len(flags) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
requested := make(map[FlagType]struct{}, len(flags))
|
||||||
|
for _, flag := range flags {
|
||||||
|
canonical := CanonicalFlagType(flag)
|
||||||
|
if canonical == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
requested[canonical] = struct{}{}
|
||||||
|
}
|
||||||
|
if len(requested) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
codes := make([]string, 0, len(legacyProductCategoryFlagsByCode))
|
||||||
|
for code, supportedFlags := range legacyProductCategoryFlagsByCode {
|
||||||
|
for _, supportedFlag := range supportedFlags {
|
||||||
|
if _, ok := requested[canonicalizeFlagType(supportedFlag)]; ok {
|
||||||
|
codes = append(codes, code)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Sort(codes)
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func LegacyFlagGroupCodeByProductCategoryCode(code string) string {
|
||||||
|
switch strings.ToUpper(strings.TrimSpace(code)) {
|
||||||
|
case "DOC", "PLT":
|
||||||
|
return "AYAM"
|
||||||
|
case "EGG":
|
||||||
|
return "TELUR"
|
||||||
|
case "RAW", "PST", "STR", "FSR":
|
||||||
|
return "PAKAN"
|
||||||
|
case "OBT", "VTM", "KMA":
|
||||||
|
return "OVK"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func IsProductMainFlag(flag FlagType) bool {
|
func IsProductMainFlag(flag FlagType) bool {
|
||||||
canonical := canonicalizeFlagType(flag)
|
canonical := canonicalizeFlagType(flag)
|
||||||
for _, f := range productMainFlags {
|
for _, f := range productMainFlags {
|
||||||
|
|||||||
Reference in New Issue
Block a user