Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1228,6 +1228,15 @@ func PostProductionProductCostingOnMLSaveHandler(w http.ResponseWriter, r *http.
|
||||
http.Error(w, "Gecersiz JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// Guardrail: do not allow blank stock codes for rows that specify a hammadde type.
|
||||
// UI should already block this, but we enforce it server-side too.
|
||||
for _, row := range req.Detail.Upserts {
|
||||
if row.NHammaddeTuruNo > 0 && strings.TrimSpace(row.SKodu) == "" {
|
||||
logger.Warn("validation failed: blank s_kodu", "n_hammadde_turu_no", row.NHammaddeTuruNo, "n_onml_det_no", row.NOnMLDetNo)
|
||||
http.Error(w, "Kod bos olamaz (hammadde turu secili satir var)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
req.DetailSource = strings.ToLower(strings.TrimSpace(req.DetailSource))
|
||||
req.Header.UrunKodu = strings.TrimSpace(req.Header.UrunKodu)
|
||||
@@ -1696,19 +1705,23 @@ WHEN NOT MATCHED THEN
|
||||
// ============================================================
|
||||
// Recipe sync (URETIM): ensure recipe contains all OnML hammadde rows
|
||||
// so future no-cost loads don't keep showing them as missing.
|
||||
// Table observed in queries: dbo.spUrtRecMBolumMik (nUrtMBolumID stores nHammaddeTuruNo).
|
||||
// IMPORTANT: In current URETIM DB, the detail table is dbo.spUrtRecMBolum (NOT NULL cols, FK to dbo.spUrtMBolum).
|
||||
// We must:
|
||||
// 1) Skip hammadde types that do not exist in dbo.spUrtMBolum (FK safety),
|
||||
// 2) Upsert by (nUrtReceteID, nUrtMBolumID, nHStokID_G=sKodu),
|
||||
// 3) When inserting, generate nUrtRecMBolumID (smallint, not identity) and fill required columns incl. sIslemKodu=''.
|
||||
// ============================================================
|
||||
if req.Header.NUrtReceteID > 0 {
|
||||
receteID := req.Header.NUrtReceteID
|
||||
logger.Info("tx step", "trace_id", traceID, "n_onml_no", nOnMLNo, "step", "recipe_sync", "n_urt_recete_id", receteID)
|
||||
|
||||
// Determine next available recipe detail id (nUrtRecMBolumID)
|
||||
// Determine next available recipe detail id (nUrtRecMBolumID) globally.
|
||||
// NOTE: nUrtRecMBolumID is smallint and not identity in this schema.
|
||||
nextRecDetID := 0
|
||||
_ = tx.QueryRowContext(ctx, `
|
||||
SELECT ISNULL(MAX(RMik.nUrtRecMBolumID), 0) + 1
|
||||
FROM dbo.spUrtRecMBolumMik RMik WITH (UPDLOCK, HOLDLOCK)
|
||||
WHERE RMik.nUrtReceteID = @p1
|
||||
`, receteID).Scan(&nextRecDetID)
|
||||
SELECT ISNULL(MAX(R.nUrtRecMBolumID), 0) + 1
|
||||
FROM dbo.spUrtRecMBolum R WITH (UPDLOCK, HOLDLOCK)
|
||||
`).Scan(&nextRecDetID)
|
||||
if nextRecDetID <= 0 {
|
||||
nextRecDetID = 1
|
||||
}
|
||||
@@ -1718,6 +1731,11 @@ WHERE RMik.nUrtReceteID = @p1
|
||||
if hNo <= 0 {
|
||||
continue
|
||||
}
|
||||
// Legacy mapping: merge deprecated hammadde types into canonical ones.
|
||||
// We migrated 1104 -> 1105 historically; keep runtime mapping to avoid FK issues.
|
||||
if hNo == 1104 {
|
||||
hNo = 1105
|
||||
}
|
||||
|
||||
// 1. FILTER: CM1/CM2 (Labor/Service) rows must NOT be written back into recipe tables.
|
||||
// We check the group label (sAciklama3) from the row itself.
|
||||
@@ -1727,132 +1745,93 @@ WHERE RMik.nUrtReceteID = @p1
|
||||
continue
|
||||
}
|
||||
|
||||
// In this version of URETIM DB, the table name is dbo.spUrtRecMBolumMik
|
||||
// but it uses _G suffixes for quantity and amount columns.
|
||||
// Also nHStokID_G stores the stock code string rather than just an ID.
|
||||
rawSKodu := strings.TrimSpace(row.SKodu)
|
||||
|
||||
// Ensure a section entry (spUrtRecMBolum) exists for this hNo (Hammadde Turu)
|
||||
// in the current recipe, otherwise detail rows (Mik) cannot be linked properly.
|
||||
var sectionExists int
|
||||
_ = tx.QueryRowContext(ctx, `
|
||||
SELECT COUNT(1) FROM dbo.spUrtRecMBolum WITH (NOLOCK)
|
||||
WHERE nUrtReceteID = @p1 AND nUrtMBolumID = @p2
|
||||
`, receteID, hNo).Scan(§ionExists)
|
||||
|
||||
if sectionExists <= 0 {
|
||||
logger.Info("creating missing recipe section", "n_urt_recete_id", receteID, "n_urt_m_bolum_id", hNo)
|
||||
_, _ = tx.ExecContext(ctx, `
|
||||
INSERT INTO dbo.spUrtRecMBolum (nUrtReceteID, nUrtUBolumID, nUrtMBolumID, nUrtMTBolumID, sKullaniciAdi, dteIslemTarihi)
|
||||
VALUES (@p1, 13, @p2, @p3, @p4, GETDATE())
|
||||
`, receteID, hNo, row.NUrtMTBolumID, user)
|
||||
}
|
||||
|
||||
// Update quantity and prices if row already exists for (recete, hammadde, stok_code)
|
||||
// Using nHStokID_G (string code) for matching as per user screenshot.
|
||||
var exists int
|
||||
// FK safety: nUrtMBolumID must exist in dbo.spUrtMBolum.
|
||||
var bolumExists int
|
||||
if err := tx.QueryRowContext(ctx, `
|
||||
SELECT COUNT(1)
|
||||
FROM dbo.spUrtRecMBolumMik RMik WITH (NOLOCK)
|
||||
WHERE RMik.nUrtReceteID = @p1
|
||||
AND RMik.nUrtMBolumID = @p2
|
||||
AND LTRIM(RTRIM(RMik.nHStokID_G)) = @p3
|
||||
`, receteID, hNo, rawSKodu).Scan(&exists); err == nil && exists > 0 {
|
||||
// Compute TRY unit price for recipe mirror columns.
|
||||
cur := strings.ToUpper(strings.TrimSpace(row.FiyatDoviz))
|
||||
in := row.FiyatGirilen
|
||||
unitTRYRec := in
|
||||
switch cur {
|
||||
case "USD":
|
||||
unitTRYRec = in * usdRate
|
||||
case "EUR":
|
||||
unitTRYRec = in * eurRate
|
||||
case "GBP":
|
||||
unitTRYRec = in * gbpRate
|
||||
case "TRY", "TL", "":
|
||||
unitTRYRec = in
|
||||
default:
|
||||
unitTRYRec = in
|
||||
}
|
||||
_, _ = tx.ExecContext(ctx, `
|
||||
UPDATE dbo.spUrtRecMBolumMik
|
||||
SET lHMiktar_G = @p4,
|
||||
lHMaliyet_G = @p5,
|
||||
sKullaniciAdiDeg = @p6,
|
||||
dteIslemTarihiDeg = GETDATE(),
|
||||
bIslem = @p7
|
||||
WHERE nUrtReceteID = @p1
|
||||
AND nUrtMBolumID = @p2
|
||||
AND LTRIM(RTRIM(nHStokID_G)) = @p3
|
||||
`, receteID, hNo, rawSKodu, row.LMiktar, unitTRYRec, user, row.MaliyeteDahil)
|
||||
SELECT COUNT(1) FROM dbo.spUrtMBolum WITH (NOLOCK)
|
||||
WHERE nUrtMBolumID = @p1
|
||||
`, hNo).Scan(&bolumExists); err != nil || bolumExists <= 0 {
|
||||
logger.Warn("recipe sync skip: missing spUrtMBolum", "n_urt_m_bolum_id", hNo, "s_kodu", strings.TrimSpace(row.SKodu))
|
||||
continue
|
||||
}
|
||||
|
||||
// Insert missing: using _G columns and storing code in nHStokID_G.
|
||||
// Compute TRY unit price for recipe mirror columns.
|
||||
cur := strings.ToUpper(strings.TrimSpace(row.FiyatDoviz))
|
||||
in := row.FiyatGirilen
|
||||
unitTRYRec := in
|
||||
switch cur {
|
||||
case "USD":
|
||||
unitTRYRec = in * usdRate
|
||||
case "EUR":
|
||||
unitTRYRec = in * eurRate
|
||||
case "GBP":
|
||||
unitTRYRec = in * gbpRate
|
||||
case "TRY", "TL", "":
|
||||
unitTRYRec = in
|
||||
default:
|
||||
unitTRYRec = in
|
||||
// Upsert target key: (receteID, hNo, sKodu).
|
||||
rawSKodu := strings.TrimSpace(row.SKodu)
|
||||
if rawSKodu == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Update qty if exists.
|
||||
var exists int
|
||||
if err := tx.QueryRowContext(ctx, `
|
||||
SELECT COUNT(1)
|
||||
FROM dbo.spUrtRecMBolum R WITH (NOLOCK)
|
||||
WHERE R.nUrtReceteID = @p1
|
||||
AND R.nUrtMBolumID = @p2
|
||||
AND LTRIM(RTRIM(R.nHStokID_G)) = @p3
|
||||
`, receteID, hNo, rawSKodu).Scan(&exists); err == nil && exists > 0 {
|
||||
_, _ = tx.ExecContext(ctx, `
|
||||
UPDATE dbo.spUrtRecMBolum
|
||||
SET lHMiktar_G = @p4
|
||||
WHERE nUrtReceteID = @p1
|
||||
AND nUrtMBolumID = @p2
|
||||
AND LTRIM(RTRIM(nHStokID_G)) = @p3
|
||||
`, receteID, hNo, rawSKodu, row.LMiktar)
|
||||
continue
|
||||
}
|
||||
|
||||
// Insert missing into dbo.spUrtRecMBolum.
|
||||
// nUrtRecMBolumID is not identity; keep incrementing, but guard against smallint overflow.
|
||||
if nextRecDetID > 32767 {
|
||||
logger.Warn("recipe sync skip: nUrtRecMBolumID overflow risk", "next_id", nextRecDetID, "n_urt_recete_id", receteID)
|
||||
continue
|
||||
}
|
||||
_, insertErr := tx.ExecContext(ctx, `
|
||||
INSERT INTO dbo.spUrtRecMBolumMik (
|
||||
INSERT INTO dbo.spUrtRecMBolum (
|
||||
nUrtRecMBolumID,
|
||||
nUrtReceteID,
|
||||
nUrtUBolumID,
|
||||
nUrtRecMBolumID,
|
||||
nStokID,
|
||||
nUrtMBolumID,
|
||||
nUrtMTBolumID,
|
||||
nStokTipiID,
|
||||
nHStokID_G,
|
||||
lHMiktar_G,
|
||||
lHFire_G,
|
||||
lHCarpan,
|
||||
nMaliyetTipiID,
|
||||
lHMaliyet_G,
|
||||
lMiktar_G,
|
||||
sIslemKodu,
|
||||
nUrtMBolumID,
|
||||
nUrtMTBolumID,
|
||||
lHCarpan,
|
||||
nMTalimat_G,
|
||||
bIslem,
|
||||
nSure,
|
||||
sAciklama,
|
||||
sKullaniciAdi,
|
||||
dteIslemTarihi,
|
||||
sIslemKodu,
|
||||
lHMiktar_GHedef,
|
||||
nMBolumSarfTipiNo
|
||||
)
|
||||
VALUES (
|
||||
@p1,
|
||||
13,
|
||||
@p2,
|
||||
0,
|
||||
@p3, -- nHStokID_G (Code)
|
||||
@p4, -- lHMiktar_G
|
||||
0,
|
||||
6,
|
||||
@p5, -- lHMaliyet_G
|
||||
1, -- lMiktar_G
|
||||
'',
|
||||
@p6,
|
||||
@p7,
|
||||
1,
|
||||
@p8, -- bIslem
|
||||
0,
|
||||
NULL,
|
||||
@p9,
|
||||
GETDATE(),
|
||||
1
|
||||
@p1, -- nUrtRecMBolumID (smallint)
|
||||
@p2, -- nUrtReceteID
|
||||
@p3, -- nUrtUBolumID
|
||||
@p4, -- nUrtMBolumID
|
||||
0, -- nUrtMTBolumID (tinyint)
|
||||
1, -- nStokTipiID
|
||||
@p5, -- nHStokID_G (sKodu)
|
||||
@p6, -- lHMiktar_G
|
||||
0, -- lHFire_G
|
||||
1, -- lHCarpan
|
||||
6, -- nMaliyetTipiID
|
||||
0, -- lHMaliyet_G
|
||||
2, -- nMTalimat_G
|
||||
0, -- bIslem
|
||||
0, -- nSure
|
||||
'', -- sIslemKodu (NOT NULL)
|
||||
0, -- lHMiktar_GHedef
|
||||
1 -- nMBolumSarfTipiNo
|
||||
)
|
||||
`, receteID, nextRecDetID, rawSKodu, row.LMiktar, unitTRYRec, hNo, row.NUrtMTBolumID, row.MaliyeteDahil, user)
|
||||
`, nextRecDetID, receteID, 13, hNo, rawSKodu, row.LMiktar)
|
||||
if insertErr == nil {
|
||||
nextRecDetID += 1
|
||||
} else {
|
||||
logger.Warn("recipe sync insert error", "err", insertErr, "n_urt_recete_id", receteID, "n_urt_m_bolum_id", hNo, "s_kodu", rawSKodu)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user