mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 14:55:42 +00:00
cmd: resolve active allocation repointment
This commit is contained in:
@@ -26,12 +26,13 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
Apply bool
|
Apply bool
|
||||||
Output string
|
Output string
|
||||||
AreaName string
|
AreaName string
|
||||||
KandangLocationName string
|
KandangLocationName string
|
||||||
DBSSLMode string
|
DBSSLMode string
|
||||||
DeleteWrongWarehouses bool
|
DeleteWrongWarehouses bool
|
||||||
|
AllowMovingAllocatedStocks bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type planRow struct {
|
type planRow struct {
|
||||||
@@ -123,6 +124,16 @@ func main() {
|
|||||||
log.Fatalf("failed to load plan rows: %v", err)
|
log.Fatalf("failed to load plan rows: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.AllowMovingAllocatedStocks {
|
||||||
|
allocatedRows, err := loadPlanRowsWithAllocations(ctx, db, opts)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to load allocated plan rows: %v", err)
|
||||||
|
}
|
||||||
|
rows = append(rows, allocatedRows...)
|
||||||
|
// Remove duplicates
|
||||||
|
rows = deduplicatePlanRows(rows)
|
||||||
|
}
|
||||||
|
|
||||||
if len(rows) == 0 {
|
if len(rows) == 0 {
|
||||||
fmt.Println("No misplaced PAKAN/OVK stocks found in wrong-location warehouses")
|
fmt.Println("No misplaced PAKAN/OVK stocks found in wrong-location warehouses")
|
||||||
return
|
return
|
||||||
@@ -158,6 +169,7 @@ func parseFlags() (*options, error) {
|
|||||||
flag.StringVar(&opts.KandangLocationName, "kandang-location-name", "", "Optional exact canonical kandang location filter")
|
flag.StringVar(&opts.KandangLocationName, "kandang-location-name", "", "Optional exact canonical kandang location filter")
|
||||||
flag.StringVar(&opts.DBSSLMode, "db-sslmode", "", "Optional database sslmode override, for example: require")
|
flag.StringVar(&opts.DBSSLMode, "db-sslmode", "", "Optional database sslmode override, for example: require")
|
||||||
flag.BoolVar(&opts.DeleteWrongWarehouses, "delete-wrong-warehouses", true, "Soft delete wrong warehouse rows after all references have been moved")
|
flag.BoolVar(&opts.DeleteWrongWarehouses, "delete-wrong-warehouses", true, "Soft delete wrong warehouse rows after all references have been moved")
|
||||||
|
flag.BoolVar(&opts.AllowMovingAllocatedStocks, "allow-moving-allocated-stocks", false, "Allow moving stocks that have active allocations (use with caution - for old recordings with completed allocations)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
opts.Output = strings.ToLower(strings.TrimSpace(opts.Output))
|
opts.Output = strings.ToLower(strings.TrimSpace(opts.Output))
|
||||||
@@ -175,6 +187,90 @@ func parseFlags() (*options, error) {
|
|||||||
return &opts, nil
|
return &opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deduplicatePlanRows(rows []planRow) []planRow {
|
||||||
|
seen := make(map[uint]struct{})
|
||||||
|
result := make([]planRow, 0, len(rows))
|
||||||
|
for _, row := range rows {
|
||||||
|
if _, ok := seen[row.SurvivorPWID]; !ok {
|
||||||
|
seen[row.SurvivorPWID] = struct{}{}
|
||||||
|
result = append(result, row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadPlanRowsWithAllocations(ctx context.Context, db *gorm.DB, opts *options) ([]planRow, error) {
|
||||||
|
filters := make([]string, 0, 2)
|
||||||
|
args := make([]any, 0, 2)
|
||||||
|
if opts.AreaName != "" {
|
||||||
|
filters = append(filters, "a.name = ?")
|
||||||
|
args = append(args, opts.AreaName)
|
||||||
|
}
|
||||||
|
if opts.KandangLocationName != "" {
|
||||||
|
filters = append(filters, "kl.name = ?")
|
||||||
|
args = append(args, opts.KandangLocationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`
|
||||||
|
SELECT
|
||||||
|
a.name AS area_name,
|
||||||
|
kl.name AS kandang_location_name,
|
||||||
|
k.id AS kandang_id,
|
||||||
|
k.name AS kandang_name,
|
||||||
|
w.id AS wrong_warehouse_id,
|
||||||
|
w.name AS wrong_warehouse_name,
|
||||||
|
correct_w.id AS correct_warehouse_id,
|
||||||
|
correct_w.name AS correct_warehouse_name,
|
||||||
|
p.id AS product_id,
|
||||||
|
p.name AS product_name,
|
||||||
|
wp.project_flock_kandang_id,
|
||||||
|
wp.id AS survivor_pw_id,
|
||||||
|
COALESCE(wp.qty, 0) AS survivor_current_qty,
|
||||||
|
cpw.id AS absorbed_pw_id,
|
||||||
|
cpw.qty AS absorbed_current_qty
|
||||||
|
FROM warehouses w
|
||||||
|
JOIN kandangs k
|
||||||
|
ON k.id = w.kandang_id
|
||||||
|
AND k.deleted_at IS NULL
|
||||||
|
JOIN locations kl
|
||||||
|
ON kl.id = k.location_id
|
||||||
|
JOIN areas a
|
||||||
|
ON a.id = kl.area_id
|
||||||
|
JOIN LATERAL (
|
||||||
|
SELECT w2.id, w2.name
|
||||||
|
FROM warehouses w2
|
||||||
|
WHERE w2.location_id = k.location_id
|
||||||
|
AND UPPER(COALESCE(w2.type, '')) = 'LOKASI'
|
||||||
|
AND w2.deleted_at IS NULL
|
||||||
|
ORDER BY w2.id ASC
|
||||||
|
LIMIT 1
|
||||||
|
) AS correct_w ON TRUE
|
||||||
|
JOIN product_warehouses wp
|
||||||
|
ON wp.warehouse_id = w.id
|
||||||
|
JOIN products p
|
||||||
|
ON p.id = wp.product_id
|
||||||
|
JOIN flags f
|
||||||
|
ON f.flagable_id = p.id
|
||||||
|
AND f.flagable_type = 'products'
|
||||||
|
AND UPPER(f.name) IN ('PAKAN', 'OVK')
|
||||||
|
LEFT JOIN product_warehouses cpw
|
||||||
|
ON cpw.product_id = wp.product_id
|
||||||
|
AND cpw.warehouse_id = correct_w.id
|
||||||
|
AND cpw.project_flock_kandang_id IS NOT DISTINCT FROM wp.project_flock_kandang_id
|
||||||
|
WHERE w.deleted_at IS NULL
|
||||||
|
AND w.kandang_id IS NOT NULL
|
||||||
|
AND w.location_id IS DISTINCT FROM k.location_id
|
||||||
|
%s
|
||||||
|
ORDER BY a.name ASC, kl.name ASC, k.name ASC, wp.id ASC
|
||||||
|
`, andClause(filters))
|
||||||
|
|
||||||
|
rows := make([]planRow, 0)
|
||||||
|
if err := db.WithContext(ctx).Raw(query, args...).Scan(&rows).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rows, nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadPlanRows(ctx context.Context, db *gorm.DB, opts *options) ([]planRow, error) {
|
func loadPlanRows(ctx context.Context, db *gorm.DB, opts *options) ([]planRow, error) {
|
||||||
filters := make([]string, 0, 2)
|
filters := make([]string, 0, 2)
|
||||||
args := make([]any, 0, 2)
|
args := make([]any, 0, 2)
|
||||||
|
|||||||
Reference in New Issue
Block a user