SmartInventory Web Portal — UI Usage & HTTP API Map
Purpose: Document how the SmartInventory web portal uses its backend, to ground the (already-mapped)
smartinventory_qadata model (docs/database/00–08) in real application usage. This is a synthesis of (a) a live read-only UI capture of the demo instance, (b) the authoritative .NET source underreferences/SmartInventory-3.0/Source/, and (c) the DB data-model docs.Companion docs:
docs/database/00-Overview.md…08-platform-security-tenancy-catalog.md;docs/SmartInventory_Legacy_Architecture_Study.md. Raw UI capture:references/ui-exploration/(LIVE_FINDINGS.md,network_*.json,shots/*.png).
1. Scope & caveat
Two distinct things were observed, and they are not the same deployment:
| Aspect | Source | What it tells us |
|---|---|---|
| Live UI | Demo instance http://networkaccess.st.leptonsoftware.com, product v8.16.4.0, admin login, captured via Playwright on 2026-06-16 | How the product is used and configured — menus, flows, request paths, POST field names. Its layers/data are a small demo set, different from the smartinventory_qa DB. |
smartinventory_qa DB | Live PostgreSQL 14.8 (~8.8 GB), analyzed in docs/database/ | The data model (tables, views, fn_* functions) — the real source of business logic. A multi-customer QA mashup (Jio geometry + Safaricom catalogue + a BharatNet postgres_fdw link). |
| .NET source | references/SmartInventory-3.0/Source/ (the develop-style mainline) | The authoritative API surface: 46 web MVC controllers + 29 Admin-area controllers + two OWIN OAuth Web APIs, all calling BL* → DA* → fn_*. |
Live-observed vs code-derived. Section 3 (UI module map) and the request paths in §2/§4 marked “(observed)” were seen live; the full controller/action tables in §4 and the traces in §6 are enumerated from source (so they include endpoints never clicked). Where the trace agent inferred a table name from a .NET return type (e.g. “cable_master”, “connection_info_master”, “network_code_details”), this doc uses the authoritative DB names from docs/database/ instead — the real tables are line_master/point_master/polygon_master, att_details_*, connection_info, att_details_networktickets/ticket_master, entity_additional_attributes. The fn_* names are quoted as found in the DA*.cs source (authoritative).
Caveat on the source clone:
AGENTS.mdreferences aGeoSureServicesGIS Web API, but that project is not present in this clone — onlySmartInventoryServicesandIntegrationServicesexist here. The clone also lacks compiled output, so action signatures are read from source.
2. App shell & technology
Stack (confirmed from source + live): ASP.NET MVC 5 / Razor (.NET 4.8), jQuery + jQuery UI + jQuery Validation (no SPA framework, no module bundler), System.Web.Optimization bundles, SignalR for realtime, Google Maps JS base layer + MapServer/WMS for feature layers, EF6/Npgsql data access. App is served under a virtual path /Products.
Auth flow (observed + LoginController.cs):
GET /Products→ login form (fieldsuser_name,password; posts to/Products/).- XHR
POST /Products/Login/validateuser(checks existence + multi-login) → on success lands on/Products/main(MainController.Index/MapManager). - Session is polled by
GET /Products/Login/checkSession; logoutGET /Products/Login/logout. - Multiple auth modes (per
AGENTS.md+LoginController): Forms (default, session timeout 120 min), ADFS, Azure AD (Login/Azuread→Login/AzureCode), LDAP, Airtel custom SSO; optional OTP/2FA (Login/ProcessOTP/VerifyOtp). Default route{controller}/{action}/{id}withLogin/Indexas home (App_Start/RouteConfig.cs). - Server-side single-login enforcement lives in
Global.asax.cs(Application_AcquireRequestState→BLUser.validateUserLoginHistory, abandons stale sessions). - Session keys drive everything downstream:
Session["userDetail"],Session["user_id"],Session["ApplicableModuleList"](the permission/menu set),Session["Language"].
Realtime — SignalR (Startup.cs, Utility/SmartInventoryHub.cs):
- Hub mapped at
/Products/signalr(GET /signalr/negotiate,/signalr/startover WebSockets,/SignalR/hubs); client bundle~/bundles/NotifySignalR. SmartInventoryHubbroadcastsBroadCastInfo(NotificationOutPut)(utilization/upload alerts) andBroadCastUploadStatus(message)(data-upload progress). Notifications also polled viaPOST /Products/Workforce/GetNotification(observed).
Map rendering (see §5): Google Maps JS provides the basemap (maps.googleapis.com; MapAuthType = KEY or CLIENT); network feature layers are MapServer WMS images over PostGIS views. The client lib is Content/js/googlewms.min.js + mapCore.js (in the ~/bundles/Scripts OSP bundle). At country zoom no GeoJSON XHR fires — WMS tiles load only over data extents.
Bundles (App_Start/BundleConfig.cs) — feature-scoped, version-stamped in production:
~/bundles/Scripts(the big OSP/map bundle: jQuery,googlewms,mapCore,Splicing,SpliceTray,FiberCutTracing, dynamic-attribute serializers,Areas/Admin/.../expressionBuilder.js),~/css.~/bundles/ISP/Scripts,~/ISPSCRIPTS(D3 vertical-cable SVG,room-view/*,equipment-workspace/workspace.js+equipment-builder.js,EquipmentEditor.js),~/ISPCSS.~/bundles/NetworkPlanning/Scripts(+SmartPlanner/SmartPlanner.js,tokml,select2),~/VizNetworkScripts(vis.js butterfly diagram),~/bundles/endToEndSchematic/Scripts(D3 dnd-tree).~/bundles/datauploader,~/bundles/regionprovincedatauploader,~/bundles/ExternalDataUploader/Scripts(KML/KMZ via geoxml3),~/bundles/AdditionalAttributes/Scripts(DynamicForms/*),~/bundles/Barcode/Scripts,~/bundles/LandBase.- Admin area:
~/bundles/Admincss,~/bundles/AdminScripts(observed) +Areas/Admin/Content/{css,js}(spectrum color-picker, expression builder).
3. UI module & feature map
3a. Map workspace (/Products/main — MainController)
The default landing surface (screenshot shots/02-dashboard.png, 03-layers-on.png). Layout = a large top toolbar + a left “NETWORK LAYERS” tree + Google Maps canvas.
- Layer tree is grouped exactly as
layer_details+layer_group_mappingdictate, with per-layer visibility / select / edit toggle columns and live feature counts. Observed groups/layers: Transmedia→Cable; Structure1→Pole; Structure→WallMount / Manhole / Central_Office / Building / Tree / Rack / Handhole / Tower; SPAN→Trench / Duct; Equipment→Splitter / CPE / FDP / Cabinet / ATB; plus FDC / CSA_Boundary / SurveyArea / Fault / Sector / DSA_Boundary / Customer / PatchPanel / FAT / SpliceClosure / ROW / CX / Area / Coupler. This is the front-end of the 66-rowlayer_detailsregistry (docs/database/01). - Toolbar capabilities (from the OSP bundle + controllers): geocoder search (
Main/GetEntitySearchResult, GoogleGoogleMap/AddressSearch), draw/place entity, edit geometry (Main/SaveEditGeometry,EditCableTPDetail), measure/distance widget, info/identify (Main/GetEntityInfo), near-by query (Main/GetNearByEntities/GetNearByCables), splicing, fiber-cut tracing, redline markup, print/export, layout (MapLayout/Index), ortho-image raster toggle.
3b. Product modules (which controllers ⇒ which module)
| Module | Web controllers (this clone) | Purpose |
|---|---|---|
| SmartInventory (core map/inventory) | Main, MapLayout, VectorLayer, GoogleMap, LandBaseLayer, Library (Area/SubArea/DSA/CSA/SurveyArea/Building/Structure/ADB), ISP (HTB/FDB/BDB/CDB/Splitter/Room/Floor/Shaft…), ItemTemplate, Audit, Report, Print, FileDownload, RegionProvince, Multilingual, WorkSpace, Redline | Place/edit/codify network assets; attribute forms; templates; history/audit; reports. |
| SmartPlanner / Planning & BOM | Plan, SmartPlanner, BOMBOQ, Integration, ProjectManagement | Auto network planning (trench→duct→cable→splice), point-to-point, loop mgmt, BOM/BOQ generation & costing, plan→inventory promotion, OSS superset integration. |
| Connectivity / Splicing | Splicing (OSP+CPE+ODF), FiberAllocationTool (FAT auto-splice), FiberCutTracing, CommonPathFinder, WorkSpace (equipment/rack workspace incl. OLT patching) | Splice ports, OLT/ODF patching, end-to-end schematic, OTDR fault trace, common-path finder, optical link budget. |
| SmartOps / WFM | Workforce, TicketManager, NetworkTicket, SurveyArea, RosterManagement, JobPack, KPIMaster | Job-order assignment, ticketing (Customer/Network/HPSM), survey assignment & location tracking, rostering/timesheets, job packs, KPI dashboards. |
| SmartSQ / Feasibility | (web entry via Main/Plan; the engine is in IntegrationServices + fn_sf_*) | Serviceability / dark-fiber feasibility (pgRouting over existing cable with free cores). |
| Wireless | Wireless/Tower, Wireless/Sector, Wireless/Antenna, Wireless/MicrowaveLink | Towers, sectors, antennas, microwave links (RF params). |
| Data ingestion | DataUploader, BulkUpdate, FileUpload (TAB/Shapefile/DXF/KMZ), RegionProvince uploader | Excel/KML upload → temp_du_* staging → validate → commit. |
| Dashboard / Auth / Error | Dashboard, Login, Error, UnAuthorized | Login, dashboards, error pages. |
3c. Admin / configuration area (/Products/Admin/<Controller>/<Action>)
The configuration surface that administers the data model (screenshots 04-admin.png, adm-layerconfig.png, adm-portstatus.png, adm-vendorspec.png, adm-equipmodels.png, adm-roles.png, adm-rolemodule.png, adm-templates.png, adm-changecode.png). Route prefix Admin/{controller}/{action}/{id}. The left menu (observed) groups 29 controllers; the menu has more sections than the original capture noted — full list: OLT Patching, Users, Dashboard, Layer Settings, Vendor Specification, Rights Management (Roles/Templates), Equipment Builder, Miscellaneous Feature, OSP Settings, Vendor, LandBase Layer Settings, Advanced Settings, API Consumer Master, Accessories, Help & FAQ’s, Project, Link Budget Settings, Application Logs (+ Resources, Email/OTP settings, Dynamic Theme/Form, Backup download, Long-running queries, WFM RCA, Business Layer).
| Admin controller | Key actions | DB structure it administers |
|---|---|---|
LayerSettings | ViewGroups, ViewLayerGroupsMapping, LayerConfigurationSettings / saveLayerConfigurationSettings, AddLayerDetailSettings/SaveLayerDetail, ShowlayerDetails, ViewLayerStyleMaster/SaveLayerStyleMasterDetails | layer_details (66×114), layer_group_master, layer_group_mapping, layer_style_master (map styling/label expression). Observed form fields: layer_id, layer_title, minzoomlevel, is_mobile_layer, is_visible_in_mobile_lib, is_visible_on_mobile_map. |
Miscellaneous | ViewPortStatus (port-status enum grid: Status, Color Code, Is Active, Is Manual, Is Splicing Allowed, audit), ChangeNetworkCode / getNewNetworkcode / getNetworkIdDependency / SaveChangeNewNetworkcode (re-codification), DropDownMaster (entity dropdown vocab), ViewUtilizationSetting, error/API/GIS logs, FAQ | port_status (vocab in docs/database/04), codification (fn_get_network_code, entity_network_code_history), dropdown_master, entity_utilization_settings. |
VendorSepcification (sic) | Add/View/Save/UploadVendorSpecification, ViewSpecificationServices, BindSplitterPortRatio, GetVendorSpecificationHistory, attachment upload | BOQ/costing catalog = item_template_master (Cost Per Unit/meter, Service Cost, Port/Fiber Info, Sub-Category 1–3, A/B/C-RFS flags) per docs/database/02/05. |
Equipment (Equipment Builder) | CreateModel/SaveModel/SaveModelMapping, ViewModels, ViewModelsImage, CreateRule/SaveRule (parent/child model rules), GetWorkspaceData/GetLibraryData (canvas), model-type/colour/port mgmt, SVG upload | The Equipment→Chassis→Slot→Card→Port→Tray hierarchy via isp_model_* (isp_model_info, isp_model_mapping, isp_model_rules, isp_model_type_master) — docs/database/04. Model categories observed: Equipment, OLT, ACT FRB, FDP, Nokia OLT, Chassis, Slot, Card, Port, Tray. |
User | AddUser/SaveUser, ViewUsers, ViewUsersLoginHistory, BulkUserUpload (→ bulk_user_*, fn_bulk_user_upload_process), region/province/subdistrict/block cascades, UserReportMapping | user_master, user_login_history, user_permission_area, bulk_user_*. |
Roles | AddRole/SaveRole, ViewRoles, UpdateRoleModule / SaveRoleModuleMapping, service-facility/JO mappings | role_master, role_module_mapping (module gating), role_permission_entity (per-layer CRUD). |
Template | AddTemplate/SaveTemplate (+ BLRoleRights.SaveRoleRights), ViewTemplates | item_template_* library + layer_rights_template_permission. |
OSPSettings | InfoSettings, SearchSettings, Zoom, labelSettings (+ expressionBuilder), TubeCoreColorSettings, ViewCableMapColorSettings | layer_details info/search/zoom/label columns; cable tube/core colour & map-colour settings (feeds the .map styling). |
AdvancedSettings | ViewGlobalSettings/SaveGlobalSetting, ModuleSettings, LayerActionSettings, ConnectionLabelSettings/SyncAllLabels, ReportColumnSettings, HistoryColumnSettings, FormInputSettings, VoiceCommandMaster | global_settings, module_master, connection-label rules, report/history/form column config. |
LandbaseSettings | layer/dropdown/search/label settings | landbase_layer_master, landbase_dropdown_master, landbase_layer_columns_settings (docs/database/06). |
Configuration / Vendor / Accessories / Project | equipment-type/brand/model masters; vendor master; accessories + entity mapping; project/planning/workorder/purpose codes | classification masters; vendor_master; accessories; project-code masters. |
APIConsumerMaster | GetAPIConsumer, AddAPIConsumer/SaveAPIConsumer | api_consumer_master (the IntegrationServices clients — note empty-password client finding in docs/database/08). |
OpticalLinkBudget | AddLinkBudget/SaveLinkBudget, splitter-loss | link-budget tables (drives Splicing/viewlossdetails). |
OTPAuthenticationSettings / EmailSettings / DynamicTheme / DynamicForm | OTP/email config, theming, dynamic-form builder | otp_authentication_configuration, mail settings, dynamic_controls. |
BulkUpdateTemplate | data-uploader column settings | data_uploader_template. |
WFM | RCAMaster (root-cause vocab) | WFM RCA dropdowns. |
LongRunningQueries / Downloadbckfile / Resources / BusinessLayer / FeTools | kill long queries; DB backup download; multilingual resource mgmt; business-logic layer registry; field-engineer tool allocation | ops/admin plumbing. |
Home | index, POST getDashboardData (observed), HeaderInfo_Admin, Export_Dashboard_Data | admin dashboard (active/last-month users). |
4. HTTP API surface (the big one)
The external contract the new platform must reckon with is three ASP.NET endpoints: the MVC web app (/Products/..., ~46 web + 29 admin controllers, mostly server-rendered + AJAX JSON), and two OWIN OAuth Web APIs consumed by mobile and third parties.
4a. Web MVC — selected controller → action map (enumerated from source)
All under /Products/{controller}/{action}; verbs are [HttpGet]/[HttpPost] where attributed, else MVC default (GET). Controllers carry [Authorize], [SessionExpire], [HandleException]; Admin adds [AdminOnly]. (Full action lists exist for every controller; representative high-value ones below.)
Auth / shell
| Controller | Actions (verb) |
|---|---|
Login | Index (GET/POST), validateuser (POST), checkSession (GET), logout (GET), ProcessOTP (POST), VerifyOtp (GET), Azuread/AzureCode (GET) |
Main | Index/MapManager (GET), GetEntityInfo (POST), GetEntitySearchResult (GET), getGeometryDetail (POST), GetNearByEntities/GetNearByCables (GET), SaveEditGeometry/UpdateOtherGeometry/EditCableTPDetail (POST), DeleteEntityFromInfo (POST), GetLayerDetail/GetLayerMapping (GET), ValidateEntityGeom/ValidateParentEntityGeom/ValidateLBEntityGeom (GET), ComputeHomePass (POST), getDependentChildElements (GET) |
Dashboard | Index (GET), HierachyList (GET), DashboardResult (GET), ExportDashboardDataDump (GET) |
Inventory / entity CRUD — each entity type has an Add<Entity> (GET form) + Save<Entity> (POST) + Delete<Entity>ById (POST):
| Controller | Representative actions |
|---|---|
Library | AddArea/SaveArea, AddSubArea/SaveSubArea, AddDSA/SaveDSA, AddCSA/SaveCSA, AddSurveyArea/SaveSurveyArea, AddBuilding/SaveBuilding (+GetBuildingRFSStatus,isValidRFSStatus), AddStructure/SaveStructure, AddADB/SaveADB, GetBarCode, UploadBuildingData |
ISP | AddHTB/FDB/BDB/CDB/Splitter/Room+Save*+Delete*ById, StructureInfo, FloorInfo/UpdateFloorInfo, ShaftInfo/UpdateShaftInfo, saveWithRiser, getElementTemplate |
LandBaseLayer | AddLandBase/SaveLandBaselayer, GetLandbaseEntityInfo, BindLandbaseDropdown, GetLBLayerSearchResult, DeleteLandbaseEntityFromInfo |
Wireless/* | AddTower/SaveTower(+POP association), AddSector/SaveSector, AddAntenna/SaveAntenna(+VSAT), AddMicrowaveLink/SaveMicrowavelink |
ItemTemplate | Index, <Entity>Template/Save<Entity>Template, GetVendorList, GetCatSubcatData, GetBrand/GetModel |
Audit | GetHistory, GetGeometryHistory, GetSiteHistory, GetLMCHistory, GetFiberLinkHistory, GetLandBaseLayerHistory (+ Download/Export each) |
Connectivity / splicing
| Controller | Representative actions |
|---|---|
Splicing | Index (GET), CableToCable/CPEToCustomer/ODFToCable (GET forms), SaveConnectionInfo (POST), deleteConnection (POST), GetAvailabePorts (GET), ConnectionPathFinder (GET), SchematicView/GetStreamWiseSchematic (GET), GetEquipmentPortInfo (POST), EntityLogicalView, GetLinkBudgetDetails, UploadConnectionData (POST), viewlossdetails |
FiberAllocationTool | Index, GetConnectionDetails, CreateSplicing (POST), ExportTempSplicing, RefreshMessage/DeleteMessage |
FiberCutTracing | index, getFiberTracingPath, getFiberCutDetails, getFiberNodeType |
CommonPathFinder | CommonPathFinder, CustomerFiberLinkPathFinder, getCableListByLinkIds, getCableListByCustomerId |
WorkSpace | GetWorkSpace/GetWorkSpaceById (GET), SaveWorkSpace/DeleteWorkSpace (POST) — equipment/rack workspace incl. OLT patching |
FiberLink | ShowFiberLinkDetails, AddFiberLink/SaveFiberLink, AssociateCustomer, AssociateFiberLinkWithCable, KML/PDF export |
Planning / BOM
| Controller | Representative actions |
|---|---|
Plan | ShowPlanTool/ShowBulkPlanTool, processPlan (GET), Point2PointPlan, GetBomData, SaveProcess (POST → commit plan), GetNetworkForMap, SaveLoop (POST), DeletePlanByPlanId |
SmartPlanner | route optimisation / demand / design (large module) |
BOMBOQ | BomBoqReport/Summary/Export, PrintBOMBOQ (POST), BOMBOQView/SaveBOMBOQView (POST), savebomlogic/Validatebomformula (POST), ConstructionBOMDetail, UnlockFSA |
Integration | ShowPlannerIntegration, ProcessIntegrationSuperset (POST), GetAllPlans, DeleteProcessedIntegrationSuperset |
SmartOps / WFM
| Controller | Representative actions |
|---|---|
Workforce | AssignJobOrder/ViewAssignJobOrder/ViewTTAssignJobOrder (POST), ManagerRouteIssueApprove/SaveRouteIssueStatus/AssingContractorRouteIssue (POST), OpenTicket/Closeticket (POST), ViewNotification, GetNotification (observed POST), route reports |
TicketManager | ShowTicketManager, AddTicket/SaveTicket (POST), EditTicket/DeleteTicket (POST), GetCustomerByCanId, UploadTicketData, AddHPSMTicket/SaveHPSMTicket (POST) |
SurveyArea | SurveyAssignment, SaveAssignedUser (POST), FreezeSurveyarea (POST), BulkApproved (POST), location-tracking & building-survey grids + exports |
RosterManagement | ViewUserTimeSheet, SaveUserTimeSheet (POST), EditUserTimeSheet (POST), DeleteUserTimeSheet (POST) |
JobPack / KPIMaster | job-pack create/assign; KPI templates/charts/export |
Ingestion / files
| Controller | Representative actions |
|---|---|
DataUploader | UploadFiles (POST), getColumnMappping, SaveMappingTemplate (POST), ValidateData (POST), ProcessData (POST), getUploadSummary, downloadTemplate, GetStatus (SignalR progress) |
BulkUpdate | UploadData, UploadFile (POST), getUploadSummary, downloadUpdateTemplate |
FileUpload | UploadOtherFile (POST — TAB/Shapefile/DXF), UploadKMLZFile (POST), external-data list/download, UploadProfileImage |
FileDownload | DownloadUploadLogs, DownloadTemplate, checkLogFileExist |
4b. SmartInventoryServices — OWIN OAuth Web API (mobile + web client)
- Token endpoint:
POST /token— OAuth2 Resource-Owner-Password-Credentials (ROPC), opaque Bearer tokens (not JWT). ProviderSmartInventoryServices/Providers/OAuthProvider.cs;App_Start/Startup.cs. Token TTL =ApplicationSettings.mobileAppLogoutTimeInSec(configurable); refresh tokens via an in-memorySimpleRefreshTokenProvider.AllowInsecureHttp = true, CORS*. Grant validation supports Forms / ADFS / Azure AD / LDAP / ADO-ID / 2FA, license checks, and a hardcoded master-password bypass (security finding). Route baseapi/{controller}/{action}/{id}+ attribute routes. - Representative endpoints (all POST, Bearer-protected, body wrapped in
ReqInput):
| Controller | Endpoints | Purpose |
|---|---|---|
User/SignIn/OTP | ValidateUser, UserLogout, SaveUserLocation, SaveUser, GetOTP/VerifyOTP | auth, self-registration, location ping, 2FA |
Main/Offline | GetDropDownItems, GetAllVendorSpecifications, GetAllVendors, GetAllDropdownData, GetAllLayerMapping, GetProvinceDetail, getLegendDetail | offline-first sync of static/config data |
VectorLayer | GetVectorData, GetVectorDataByGeom, GetVectorDelta, GetVectorDeltaByGeom | fetch/sync network layers + delta sync |
Building/SurveyArea | GetBulidingInfo, insertbuilding, updatebuildinginfo, updatebuildinggeometry, Checknearbybuilding, SurveyareaInfo | mobile survey capture |
ISP/Library/Splicing/Connection | EntityOperations, SaveISPDevices, GetDeviceDetails, splicing ops | device/equipment CRUD (the web Wireless/* controllers call api/Library/EntityOperations) |
FE (wfm/mobile/v1.0) | getJobList, getTTJobList, UpdateJobOrder, getCustomerDetail, UploadAttachment, UpdateStatus, activatecpe, reschedule, closeTicket (~55) | field-engineer WFM app |
CRM/Report/GoogleMapAPI (api/mapsapi) | ticket queries; export reports; Maps proxy (geocode/reversegeocode/directions/distancematrix/placesearch) | CRM, reporting, Google Maps proxy |
4c. IntegrationServices — OWIN OAuth Web API (third-party OSS/BSS)
- Token endpoint:
POST /GenerateToken— ROPC bearer; validated againstapi_consumer_masterviaBLAPIConsumerMaster.ValidateIntegrationServiceConsumer. Params: base64username,password,Source(third-party id, required), optionalClientIP,ExpireTime(per-call TTL override; default 86400 s). No 2FA.AllowInsecureHttp=true, CORS*. ProviderIntegrationServices/Providers/OAuthProvider.cs; Swagger present. - Endpoints (all Bearer-protected; carry a
source_ref_typetoken claim):
| Controller (RoutePrefix) | Endpoints | Purpose |
|---|---|---|
Ticket (api/v1) | getAppointmentSlots, reserveAppointmentSlot, createJobOrder/createJobOrdernew, createTTJobOrder, appointmentDetails, cancel/rescheduleAppointmentSlot, cancelJobOrder, updateCpeStatus, updateConnectedDevice, GetStatusDetailByJobOrderId | WFM/BSS appointment & job-order integration |
Service (serviceability/v2.0) | GetServiceability, GetAPIsettings, UpdateAPIsettings | service-qualification (GPON NAP availability by lat/lng) |
OSSIntegration (api/v1) | entityLocation (GET), intermediateEntities (GET), updateAlarmStatus, serviceability, updateDiscoveredEntity, reserveFatPort/releaseFatPort, ontActivationStatusUpdate, entitySearch | GIS↔OSS: location lookup, fiber-path trace, FAT/OLT port reserve/release, ONT activation, discovery |
Search (api/entity) | GetAvailableDevices, UpdatePortStatus, GetFaultTrace | device/port queries, fiber-cut trace |
DaFiFeasibility (api/v1) | darkFiberFeasibility, feasibilityKML, reserveFeasibilityRoute/releaseFeasibilityRoute | dark-fiber routing (SmartSQ) |
LocationDelta (api/v1) | locationDelta, locations, faultLocation, fttxFeasibility | location sync & FTTx feasibility |
ProjectSpecification (api/v1) | SaveProjectCode/SavePlanningCode/SaveWorkorderCode/SavePurposeCode, GetNetworkTicketSummary | project-code integration |
FiberLink / Distance (v1.0) / Health (api) | linkOwnerShip; getnewcustomerdistance/getcustomerdistance; health | link ownership; customer distance; liveness |
The DB exposes a parallel
fn_api_*function family (63 functions,docs/database/08) that these API controllers ultimately call (e.g.fn_api_get_fault_location_detail,fn_api_nwt_insert_update_ticket).
5. Map rendering pipeline
Pipeline: Google Maps JS basemap + MapServer WMS overlay images, where each map layer is a PostGIS view (vw_*_map) over the master+att_details tables, styled by attribute expressions and codification status.
- Client.
Content/js/googlewms.min.js+mapCore.js(OSP bundle) overlay MapServer WMS tiles on the Google base layer, filtered by the layer tree (visibility flags fromlayer_details) and by user province (%provinceFilter%). - MapServer mapfiles (
Source/MapFiles/). The active files areNetworkEntitiesLabel.map/NetworkEntitiesNoLabel.map(~60LAYERblocks each) plus-Scale2(200×200, doubled fonts/symbols/widths for high zoom),*Mobilevariants,LandBaseEntities*.map(point/polygon/line landbase),OrthoImage.map(raster),Legend.map,jiolayers.map. All sharedatashare.inc. - Connection.
datashare.inchardcodes a PostGIS connection:CONNECTIONTYPE postgis/CONNECTION "dbname='Smartinventory_qa' host=192.168.1.40 port=5014 user='postgres' password='Lepton@#2022'"— a plaintext DB superuser credential committed in the repo (add to the security remediation list). - DATA = PostGIS views. Each
LAYERreads avw_*_mapview, e.g.DATA 'sp_geometry FROM "vw_region_boundary_map" USING UNIQUE region_id USING srid=4326',DATA 'sp_centroid FROM vw_att_details_building_MAP USING UNIQUE system_id USING srid=4326',DATA 'center_line_geom FROM vw_att_details_row_map ...'. ~55 distinctvw_att_details_<entity>_mapviews are referenced (pole, cable, duct, trench, manhole, building, structure, splitter, spliceclosure, ADB/BDB/CDB/FDB, POD/MPOD, FMS, HTB, equipment, rack, cabinet, vault, ONT, customer, fault, area/dsa/csa/subarea/surveyarea/networkticket boundaries, …) — matching the ~60 map views indocs/database/01. These views join<geom>_master ⋈ att_details_<entity>onsystem_idand compute presentation fields (icon_path,color_code,label_column = network_id,upload_id = db_flag). - Projection / WMS.
PROJECTION 'proj=longlat' 'datum=WGS84'(EPSG:4326).WEB.METADATAsetsows_srs 'EPSG:4326',ows_enable_request '*'(so GetMap, GetFeatureInfo, GetCapabilities are all enabled),wms_allow_getmap_without_styles 'true'; output PNG/RGBA. (Note the SRID-0-vs-4326 mismatch fromdocs/database/01: the views compensate with explicitST_GeomFromText(...,4326).) - Attribute-driven styling.
CLASS/EXPRESSIONblocks key off DB columns:('[network_status]' eq 'P')Planned /'A'As-built /'D'Dormant (mapping to icon foldersicons/Planned|AsBuild|Dorment/),[entity_category](Feeder/Distribution/Drop),[pole_type],[building_status], and bindSYMBOL [image_icon]/COLOR [color_code]directly from view columns.VALIDATION/FILTERblocks accept runtime params (provinceFilter, label filters) from the WMS URL — i.e. per-request, per-user scoping without recompiling the mapfile. - GetFeatureInfo / identify. The map identify (“info” tool) is served by
GetFeatureInfoagainst the same views (the mapfile setsTEMPLATE 'fooOnlyForWMSGetFeatureInfo'), but the richer attribute panel in the UI is the MVC pathMain/GetEntityInfo→fn_get_entity_info(§6.3), not raw WMS. - Resources.
MapFiles/{conf,fonts,symbols,icons}hold EPSG defs, label fonts (Arial/Segoe/icomoon/flaticon), symbol defs, and ~68 status-categorised entity PNGs.
6. End-to-end traces (UI → Controller → BL → DA → fn_* → tables)
fn_*names are quoted from theDA*.cssource (authoritative). Tables use the authoritative DB names fromdocs/database/(the masters arepoint_master/line_master/polygon_master+att_details_*, not per-entity*_master).
6.1 Login / auth
Login/Index (POST) → BLUser.ValidateUser(user,pwd,type) → DAUser.ValidateUser(...) → fn_check_user_details → tables user_master (+ user_login_history via BLUserLogin.UpdateLogOutTime, user_permission_area for scope). Reversible-AES password (not hashed) per docs/database/07/08.
Files: BusinessLogics/BLUser.cs, DataAccess/DAUser.cs, Controllers/LoginController.cs, Global.asax.cs.
6.2 Load layer features (map)
Layer tree build → BLLayer.GetNetworkLayers(userId,groupId,roleId) → DALayer.GetNetworkLayers(...) → fn_get_network_layers → layer_details + layer_group_mapping (+ role_permission_entity for per-layer rights). Geometry tiles themselves come via WMS over vw_att_details_*_map (§5), not this call.
Files: DataAccess/DALayer.cs. Then per-feature identify → §6.3.
6.3 Open / edit an entity’s attributes (att_details + layer_details-driven form)
Main/GetEntityInfo(systemId,entityType,geomType) (POST) → BLMisc.getEntityInfo(...) → DAMisc.getEntityInfo(...) → fn_get_entity_info → reads att_details_<entity> ⋈ master, with the form/columns driven by layer_details (layer_form_url, info/search column config) and layer_details_column. Additional/dynamic attributes via DAAdditionalAttributes (→ entity_additional_attributes / other_info jsonb / osp_attribute_* per docs/database/02). GIS crosstab attributes via fn_get_gis_attribute.
Files: DataAccess/DAMisc.cs, DataAccess/DAAdditionalAttributes.cs.
6.4 Save / codify an entity (parent via ST_WITHIN + network code)
Library/SaveBuilding (or Save<Entity>) (POST) → BL<Entity>.Save<Entity>(...) → DA<Entity>.Save<Entity>(...):
- spatial parent resolution —
DAGeom.CheckGeomWithin→fn_Within(ST_WITHIN), backing the DB’sfn_get_parent_infoparent-by-containment logic; - network code —
DAMisc.getNetworkCodeDetails→fn_get_network_code+fn_Save_New_Network_Code(writesatt_details_<entity>.network_id, formatted vialayer_mapping.network_code_format); - persist geometry to
point_master/line_master/polygon_master+ attributes toatt_details_<entity>(source_ref_type='WEB'); - refresh map cache —
DAMisc.updateGeojsonEntityAttribute→fn_geojson_update_entity_attribute→<entity>_geojson_master. The heavy GIS-design-ID path (fn_auto_codification) is admin/batch, rarely run (docs/database/01). Re-codification UI = AdminMiscellaneous/ChangeNetworkCode→fn_get_new_networkcode/fn_save_change_network_code→entity_network_code_history. Files:DataAccess/DAMisc.cs,DataAccess/DAGeom.cs,DataAccess/DACable.cs/DABuilding.cs.
6.5 Splicing / OLT patching
Splicing/SaveConnectionInfo (POST) (or FiberAllocationTool/CreateSplicing, or WorkSpace OLT patching) → BLOSPSplicing / DAOSPSplicing:
- permission —
fn_Check_Splicing_Permission; - save —
fn_splicing_save_connections(JSON payload) → writes the directed edge tableconnection_info(source/destinationentity_type+system_id+port_no, tray, through-connection); - OLT/ODF port status —
fn_splicing_update_port_status→isp_port_info.port_status+ (viafn_trg_update_core_port_status) flipsatt_details_cable_infostrand status; - read/trace —
fn_splicing_get_connection,fn_get_schematic_view+fn_get_connection_info_path(the procedural cursor-walk + recursive CTE),fn_get_logical_view, butterfly viafn_get_vis_butterfly_network; - FAT auto-splice —
fn_fat_generate_splicing(2,895-line geometry-derived splicer) →fat_connection_info→ promoted toconnection_info; - delete —
fn_splicing_delete_connection. Files:DataAccess/DAOSPSplicing.cs,DAFATConnection.cs,DAWorkSpace.cs. Tables:connection_info,isp_port_info,att_details_cable_info,att_details_spliceclosure/_splice_tray,isp_model_*(docs/database/04).
6.6 Data upload (datauploader → temp_du_* → fn_uploader_*)
DataUploader/UploadFiles (POST) → create upload_summary job (fn_uploader_getuploadid) → bulk-insert raw rows into temp_du_<entity> (all-VARCHAR staging, named by layer_details.data_upload_table). Column map from data_uploader_template (DataUploader/getColumnMappping → fn_uploader_get_entity_template). DataUploader/ValidateData → fn_uploader_validate_parent_details (+ _validate_point/line/polygon, _check_termination_points) sets is_valid/error_msg in place; fn_uploader_get_invalid_record_count. DataUploader/ProcessData → fn_uploader_insert_<entity> (one per entity) → commits to att_details_<entity> + master (db_flag=upload_id, source_ref_type='DU') + fn_geojson_update_entity_attribute. Results grid via fn_uploader_getuploadlogs. Progress pushed over SignalR (DataUploader/GetStatus → SmartInventoryHub.BroadCastUploadStatus). SQL-injection risk in the uploader procs (docs/database/06).
Files: Controllers/DataUploaderController.cs, DataAccess/TempUpload/DAUploadSummary.cs, DATempCable.cs, DataAccess/DAMisc.cs; project DataUploader/.
6.7 WFM ticket
TicketManager/SaveTicket (POST, Network_Ticket) → BLTicketManager.SaveTicket → DANetworkTicket.SaveNetworkTicket → fn_nwt_insert_update_ticket (API path: fn_api_nwt_insert_update_ticket) → att_details_networktickets (+ ticket_status_master, ticket_type_master, ticket_type_role_mapping, ticket_steps_master state machine). Customer tickets → ticket_master; HPSM → hpsm_ticket_master. Entity edits from a ticket → fn_nwt_update_entity_info (writes master + att_details_*). Field execution via Workforce/* and the mobile FE API (getJobList/UpdateJobOrder). docs/database/07 covers the three parallel ticket subsystems.
Files: BusinessLogics/BLTicketManager.cs, DataAccess/DANetworkTicket.cs.
6.8 Admin config edits
- Layer Configuration —
Admin/LayerSettings/saveLayerConfigurationSettings(+SaveLayerDetail) →BLLayerMaster.SaveLayerSettings→DALayerMaster.SavelayerSettingDetails→fn_save_layer_settings_details→layer_details(thenApplicationSettings.InitializeGlobalSettings()reloads). Read =fn_layer_details_column_data/fn_get_layer_setting_details. - Vendor Specification (BOQ/costing) —
Admin/VendorSepcification/SaveVendorSpecification→BLVendorSpecification→DAVendorSpecification(insert/update) +fn_insert/update_specification_service_data; readfn_get_vendor_specification_details,fn_get_allvendor_list. Tables:item_template_master(cost/RFS catalog) +item_template_<entity>+vendor_master. Price-change triggers a notification email. - Equipment Builder (model hierarchy) —
Admin/Equipment/SaveModel+SaveModelMapping+SaveRule→BLISPModelInfo→DA→isp_model_info/isp_model_mapping/isp_model_rules/isp_model_type_master(the Equipment→Chassis→Slot→Card→Port→Tray parent/child rules). Files:BusinessLogics/Admin/BLVendorSpecification.cs,DataAccess/Admin/DALayerMaster.cs,DataAccess/Admin/DAVendorSpecification.cs,Areas/Admin/Controllers/{LayerSettings,VendorSepcification,Equipment}Controller.cs.
7. How the data model surfaces to users
The web client is essentially a thin renderer over the layer_details registry and the DB stored functions — almost every UI behaviour is config in a table or logic in a fn_*.
- Config-driven layer/entity model. The left layer tree, every Add/Edit form, the map styling, search, info panel, upload availability, mobile visibility, and report/history columns are all read from
layer_details(66 rows × 114 cols — ~80 capability booleans + table/view/URL pointers). Admin → Layer Settings / OSP Settings / Advanced Settings edit those columns; the app dereferenceslayer_form_url/save_entity_url/layer_table/layer_viewat runtime. New entity type ≈ a newlayer_detailsrow (plus itsatt_details_*table) — “config-not-code,” exactly the model the rewrite generalises. - Geometry ↔ attribute decoupling. The map shows
point_master/line_master/polygon_master(viavw_*_map); the info/edit panel shows the pairedatt_details_<entity>joined bysystem_id. Users never see the split —fn_get_entity_infore-joins it. - Equipment hierarchy. Equipment Builder exposes the physical Equipment → Chassis → Slot → Card → Port → Tray model (
isp_model_*) with parent/child placement rules and port layouts; OLT/ODF/rack are equipment models. This is what makes OLT patching and ISP splicing port-aware. - Vendor spec / BOQ. Vendor Specification + Item Templates surface
item_template_master/item_template_*as the costing/spec catalogue (cost per unit/metre, service cost, port/fibre info, sub-categories, A/B/C-RFS flags) that pre-fills placement forms and feeds BOM/BOQ. - Port-status vocabulary. Miscellaneous → ViewPortStatus exposes the port-status enum (Status, Color Code, Is Active, Is Manual, Is Splicing Allowed) that governs splicing and the
att_details_cable_infocore-status codes (1=available … 6) used by feasibility/utilization. - Codification. Saving an asset auto-generates
network_id(fn_get_network_code, parent resolved byST_WITHIN); Miscellaneous → ChangeNetworkCode re-codes with dependency checks. The hierarchical GIS-design-ID (fn_auto_codification) is a heavier admin/batch path. - Connectivity as an explicit graph. Splicing/FAT/OLT-patching write
connection_infoedges and flip port/strand status — the cleanest graph-shaped structure in the DB (docs/database/04).
8. Implications for the new platform
What a modern web client needs from the new API, vs the current coupling:
- A clean, versioned REST/GraphQL contract to replace ~75 server-rendered MVC controllers that return Razor partials + ad-hoc JSON, and the AGENTS-described pattern of controllers calling
BL → DA → fn_*directly (logic in 2,210 stored functions). The two OAuth APIs (/token,/GenerateToken) already define the external contract third parties depend on — preserve those semantics (slot/job-order, serviceability, FAT/OLT port reserve, dark-fiber feasibility, ticket/codes) behind a stable façade while re-implementing internals. - Schema-driven entity model as a first-class API, not 80 boolean columns + per-entity tables + per-entity
fn_get_template_detailbranches. Expose entity-type/attribute-schema metadata (thelayer_details+osp_attribute_defidea) so the client renders forms generically. - Drop the MapServer + 60
vw_*_map+ 60 geojson-cache dependency for modern vector tiles (single spatial source, GIST-indexed, declared SRID 4326), with attribute-driven styling done client-side from a typed style spec rather than.mapEXPRESSIONblocks. Remove the plaintext DB superuser credential indatashare.inc. - Connectivity/topology as a native graph API.
connection_infomaps 1:1 to typed graph edges (port/strand nodes); replace the proceduralfn_get_schematic_viewcursor-walk with native traversal so schematic / fiber-trace / OTDR / feasibility are real graph queries. - One generic ingestion service (template-driven, parameterised SQL, idempotent, transactional, auto-purged staging) replacing 44
temp_du_*tables + ~45fn_uploader_insert_*clones; keep thedata_uploader_template+upload_summaryconcepts. - Realtime via a modern channel (the SignalR upload/utilization push is genuinely useful) but decoupled from session/Forms-auth; keep a single, JWT-based identity with real MFA (the current OTP is configured-but-off; ADFS/AAD/LDAP/SSO multiplicity and the hardcoded master-password bypass must go).
- First-class multi-tenancy & integrity (the DB has no tenant key, 84 FKs, reversible passwords, a cross-customer
postgres_fdwlink) — the API must enforce tenant scope, typed keys, and audited codification/connectivity rather than relying on stringnetwork_id+ST_WITHINrecomputation.
Status: complete. Live UI capture grounds usage; controller/action/fn_*/table names are source- and DB-doc-derived. Table-name discrepancies between the .NET return-type inference and the authoritative smartinventory_qa schema were reconciled to the DB docs.
Appendix A — Live visual UI walkthrough (captured 2026-06-16)
Screenshots in references/ui-exploration/shots/ (W-main, W-toolbar, W-nelibrary, F-createmodel, F-layerconfig, adm-*, 02-dashboard). The full client action surface (4,081 distinct tooltip/onclick entries) is in references/ui-exploration/TOOL_INVENTORY.txt. All actions live in a single global JS namespace si.* (= SmartInventory), confirming a server-rendered jQuery monolith, not a componentized SPA.
A.1 Map workspace (/Products/main) layout
- Top blue bar:
SMARTINVENTORYlogo · centered “Enter a location” geocoder (Google) · a dense ~30-icon command toolbar · notification bell (SignalR count) · workspace/user menu · Admin dropdown (si.getWorkSpaces,si.getChangePassword,si.uploadProfileImage,si.SignOut). - Left “NETWORK LAYERS” panel: “Select All” + “Advanced Filters” (
si.GetProjecSpeciFilter/ClearProjectSpeciFilter), then a grouped layer tree (groups: Transmedia, Structure1, Structure, SPAN, Equipment, …) — each layer row has toggle columns (visibility / select / edit / label) + a live feature count. Layer rows are driven bylayer_details. - Map canvas: Google Maps base; feature layers as MapServer WMS image overlays; basemap toggles (
si.toggleBaseMap,toggleWhiteMap“No Map”). Bottom status bar: Coordinates · Version · Zoom · Legend.
A.2 The command toolbar — action inventory (grouped by si.* namespace)
- Create/edit entities: NE Library palette (
si.getNeLibrary) with the full entity creation palette (Wall Mount, Pole, PDP, Manhole, Central_Office, Building, Tree, CDB, Handhole, Cable, Trench, Duct, CPE, FDP, Cabinet, ATB, Tower, FDC, CSA/DSA boundary, SurveyArea, Fault, Customer, FAT, Splice Closure, ROW, CX, GX, Coupler, Loop, Patch Cord, GI Pipe, SubArea …); Single vs Group clone (si.GroupClone); Entity Along The Direction (si.entityAlongDirection); Layout auto-draw (si.toggleLayout); Merge Tool for cables (si.MiscellaneousTools.MergeTool); point Buffer (si.EnablePointBufferRadius). - Connectivity/splicing: Manual Splicing (
splicing.spliceHere), Bulk Splicing (splicing.toggleConnectionUpload), Connection Path Finder (splicing.SinglePathFind) — the live fiber-trace tool overconnection_info. - Workforce (SmartOps):
si.WorkForceManagement.*— Assign / View Assigned / View Unassigned Job Order (+RM/reporting-manager variants), Save/View Roster, WFM Dashboard (+RM), View User Permission Area. - Tickets:
si.Networkticket.*— Ticket Dashboard, Add Network Ticket, Draw Ticket Area. - Redline/markup:
si.Redline.*(Point/PolyLine/Polygon + dashboard). - Reports (each with draw-area Polygon/Rect/Circle): Entity Export Report, Entity Association Report, Utilization Report, Audit Log Report, Split Report, BOM/BOQ Report (+“FSA-wise overhead logics”), LMC (Last-Mile Connectivity) Report, ROW Report, VSAT Report, GeoTagged Images Report, Potential/homepass (
initiateDrawingsPotential), Menu Report. Each has an async export-log companion (*ExportReportLog). - Survey & upload: Survey Assignment (
Opensurveyassignment), Survey Building (OpenSurveyBuilding), Upload Buildings (si.toggleBuildingUpload), data upload (si.toggleUpload), Bulk Update (si.toggleBulkUpdate), XML Builder dashboard (si.xmlbuilderdashboard). - Map/print: Layer Manager (
showLayerManager), Print/Export with draw-area (si.togglePrint), search (si.performSearch). - Region navigator: a full India province→district tree (~2,544
si.EditRegionProvinceDetails(...,'SHOWONMAP',...)entries — every state & district), used to zoom/scope the map by administrative area (the “circle”/region dimension in UI form).
A.3 Admin / configuration area (/Products/admin/Home/index)
Left-nav modules: OLT Patching · Users · Dashboard · Layer Settings · Vendor Specification · Rights Management · Equipment Builder · Miscellaneous Feature · OSP Settings · Vendor · LandBase Layer Settings · Advanced Settings · API Consumer Master · Accessories · Help & FAQ’s. Key screens observed:
- Equipment Builder → Create Model: a CAD-style visual grid designer (“Scale: 1M grid = 50 mm”, grid-color palette, Model/Type dropdowns, Create/Save Model) for drawing the Equipment → Chassis → Slot → Card → Port → Tray model — plus View Model / View Model Images. This is how OLT/ODF/rack equipment templates (e.g. “22 Port OLT”, “96 Port ODF”) are authored.
- Layer Settings → Layer Configuration: edits
layer_details— but only exposes 5 fields (Layer Name, Minimum Zoom Level, Is Mobile Layer, Is Visible In Mobile Library, Is Visible On Mobile Map). ⇒ ~75 of the ~80 registry flags are NOT editable in the UI; they’re set at the DB/deployment level. “Config-not-code” is only partially realized for end users — deep entity behavior still requires DB changes (a key driver of per-customer forking). - Vendor Specification: the BOQ/costing catalog (Entity Type, Specification, Vendor, Item Code, Cost/unit, Service Cost, Port/Fiber Info, SubCat 1-3, Item Type, Unit, is A/B/C-RFS item).
- Rights Management: Roles + Role Module Mapping (role × module/layer grid →
role_module_mapping). - Miscellaneous: Core/Port Status Settings (Status, Color Code, Is Active, Is Manual, Is Splicing Allowed), Change Network Code (codification re-code), Ortho Image, User Activity Log.
- Users: Add/View User, User Login History, Bulk User Upload, User Tools (FE tools).
- API Consumer Master: registers third-party
IntegrationServicesclients (this is where the empty-password API-consumer finding lives).
UI takeaways for the rewrite: (1) the toolbar is an enormous flat set of modal tools driven by one global si.* object — the new UI wants a composable, permissioned action model; (2) entity creation is map-palette + clone-based — preserve, but back it with the typed schema; (3) reports are all “draw area → export + poll log” — a generic async export/job framework replaces ~12 bespoke report tools; (4) the visual Equipment Builder is a genuinely good feature worth re-imagining; (5) the admin UI exposes only a sliver of the config model — the new platform must make the whole entity/attribute schema safely tenant-editable.