654 lines
31 KiB
Go
654 lines
31 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 = ISNULL(I.Doc_Amount, 0) * ISNULL(I.Loc_ExchangeRate, 0),
|
|
USDAmount = (ISNULL(I.Doc_Amount, 0) * ISNULL(I.Loc_ExchangeRate, 0)) / ISNULL((
|
|
SELECT TOP 1 Rate
|
|
FROM AllExchangeRates WITH(NOLOCK)
|
|
WHERE CurrencyCode = 'USD'
|
|
AND RelationCurrencyCode = 'TRY'
|
|
AND ExchangeTypeCode = 6
|
|
AND Rate > 1
|
|
ORDER BY ABS(DATEDIFF(DAY, AllExchangeRates.Date, I.InvoiceDate)) ASC
|
|
), 1),
|
|
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
|
|
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') 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 market_key) AS market_count_90d
|
|
FROM SalesAgg
|
|
WHERE COALESCE(sales_qty_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),
|
|
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) 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
|
|
`
|
|
}
|