Skip to content

Module — Logistics

A self-contained inventory and fixed-asset system on its own database (NKO_DB_Warehouse). It tracks consumable stock (entry, internal / external release via Stock Release Requests and Waybills, centre-to-centre transfers) and serialised assets (registration approval, hand-out to employees / offices / centres, maintenance, return-to-store via GRN reports, and disposal / destruction), with per-category permissioned warehouses and its own reporting suite.

Source: NKO.Main/NKO.Main/WarehouseControllers/*.cs, NKO.Main/NKO.Main/WareBAL/*.cs, NKO.Lib/NKO.Warehouse.DataAccess/DbModel/, NKO.Main/NKO.Main/Helpers/OperationConstants.cs (the warehouse workflow constants), NKO.Main/NKO.Main/Startup.cs (the second DbContext).

Purpose & scope

  • In scope: warehouses and categories, the stock catalogue and on-hand balances, stock movements and releases, waybills, centre transfers, the asset register and its status history, asset dispatch, maintenance requests, asset-return GRN reports, destruction reports, the evidence library, and the warehouse reports.
  • Out of scope: purchasing the goods (Procurement) — a procurement GRN can push items into this module via GRN → Transfer to Warehouse.
  • Database: NKO_DB_Warehouse, context WarehouseDBContext, connection string WareConnection. Identity, signatures, notifications, permissions and org data are read from the core NKO_DB.

Database wiring

  • Startup.cs registers AddDbContext<WarehouseDBContext>(GetConnectionString("WareConnection")) immediately after the core context; WarehouseDBContext maps 21 DbSets, every FK DeleteBehavior.NoAction, Computer ↔ Asset one-to-one. There are 5 migrations.
  • WareBAL classes are all AddTransient and each take WarehouseDBContext; they reuse the core BUser, BSign, BNotification, EmailManager, NextUserHelper, CurrentRequestData, PermissionChecker, ExportHelper, RealTimeNotifier.
  • Link to Procurement: BGRN.TransfareToWarehouse(id, userId) (core) resolves BWarehouse.CurrentWarehouse and writes CenterStock + StockDetails{Entry, RealEntry} (consumables) or Asset rows (assets) directly into NKO_DB_Warehouse, then sets GoodReceivedNote.IsTransfareToWarehouse on the core record.
  • Visibility: BUser.GetPermission(SharedPermissions.{Stocks = 10, Assets = 11, GDO = 12}) returns All or project-scoped; category-level scope is EmpCat1Permission (employee ↔ CatL1) plus CatL1.StockManager.

Key features

  • Warehouses — per branch, two kinds: consumable (IsAsset = false) and asset (IsAsset = true), each with a Manager (guard) and optional SRRNoter.
  • Stock master — CatL1 (category, IsAsset, StockManager, Code) → Stock (item, ItemCode, UnitId) → StockSpecification (variant; auto "عام" if none) → CenterStock (the physical on-hand row keyed by warehouse + stock + spec + project + donor, with CurrentAmount).
  • Stock entry — StockDetails rows with an OpType (Entry / Release / PendingRelease) and a StockTransferType; entry can be manual or fed from a procurement GRN.
  • Stock Release Request (SRR / GD order) — StockReleaseReq + StockReleaseReqDetail; TransferType = Employee / Centre / Office / Distribution area, or IsExternal with a free-text destination + recipient. Flow: Draft → Pending (programme/branch approver) → WaitingRelease → Released; plus Refused / Cancelled / transfer states. Sending writes PendingRelease StockDetails rows; releasing flips them to Release; refusing / cancelling deletes them.
  • Waybill — Waybill + WaybillDetail (consignee, transporter, plate, departure date, batch no, weight), attached to an SRR for physical dispatch.
  • Centre-to-centre transfer — request / accept / refuse on an SRR of TransferType.Centre, moving CenterStock between warehouses.
  • Assets — serialised (Asset: spec, project / donor, purchase price / currency / date, PO / invoice / supplier, account code, BIS licence, OriginType Buying / Donation) with an append-only AssetDetail status history and denormalised CStatusId / CWarehouse / CUserId; an optional 1:1 Computer extension when the spec is the computer type.
  • Asset registration approval — Send (Draft → AwaitingFinance, requires a serial no) → FinanceApprove (adds the account code, → AwaitingLogistic) → LogisticApprove (→ Repo).
  • Asset dispatch (ADO) — assets attached to an SRR; ChangeStatus / TransferToUser / TransferToWare move an asset to an employee (PendingDelivered → Delivered on release), back to store (Repo), or between centres.
  • Maintenance — a MaintenanceReq per asset; Draft → AwaitingLogistic → AwaitingStockManager → AwaitingLogistic2 → Accepted; Send sets the asset to Maintenance, LogisticApprove2 returns it to Delivered.
  • Asset return GRN report ("ARR") — GRNReport + AssetsReturn return previously-issued assets into store; Draft → AwaitingWarhouseResponsible → AwaitingSC → Closed; on approval calls BAsset.TransferToWare for each asset (→ Repo).
  • Destruction / disposal — Destruction + Asset.DestructionId; Draft → WaitingForManagement → WaitingForProcurement → WaitingForGM → Accepted; SetSent marks assets PendingDestructed, SetGMApprove marks them Destructed.
  • Evidence library — WarehouseEvidence: uploaded scans (S3) categorised (GRN & invoice, GDN, SRR, waybill, destroy, donation) with GRN / invoice numbers.
  • Reporting — asset report, general stock report, per-stock report, SRR / waybill / entry-release monthly reports, employee asset card, entries report — all with Excel export driven by RealTimeNotifier progress.
  • Admin — warehouse CRUD, CatL1 CRUD, Stock + StockSpecification CRUD, and bulk Excel importers (stock data, SRR data, recipients, centre data, specifications).

Screens

Warehouse controllers live in namespace NKO.Warehouse.Controllers but are reached at /{Controller}/{Action} like any other. Primary screens only.

StockController — /Stock/* · AssetController — /Asset/*

Feature Route Permission key
Consumable stock grid /Stock/Index StockIndex
Stock item detail /Stock/Details/{id} StockDetails
Add / edit / release a stock movement /Stock/AddStockDetail, /Stock/EditStockDetail/{id}, /Stock/ReleaseStockDetail/{id} StockAddStockDetail, StockEditWaybillDetail
SRR list / create / detail /Stock/SRR, /Stock/CreateSRR, /Stock/SRRDetails/{id} StockSRR, StockCreateSRR, StockSRRDetails
Waybills list / create / detail /Stock/Waybills, /Stock/CreateWaybill, /Stock/WaybillDetails/{id} StockWaybills, StockCreateWaybill, StockWaybillDetails
SRR / asset-SRR workflow transition /Stock/ContextActions, /Asset/ContextActions StockContextActions
Asset register /Asset/Index AssetIndex
Asset detail /Asset/Details/{id} AssetDetails
Register a new asset /Asset/AddAsset AssetAddAsset
Warehouse list (per branch) /Asset/WarehouseList AssetIndex
Move asset to store / user /Asset/TransferToWare, /Asset/TransferToUser, /Asset/ChangeStatus AssetTransferToWare, AssetTransferToUser
Asset registration transition /Asset/RegisterContextActions AssetDetails
Asset export /Asset/Export AssetExport

Maintenance · GRN report · Destruction · Reports · Admin

Feature Route Permission key
Maintenance requests /MaintenanceReq/Index, /MaintenanceReq/Details/{id}, /MaintenanceReq/Create AssetMaintenanceIndex, AssetMaintenanceDetails, AssetMaintenanceCreate
Maintenance transition /MaintenanceReq/ContextActions AssetMaintenanceDetails
Asset-return GRN report /GRNReport/Index, /GRNReport/Details/{id}, /GRNReport/Create WareGRNIndex, WareGRNDetails, WareGRNCreate
GRN report transition /GRNReport/ContextActions WareGRNDetails
Destruction reports /Destruction/Index, /Destruction/Details/{id}, /Destruction/Create, /Destruction/AssetsForDestruction DestructionIndex, DestructionDetails, DestructionCreate
Reporting suite /Report/Index, /Report/EntriesReport, /Report/EmployeeCard ReportIndex, WareReportEmployeeCard
Warehouse / category / stock admin + importers /WareAdmin/Index, /WareAdmin/Warehouses, /WareAdmin/Stocks, /WareAdmin/ImportData StockAdminAdvance, StockAdmin, StockAdminImportData
Evidence library /Attachments/Index, /Attachments/AddAttachment WarehouseAttachments

WareBaseController (/WareBase/*) is a standalone AJAX helper (GetStocks, GetStockSpecs, GetImage, Thumbnail, Download) — it is not an abstract base and carries no permission key. EvidencesController (/Evidences/*) exposes only Index and GetRefrenceCode (no key).

Business logic

Class File Responsibility & notable logic
BWarehouse WareBAL/BWarehouse.cs (~115 ln) Warehouse master CRUD + lookups. CurrentWarehouse(userId, isAsset) (manager match), CurrentWarehouseByBranch, SearchWarehouses.
BStock WareBAL/BStock.cs (~4020 ln — largest) Masters (CreateStock + child specs, CreateCat1, CreateStockSpec). Entry — CreateStockDetails finds/creates the CenterStock (warehouse + stock + spec + project; donor via _common.GetDonorByProject) and adds StockDetails{OpType = Entry, StockTransferType = RealEntry}. SRR — CreateSRR, CreateSRRDetails (duplicate-line guard), GetSRRs(...). Waybills — CreateWaybill, GetWaybill(s). Availability — IsStockAvailabeInWarehouse, GetAvailableStockQty. Workflow — SetSent (validate each detail's availability; StatusId → Pending; ApproverId = project.ProgramManager; next via _nextUserHelper.GetStockNextUser; write PendingRelease StockDetails rows), SetCMApproved (→ WaitingRelease), SetCMRefused (→ Refused; delete pending rows + soft-delete AssetPendingAmount), SetReleased (flip PendingRelease → Release, PendingDelivered assets → Delivered), RequestTransfer / AcceptTransfer / RefuseTransfer.
BAsset WareBAL/BAsset.cs (~4205 ln) CreateAsset(CreateAssetVM) — loops Count; CStatusId = Draft; seeds one AssetDetail{Draft}; creates a Computer row if the spec is the computer type. Registration — Send(id, userId, serialNo) (Draft → AwaitingFinance), FinanceApprove(…, accountCode) (→ AwaitingLogistic), LogisticApprove (→ Repo). Movement — TransferToWare(model, path[, grnId]) (→ Repo; with a grnId records FromState + GRNId), TransferToUser (→ PendingDelivered, sets PerndingForSrrId), ChangeStatus(srrId, specId, assetIds, transferType, attachmentId). Asset-SRR workflow (SetSent / SetStockManager / SetCMApproved / SetReleased / …). Queries — GetAssets(...) (filter by status / category / stock / spec / donor / project / user), GetAssetByUser, ExportAssetsAsync.
BMaintenance WareBAL/BMaintenance.cs (~565 ln) GetMaintenanceReq (permission via GetPermission(SharedPermissions.GDO) — All else LogisticId == userId || StockManagerId == userId), CreateMaintenanceReq (StatusId = Draft), Send (asset → Maintenance, AssetDetail{FromState = Delivered}, → AwaitingLogistic), LogisticApprove (→ AwaitingStockManager, StockManagerId = CatL1.StockManager), StockManagerApprove (→ AwaitingLogistic2), LogisticApprove2 (→ Accepted, asset → Delivered), AddAssetDeatilsRefuse (asset back to Delivered on any refuse).
DestructionHandler WareBAL/DestructionHandler.cs (~625 ln) CreateDestruction(DestructionVM) (sets Asset.DestructionId for each existing asset). Workflow — SetSent (assets → PendingDestructed; → WaitingForManagement; next via GetDestructionNextUser), SetManagementApprove/Refuse, SetProcurementApprove/Refuse, SetGMApprove (assets PendingDestructed → Destructed, status → Accepted).
GRNHandler WareBAL/GRNHandler.cs (~640 ln) Asset-return GRN report. CreateGRNReport (acting asset-warehouse by branch; StatusId = Draft; adds AssetsReturn per asset), SetSent (→ AwaitingWarhouseResponsible; next via GetAssetGRNNextUser), WarhouseResponsibleApprove (→ AwaitingSC), AuhtorizeApprove (→ Closed; calls BAsset.TransferToWare(asset, null, grnReportId) per asset), CancelRequest (needs the GRNCancel key; reversing AssetDetail rows if already warehouse-approved).
BReport WareBAL/BReport.cs (~1030 ln) GetAssetReport / GetGeneralReport / GetStockReport(level, …) (drill-down), GetSRRReport(year, month), GetWaybillReport, GetEntryReleaseReport, ExportEntriesReport.
WarehouseEvidencesHandler WareBAL/WarehouseEvidencesHandler.cs (~215 ln) GetAtachments(userId, …, category?, page) (permission via GetPermission(SharedPermissions.Stocks)), AddEvidence (resolves the acting warehouse, uploads to S3 Functionality.NKOWarehouse), EditEvidence.

Data

The WarehouseDBContext maps 21 entities (15 in DbModel/ + 6 in DbModel/Assets/):

Group Entities
Warehouses & categories Warehouse, CatL1, EmpCat1Permission
Stock catalogue & on-hand Stock, StockSpecification, CenterStock
Stock movements & release StockDetails, StockReleaseReq, StockReleaseReqDetail, Waybill, WaybillDetail
Assets Asset, AssetDetail, AssetPendingAmount, AssetsReturn, Computer, GRNReport
Maintenance & disposal MaintenanceReq, Destruction
Evidence & files WarehouseEvidence, WareArchiveFile

Full column detail: Warehouse database.

Permissions

Distinct keys: AssetIndex, AssetExport, AssetDetails, AssetAddAsset, AssetEditAsset, AssetDeleteAsset, AssetDeleteAssetDetail, AssetTransferToWare, AssetTransferToUser, AssetCancelAsset, AssetMaintenanceIndex, AssetMaintenanceCreate, AssetMaintenanceDetails, AssetMaintenanceEdit, AssetMaintenanceDelete, StockIndex, StockDetails, StockSRR, StockSRRDetails, StockWaybills, StockWaybillDetails, StockCreateSRR, StockCreateWaybill, StockAddStockDetail, StockEditWaybillDetail, StockDeleteStockDetail, StockContextActions, StockGetStocks, StockGetCenters, StockAdmin, StockAdminAdvance, StockAdminImportData, WareGRNIndex, WareGRNDetails, WareGRNCreate, WareGRNEdit, WareGRNDelete, DestructionIndex, DestructionCreate, DestructionDetails, ReportIndex, WareReportEmployeeCard, WarehouseAttachments, plus GRNCancel (checked in code). Data scoping: SharedPermissions.{Stocks = 10, Assets = 11, GDO = 12} + EmpCat1Permission / CatL1.StockManager.

Screenshots

Consumable stock — /Stock (category / warehouse / project filter panel; the grid is empty for an account without EmpCat1Permission on any category):

Stock on-hand grid

Fixed-asset register — /Asset (status / category / holder columns; category-scoped like Stock):

Asset register

Warehouse control panel — /WareAdmin (stock categories CatL1):

Warehouse categories admin