Merge remote-tracking branch 'origin/master'
This commit is contained in:
188
svc/queries/pricing_calc_infra.go
Normal file
188
svc/queries/pricing_calc_infra.go
Normal file
@@ -0,0 +1,188 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func EnsurePricingCalcInfraTables(pg *sql.DB) error {
|
||||
stmts := []string{
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_fx_rate_cache (
|
||||
rate_date DATE PRIMARY KEY,
|
||||
usd_try NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur_try NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd_eur NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
source_system TEXT NOT NULL DEFAULT 'MSSQL',
|
||||
source_updated_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_fx_rate_cache_updated_at ON mk_fx_rate_cache (updated_at DESC)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_price_snapshot (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
product_code TEXT NOT NULL,
|
||||
pricing_parameter_id BIGINT REFERENCES mk_urunpricingprmtr(id) ON DELETE CASCADE,
|
||||
rule_id UUID REFERENCES mk_pricing_rule(id) ON DELETE SET NULL,
|
||||
strategy_code TEXT NOT NULL DEFAULT 'CORE',
|
||||
anchor_mode TEXT NOT NULL DEFAULT 'USD',
|
||||
fx_date DATE NOT NULL,
|
||||
cost_date DATE,
|
||||
base_price_try NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
base_price_usd NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
try1 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
try2 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
try3 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
try4 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
try5 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
try6 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd1 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd2 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd3 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd4 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd5 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
usd6 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur1 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur2 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur3 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur4 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur5 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
eur6 NUMERIC(18,6) NOT NULL DEFAULT 0,
|
||||
calc_hash TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT uq_mk_price_snapshot_product_scope UNIQUE (product_code, pricing_parameter_id),
|
||||
CONSTRAINT ck_mk_price_snapshot_strategy_code CHECK (strategy_code IN ('CORE','PREMIUM','SARTORIAL')),
|
||||
CONSTRAINT ck_mk_price_snapshot_anchor_mode CHECK (anchor_mode IN ('TRY','USD'))
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_price_snapshot_rule ON mk_price_snapshot (rule_id)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_price_snapshot_updated_at ON mk_price_snapshot (updated_at DESC)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_price_target_map_pg (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
currency TEXT NOT NULL,
|
||||
level_no SMALLINT NOT NULL,
|
||||
sdprcgrp_id INTEGER,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT uq_mk_price_target_map_pg UNIQUE (currency, level_no),
|
||||
CONSTRAINT ck_mk_price_target_map_pg_currency CHECK (currency IN ('TRY','USD','EUR')),
|
||||
CONSTRAINT ck_mk_price_target_map_pg_level_no CHECK (level_no BETWEEN 1 AND 6)
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_price_target_map_pg_active ON mk_price_target_map_pg (is_active, currency, level_no)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_price_target_map_nebim (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
currency TEXT NOT NULL,
|
||||
level_no SMALLINT NOT NULL,
|
||||
price_group_code TEXT NOT NULL DEFAULT '',
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT uq_mk_price_target_map_nebim UNIQUE (currency, level_no),
|
||||
CONSTRAINT ck_mk_price_target_map_nebim_currency CHECK (currency IN ('TRY','USD','EUR')),
|
||||
CONSTRAINT ck_mk_price_target_map_nebim_level_no CHECK (level_no BETWEEN 1 AND 6)
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_price_target_map_nebim_active ON mk_price_target_map_nebim (is_active, currency, level_no)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_price_recalc_queue (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
product_code TEXT NOT NULL,
|
||||
pricing_parameter_id BIGINT REFERENCES mk_urunpricingprmtr(id) ON DELETE SET NULL,
|
||||
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_price_recalc_queue_status CHECK (status IN ('pending','processing','done','failed'))
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_price_recalc_queue_status ON mk_price_recalc_queue (status, available_at, queued_at)`,
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS uq_mk_price_recalc_queue_pending ON mk_price_recalc_queue (product_code, COALESCE(pricing_parameter_id, 0)) WHERE status IN ('pending','processing')`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_mmitem_dim_combo (
|
||||
product_code TEXT NOT NULL,
|
||||
dim1 INTEGER NOT NULL,
|
||||
dim3 INTEGER,
|
||||
dim3_key INTEGER GENERATED ALWAYS AS (COALESCE(dim3, 0)) STORED,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT pk_mk_mmitem_dim_combo PRIMARY KEY (product_code, dim1, dim3_key)
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_mmitem_dim_combo_product ON mk_mmitem_dim_combo (product_code, updated_at DESC)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS mk_dim_token_map (
|
||||
dim_column TEXT NOT NULL, -- dimval1 or dimval3
|
||||
token TEXT NOT NULL, -- normalized token (e.g. "001", "82", etc.)
|
||||
dim_id INTEGER NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT pk_mk_dim_token_map PRIMARY KEY (dim_column, token)
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_mk_dim_token_map_updated ON mk_dim_token_map (updated_at DESC)`,
|
||||
}
|
||||
|
||||
for _, stmt := range stmts {
|
||||
if _, err := pg.Exec(stmt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := seedPricingTargetMapRows(pg, "mk_price_target_map_pg", "sdprcgrp_id"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := seedPricingTargetMapRows(pg, "mk_price_target_map_nebim", "price_group_code"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Repair invalid/missing pg target mappings after manual edits or table resets.
|
||||
// sdprcgrp_id is expected to be 1..6 in this installation.
|
||||
if _, err := pg.Exec(`
|
||||
UPDATE mk_price_target_map_pg
|
||||
SET sdprcgrp_id = level_no,
|
||||
updated_at = now()
|
||||
WHERE is_active = TRUE
|
||||
AND (sdprcgrp_id IS NULL OR sdprcgrp_id NOT BETWEEN 1 AND 6)
|
||||
`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func seedPricingTargetMapRows(pg *sql.DB, tableName string, valueColumn string) error {
|
||||
currencies := []string{"TRY", "USD", "EUR"}
|
||||
for _, currency := range currencies {
|
||||
for level := 1; level <= 6; level++ {
|
||||
stmt := fmt.Sprintf(`
|
||||
INSERT INTO %s (currency, level_no, %s, description, is_active, created_at, updated_at)
|
||||
VALUES ($1, $2, NULL, '', TRUE, now(), now())
|
||||
ON CONFLICT (currency, level_no) DO NOTHING
|
||||
`, tableName, valueColumn)
|
||||
// PG targets: default sdprcgrp_id = level_no (1..6). This keeps sdprc writes valid after resets.
|
||||
if tableName == "mk_price_target_map_pg" && valueColumn == "sdprcgrp_id" {
|
||||
stmt = fmt.Sprintf(`
|
||||
INSERT INTO %s (currency, level_no, %s, description, is_active, created_at, updated_at)
|
||||
VALUES ($1, $2, $2, '', TRUE, now(), now())
|
||||
ON CONFLICT (currency, level_no) DO NOTHING
|
||||
`, tableName, valueColumn)
|
||||
}
|
||||
if valueColumn == "price_group_code" {
|
||||
stmt = fmt.Sprintf(`
|
||||
INSERT INTO %s (currency, level_no, %s, description, is_active, created_at, updated_at)
|
||||
VALUES ($1, $2, '', '', TRUE, now(), now())
|
||||
ON CONFLICT (currency, level_no) DO NOTHING
|
||||
`, tableName, valueColumn)
|
||||
}
|
||||
if _, err := pg.Exec(stmt, currency, level); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user