Stock vs Pending Plan Report Proposal (Refined Parameter & Issue-Line Flow)
This document outlines the detailed database query logic and report design for the Item & Parameter Wise Stock vs Pending Production Plan report.
1. Practical Multi-Plan Example (Different Issue Widths)
Scenario:
Suppose there are 2 Production Plans (PLAN-001 and PLAN-002) created with different issue widths:
Plan 1 (PLAN-001):
- Raw Material Issue Line (
MovementType = 'I'):- Quantity: 2500 kg
- Issue Width: 200mm (Item =
CRGO Coil, Grade =M4, Coating =C3, WattLoss =0.97, AirGap =0.05)
- Finished Receipts Lines (
MovementType = 'R') (Total Receipt Width = $150 + 50 = \mathbf{200\text{mm}}$, matching Issue Width):- Receipt 1 (
PlanTrnId: P000101): 1500 kg (Cut width: 150mm) - Receipt 2 (
PlanTrnId: P000102): 1000 kg (Cut width: 50mm)
- Receipt 1 (
- Actual Production Linkage (
LinkPlanToPrdn):- Receipt 1 (
P000101): 1400 kg linked $\rightarrow$ 100 kg Pending ($1500 - 1400$) - Receipt 2 (
P000102): 700 kg linked $\rightarrow$ 300 kg Pending ($1000 - 700$)
- Receipt 1 (
- Total Pending Qty for
PLAN-001(Width 200mm): $100 + 300 = \mathbf{400\text{ kg}}$.
Plan 2 (PLAN-002):
- Raw Material Issue Line (
MovementType = 'I'):- Quantity: 1800 kg
- Issue Width: 300mm (Item =
CRGO Coil, Grade =M4, Coating =C3, WattLoss =0.97, AirGap =0.05)
- Finished Receipts Lines (
MovementType = 'R') (Total Receipt Width = $200 + 100 = \mathbf{300\text{mm}}$, matching Issue Width):- Receipt 1 (
PlanTrnId: P000201): 1200 kg (Cut width: 200mm) - Receipt 2 (
PlanTrnId: P000202): 600 kg (Cut width: 100mm)
- Receipt 1 (
- Actual Production Linkage (
LinkPlanToPrdn):- Receipt 1 (
P000201): 1000 kg linked $\rightarrow$ 200 kg Pending ($1200 - 1000$) - Receipt 2 (
P000202): 450 kg linked $\rightarrow$ 150 kg Pending ($600 - 450$)
- Receipt 1 (
- Total Pending Qty for
PLAN-002(Width 300mm): $200 + 150 = \mathbf{350\text{ kg}}$.
Step-by-Step Computation Flow:
- Line-Level Pending (
PlanTrnId):P000101: 100 kg |P000102: 300 kgP000201: 200 kg |P000202: 150 kg
YearPlanNoLevel Aggregation (Grouped strictly byYearPlanNo):- Pending for
PLAN-001= $100 + 300 = 400\text{ kg}$ - Pending for
PLAN-002= $200 + 150 = 350\text{ kg}$
- Pending for
- Issue Line Attribute Binding (
MovementType = 'I'):PLAN-001: Item =CRGO Coil, Grade =M4, Width = 200mmPLAN-002: Item =CRGO Coil, Grade =M4, Width = 300mm
- Parameter-Level Aggregation & Plan Remark:
- Group by
(ItemId, GradeId, WidthId, CoatingId, WattLossId, AirGapId). - Since
PLAN-001(Width 200mm) andPLAN-002(Width 300mm) have different widths, they form two distinct rows in the parameter report. - If another plan (
PLAN-003) is created with Width 200mm and $150\text{ kg}$ pending, it will aggregate withPLAN-001to total $550\text{ kg}$ ($400 + 150$) and displayPLAN-001, PLAN-003in the remark column.
- Group by
2. Refined T-SQL Query Logic
-- CTE 1: Physical Closing Stock per Item & All Parameters
WITH CTE_PhysicalStock AS (
SELECT
itemid,
COALESCE(gradeid, '000000') AS gradeid,
COALESCE(widthid, '000000') AS widthid,
COALESCE(coatingid, '000000') AS coatingid,
COALESCE(wattlossid, '000000') AS wattlossid,
COALESCE(airgapid, '000000') AS airgapid,
SUM(qty) AS BalanceStockQty,
SUM(qty1) AS BalanceStockNos
FROM #DprInventory -- Generated from physical inventory ledger
GROUP BY itemid, gradeid, widthid, coatingid, wattlossid, airgapid
),
-- CTE 2: All Active Receipt Lines (MovementType = 'R')
CTE_PlanReceipts AS (
SELECT
P1.PlanTrnId,
P1.YearPlanNo,
P1.Qty AS PlanQty,
P1.Qty1 AS PlanQty1
FROM PrdnPlan1 P1
INNER JOIN PrdnPlan P ON P1.YearPlanNo = P.YearPlanNo
WHERE P1.MovementType = 'R'
AND LEFT(P1.PlanTrnId, 1) != 'X' -- Exclude scrap
AND NOT EXISTS (SELECT 1 FROM DprShortClose SC WHERE SC.trnid = P1.PlanTrnId)
),
-- CTE 3: Calculate Pending Quantity per PlanTrnId
CTE_PlanTrnPending AS (
SELECT
R.PlanTrnId,
R.YearPlanNo,
(R.PlanQty - COALESCE(SUM(L.LinkedQty), 0)) AS PendingQty,
(R.PlanQty1 - COALESCE(SUM(L.LinkedQty1), 0)) AS PendingQty1
FROM CTE_PlanReceipts R
LEFT JOIN LinkPlanToPrdn L ON R.PlanTrnId = L.PlanTrnId
GROUP BY R.PlanTrnId, R.YearPlanNo, R.PlanQty, R.PlanQty1
),
-- CTE 4: Sum Pending Quantity grouped STRICTLY by YearPlanNo
CTE_YearPlanPending AS (
SELECT
YearPlanNo,
SUM(PendingQty) AS YearPlanPendingQty,
SUM(PendingQty1) AS YearPlanPendingQty1
FROM CTE_PlanTrnPending
GROUP BY YearPlanNo
HAVING SUM(PendingQty) > 0
),
-- CTE 5: Bind Issue Line ('I') Parameters & PlanNo to each YearPlanNo
CTE_PlanIssueHeader AS (
SELECT
YP.YearPlanNo,
P.PlanNo,
P1.ItemId,
COALESCE(P1.GradeId, '000000') AS GradeId,
COALESCE(P1.WidthId, '000000') AS WidthId,
COALESCE(P1.CoatingId, '000000') AS CoatingId,
COALESCE(P1.WattLossId, '000000') AS WattLossId,
COALESCE(P1.AirGapId, '000000') AS AirGapId,
YP.YearPlanPendingQty,
YP.YearPlanPendingQty1
FROM CTE_YearPlanPending YP
INNER JOIN PrdnPlan P ON YP.YearPlanNo = P.YearPlanNo
INNER JOIN PrdnPlan1 P1 ON YP.YearPlanNo = P1.YearPlanNo AND P1.MovementType = 'I'
),
-- CTE 6: Aggregate by Parameters and concatenate Plan Numbers into Remark using STRING_AGG
CTE_ParamPendingSummary AS (
SELECT
ItemId, GradeId, WidthId, CoatingId, WattLossId, AirGapId,
SUM(YearPlanPendingQty) AS TotalPendingPlanQty,
SUM(YearPlanPendingQty1) AS TotalPendingPlanNos,
STRING_AGG(RIGHT(PlanNo, 6), ', ') WITHIN GROUP (ORDER BY PlanNo) AS AssociatedPlans
FROM CTE_PlanIssueHeader
GROUP BY ItemId, GradeId, WidthId, CoatingId, WattLossId, AirGapId
)
-- Final SELECT: Combine Stock & Plan Pending quantities via FULL OUTER JOIN
SELECT
I.ItemName,
G.GradeName,
W.WidthName,
C.CoatingName,
WL.WattLossName,
AG.AirGapName,
COALESCE(S.BalanceStockQty, 0) AS BalanceStockQty,
COALESCE(S.BalanceStockNos, 0) AS BalanceStockNos,
COALESCE(P.TotalPendingPlanQty, 0) AS PendingPlanQty,
COALESCE(P.TotalPendingPlanNos, 0) AS PendingPlanNos,
(COALESCE(S.BalanceStockQty, 0) - COALESCE(P.TotalPendingPlanQty, 0)) AS NetAvailableQty,
COALESCE(P.AssociatedPlans, '') AS PendingPlanNoRemark
FROM CTE_PhysicalStock S
FULL OUTER JOIN CTE_ParamPendingSummary P
ON S.ItemId = P.ItemId
AND S.GradeId = P.GradeId
AND S.WidthId = P.WidthId
AND S.CoatingId = P.CoatingId
AND S.WattLossId = P.WattLossId
AND S.AirGapId = P.AirGapId
LEFT JOIN DprItem I ON COALESCE(S.ItemId, P.ItemId) = I.ItemId
LEFT JOIN DprGrade G ON COALESCE(S.GradeId, P.GradeId) = G.GradeId
LEFT JOIN DprWidth W ON COALESCE(S.WidthId, P.WidthId) = W.WidthId
LEFT JOIN DprCoating C ON COALESCE(S.CoatingId, P.CoatingId) = C.CoatingId
LEFT JOIN DprWattLoss WL ON COALESCE(S.WattLossId, P.WattLossId) = WL.WattLossId
LEFT JOIN DprAirGap AG ON COALESCE(S.AirGapId, P.AirGapId) = AG.AirGapId
ORDER BY I.ItemName, G.GradeName, W.WidthName;3. How it Reflects in the Report
In the exported Excel / UI table, each row represents a unique combination of Item + Grade + Issue Width + Coating + Watt Loss + Air Gap.
Sample Output Presentation:
| Item Name | Grade | Width | Coating | Watt Loss | Air Gap | Balance Stock (Kg) | Pending Plan Qty (Kg) | Net Available Stock (Kg) | Pending Plan Nos. Remark |
|---|---|---|---|---|---|---|---|---|---|
| CRGO Coil | M4 | 200 | C3 | 0.97 | 0.05 | 1200.000 | 400.000 | 800.000 | PLAN-001 |
| CRGO Coil | M4 | 300 | C3 | 0.97 | 0.05 | 800.000 | 350.000 | 450.000 | PLAN-002 |
| CRGO Sheet | M5 | 1200 | C5 | 1.10 | 0.00 | 500.000 | 850.000 | -350.000 | PLAN-003, PLAN-005 |
| HR Coil | Commercial | 900 | Plain | 0.00 | 0.00 | 3000.000 | 0.000 | 3000.000 |
Key Benefits:
- Per-Width Separation:
PLAN-001(Width 200mm) andPLAN-002(Width 300mm) form distinct parameter rows, clearly displaying the balance stock vs pending plan qty for each specific width. - Receipt Cut Width Alignment: Within each plan, receipt cut widths ($150 + 50 = 200\text{mm}$ for Plan 1; $200 + 100 = 300\text{mm}$ for Plan 2) sum to match the main Issue width.
- Automatic Aggregation: Plans sharing the exact same Issue parameters (e.g.
PLAN-003andPLAN-005) automatically group together, summing their pending quantities and concatenating plan numbers in the Pending Plan Nos. Remark column.