Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-06-22 22:25:43 +03:00
parent a839cae840
commit 4e36e2b057
14 changed files with 2946 additions and 372 deletions

View File

@@ -0,0 +1,89 @@
package queries
import "database/sql"
func EnsureProductSeriesAutoInfraTables(pg *sql.DB) error {
stmts := []string{
`
CREATE TABLE IF NOT EXISTS mk_product_series_rule (
id BIGSERIAL PRIMARY KEY,
series_id BIGINT NOT NULL REFERENCES dfgrp(id) ON DELETE CASCADE,
size_group TEXT NOT NULL DEFAULT '',
size_code TEXT NOT NULL,
ratio_qty INTEGER NOT NULL DEFAULT 1,
priority INTEGER NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
source TEXT NOT NULL DEFAULT 'manual',
notes TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT ck_mk_product_series_rule_ratio CHECK (ratio_qty > 0),
CONSTRAINT uq_mk_product_series_rule UNIQUE (series_id, size_group, size_code)
)`,
`CREATE INDEX IF NOT EXISTS ix_mk_product_series_rule_series ON mk_product_series_rule (series_id, is_active)`,
`CREATE INDEX IF NOT EXISTS ix_mk_product_series_rule_group ON mk_product_series_rule (size_group, size_code)`,
`
CREATE TABLE IF NOT EXISTS mk_product_series_stock_state (
row_key TEXT PRIMARY KEY,
product_code TEXT NOT NULL,
color_code TEXT NOT NULL,
dim3_code TEXT NOT NULL DEFAULT '',
stock_hash TEXT NOT NULL DEFAULT '',
total_qty NUMERIC(18,2) NOT NULL DEFAULT 0,
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
)`,
`CREATE INDEX IF NOT EXISTS ix_mk_product_series_stock_state_product ON mk_product_series_stock_state (product_code, updated_at DESC)`,
`
CREATE TABLE IF NOT EXISTS mk_product_series_recalc_queue (
id BIGSERIAL PRIMARY KEY,
row_key TEXT NOT NULL,
product_code TEXT NOT NULL,
color_code TEXT NOT NULL,
dim3_code TEXT NOT NULL DEFAULT '',
reason TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'pending',
attempts SMALLINT NOT NULL DEFAULT 0,
available_at TIMESTAMPTZ NOT NULL DEFAULT now(),
queued_at TIMESTAMPTZ NOT NULL DEFAULT now(),
processed_at TIMESTAMPTZ,
last_error TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT ck_mk_product_series_recalc_queue_status CHECK (status IN ('pending','processing','done','failed'))
)`,
`CREATE INDEX IF NOT EXISTS ix_mk_product_series_recalc_queue_status ON mk_product_series_recalc_queue (status, available_at, queued_at)`,
`CREATE UNIQUE INDEX IF NOT EXISTS uq_mk_product_series_recalc_queue_pending ON mk_product_series_recalc_queue (row_key) WHERE status IN ('pending','processing')`,
`
CREATE TABLE IF NOT EXISTS mk_product_series_job_log (
id BIGSERIAL PRIMARY KEY,
job_name TEXT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
finished_at TIMESTAMPTZ,
status TEXT NOT NULL DEFAULT 'running',
scanned_rows INTEGER NOT NULL DEFAULT 0,
changed_rows INTEGER NOT NULL DEFAULT 0,
processed_rows INTEGER NOT NULL DEFAULT 0,
written_rows INTEGER NOT NULL DEFAULT 0,
skipped_rows INTEGER NOT NULL DEFAULT 0,
error_text TEXT NOT NULL DEFAULT ''
)`,
`CREATE INDEX IF NOT EXISTS ix_mk_product_series_job_log_started ON mk_product_series_job_log (started_at DESC)`,
}
for _, stmt := range stmts {
if _, err := pg.Exec(stmt); err != nil {
return err
}
}
_, err := pg.Exec(`
INSERT INTO mk_product_series_rule (series_id, size_group, size_code, ratio_qty, priority, source, notes)
SELECT d.id, '', BTRIM(x.size_code), 1, 0, 'dfgrp_title', 'auto-seeded from dfgrp.title'
FROM dfgrp d
CROSS JOIN LATERAL regexp_split_to_table(COALESCE(d.title, ''), '-') AS x(size_code)
WHERE d.master='zbggseri'
AND BTRIM(x.size_code) <> ''
ON CONFLICT (series_id, size_group, size_code) DO NOTHING
`)
return err
}