+ Every stock movement that ever happened — GRNs in, sales out, and returns — in one
+ ledger. Shows everything by default; use the filters to narrow it down.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setDateFrom(e.target.value)} />
+
+
+
+ setDateTo(e.target.value)} />
+
+
+ {hasActiveFilters && (
+
+ )}
+
+
+ `${row.type}-${row.productId}-${row.reference}-${row.date}-${row.amount}`}
+ emptyMessage={hasActiveFilters ? "No movements match these filters." : "No stock movements recorded yet."}
+ renderMobileCard={(row) => (
+
+ )}
+ />
+
+
+
+ Read-only — this tab is a combined view of the GRN, Sales and Returns tabs. To record a
+ new movement, use the relevant tab directly.
+
+
+ )
+}
+
+export { InventoryStockTrackingTab }
diff --git a/src/components/hexa/views/inventory-view.tsx b/src/components/hexa/views/inventory-view.tsx
index f4948fa..ab87120 100644
--- a/src/components/hexa/views/inventory-view.tsx
+++ b/src/components/hexa/views/inventory-view.tsx
@@ -4,6 +4,7 @@ import { InventoryGrnTab } from "@/components/hexa/views/inventory-grn-tab"
import { InventoryProductsTab } from "@/components/hexa/views/inventory-products-tab"
import { InventoryReturnsTab } from "@/components/hexa/views/inventory-returns-tab"
import { InventorySalesTab } from "@/components/hexa/views/inventory-sales-tab"
+import { InventoryStockTrackingTab } from "@/components/hexa/views/inventory-stock-tracking-tab"
import { InventorySuppliersTab } from "@/components/hexa/views/inventory-suppliers-tab"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
@@ -16,6 +17,7 @@ function InventoryView() {
GRNSalesReturns
+ Stock Tracking
@@ -33,6 +35,9 @@ function InventoryView() {
+
+
+
)
}
diff --git a/src/lib/api/inventory.ts b/src/lib/api/inventory.ts
index 1a3c96d..4c95141 100644
--- a/src/lib/api/inventory.ts
+++ b/src/lib/api/inventory.ts
@@ -8,6 +8,7 @@ import type {
ProductDetail,
ProductInput,
Sale,
+ StockMovement,
StockReturn,
Supplier,
SupplierInput,
@@ -79,6 +80,10 @@ function createStockReturn(input: CreateStockReturnInput) {
return apiRequest("client/inventory/returns", { method: "POST", body: input })
}
+function getStockMovements() {
+ return apiRequest("client/inventory/stock-movements")
+}
+
export {
getProducts,
getProduct,
@@ -96,4 +101,5 @@ export {
getStockReturns,
getStockReturn,
createStockReturn,
+ getStockMovements,
}
diff --git a/src/lib/models/inventory.ts b/src/lib/models/inventory.ts
index c770529..e288fe9 100644
--- a/src/lib/models/inventory.ts
+++ b/src/lib/models/inventory.ts
@@ -146,6 +146,20 @@ export interface StockReturn {
amount: number
}
+/** One row in the Stock Tracking tab's unified ledger. Mirrors StockMovementDto. */
+export interface StockMovement {
+ type: "GRN" | "Sale" | "Return"
+ productId: string
+ productName: string
+ reference: string
+ /** Only set when type === "Return". */
+ category?: ReturnCategory | null
+ /** Signed: positive for a GRN or a CustomerReturn, negative for a Sale or any other return. */
+ quantityChange: number
+ amount: number
+ date: string
+}
+
export interface CreateStockReturnInput {
productId: string
quantity: number