Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"bssapp-backend/models"
|
||||
"bssapp-backend/utils"
|
||||
"context"
|
||||
"database/sql"
|
||||
@@ -227,17 +228,47 @@ func UpsertV3ItemBasePriceUSD(
|
||||
return fmt.Errorf("missing params for base price upsert")
|
||||
}
|
||||
|
||||
// NOTE: In this DB, PRIMARY KEY is on:
|
||||
// (ItemTypeCode, ItemCode, CountryCode, SeasonCode, BasePriceCode)
|
||||
// so we cannot insert multiple rows for different dates under the same base price.
|
||||
// We update the single row's PriceDate/Price to reflect latest costing.
|
||||
// 1. Find a CountryCode that is NOT yet used for this specific item in prItemBasePrice.
|
||||
// We query cdCountry for a code that has no matching entry in prItemBasePrice for this item.
|
||||
// We exclude 'TR' to keep the original record safe.
|
||||
var targetCountry string
|
||||
err := mssqlDB.QueryRowContext(ctx, `
|
||||
SELECT TOP 1 C.CountryCode
|
||||
FROM dbo.cdCountry C WITH (NOLOCK)
|
||||
WHERE C.CountryCode <> 'TR'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM dbo.prItemBasePrice P WITH (NOLOCK)
|
||||
WHERE P.ItemTypeCode = 1
|
||||
AND LTRIM(RTRIM(P.ItemCode)) = LTRIM(RTRIM(@p1))
|
||||
AND P.BasePriceCode = 1
|
||||
AND P.CountryCode = C.CountryCode
|
||||
)
|
||||
ORDER BY NEWID() -- Randomly pick one of the available country codes
|
||||
`, itemCode).Scan(&targetCountry)
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
// Fallback: If ALL countries are exhausted (unlikely), default to 'AD' as a last resort.
|
||||
targetCountry = "AD"
|
||||
} else {
|
||||
return fmt.Errorf("failed to find available country code: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
appUser := user
|
||||
if strings.TrimSpace(appUser) == "" {
|
||||
appUser = "BSSAPP"
|
||||
} else {
|
||||
appUser = "BSSAPP:" + strings.TrimSpace(appUser)
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
MERGE dbo.prItemBasePrice AS T
|
||||
USING (
|
||||
SELECT
|
||||
@p1 AS ItemTypeCode,
|
||||
@p2 AS ItemCode,
|
||||
'TR' AS CountryCode,
|
||||
@p6 AS CountryCode,
|
||||
'' AS SeasonCode,
|
||||
1 AS BasePriceCode,
|
||||
CONVERT(date, @p3, 23) AS PriceDate,
|
||||
@@ -266,7 +297,7 @@ WHEN NOT MATCHED THEN
|
||||
);
|
||||
`
|
||||
|
||||
_, err := mssqlDB.ExecContext(ctx, sqlText, 1, itemCode, priceDate, priceUSD, user)
|
||||
_, err = mssqlDB.ExecContext(ctx, sqlText, 1, itemCode, priceDate, priceUSD, appUser, targetCountry)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1228,6 +1259,73 @@ ORDER BY
|
||||
return uretimDB.QueryContext(ctx, sqlText, search, limit, searchLike)
|
||||
}
|
||||
|
||||
func GetProductionHammaddeByNos(ctx context.Context, uretimDB *sql.DB, nos []int) ([]models.ProductionProductCostingHammaddeByNosItem, error) {
|
||||
clean := make([]int, 0, len(nos))
|
||||
seen := make(map[int]struct{}, len(nos))
|
||||
for _, n := range nos {
|
||||
if n <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[n]; ok {
|
||||
continue
|
||||
}
|
||||
seen[n] = struct{}{}
|
||||
clean = append(clean, n)
|
||||
}
|
||||
if len(clean) == 0 {
|
||||
return []models.ProductionProductCostingHammaddeByNosItem{}, nil
|
||||
}
|
||||
if len(clean) > 5000 {
|
||||
return nil, fmt.Errorf("too many nos")
|
||||
}
|
||||
|
||||
valueRows := make([]string, 0, len(clean))
|
||||
args := make([]any, 0, len(clean))
|
||||
for i, n := range clean {
|
||||
valueRows = append(valueRows, "(@p"+strconv.Itoa(i+1)+")")
|
||||
args = append(args, n)
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
WITH req(nHammaddeTuruNo) AS (
|
||||
SELECT DISTINCT v.nHammaddeTuruNo
|
||||
FROM (VALUES ` + strings.Join(valueRows, ",") + `) v(nHammaddeTuruNo)
|
||||
)
|
||||
SELECT
|
||||
ISNULL(T.nHammaddeTuruNo, 0) AS nHammaddeTuruNo,
|
||||
ISNULL(T.sAciklama, '') AS sAciklama,
|
||||
ISNULL(T.MTnUrtMTBolumID, 0) AS mtUrtMTBolumID,
|
||||
ISNULL(B.sAdi, '') AS sParcaAdi
|
||||
FROM dbo.spUrtOnMLHammaddeTuru T WITH (NOLOCK)
|
||||
INNER JOIN req R
|
||||
ON R.nHammaddeTuruNo = T.nHammaddeTuruNo
|
||||
LEFT JOIN dbo.spUrtMTBolum B WITH (NOLOCK)
|
||||
ON B.nUrtMTBolumID = T.MTnUrtMTBolumID
|
||||
AND ISNULL(B.nUrtTipiID, 0) = 1
|
||||
WHERE ISNULL(T.bAktif, 0) = 1
|
||||
ORDER BY T.nHammaddeTuruNo;
|
||||
`
|
||||
|
||||
rows, err := uretimDB.QueryContext(ctx, sqlText, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingHammaddeByNosItem, 0, len(clean))
|
||||
for rows.Next() {
|
||||
var it models.ProductionProductCostingHammaddeByNosItem
|
||||
if err := rows.Scan(&it.NHammaddeTuruNo, &it.SAciklama, &it.MTUrtMTBolumID, &it.SParcaAdi); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, it)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Default quantities (URETIM): mk_MaliyetParcaEslestirme_vmiktarlar
|
||||
// ============================================================
|
||||
@@ -1248,7 +1346,9 @@ SELECT TOP (@p3)
|
||||
ISNULL(H.sAciklama, '') AS sAciklama,
|
||||
ISNULL(V.lDefaultMiktar, 0) AS lDefaultMiktar,
|
||||
CONVERT(VARCHAR(16), V.dteCalcTarihi, 120) AS dteCalcTarihi,
|
||||
CAST(CASE WHEN ISNULL(V.bAktif, 0) = 1 THEN 1 ELSE 0 END AS bit) AS bAktif
|
||||
-- We intentionally don't depend on mk_MaliyetParcaEslestirme_vmiktarlar.bAktif
|
||||
-- to keep this feature robust across schema changes; only active hammadde types are listed.
|
||||
CAST(1 AS bit) AS bAktif
|
||||
FROM dbo.mk_MaliyetParcaEslestirme_vmiktarlar V WITH (NOLOCK)
|
||||
LEFT JOIN dbo.spUrtOnMLHammaddeTuru H WITH (NOLOCK)
|
||||
ON H.nHammaddeTuruNo = V.nHammaddeTuruNo
|
||||
@@ -1264,26 +1364,16 @@ ORDER BY
|
||||
|
||||
func UpsertProductionProductCostingDefaultQtyRow(ctx context.Context, uretimDB *sql.DB, nHammaddeTuruNo int, lDefaultMiktar float64, bAktif *bool) error {
|
||||
// NOTE: Legacy helper kept for backward-compat but now behaves as UPDATE-only.
|
||||
activeVal := -1
|
||||
if bAktif != nil {
|
||||
if *bAktif {
|
||||
activeVal = 1
|
||||
} else {
|
||||
activeVal = 0
|
||||
}
|
||||
}
|
||||
|
||||
sqlText := `
|
||||
UPDATE dbo.mk_MaliyetParcaEslestirme_vmiktarlar
|
||||
SET
|
||||
lDefaultMiktar = @p2,
|
||||
dteCalcTarihi = GETDATE(),
|
||||
bAktif = CASE WHEN @p3 < 0 THEN ISNULL(bAktif, 1) ELSE @p3 END
|
||||
dteCalcTarihi = GETDATE()
|
||||
WHERE nHammaddeTuruNo = @p1;
|
||||
SELECT @@ROWCOUNT;
|
||||
`
|
||||
var affected int
|
||||
if err := uretimDB.QueryRowContext(ctx, sqlText, nHammaddeTuruNo, lDefaultMiktar, activeVal).Scan(&affected); err != nil {
|
||||
if err := uretimDB.QueryRowContext(ctx, sqlText, nHammaddeTuruNo, lDefaultMiktar).Scan(&affected); err != nil {
|
||||
return err
|
||||
}
|
||||
if affected == 0 {
|
||||
@@ -1333,11 +1423,10 @@ USING agg AS S
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET
|
||||
T.lDefaultMiktar = S.lDefaultMiktar,
|
||||
T.dteCalcTarihi = GETDATE(),
|
||||
T.bAktif = 1
|
||||
T.dteCalcTarihi = GETDATE()
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (nHammaddeTuruNo, lDefaultMiktar, dteCalcTarihi, bAktif)
|
||||
VALUES (S.nHammaddeTuruNo, S.lDefaultMiktar, GETDATE(), 1);
|
||||
INSERT (nHammaddeTuruNo, lDefaultMiktar, dteCalcTarihi)
|
||||
VALUES (S.nHammaddeTuruNo, S.lDefaultMiktar, GETDATE());
|
||||
`
|
||||
_, err := uretimDB.ExecContext(ctx, sqlText, topN)
|
||||
return err
|
||||
@@ -1377,7 +1466,11 @@ FROM ranked;
|
||||
return avg, cnt, nil
|
||||
}
|
||||
|
||||
func LookupProductionProductCostingDefaultQtyByNos(ctx context.Context, uretimDB *sql.DB, nos []int) (map[int]float64, error) {
|
||||
func LookupProductionProductCostingDefaultQtyByNos(ctx context.Context, uretimDB *sql.DB, nos []int) ([]struct {
|
||||
No int
|
||||
Aciklama string
|
||||
Qty float64
|
||||
}, error) {
|
||||
clean := make([]int, 0, len(nos))
|
||||
seen := make(map[int]struct{}, len(nos))
|
||||
for _, n := range nos {
|
||||
@@ -1391,7 +1484,11 @@ func LookupProductionProductCostingDefaultQtyByNos(ctx context.Context, uretimDB
|
||||
clean = append(clean, n)
|
||||
}
|
||||
if len(clean) == 0 {
|
||||
return map[int]float64{}, nil
|
||||
return []struct {
|
||||
No int
|
||||
Aciklama string
|
||||
Qty float64
|
||||
}{}, nil
|
||||
}
|
||||
if len(clean) > 1000 {
|
||||
return nil, fmt.Errorf("too many hammadde nos")
|
||||
@@ -1409,9 +1506,10 @@ WITH req(nHammaddeTuruNo) AS (
|
||||
SELECT DISTINCT v.nHammaddeTuruNo
|
||||
FROM (VALUES ` + strings.Join(valueRows, ",") + `) v(nHammaddeTuruNo)
|
||||
)
|
||||
SELECT
|
||||
ISNULL(V.nHammaddeTuruNo, 0) AS nHammaddeTuruNo,
|
||||
CAST(ISNULL(V.lDefaultMiktar, 0) AS FLOAT) AS lDefaultMiktar
|
||||
SELECT
|
||||
ISNULL(V.nHammaddeTuruNo, 0) AS nHammaddeTuruNo,
|
||||
ISNULL(H.sAciklama, '') AS sAciklama,
|
||||
CAST(ISNULL(V.lDefaultMiktar, 0) AS FLOAT) AS lDefaultMiktar
|
||||
FROM req R
|
||||
INNER JOIN dbo.mk_MaliyetParcaEslestirme_vmiktarlar V WITH (NOLOCK)
|
||||
ON V.nHammaddeTuruNo = R.nHammaddeTuruNo
|
||||
@@ -1426,15 +1524,24 @@ WHERE ISNULL(H.bAktif, 0) = 1;
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make(map[int]float64, len(clean))
|
||||
out := make([]struct {
|
||||
No int
|
||||
Aciklama string
|
||||
Qty float64
|
||||
}, 0, len(clean))
|
||||
for rows.Next() {
|
||||
var no int
|
||||
var aciklama sql.NullString
|
||||
var qty float64
|
||||
if err := rows.Scan(&no, &qty); err != nil {
|
||||
if err := rows.Scan(&no, &aciklama, &qty); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if no > 0 && qty > 0 {
|
||||
out[no] = qty
|
||||
out = append(out, struct {
|
||||
No int
|
||||
Aciklama string
|
||||
Qty float64
|
||||
}{No: no, Aciklama: strings.TrimSpace(aciklama.String), Qty: qty})
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
@@ -1443,6 +1550,128 @@ WHERE ISNULL(H.bAktif, 0) = 1;
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func LookupLastOnMLMasDetByHammaddeNos(
|
||||
ctx context.Context,
|
||||
uretimDB *sql.DB,
|
||||
nos []int,
|
||||
beforeDate string, // YYYY-MM-DD optional
|
||||
excludeOnMLNo int,
|
||||
nFirmaID int,
|
||||
onlyICode bool,
|
||||
limitPerType int,
|
||||
) ([]models.ProductionProductCostingLastOnMLDetLookupItem, error) {
|
||||
if limitPerType <= 0 {
|
||||
limitPerType = 1
|
||||
}
|
||||
if limitPerType > 1 {
|
||||
limitPerType = 1
|
||||
}
|
||||
|
||||
clean := make([]int, 0, len(nos))
|
||||
seen := make(map[int]struct{}, len(nos))
|
||||
for _, n := range nos {
|
||||
if n <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[n]; ok {
|
||||
continue
|
||||
}
|
||||
seen[n] = struct{}{}
|
||||
clean = append(clean, n)
|
||||
}
|
||||
if len(clean) == 0 {
|
||||
return []models.ProductionProductCostingLastOnMLDetLookupItem{}, nil
|
||||
}
|
||||
if len(clean) > 500 {
|
||||
return nil, fmt.Errorf("too many hammadde nos")
|
||||
}
|
||||
|
||||
valueRows := make([]string, 0, len(clean))
|
||||
args := make([]any, 0, len(clean)+2)
|
||||
for i, n := range clean {
|
||||
valueRows = append(valueRows, "(@p"+strconv.Itoa(i+1)+")")
|
||||
args = append(args, n)
|
||||
}
|
||||
// extra params at the end
|
||||
args = append(args, strings.TrimSpace(beforeDate))
|
||||
args = append(args, excludeOnMLNo)
|
||||
args = append(args, nFirmaID)
|
||||
if onlyICode {
|
||||
args = append(args, 1)
|
||||
} else {
|
||||
args = append(args, 0)
|
||||
}
|
||||
|
||||
beforeParam := "@p" + strconv.Itoa(len(clean)+1)
|
||||
excludeParam := "@p" + strconv.Itoa(len(clean)+2)
|
||||
firmaParam := "@p" + strconv.Itoa(len(clean)+3)
|
||||
onlyIParam := "@p" + strconv.Itoa(len(clean)+4)
|
||||
|
||||
sqlText := `
|
||||
WITH req(nHammaddeTuruNo) AS (
|
||||
SELECT DISTINCT v.nHammaddeTuruNo
|
||||
FROM (VALUES ` + strings.Join(valueRows, ",") + `) v(nHammaddeTuruNo)
|
||||
),
|
||||
ranked AS (
|
||||
SELECT
|
||||
D.nHammaddeTuruNo,
|
||||
LTRIM(RTRIM(ISNULL(D.sKodu, ''))) AS sKodu,
|
||||
LTRIM(RTRIM(ISNULL(D.sAciklama, ''))) AS sAciklama,
|
||||
LTRIM(RTRIM(ISNULL(D.sBirim, ''))) AS sBirim,
|
||||
LTRIM(RTRIM(ISNULL(D.fiyat_doviz, ''))) AS fiyat_doviz,
|
||||
CAST(ISNULL(D.fiyat_girilen, 0) AS FLOAT) AS fiyat_girilen,
|
||||
CAST(CASE WHEN ISNULL(` + firmaParam + `, 0) > 0 AND ISNULL(M.nFirmaID, 0) = ISNULL(` + firmaParam + `, 0) THEN 1 ELSE 0 END AS bit) AS is_same_firma,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY D.nHammaddeTuruNo
|
||||
ORDER BY
|
||||
CASE WHEN ISNULL(` + firmaParam + `, 0) > 0 AND ISNULL(M.nFirmaID, 0) = ISNULL(` + firmaParam + `, 0) THEN 0 ELSE 1 END,
|
||||
COALESCE(M.Tarihi, M.dteKayitTarihi) DESC,
|
||||
M.nOnMLNo DESC,
|
||||
D.nOnMLDetNo DESC
|
||||
) AS rn
|
||||
FROM dbo.spUrtOnMLMasDet D WITH (NOLOCK)
|
||||
INNER JOIN dbo.spUrtOnMLMas M WITH (NOLOCK)
|
||||
ON M.nOnMLNo = D.nOnMLNo
|
||||
INNER JOIN req R
|
||||
ON R.nHammaddeTuruNo = D.nHammaddeTuruNo
|
||||
WHERE ISNULL(D.fiyat_girilen, 0) > 0
|
||||
AND LTRIM(RTRIM(ISNULL(D.sKodu, ''))) <> ''
|
||||
AND (ISNULL(` + onlyIParam + `, 0) = 0 OR LTRIM(RTRIM(ISNULL(D.sKodu, ''))) LIKE 'I.%')
|
||||
AND (` + beforeParam + ` = '' OR CONVERT(date, COALESCE(M.Tarihi, M.dteKayitTarihi)) < CONVERT(date, ` + beforeParam + `, 23))
|
||||
AND (ISNULL(` + excludeParam + `, 0) <= 0 OR M.nOnMLNo <> ` + excludeParam + `)
|
||||
)
|
||||
SELECT
|
||||
ISNULL(nHammaddeTuruNo, 0) AS nHammaddeTuruNo,
|
||||
ISNULL(sKodu, '') AS sKodu,
|
||||
ISNULL(sAciklama, '') AS sAciklama,
|
||||
ISNULL(sBirim, '') AS sBirim,
|
||||
ISNULL(fiyat_doviz, '') AS fiyat_doviz,
|
||||
ISNULL(fiyat_girilen, 0) AS fiyat_girilen,
|
||||
CAST(ISNULL(is_same_firma, 0) AS bit) AS is_same_firma
|
||||
FROM ranked
|
||||
WHERE rn = 1;
|
||||
`
|
||||
|
||||
rows, err := uretimDB.QueryContext(ctx, sqlText, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]models.ProductionProductCostingLastOnMLDetLookupItem, 0, len(clean))
|
||||
for rows.Next() {
|
||||
var item models.ProductionProductCostingLastOnMLDetLookupItem
|
||||
if err := rows.Scan(&item.NHammaddeTuruNo, &item.SKodu, &item.SAciklama, &item.SBirim, &item.FiyatDoviz, &item.FiyatGirilen, &item.IsSameFirma); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func buildSQLServerFullTextPrefixQuery(search string) string {
|
||||
terms := strings.Fields(strings.TrimSpace(search))
|
||||
parts := make([]string, 0, len(terms))
|
||||
|
||||
Reference in New Issue
Block a user