Files
bssapp/svc/queries/product_performance_sql.go
T

692 lines
32 KiB
Go

package queries
func productPerformanceSalesSQL() string {
return `
;WITH SalesLines AS (
SELECT
I.InvoiceLineID,
SalesDate = CAST(I.InvoiceDate AS date),
I.InvoiceHeaderID,
I.InvoiceNumber,
ProductCode = UPPER(LTRIM(RTRIM(I.ItemCode))),
ColorCode = UPPER(LTRIM(RTRIM(ISNULL(I.ColorCode, '')))),
YakaKodu = UPPER(LTRIM(RTRIM(ISNULL(I.ItemDim2Code, '')))),
ItemDescription = dbo.HG_Temizlik(ISNULL((
SELECT ItemDescription
FROM cdItemDesc WITH(NOLOCK)
WHERE cdItemDesc.ItemTypeCode = I.ItemTypeCode
AND cdItemDesc.ItemCode = I.ItemCode
AND cdItemDesc.LangCode = 'TR'
), SPACE(0))),
UrunAnaGrubu = dbo.HG_Temizlik(ISNULL(PAF.ProductAtt01, SPACE(0))),
UrunAltGrubu = dbo.HG_Temizlik(ISNULL(PAF.ProductAtt02, SPACE(0))),
Kategori = dbo.HG_Temizlik(ISNULL(PAF.ProductAtt44, SPACE(0))),
UrunIlkGrubu = dbo.HG_Temizlik(ISNULL(PAF.ProductAtt42, SPACE(0))),
AskiliYan = dbo.HG_Temizlik(ISNULL(PAF.ProductAtt45, SPACE(0))),
ChannelCode = CASE
WHEN I.ProcessCode IN ('R') THEN dbo.HG_Temizlik(ISNULL((
SELECT OfficeDescription
FROM cdOfficeDesc WITH(NOLOCK)
WHERE cdOfficeDesc.OfficeCode = I.OfficeCode
AND cdOfficeDesc.LangCode = 'TR'
), SPACE(0)))
ELSE dbo.HG_Temizlik(ISNULL((
SELECT AttributeDescription
FROM cdCurrAccAttributeDesc WITH(NOLOCK)
WHERE cdCurrAccAttributeDesc.CurrAccTypeCode = 3
AND AttributeTypeCode = 1
AND CAF.CustomerAtt01 = AttributeCode
AND cdCurrAccAttributeDesc.LangCode = 'TR'
), SPACE(0)))
END,
CustomerCountry = dbo.HG_Temizlik(ISNULL((
SELECT AttributeDescription
FROM cdCurrAccAttributeDesc WITH(NOLOCK)
WHERE cdCurrAccAttributeDesc.CurrAccTypeCode = 3
AND AttributeTypeCode = 5
AND CAF.CustomerAtt05 = AttributeCode
AND cdCurrAccAttributeDesc.LangCode = 'TR'
), SPACE(0))),
CustomerSegment = dbo.HG_Temizlik(ISNULL((
SELECT AttributeDescription
FROM cdCurrAccAttributeDesc WITH(NOLOCK)
WHERE cdCurrAccAttributeDesc.CurrAccTypeCode = 3
AND AttributeTypeCode = 11
AND CAF.CustomerAtt11 = AttributeCode
AND cdCurrAccAttributeDesc.LangCode = 'TR'
), SPACE(0))),
CustomerCode = CASE
WHEN I.ProcessCode = 'R' THEN dbo.HG_Temizlik(ISNULL(I.StoreCode, ''))
ELSE dbo.HG_Temizlik(ISNULL(I.CurrAccCode, ''))
END,
CustomerDescription = CASE
WHEN I.ProcessCode = 'R' THEN dbo.HG_Temizlik(ISNULL((
SELECT CurrAccDescription
FROM cdCurrAccDesc WITH(NOLOCK)
WHERE cdCurrAccDesc.CurrAccTypeCode = 5
AND cdCurrAccDesc.CurrAccCode = I.StoreCode
AND cdCurrAccDesc.LangCode = 'TR'
), SPACE(0)))
ELSE dbo.HG_Temizlik(ISNULL((
SELECT CurrAccDescription
FROM cdCurrAccDesc WITH(NOLOCK)
WHERE cdCurrAccDesc.CurrAccTypeCode = I.CurrAccTypeCode
AND cdCurrAccDesc.CurrAccCode = I.CurrAccCode
AND cdCurrAccDesc.LangCode = 'TR'
), SPACE(0)))
END,
Qty1 = ISNULL(I.Qty1, 0),
TLAmount = CASE
WHEN Amount.DocCurrencyCode = 'TRY' THEN Amount.DocNetAmount
WHEN CurRate.Rate > 0 THEN Amount.DocNetAmount * CurRate.Rate
WHEN ISNULL(I.Loc_ExchangeRate, 0) > 0 THEN Amount.DocNetAmount * I.Loc_ExchangeRate
ELSE 0
END,
USDAmount = CASE
WHEN Amount.DocCurrencyCode = 'USD' THEN Amount.DocNetAmount
WHEN Amount.DocCurrencyCode = 'TRY' AND UsdRate.Rate > 0 THEN Amount.DocNetAmount / UsdRate.Rate
WHEN CurRate.Rate > 0 AND UsdRate.Rate > 0 THEN (Amount.DocNetAmount * CurRate.Rate) / UsdRate.Rate
WHEN ISNULL(I.Loc_ExchangeRate, 0) > 0 AND UsdRate.Rate > 0 THEN (Amount.DocNetAmount * I.Loc_ExchangeRate) / UsdRate.Rate
ELSE 0
END,
RN = ROW_NUMBER() OVER (
PARTITION BY I.InvoiceLineID
ORDER BY I.InvoiceDate DESC, I.InvoiceNumber
)
FROM AllInvoicesWithAttributes I WITH(NOLOCK)
LEFT OUTER JOIN CustomerAttributesFilter CAF WITH(NOLOCK)
ON CAF.CurrAccTypeCode = I.CurrAccTypeCode
AND CAF.CurrAccCode = I.CurrAccCode
LEFT OUTER JOIN ProductAttributesFilter PAF WITH(NOLOCK)
ON PAF.ItemCode = I.ItemCode
LEFT OUTER JOIN dbo.trInvoiceLineCurrency ILC WITH(NOLOCK)
ON ILC.InvoiceLineID = I.InvoiceLineID
AND UPPER(LTRIM(RTRIM(ILC.CurrencyCode))) = UPPER(LTRIM(RTRIM(ISNULL(NULLIF(LTRIM(RTRIM(I.Doc_CurrencyCode)), ''), 'TRY'))))
OUTER APPLY (
SELECT
DocCurrencyCode = UPPER(LTRIM(RTRIM(ISNULL(NULLIF(LTRIM(RTRIM(I.Doc_CurrencyCode)), ''), ISNULL(NULLIF(LTRIM(RTRIM(ILC.CurrencyCode)), ''), 'TRY'))))),
DocNetAmount = COALESCE(
NULLIF(ISNULL(ILC.NetAmount, 0), 0),
NULLIF(ISNULL(I.Doc_Amount, 0), 0),
NULLIF(ISNULL(I.Doc_Price, 0) * ISNULL(I.Qty1, 0), 0),
0
)
) Amount
OUTER APPLY (
SELECT TOP 1 Rate
FROM AllExchangeRates WITH(NOLOCK)
WHERE CurrencyCode = 'USD'
AND RelationCurrencyCode = 'TRY'
AND ExchangeTypeCode = 6
AND Rate > 0
AND Date <= CAST(I.InvoiceDate AS date)
ORDER BY Date DESC
) UsdRate
OUTER APPLY (
SELECT TOP 1 Rate
FROM AllExchangeRates WITH(NOLOCK)
WHERE CurrencyCode = Amount.DocCurrencyCode
AND RelationCurrencyCode = 'TRY'
AND ExchangeTypeCode = 6
AND Rate > 0
AND Date <= CAST(I.InvoiceDate AS date)
ORDER BY Date DESC
) CurRate
WHERE I.InvoiceDate >= @p1
AND I.InvoiceDate < DATEADD(DAY, 1, @p2)
AND I.ItemTypeCode = 1
AND LEN(LTRIM(RTRIM(I.ItemCode))) = 13
AND (@p3 = '' OR UPPER(LTRIM(RTRIM(I.ItemCode))) LIKE @p3 + '%')
AND (
(I.CompanyCode = 1 AND I.ATAtt01 IN (1,2) AND I.ProcessCode IN ('WS','R'))
OR (I.CompanyCode = 4 AND I.ProcessCode = 'R')
)
AND EXISTS (
SELECT 1
FROM trDebitHeader DH WITH(NOLOCK)
INNER JOIN trDebitLine DL WITH(NOLOCK)
ON DL.DebitHeaderID = DH.DebitHeaderID
WHERE DH.ApplicationCode = 'Invoi'
AND DH.ApplicationID = I.InvoiceHeaderID
)
)
SELECT
SalesDate,
ProductCode,
ColorCode,
YakaKodu,
ItemDescription = MAX(ItemDescription),
Kategori = MAX(Kategori),
Seri = '',
YasGrubu = '',
AskiliYan = ISNULL(NULLIF(MAX(AskiliYan), '-'), ''),
UrunIlkGrubu = MAX(UrunIlkGrubu),
UrunAnaGrubu = MAX(UrunAnaGrubu),
UrunAltGrubu = MAX(UrunAltGrubu),
MarketKey = CONCAT(MAX(Kategori), '|', MAX(UrunIlkGrubu), '|', ISNULL(NULLIF(MAX(AskiliYan), '-'), ''), '|', MAX(UrunAnaGrubu), '|', MAX(UrunAltGrubu), '|', ChannelCode),
ChannelCode,
CustomerCountry = ISNULL(NULLIF(CustomerCountry, ''), '-'),
CustomerSegment = ISNULL(NULLIF(CustomerSegment, ''), '-'),
CustomerCode = ISNULL(NULLIF(CustomerCode, ''), '-'),
CustomerDescription = MAX(ISNULL(NULLIF(CustomerDescription, ''), '-')),
SalesQty = ISNULL(SUM(Qty1), 0),
SalesTL = ISNULL(SUM(TLAmount), 0),
SalesUSD = ISNULL(SUM(USDAmount), 0),
AvgPriceUSD = ISNULL(SUM(USDAmount) / NULLIF(SUM(Qty1), 0), 0),
InvoiceLineCount = COUNT(DISTINCT InvoiceLineID),
InvoiceCount = COUNT(DISTINCT InvoiceHeaderID),
CustomerCount = COUNT(DISTINCT CustomerCode),
LastRefNumber = MAX(InvoiceNumber)
FROM SalesLines
WHERE RN = 1
GROUP BY SalesDate, ProductCode, ColorCode, YakaKodu, ChannelCode, CustomerCountry, CustomerSegment, CustomerCode
`
}
func productPerformanceStockSQLUnused() string {
return `
;WITH ActiveWarehouses AS (
SELECT WarehouseCode
FROM (VALUES
('1-0-12'),('1.01.2014'),('1.02.2005'),('1.02.2004'),('1-0-43'),
('4.02.2001'),('1-0-55'),('1.01.2003'),('1-0-21'),('1-0-2'),
('1.01.2004'),('1-0-49'),('1-0-37'),('1-0-29'),('1-0-28'),
('1-0-10'),('100'),('1.02.2006'),('1-0-42'),('1.01.2002'),
('1-0-52')
) W(WarehouseCode)
),
Raw AS (
SELECT
ProductCode = UPPER(LTRIM(RTRIM(S.ItemCode))),
ColorCode = UPPER(LTRIM(RTRIM(ISNULL(S.ColorCode, '')))),
YakaKodu = UPPER(LTRIM(RTRIM(ISNULL(S.ItemDim2Code, '')))),
MovementDate = CAST(S.DocumentDate AS date),
ProcessCode = CASE
WHEN LTRIM(RTRIM(ISNULL(S.ProcessCode, ''))) <> '' THEN LTRIM(RTRIM(S.ProcessCode))
ELSE LTRIM(RTRIM(ISNULL(S.InnerProcessCode, '')))
END,
InQty = SUM(S.In_Qty1),
OutQty = SUM(S.Out_Qty1),
NetQty = SUM(S.InventoryQty1)
FROM StockWithCost S WITH(NOLOCK)
INNER JOIN ActiveWarehouses W
ON W.WarehouseCode = LTRIM(RTRIM(S.WarehouseCode))
WHERE S.ItemTypeCode = 1
AND LEN(LTRIM(RTRIM(S.ItemCode))) = 13
AND (@p3 = '' OR UPPER(LTRIM(RTRIM(S.ItemCode))) LIKE @p3 + '%')
AND S.DocumentDate < DATEADD(DAY, 1, @p2)
GROUP BY
S.ItemCode,
S.ColorCode,
S.ItemDim2Code,
CAST(S.DocumentDate AS date),
CASE
WHEN LTRIM(RTRIM(ISNULL(S.ProcessCode, ''))) <> '' THEN LTRIM(RTRIM(S.ProcessCode))
ELSE LTRIM(RTRIM(ISNULL(S.InnerProcessCode, '')))
END
),
Opening AS (
SELECT
StockDate = @p1,
ProductCode,
ColorCode,
YakaKodu,
NetQty = SUM(NetQty),
InQty = CAST(0 AS decimal(18,4)),
OutQty = CAST(0 AS decimal(18,4)),
KpiInQty = CAST(0 AS decimal(18,4)),
KpiOutQty = CAST(0 AS decimal(18,4)),
SalesMovementQty = CAST(0 AS decimal(18,4)),
ProductionInQty = CAST(0 AS decimal(18,4)),
PurchaseInQty = CAST(0 AS decimal(18,4)),
ConsumptionOutQty = CAST(0 AS decimal(18,4)),
CountDiffQty = CAST(0 AS decimal(18,4))
FROM Raw
WHERE MovementDate < @p1
GROUP BY ProductCode, ColorCode, YakaKodu
),
Daily AS (
SELECT
StockDate = MovementDate,
ProductCode,
ColorCode,
YakaKodu,
NetQty = SUM(NetQty),
InQty = SUM(InQty),
OutQty = SUM(OutQty),
KpiInQty = SUM(CASE WHEN ProcessCode IN ('OP','BP','CI') THEN InQty ELSE 0 END),
KpiOutQty = SUM(CASE WHEN ProcessCode IN ('R','WS','OC','CO') THEN OutQty ELSE 0 END),
SalesMovementQty = SUM(CASE WHEN ProcessCode IN ('R','WS') THEN OutQty ELSE 0 END),
ProductionInQty = SUM(CASE WHEN ProcessCode = 'OP' THEN InQty ELSE 0 END),
PurchaseInQty = SUM(CASE WHEN ProcessCode = 'BP' THEN InQty ELSE 0 END),
ConsumptionOutQty = SUM(CASE WHEN ProcessCode = 'OC' THEN OutQty ELSE 0 END),
CountDiffQty = SUM(CASE WHEN ProcessCode IN ('CO','CI') THEN NetQty ELSE 0 END)
FROM Raw
WHERE MovementDate BETWEEN @p1 AND @p2
GROUP BY MovementDate, ProductCode, ColorCode, YakaKodu
),
Series AS (
SELECT * FROM Opening
UNION ALL
SELECT * FROM Daily
),
Collapsed AS (
SELECT
StockDate,
ProductCode,
ColorCode,
YakaKodu,
NetQty = SUM(NetQty),
InQty = SUM(InQty),
OutQty = SUM(OutQty),
KpiInQty = SUM(KpiInQty),
KpiOutQty = SUM(KpiOutQty),
SalesMovementQty = SUM(SalesMovementQty),
ProductionInQty = SUM(ProductionInQty),
PurchaseInQty = SUM(PurchaseInQty),
ConsumptionOutQty = SUM(ConsumptionOutQty),
CountDiffQty = SUM(CountDiffQty)
FROM Series
GROUP BY StockDate, ProductCode, ColorCode, YakaKodu
),
Running AS (
SELECT
StockDate,
ProductCode,
ColorCode,
YakaKodu,
StockQty = SUM(NetQty) OVER (
PARTITION BY ProductCode, ColorCode, YakaKodu
ORDER BY StockDate
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
),
InQty,
OutQty,
KpiInQty,
KpiOutQty,
SalesMovementQty,
ProductionInQty,
PurchaseInQty,
ConsumptionOutQty,
CountDiffQty
FROM Collapsed
)
SELECT
StockDate,
ProductCode,
ColorCode,
YakaKodu,
StockQty,
InQty,
OutQty,
KpiInQty,
KpiOutQty,
SalesMovementQty,
ProductionInQty,
PurchaseInQty,
ConsumptionOutQty,
CountDiffQty
FROM Running
WHERE StockDate BETWEEN @p1 AND @p2
ORDER BY StockDate, ProductCode, ColorCode, YakaKodu
`
}
func productPerformancePriceSQL() string {
return `
;WITH ProductCodes AS (
SELECT DISTINCT ItemCode
FROM cdItem WITH(NOLOCK)
WHERE ItemTypeCode = 1
AND LEN(LTRIM(RTRIM(ItemCode))) = 13
AND (@p1 = '' OR UPPER(LTRIM(RTRIM(ItemCode))) LIKE @p1 + '%')
UNION
SELECT DISTINCT ItemCode
FROM trPriceListLine WITH(NOLOCK)
WHERE ItemTypeCode = 1
AND LEN(LTRIM(RTRIM(ItemCode))) = 13
AND (@p1 = '' OR UPPER(LTRIM(RTRIM(ItemCode))) LIKE @p1 + '%')
UNION
SELECT DISTINCT ItemCode
FROM prItemBasePrice WITH(NOLOCK)
WHERE ItemTypeCode = 1
AND LEN(LTRIM(RTRIM(ItemCode))) = 13
AND (@p1 = '' OR UPPER(LTRIM(RTRIM(ItemCode))) LIKE @p1 + '%')
),
LatestPrice AS (
SELECT
p.ItemCode,
DocCurrencyCode = LTRIM(RTRIM(p.DocCurrencyCode)),
p.Price,
rn = ROW_NUMBER() OVER (
PARTITION BY p.ItemCode, LTRIM(RTRIM(p.DocCurrencyCode))
ORDER BY p.ValidDate DESC, p.ValidTime DESC, p.LastUpdatedDate DESC
)
FROM trPriceListLine p WITH(NOLOCK)
INNER JOIN ProductCodes pc ON pc.ItemCode = p.ItemCode
WHERE p.ItemTypeCode = 1
AND ISNULL(p.IsDisabled, 0) = 0
AND LTRIM(RTRIM(p.DocCurrencyCode)) IN ('USD', 'TRY')
AND (
(LTRIM(RTRIM(p.DocCurrencyCode)) = 'USD' AND LTRIM(RTRIM(p.PriceGroupCode)) = 'TM-USD')
OR (LTRIM(RTRIM(p.DocCurrencyCode)) = 'TRY' AND LTRIM(RTRIM(p.PriceGroupCode)) = 'TM-TRY')
)
AND p.Price > 0
),
BasePrice AS (
SELECT
ItemCode,
BasePriceUsd = MAX(CASE WHEN DocCurrencyCode = 'USD' THEN Price END),
BasePriceTry = MAX(CASE WHEN DocCurrencyCode = 'TRY' THEN Price END)
FROM LatestPrice
WHERE rn = 1
GROUP BY ItemCode
),
Cost AS (
SELECT
b.ItemCode,
CostPriceUsd = CAST(b.Price AS decimal(18,2)),
LastPricingDate = CAST(b.PriceDate AS date),
rn = ROW_NUMBER() OVER (
PARTITION BY b.ItemCode
ORDER BY b.PriceDate DESC, b.LastUpdatedDate DESC
)
FROM prItemBasePrice b WITH(NOLOCK)
INNER JOIN ProductCodes pc ON pc.ItemCode = b.ItemCode
WHERE b.ItemTypeCode = 1
AND b.BasePriceCode = 1
AND LTRIM(RTRIM(b.CurrencyCode)) = 'USD'
)
SELECT
UPPER(LTRIM(RTRIM(pc.ItemCode))) AS ItemCode,
ItemDescription = dbo.HG_Temizlik(ISNULL((
SELECT ItemDescription
FROM cdItemDesc WITH(NOLOCK)
WHERE cdItemDesc.ItemTypeCode = 1
AND cdItemDesc.ItemCode = pc.ItemCode
AND cdItemDesc.LangCode = 'TR'
), SPACE(0))),
Kategori = dbo.HG_Temizlik(ISNULL(paf.ProductAtt44, SPACE(0))),
AskiliYan = dbo.HG_Temizlik(ISNULL(paf.ProductAtt45, SPACE(0))),
UrunIlkGrubu = dbo.HG_Temizlik(ISNULL(paf.ProductAtt42, SPACE(0))),
UrunAnaGrubu = dbo.HG_Temizlik(ISNULL(paf.ProductAtt01, SPACE(0))),
UrunAltGrubu = dbo.HG_Temizlik(ISNULL(paf.ProductAtt02, SPACE(0))),
CostPriceUsd = ISNULL(c.CostPriceUsd, 0),
BasePriceUsd = ISNULL(bp.BasePriceUsd, 0),
BasePriceTry = ISNULL(bp.BasePriceTry, 0),
c.LastPricingDate
FROM ProductCodes pc
LEFT JOIN ProductAttributesFilter paf WITH(NOLOCK)
ON paf.ItemCode = pc.ItemCode
LEFT JOIN BasePrice bp ON bp.ItemCode = pc.ItemCode
LEFT JOIN Cost c ON c.ItemCode = pc.ItemCode AND c.rn = 1
`
}
func productPerformanceKPISQL() string {
return `
WITH LatestStock AS (
SELECT DISTINCT ON (product_code, color_code, yaka_kodu)
product_code, color_code, yaka_kodu, stock_qty
FROM mk_product_performance_stock_daily
WHERE stock_date <= $1
ORDER BY product_code, color_code, yaka_kodu, stock_date DESC
),
Stock90Start AS (
SELECT DISTINCT ON (product_code, color_code, yaka_kodu)
product_code, color_code, yaka_kodu, stock_qty
FROM mk_product_performance_stock_daily
WHERE stock_date <= $1::date - INTERVAL '89 days'
ORDER BY product_code, color_code, yaka_kodu, stock_date DESC
),
Stock180Start AS (
SELECT DISTINCT ON (product_code, color_code, yaka_kodu)
product_code, color_code, yaka_kodu, stock_qty
FROM mk_product_performance_stock_daily
WHERE stock_date <= $1::date - INTERVAL '179 days'
ORDER BY product_code, color_code, yaka_kodu, stock_date DESC
),
Stock365Start AS (
SELECT DISTINCT ON (product_code, color_code, yaka_kodu)
product_code, color_code, yaka_kodu, stock_qty
FROM mk_product_performance_stock_daily
WHERE stock_date <= $1::date - INTERVAL '359 days'
ORDER BY product_code, color_code, yaka_kodu, stock_date DESC
),
StockTotalStart AS (
SELECT DISTINCT ON (product_code, color_code, yaka_kodu)
product_code, color_code, yaka_kodu, stock_qty
FROM mk_product_performance_stock_daily
WHERE stock_date <= DATE '2022-01-01'
ORDER BY product_code, color_code, yaka_kodu, stock_date DESC
),
SalesAgg AS (
SELECT
product_code,
color_code,
yaka_kodu,
market_key,
MAX(item_description) AS item_description,
MAX(kategori) AS kategori,
MAX(seri) AS seri,
MAX(yas_grubu) AS yas_grubu,
COALESCE(MAX(NULLIF(askili_yan, '-')), '') AS askili_yan,
MAX(urun_ilk_grubu) AS urun_ilk_grubu,
MAX(urun_ana_grubu) AS urun_ana_grubu,
MAX(urun_alt_grubu) AS urun_alt_grubu,
SUM(sales_qty) FILTER (WHERE sales_date >= $1::date - INTERVAL '29 days') AS sales_qty_30d,
SUM(sales_qty) FILTER (WHERE sales_date >= $1::date - INTERVAL '89 days') AS sales_qty_90d,
SUM(sales_qty) FILTER (WHERE sales_date >= $1::date - INTERVAL '179 days') AS sales_qty_180d,
SUM(sales_qty) FILTER (WHERE sales_date >= $1::date - INTERVAL '359 days') AS sales_qty_365d,
SUM(sales_qty) FILTER (WHERE sales_date >= $1::date - INTERVAL '729 days') AS sales_qty_730d,
SUM(sales_qty) FILTER (WHERE sales_date >= DATE '2022-01-01') AS sales_qty_total,
SUM(sales_usd) FILTER (WHERE sales_date >= $1::date - INTERVAL '29 days') AS sales_usd_30d,
SUM(sales_usd) FILTER (WHERE sales_date >= $1::date - INTERVAL '89 days') AS sales_usd_90d,
SUM(sales_usd) FILTER (WHERE sales_date >= $1::date - INTERVAL '179 days') AS sales_usd_180d,
SUM(sales_usd) FILTER (WHERE sales_date >= $1::date - INTERVAL '359 days') AS sales_usd_365d,
SUM(sales_usd) FILTER (WHERE sales_date >= DATE '2022-01-01') AS sales_usd_total,
COUNT(DISTINCT NULLIF(customer_code, '-')) FILTER (WHERE sales_date >= $1::date - INTERVAL '89 days' AND COALESCE(sales_usd, 0) > 0) AS customer_count_90d,
MAX(sales_date) AS last_sale_date,
MAX(last_ref_number) AS last_ref_number
FROM mk_product_performance_sales_daily
WHERE sales_date >= DATE '2022-01-01'
AND sales_date <= $1::date
AND upper(translate(btrim(COALESCE(urun_ilk_grubu,'')), U&'\0130\015E\011E\00DC\00D6\00C7\0131\015F\011F\00FC\00F6\00E7', 'ISGUOCisguoc')) NOT IN ('MALZEMELI FASON', 'MALZEMESIZ FASON', 'MAZLEMELI FASON', 'MAZEMESIZ FASON', 'DIGER')
GROUP BY product_code, color_code, yaka_kodu, market_key
),
Scope AS (
SELECT
product_code, color_code, yaka_kodu, market_key,
item_description, kategori, seri, yas_grubu, askili_yan, urun_ilk_grubu, urun_ana_grubu, urun_alt_grubu,
sales_qty_30d, sales_qty_90d, sales_qty_180d, sales_qty_365d, sales_qty_730d, sales_qty_total,
sales_usd_30d, sales_usd_90d, sales_usd_180d, sales_usd_365d, sales_usd_total,
customer_count_90d, last_sale_date, last_ref_number
FROM SalesAgg
UNION ALL
SELECT
ls.product_code,
ls.color_code,
ls.yaka_kodu,
'STOK' AS market_key,
'' AS item_description,
'' AS kategori,
'' AS seri,
'' AS yas_grubu,
'' AS askili_yan,
COALESCE(pd.urun_ilk_grubu, '') AS urun_ilk_grubu,
'' AS urun_ana_grubu,
'' AS urun_alt_grubu,
0 AS sales_qty_30d,
0 AS sales_qty_90d,
0 AS sales_qty_180d,
0 AS sales_qty_365d,
0 AS sales_qty_730d,
0 AS sales_qty_total,
0 AS sales_usd_30d,
0 AS sales_usd_90d,
0 AS sales_usd_180d,
0 AS sales_usd_365d,
0 AS sales_usd_total,
0 AS customer_count_90d,
NULL::date AS last_sale_date,
'' AS last_ref_number
FROM LatestStock ls
LEFT JOIN mk_product_performance_price_dim pd ON pd.product_code=ls.product_code
WHERE COALESCE(ls.stock_qty, 0) <> 0
AND upper(translate(btrim(COALESCE(pd.urun_ilk_grubu,'')), U&'\0130\015E\011E\00DC\00D6\00C7\0131\015F\011F\00FC\00F6\00E7', 'ISGUOCisguoc')) NOT IN ('MALZEMELI FASON', 'MALZEMESIZ FASON', 'MAZLEMELI FASON', 'MAZEMESIZ FASON', 'DIGER')
AND NOT EXISTS (
SELECT 1
FROM SalesAgg sa
WHERE sa.product_code = ls.product_code
AND sa.color_code = ls.color_code
AND sa.yaka_kodu = ls.yaka_kodu
)
),
PriceDim AS (
SELECT
product_code,
COALESCE(urun_ilk_grubu, '') AS urun_ilk_grubu,
COALESCE(urun_ana_grubu, '') AS urun_ana_grubu,
COALESCE(urun_alt_grubu, '') AS urun_alt_grubu,
CASE
WHEN cost_price_usd > 0 AND base_price_usd > 0 AND cost_price_usd < base_price_usd THEN base_price_usd
ELSE cost_price_usd
END AS cost_price_usd,
CASE
WHEN cost_price_usd > 0 AND base_price_usd > 0 AND cost_price_usd < base_price_usd THEN cost_price_usd
ELSE base_price_usd
END AS base_price_usd,
base_price_try
FROM mk_product_performance_price_dim
),
Base AS (
SELECT
s.*,
COALESCE(ls.stock_qty, 0) AS stock_qty,
COALESCE(pd.cost_price_usd, 0) AS cost_price_usd,
COALESCE(pd.base_price_usd, 0) AS base_price_usd,
COALESCE(pd.base_price_try, 0) AS base_price_try,
COALESCE(s.sales_qty_90d, 0) / 90.0 AS avg_daily_sales_90d,
COALESCE(s.sales_qty_180d, 0) / 180.0 AS avg_daily_sales_180d,
COALESCE(s.sales_qty_365d, 0) / 360.0 AS avg_daily_sales_365d,
COALESCE(s.sales_qty_total, 0) / GREATEST(1, ($1::date - DATE '2022-01-01') + 1) AS avg_daily_sales_total,
(COALESCE(s90.stock_qty, 0) + COALESCE(ls.stock_qty, 0)) / 2.0 AS avg_stock_90d,
(COALESCE(s180.stock_qty, 0) + COALESCE(ls.stock_qty, 0)) / 2.0 AS avg_stock_180d,
(COALESCE(s365.stock_qty, 0) + COALESCE(ls.stock_qty, 0)) / 2.0 AS avg_stock_365d,
(COALESCE(stotal.stock_qty, 0) + COALESCE(ls.stock_qty, 0)) / 2.0 AS avg_stock_total,
CASE WHEN COALESCE(s.sales_qty_90d, 0) = 0 THEN 0 ELSE COALESCE(s.sales_usd_90d, 0) / NULLIF(s.sales_qty_90d, 0) END AS avg_price_usd_90d,
CASE WHEN COALESCE(s.sales_qty_180d, 0) = 0 THEN 0 ELSE COALESCE(s.sales_usd_180d, 0) / NULLIF(s.sales_qty_180d, 0) END AS avg_price_usd_180d,
COALESCE(s.sales_usd_90d, 0) - (COALESCE(s.sales_qty_90d, 0) * COALESCE(pd.cost_price_usd, 0)) AS gross_profit_usd_90d,
COALESCE(s.sales_usd_180d, 0) - (COALESCE(s.sales_qty_180d, 0) * COALESCE(pd.cost_price_usd, 0)) AS gross_profit_usd_180d,
CASE WHEN COALESCE(s.sales_usd_90d, 0) = 0 THEN 0
ELSE (COALESCE(s.sales_usd_90d, 0) - (COALESCE(s.sales_qty_90d, 0) * COALESCE(pd.cost_price_usd, 0))) / NULLIF(s.sales_usd_90d, 0)
END AS gross_margin_90d,
CASE WHEN COALESCE(s.sales_usd_180d, 0) = 0 THEN 0
ELSE (COALESCE(s.sales_usd_180d, 0) - (COALESCE(s.sales_qty_180d, 0) * COALESCE(pd.cost_price_usd, 0))) / NULLIF(s.sales_usd_180d, 0)
END AS gross_margin_180d,
CASE WHEN COALESCE(s.sales_qty_90d, 0) = 0 THEN 0 ELSE (COALESCE(s.sales_usd_90d, 0) / NULLIF(s.sales_qty_90d, 0)) - COALESCE(pd.cost_price_usd, 0) END AS unit_profit_cost_90d,
CASE WHEN COALESCE(s.sales_qty_180d, 0) = 0 THEN 0 ELSE (COALESCE(s.sales_usd_180d, 0) / NULLIF(s.sales_qty_180d, 0)) - COALESCE(pd.cost_price_usd, 0) END AS unit_profit_cost_180d,
CASE WHEN COALESCE(s.sales_qty_90d, 0) = 0 THEN 0 ELSE (COALESCE(s.sales_usd_90d, 0) / NULLIF(s.sales_qty_90d, 0)) - COALESCE(pd.base_price_usd, 0) END AS unit_profit_base_90d,
CASE WHEN COALESCE(s.sales_qty_180d, 0) = 0 THEN 0 ELSE (COALESCE(s.sales_usd_180d, 0) / NULLIF(s.sales_qty_180d, 0)) - COALESCE(pd.base_price_usd, 0) END AS unit_profit_base_180d
FROM Scope s
LEFT JOIN LatestStock ls ON ls.product_code=s.product_code AND ls.color_code=s.color_code AND ls.yaka_kodu=s.yaka_kodu
LEFT JOIN Stock90Start s90 ON s90.product_code=s.product_code AND s90.color_code=s.color_code AND s90.yaka_kodu=s.yaka_kodu
LEFT JOIN Stock180Start s180 ON s180.product_code=s.product_code AND s180.color_code=s.color_code AND s180.yaka_kodu=s.yaka_kodu
LEFT JOIN Stock365Start s365 ON s365.product_code=s.product_code AND s365.color_code=s.color_code AND s365.yaka_kodu=s.yaka_kodu
LEFT JOIN StockTotalStart stotal ON stotal.product_code=s.product_code AND stotal.color_code=s.color_code AND stotal.yaka_kodu=s.yaka_kodu
LEFT JOIN PriceDim pd ON pd.product_code=s.product_code
WHERE upper(translate(btrim(COALESCE(NULLIF(s.urun_ilk_grubu,''), pd.urun_ilk_grubu, '')), U&'\0130\015E\011E\00DC\00D6\00C7\0131\015F\011F\00FC\00F6\00E7', 'ISGUOCisguoc')) NOT IN ('MALZEMELI FASON', 'MALZEMESIZ FASON', 'MAZLEMELI FASON', 'MAZEMESIZ FASON', 'DIGER')
),
Spread AS (
SELECT
product_code,
color_code,
yaka_kodu,
COUNT(DISTINCT NULLIF(NULLIF(market_key, 'STOK'), '')) AS market_count_90d
FROM SalesAgg
WHERE COALESCE(sales_usd_90d, 0) > 0
GROUP BY product_code, color_code, yaka_kodu
),
Market AS (
SELECT
market_key,
AVG(NULLIF(sales_qty_90d, 0)) AS market_avg_sales_qty_90d,
AVG(NULLIF(avg_price_usd_90d, 0)) AS market_avg_price_usd_90d,
AVG(NULLIF(gross_margin_90d, 0)) AS market_avg_margin_90d
FROM Base
GROUP BY market_key
),
Scored AS (
SELECT
b.*,
COALESCE(sp.market_count_90d, 0) AS market_count_90d,
CASE WHEN b.avg_daily_sales_90d = 0 THEN 0 ELSE b.avg_stock_90d / NULLIF(b.avg_daily_sales_90d, 0) END AS stock_days_90d,
CASE WHEN b.avg_daily_sales_180d = 0 THEN 0 ELSE b.avg_stock_180d / NULLIF(b.avg_daily_sales_180d, 0) END AS stock_days_180d,
CASE WHEN b.avg_daily_sales_365d = 0 THEN 0 ELSE b.avg_stock_365d / NULLIF(b.avg_daily_sales_365d, 0) END AS stock_days_365d,
CASE WHEN b.avg_daily_sales_total = 0 THEN 0 ELSE b.avg_stock_total / NULLIF(b.avg_daily_sales_total, 0) END AS stock_days_total,
CASE WHEN b.avg_stock_90d = 0 THEN 0 ELSE b.sales_qty_90d / NULLIF(b.avg_stock_90d, 0) END AS stock_turnover_90d,
CASE WHEN b.avg_stock_180d = 0 THEN 0 ELSE b.sales_qty_180d / NULLIF(b.avg_stock_180d, 0) END AS stock_turnover_180d,
CASE WHEN b.avg_stock_365d = 0 THEN 0 ELSE b.sales_qty_365d / NULLIF(b.avg_stock_365d, 0) END AS stock_turnover_365d,
CASE WHEN b.avg_stock_total = 0 THEN 0 ELSE b.sales_qty_total / NULLIF(b.avg_stock_total, 0) END AS stock_turnover_total,
CASE WHEN COALESCE(m.market_avg_sales_qty_90d, 0) = 0 THEN 0 ELSE b.sales_qty_90d / NULLIF(m.market_avg_sales_qty_90d, 0) END AS sales_index_90d,
CASE WHEN COALESCE(m.market_avg_price_usd_90d, 0) = 0 THEN 0 ELSE b.avg_price_usd_90d / NULLIF(m.market_avg_price_usd_90d, 0) END AS price_index_90d,
CASE WHEN COALESCE(m.market_avg_margin_90d, 0) = 0 THEN 0 ELSE b.gross_margin_90d / NULLIF(m.market_avg_margin_90d, 0) END AS margin_index_90d
FROM Base b
LEFT JOIN Market m ON m.market_key=b.market_key
LEFT JOIN Spread sp ON sp.product_code=b.product_code AND sp.color_code=b.color_code AND sp.yaka_kodu=b.yaka_kodu
)
INSERT INTO mk_product_performance_kpi_daily (
kpi_date, product_code, color_code, yaka_kodu, item_description,
kategori, seri, yas_grubu, askili_yan, urun_ilk_grubu, urun_ana_grubu, urun_alt_grubu, market_key, stock_qty,
sales_qty_30d, sales_qty_90d, sales_qty_180d, sales_qty_365d, sales_qty_730d, sales_qty_total,
sales_usd_30d, sales_usd_90d, sales_usd_180d, sales_usd_365d, sales_usd_total, avg_daily_sales_90d, avg_daily_sales_180d, avg_daily_sales_365d, avg_daily_sales_total,
stock_days_90d, stock_days_180d, stock_days_365d, stock_days_total, stock_turnover_90d, stock_turnover_180d, stock_turnover_365d, stock_turnover_total,
avg_price_usd_90d, avg_price_usd_180d, cost_price_usd, base_price_usd, base_price_try,
gross_profit_usd_90d, gross_profit_usd_180d, gross_margin_90d, gross_margin_180d,
unit_profit_cost_90d, unit_profit_cost_180d, unit_profit_base_90d, unit_profit_base_180d, market_count_90d, customer_count_90d,
sales_index_90d, price_index_90d, margin_index_90d, performance_score,
performance_bucket, recommendation, last_sale_date, last_ref_number, updated_at
)
SELECT
$1::date,
product_code, color_code, yaka_kodu, item_description,
kategori, seri, yas_grubu, askili_yan, urun_ilk_grubu, urun_ana_grubu, urun_alt_grubu, market_key, stock_qty,
COALESCE(sales_qty_30d, 0), COALESCE(sales_qty_90d, 0), COALESCE(sales_qty_180d, 0), COALESCE(sales_qty_365d, 0), COALESCE(sales_qty_730d, 0), COALESCE(sales_qty_total, 0),
COALESCE(sales_usd_30d, 0), COALESCE(sales_usd_90d, 0), COALESCE(sales_usd_180d, 0), COALESCE(sales_usd_365d, 0), COALESCE(sales_usd_total, 0), COALESCE(avg_daily_sales_90d, 0), COALESCE(avg_daily_sales_180d, 0), COALESCE(avg_daily_sales_365d, 0), COALESCE(avg_daily_sales_total, 0),
COALESCE(stock_days_90d, 0), COALESCE(stock_days_180d, 0), COALESCE(stock_days_365d, 0), COALESCE(stock_days_total, 0), COALESCE(stock_turnover_90d, 0), COALESCE(stock_turnover_180d, 0), COALESCE(stock_turnover_365d, 0), COALESCE(stock_turnover_total, 0),
COALESCE(avg_price_usd_90d, 0), COALESCE(avg_price_usd_180d, 0), COALESCE(cost_price_usd, 0), COALESCE(base_price_usd, 0), COALESCE(base_price_try, 0),
COALESCE(gross_profit_usd_90d, 0), COALESCE(gross_profit_usd_180d, 0), COALESCE(gross_margin_90d, 0), COALESCE(gross_margin_180d, 0),
COALESCE(unit_profit_cost_90d, 0), COALESCE(unit_profit_cost_180d, 0), COALESCE(unit_profit_base_90d, 0), COALESCE(unit_profit_base_180d, 0), COALESCE(market_count_90d, 0), COALESCE(customer_count_90d, 0),
COALESCE(sales_index_90d, 0), COALESCE(price_index_90d, 0), COALESCE(margin_index_90d, 0),
CASE WHEN COALESCE(sales_usd_90d, 0) <= 0 THEN 1 ELSE
ROUND(
LEAST(35, COALESCE(sales_index_90d, 0) * 18)
+ LEAST(25, GREATEST(COALESCE(gross_margin_90d, 0), 0) * 50)
+ LEAST(20, COALESCE(customer_count_90d, 0) * 2)
+ LEAST(10, COALESCE(market_count_90d, 0) * 3)
+ CASE WHEN COALESCE(stock_days_90d, 0) BETWEEN 10 AND 90 THEN 10 WHEN COALESCE(stock_days_90d, 0) > 180 THEN -10 ELSE 0 END
, 4)
END AS performance_score,
CASE
WHEN COALESCE(sales_index_90d,0) >= 1.25 AND COALESCE(gross_margin_90d,0) >= 0.25 THEN 'YILDIZ_URUN'
WHEN COALESCE(stock_qty,0) <= 0 AND COALESCE(sales_qty_90d,0) > 0 THEN 'STOKSUZ_TALEP'
WHEN COALESCE(stock_days_90d,0) > 180 AND COALESCE(sales_index_90d,0) < 0.75 THEN 'STOK_RISKI'
WHEN COALESCE(price_index_90d,0) > 1.10 AND COALESCE(sales_index_90d,0) < 0.80 THEN 'FIYAT_BASKISI'
WHEN COALESCE(price_index_90d,0) < 0.90 AND COALESCE(sales_index_90d,0) > 1.00 THEN 'FIYAT_FIRSATI'
ELSE 'TAKIP'
END AS performance_bucket,
CASE
WHEN COALESCE(sales_index_90d,0) >= 1.25 AND COALESCE(gross_margin_90d,0) >= 0.25 THEN 'Piyasa ustu satis ve iyi marj: stok ve fiyat gucu takip edilmeli.'
WHEN COALESCE(stock_qty,0) <= 0 AND COALESCE(sales_qty_90d,0) > 0 THEN 'Talep var, stok yok: uretim/satin alma planina alinmali.'
WHEN COALESCE(stock_days_90d,0) > 180 AND COALESCE(sales_index_90d,0) < 0.75 THEN 'Stok yuksek, satis piyasa alti: kampanya veya fiyat kontrolu gerekli.'
WHEN COALESCE(price_index_90d,0) > 1.10 AND COALESCE(sales_index_90d,0) < 0.80 THEN 'Fiyat piyasa ustunde ve satis zayif: fiyat revizyonu degerlendirilmeli.'
WHEN COALESCE(price_index_90d,0) < 0.90 AND COALESCE(sales_index_90d,0) > 1.00 THEN 'Satis guclu, fiyat piyasa alti: taban fiyat artisi degerlendirilebilir.'
ELSE 'Duzenli takip.'
END AS recommendation,
last_sale_date,
COALESCE(last_ref_number, ''),
now()
FROM Scored
`
}