mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 05:21:57 +00:00
cmd: resolve active allocation repointment
This commit is contained in:
@@ -26,12 +26,13 @@ const (
|
||||
)
|
||||
|
||||
type options struct {
|
||||
Apply bool
|
||||
Output string
|
||||
AreaName string
|
||||
KandangLocationName string
|
||||
DBSSLMode string
|
||||
DeleteWrongWarehouses bool
|
||||
Apply bool
|
||||
Output string
|
||||
AreaName string
|
||||
KandangLocationName string
|
||||
DBSSLMode string
|
||||
DeleteWrongWarehouses bool
|
||||
AllowMovingAllocatedStocks bool
|
||||
}
|
||||
|
||||
type planRow struct {
|
||||
@@ -123,6 +124,16 @@ func main() {
|
||||
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 {
|
||||
fmt.Println("No misplaced PAKAN/OVK stocks found in wrong-location warehouses")
|
||||
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.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.AllowMovingAllocatedStocks, "allow-moving-allocated-stocks", false, "Allow moving stocks that have active allocations (use with caution - for old recordings with completed allocations)")
|
||||
flag.Parse()
|
||||
|
||||
opts.Output = strings.ToLower(strings.TrimSpace(opts.Output))
|
||||
@@ -175,6 +187,90 @@ func parseFlags() (*options, error) {
|
||||
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) {
|
||||
filters := make([]string, 0, 2)
|
||||
args := make([]any, 0, 2)
|
||||
|
||||
Reference in New Issue
Block a user