SmartInventory Web UI — Splicing/Connectivity, OLT Patching & Entity Attribute Forms
Source-grounded documentation of three data-dependent screens that are hard to reach in the live demo (which has no loaded project data at the demo extent). Authoritative source = the repo
references/SmartInventory-3.0/Source/SmartInventory/, cross-referenced to the live demo (http://networkaccess.st.leptonsoftware.com, product v8.16.4.0, admin login) and todocs/database/04-isp-ports-splicing-connectivity.md. READ-ONLY exploration — no form was ever submitted, no Save/Delete/Update clicked, no DB row mutated.Repo paths below are relative to
Source/SmartInventory/unless noted. The repo (branded “SmartInventory-3.0”) and the live demo differ slightly in version/customer config; where they diverge it is called out. Some controller line numbers cited by automated tracing are approximate — file paths, action/JS/view names, endpoints,fn_*names and DB tables are verified.
0. Shared conventions (apply to all three screens)
- 3-layer flow: Controller (
SmartInventory/Controllers/*.cs) →BusinessLogics/BL*.cs→DataAccess/DA*.cs→ PostgreSQLfn_*stored procedure. UI is server-rendered Razor partial views loaded by jQuery AJAX into modals/panels. No SPA, no module bundler. - Two parallel web apps render splice/patch UIs from near-identical view trees: the main app
SmartInventory/and the mobile/API appSmartInventoryServices/(its ownContent/js/Splice/andViews/Splicing/). - Global JS namespaces (verified live):
si.*(735 functions — map, entities, info windows) andsplicing.*(80 functions — splicing, patching, path-find). The splicing object is aliasedappinsideSplicing.js. - Connectivity is an explicit directed edge table
connection_info(26,325 rows in QA), keyed by composite logical endpoints(entity_type, system_id, port_no)— not FKs. Traversal is procedural PL/pgSQL (temp-table cursor walk + final recursive CTE). Seedocs/database/04-isp-ports-splicing-connectivity.mdfor the full data-model analysis.
1. Splicing / connectivity diagram UI
1.1 What it is
A jsPlumb drag-to-connect port diagram. Confirmed live: splicing.createConnection() runs app.mainJSPlumb = jsPlumb.getInstance() and draws Bezier connectors between port DOM nodes. The bundled library is jsPlumb 1.4.1 (SmartInventory/Content/js/Splice/Js-Plumb-1.4.1.min.js); the SmartInventoryServices splice app additionally bundles html2canvas and canvg.min.js (SmartInventoryServices/Content/js/Splice/) to export the diagram to an image/PDF.
1.2 Entry point and the splice entity panel
The user activates the splice tool from the map toolbar (live: button title “Manual Splicing” → onclick="splicing.spliceHere(this)"). When the map is zoomed in past level 18 and the user clicks a location, splicing.initiateSplicing(e) fires:
ajaxReq('Splicing/Index', { latitude, longitude, bufferRadius }, ...) // splicing.initiateSplicing- Controller:
SplicingController.Index(double latitude, double longitude, double bufferRadius)→BLOSPSplicing.getEntityForSplicing(lat,lng,bufferRadius,role_id)→PartialView("_Splicing", …). - DA → DB:
DAOSPSplicing→fn_splicing_get_entity(longitude, latitude, p_buffer_radius, p_role_id)(returns equipment within the buffer). - View:
SmartInventory/Views/Splicing/_Splicing.cshtml— the splice entry panel. Live capture (splice-03-entitypanel.png) shows: two modes “Cable to Equipment” and “CPE to Customer”; a “Filter cables on device only” checkbox; Equipment / Left Cable / Right Cable pickers; a port-status legend (Selected / ISP Equipment / Virtual); and the Splice button.
1.3 The connection diagram (nodes & edges)
Choosing the source/destination opens the diagram via a POST to one of:
SplicingController.CableToCable(connectionInput)→_CableToCable.cshtml(cable↔cable, or cable↔equipment).SplicingController.ODFToCable(connectionInput)→_ODFToCable.cshtml.SplicingController.CPEToCustomer(connectionInput)→_CPEToCustomer.cshtml(manual CPE→customer).
Which one is chosen is driven by the connecting entity’s capability flags, decided in JS (splicing.splicingWindow — verified live):
let _isMiddlewareEntity = $(... ':selected').attr('data-is-middleware-entity') == 'true';if (_isMiddlewareEntity) { app.FMSSplicingWindow(); } else { app.cableToCableSplicing(); }is_middleware_entity is a layer_details flag — in QA only FMS is middleware (see DB doc).
Visual NODES rendered in the diagram are ports, laid out as left/right columns:
- Cables (
.leftFiber/.rightFibercontainers) decomposed to tube → core → fiber strand elements (.tube,.innerFiber/.otherEndFiber). A cable’s “ports” are fiber strands fromatt_details_cable_info(one row per cable/tube/core/fiber; ~1.0M rows in QA), carryingtube_color/core_color/fiber_usage_status/is_connected. - Equipment ports (ODF/FMS/Splitter/HTB/ONT/PatchPanel) from
isp_port_info(port_number,input_outputI/O,port_status_id). - Each port DOM node carries
data-system-id,data-entity-type,data-port-no,data-is-connected,data-status-id,data-is-cable-a-end,data-network-id,data-link-id, anddata-is-multiconnection. Port-id pattern:Left_<sysid>_CABLE_<core>,Right_<sysid>_CABLE_<core>,<sysid>_<TYPE>_<port>.
Edges (splices) are jsPlumb connectors:
- Connected = teal
#00ba8a; through-connection (straight pass-through, same core both sides) = grey#808080; vacant = grey. jsPlumb endpoints areDot(radius ~3.5), connector = Bezier (curviness ~100),maxConnections: 1per port. splicing.InitilizeJsPlumb()adds endpoints to.src/.trgnodes;splicing.getConnections()reads existing connections from the rendered DOM (data-is-connected-to-same) and callssplicing.createConnection(sourceId, targetId)to draw them.
1.4 Tube / core color coding (12-color fiber standard)
Configured in the admin OSP settings, not hard-coded:
Admin/OSPSettings/TubeCoreColorSettings— gridNumber | Color Character | Color, with atypeselector of Tube / Core. This is the 12-color (Blue, Orange, Green, …) fiber position standard, editable per deployment.Admin/OSPSettings/ViewCableMapColorSettings— percable_type(Underground/Aerial/Overhead) ×cable_category×fiber_count(2/6/12/24/48/96/144/192/288) color codes. The colors come back on the strands viaatt_details_cable_info.tube_color/core_colorand are surfaced in the diagram (fn_get_schematic_viewresolves color codes per hop).
1.5 Loading existing connections (read path)
- List/grid:
SplicingController.GetConnectionInfo(...)→DAOSPSplicing→fn_get_connection_info. - Splice diagram port+connection state:
CableToCable→BLOSPSplicing.getSplicingInfo(connectionInput, …)→fn_splicing_get_connection. The action also loads the port-status legend viaBLPortStatus().getPortStatus(), the available-port count viagetAvailablePorts, and gates editing behind theEDSmodule permission (lstUserModule.Contains("EDS")). - Schematic / path view:
SplicingController.SchematicView(...)→DAOSPSplicing→fn_get_schematic_view(478-line traversal: imperative edge-walk overconnection_infointo aCPF_TEMP_RESULTtemp table, finished with aWITH RECURSIVECTE infn_getchildren_connection_info_path). View:Views/Splicing/SchematicView.cshtml(+_EntityLogicalView.cshtml,_EntityLogicalViewDiagram.cshtml).
1.6 Creating a splice (save path — described, NOT executed)
- User drags a connector between two ports;
splicing.crossConnect()/splicing.getConnectionsData()build connection objects (range-based bulk viasplicing.spliceAll/splicing.cableToCableSplicing). - JS posts the array to
POST Splicing/SaveConnectionInfo→SplicingController.SaveConnectionInfo(List<ConnectionInfoMaster> objConnectionInfo). BLOSPSplicing.SaveConnectionInfo(JsonConvert.SerializeObject(objConnectionInfo))→DAOSPSplicing.DAConnectionInfo→fn_splicing_save_connections(p_connections := <json>)(405-line proc): validates (fn_validate_splicing), inserts intoconnection_info, and thefn_trg_update_core_port_statustrigger flipsatt_details_cable_info.is_connectedandisp_port_info.port_status. OSP/ISP cable-split re-pointing usesfn_splicing_save_osp_split_connection/fn_splicing_save_isp_split_connection.ConnectionInfoMasterfields:source_*/destination_*(system_id, entity_type, port_no, network_id),is_source_cable_a_end,equipment_system_id/equipment_entity_type,equipment_tray_system_id,is_through_connection,splicing_source(OSP_SPLICING/ISP_SPLICING/ …).
- Delete:
Splicing/deleteConnection→fn_splicing_delete_connection. - Bulk upload: live
splicing.toggleConnectionUpload()→ modalSplicing/UploadConnection→_UploadConnection.cshtml(Excel/CSV bulk splice import).
1.7 OSP vs ISP vs SpliceTray
| Plant | Entities | View / JS | splicing_source | |
|---|---|---|---|---|
| OSP splice | Outside | Cable ↔ SpliceClosure (att_details_spliceclosure), FMS, ODF, distribution boxes (ADB/BDB/CDB), Cabinet | _CableToCable.cshtml, _ODFToCable.cshtml; Splicing.js, OSPSplice.js | OSP_SPLICING / OSP SPLIT |
| ISP splice | Inside (building) | HTB / FDB / Splitter / ONT / PatchPanel in floor/shaft/room | ISPSplice.js (jsPlumb on a room/building diagram), room-view/ConnectionBuilder.js, _ModelConnections.cshtml | ISP_SPLICING |
| Splice tray | Either | Trays inside a closure (att_details_splice_tray: parent_system_id→closure, tray_number, no_of_ports) | SpliceTray.js; tray recorded on the edge via connection_info.source_tray_system_id/destination_tray_system_id (21,408/26,325 edges reference a tray) | — |
1.8 FiberAllocationTool (FAT) and Connection Path Finder
- FAT (auto-splice from geometry):
Controllers/FiberAllocationToolController.cs→BLFATConnection→DAFATConnection. Commands callfn_fat_getconnection_details,fn_fat_generate_splicing(2,895-line proc — follows cables that spatiallyST_INTERSECTS/snap to a feeding FDP/closure and auto-generates splices intofat_connection_info), andfn_fat_update_connection_status(Accept/Reset temp splicing). View:Views/FiberAllocationTool/_FAT_Allocation.cshtml. Live: the layer tree shows FAT as a layer (mapped from internalFDB). - Connection Path Finder: live toolbar “Connection Path Finder” →
splicing.SinglePathFind(value)opens modalSplicing/ConnectionPathFinder(_ConnectionPathFinder.cshtml); trace data fromfn_get_connection_info_path. A separate “Common Path Finder” →si.openLinkSearch(). Optical-link budget views:_OpticalLinkBudget.cshtml,_ViewLinkBudgetDetail.cshtml,_viewlossdetails.cshtml.
2. OLT Patching UI
2.1 What / where it is
In the live admin nav (/Products/Admin/...) “OLT Patching” is a top-level item with href="#" (a dynamic-module menu entry, no literal string in the repo source — it comes from the module_master/sub_module_master config tables, so the label is deployment-specific). It opens the equipment connection editor, which is served by the Splicing controller, not a dedicated OLT controller. (The repo has no OltPatching/OLTPatching controller; the live demo’s separate “Equipment Config” group — EquipmentModelConfig controller with ViewAttributeDefs / ViewSectionConfigs / Dependencies — is a newer addition not present in this repo snapshot.)
2.2 The patch editor (grid/matrix)
- JS:
SmartInventory/Content/js/room-view/ConnectionBuilder.js(objectconnectionBuilder, instantiated asconBuilder). It is jsPlumb-based (this.mainJSPlumb,InitilizeJsPlumb(),addEndPoint()adding endpoints to.src/.trgnodes filtered bydata-is-multiconnectionanddata-status-id). Opens the editor via:ajaxReq('Splicing/ModelConnections', _data, ...) // ConnectionBuilder.js:870var dataURL = 'Splicing/ConnectionEditor'; // ConnectionBuilder.js:207 (and Splicing.js:2865)var dataURL = 'Splicing/FilterConnection'; // ConnectionBuilder.js:927 - Controller:
SplicingControllerConnectionEditor()→PartialView("_ConnectionEditor", PatchingViewModel)— the editor shell.FilterConnection(ConnectionFilter)→getModelSplicingInfo(SourceEquipmentId, "Equipment", DestinationEquipmentId, "Equipment", isInsideConnectivity)→_ConnectionEditor.ModelConnections(ConnectionFilter)→ same BL, returns_ModelConnections(the inner connection grid).
- Views:
Views/Splicing/_ConnectionEditor.cshtml(source/destination equipment dropdownsddlSourcePort/ddlDestinationPort→conBuilder.filterConnections(this,…); port-status legend; Save-as-PDF; Unlink-All; renders@Html.Partial("_ModelConnections", Model)for the matrix) andViews/Splicing/_ConnectionFilter.cshtml. - Live capture (
olt-04-connectioneditor.png): the editor scaffold — “Select the equipment to view the connections” + Filter button. The port matrix renders only after two equipment units are selected (needs loaded equipment data — none in the demo extent).
2.3 What it patches & the port hierarchy
Patches OLT/equipment ports ↔ ODF / splitter / equipment ports (left equipment ports → right equipment ports, organized by the parent Chassis/Card). Ports come from isp_port_info (port_number, input_output, port_status_id, parent_system_id, parent_entity_type such as equipment/Splitter/PatchPanel; port_type includes ODFPORT, OpticalPort, PowerPort). Loaded via:
DAOSPSplicing→fn_splicing_isp_model_get_connection(p_source_system_id, p_source_entity_type, p_destination_system_id, p_destination_entity_type, p_port_type)— the model-rule-aware patch matrix (applies theisp_model_*parent/child rules to decide which ports may legally connect).- Port list per equipment:
fn_get_equipement_port(p_system_id, p_entity_type). - Export:
fn_export_patching_report.
The equipment-model port hierarchy is Equipment → Chassis → Slot → Card → Port → Tray, defined in the Equipment Builder (live admin: Admin/Equipment/CreateModel, ViewModels). Model/port templates live in the isp_model_* catalogue (isp_model_info, isp_model_mapping, isp_model_rules, isp_model_type_master, isp_base_model, plus isp_template_*) and parent/child model_id rules; specifications seen live include “22 Port OLT”, “96 Port ODF”, “16 Port”, “Generic”. The placed-equipment instance lives in the att_details_model table; its ports in isp_port_info.
2.4 Port status (Is Splicing Allowed / Is Active / Is Manual)
The legend and per-port connectability come from the Core/Port Status master (live admin: Admin/Miscellaneous/ViewPortStatus — columns Status, Color Code, Is Active, Is Manual, Is Splicing Allowed), loaded by BLPortStatus().getPortStatus() and rendered into _ConnectionEditor.cshtml/_ModelConnections.cshtml. Each port node’s data-status-id controls whether jsPlumb lets it accept a connector (blocked statuses are non-droppable); status 1 = vacant. Saving a patch flips the port status (and, for cable strands, att_details_cable_info) via the fn_trg_update_core_port_status trigger.
2.5 Save path (described, NOT executed)
Patches are posted to Splicing/SaveConnectionInfo → BLOSPSplicing.SaveConnectionInfo(json) → fn_splicing_save_connections, writing rows to connection_info (same edge table as splices; the connection_info_master name some traces use is incorrect — the live table is connection_info). Delete = Splicing/deleteConnection → fn_splicing_delete_connection.
3. Entity attribute form (add / edit / info)
3.1 How it is built — schema-driven, two-part
The add/edit form is not hand-coded per entity. It is composed of (a) a per-entity Razor partial that lays out the fixed/known tabs, plus (b) a dynamic EAV section generated from the dynamic_controls table. Routing is data-driven from layer_details.
Live proof (NE Library DOM, entform-04-nelibrary.png + pass4 capture): every layer in the left “NETWORK LAYERS” / NE-Library tree carries its full add/edit contract as data-* attributes, e.g. for Pole:
data-lyrname="Pole" data-title="Pole" data-geomtype="Point" data-networkidtype="A"data-istemplate="True" data-isdirectsave="False"data-href="Library/AddPole" (= layer_details.layer_form_url)data-save-url="Library/SavePole" (= layer_details.save_entity_url)The full set captured live includes Pole, WallMount, Manhole, Building, Tree, Handhole, CDB, Cable(Line), Trench(Line), Duct(Line), Cabinet, Tower, ROW, CSA/SurveyArea(Polygon), Fault, Customer, and the equipment entities under their customer display labels that differ from the internal data-lyrname:
FAT→FDB, Central_Office→POD, CPE→ONT, ATB→HTB, FDP→FMS, PDP→ADB, FDC→BDB. (This label/entity remapping is exactly the customer-spec relabeling driven by layer_details.)
3.2 The endpoints and JS that open the form
- Open (JS):
si.GetEntityAttrDetails(libItem)reads thedata-*off the clicked library item;si.SetEntityAttributes(layerDetails)(from alayer_detailsobject);si.CreateEntityFromInfo(_data)(re-create from an info window). These resolvelayer_form_url/save_entity_url/is_direct_save/is_template_requiredand callpopup.LoadModalDialog(..., pageUrl, ...).si.geomToForm(...)binds the drawn map geometry to the form. (Live:SetEntityAttributes('Pole')opens the dialog but it renders empty without a drawn geometry/system_id— the form is geometry-bound and needs project data.) - Controller action that RETURNS the form:
<Controller>.Add<Entity>()returnsPartialView("_Add<Entity>", model). Two controllers:Controllers/LibraryController.cs— OSP/outdoor + most layers:AddPole/SavePole,AddCable/SaveCable,AddSpliceClosure,AddFMS,AddFDB,AddHTB,AddBuilding,AddManhole, etc. (URLs verified live fromdata-href/data-save-url).Controllers/ISPController.cs— inside-plant entities (Splitter, BDB/ADB/CDB, Room, ONT, Customer, Rack, Equipment, OpticalRepeater).- Direct GET of
Library/AddPolereturns an Error page — these are POST-only partials requiring session form-state; they are only reachable through the JS add flow with a geometry. (Hence no clean blank-form screenshot — see §4.)
- Info/edit on an existing feature:
si.OpenElementInfoWindow/si.showElementInfo/si.ShowDetailFromInfoopen the info window; edit reusesAdd<Entity>partial pre-filled bysystem_id.
3.3 The dynamic field section (EAV)
- Controller calls
BLDynamicAttributes.GetDynanicControlsById(layer_id)(→DADynamicAttributes, EF query onDbSet<DynamicControls>whereentity_id == layer_id && is_visible, ordered byfield_order) andGetDDLByControlsId(...)for dropdown options. - Model:
Models/AdditionalAttributes.cs—DynamicControls(field_label,field_name,control_type,is_mandatory,is_visible,min_length,max_length,format,default_value,placeholder_text,control_css_class,field_order),DynamicControlsDDLMaster(control_id,value_text,display_text,is_default), and the view-modelvm_dynamic_form(lstFormControls,lstFormDDLValues). - Partial (verified):
Views/Shared/_AdditionalAttributesForm.cshtmlrenders a 2-column chunked layout, switching oncontrol_type.ToUpper():TEXT→<input type=text>withminlength/maxlength/data-val-required.DATETIME→ readonly<input>+ calendar picker (si.setDateTimeCalendar).DROPDOWN→<select>populated fromlstFormDDLValues.Where(x => x.control_id == item.id); validated byfnValidateDropdownValue(...).- Mandatory fields marked
<i class="clsMandatory">*</i>.
- Tabs in the per-entity partial (
_Add<Entity>.cshtml): GIS info, Item Spec (vendor/template), Port info (equipment), Barcode (ifis_barcode_enabled), POD association, Additional Attributes (the EAV partial), Reference/attachments. Shared tab partials:_ProjectSpecification.cshtml,_OwnershipInfo.cshtml,_Reference.cshtml,_GeographicDetails.cshtml.
3.4 Field types, masters, barcode, attachments
- Master dropdowns are populated from drop-down master tables (admin:
Admin/Miscellaneous/DropDownMaster,ManageDropdownValues) andDynamicControlsDDLMaster. - Vendor-spec / template pickers: controlled by
layer_details.is_vendor_spec_requiredand the livedata-istemplate(=is_template_required). Bound viaBLItemTemplate.Instance.BindItemDropdowns(model, entityType); fieldsspecification,category,subcategory1..3,item_code,vendor_id, etc. Catalog admin:Admin/VendorSpecification/*,Admin/Template/*→item_template_*tables. - Barcode:
layer_details.barcode_column+is_barcode_enabled; helper inSmartInventory/Helper/(barcode generator). - Attachments/photos:
si.uploadDocumentFile/si.deleteEntityImage/downloadDocsFullParams.
3.5 network_status context (Planned / As-Built / Dormant)
Stored on each entity as network_status (single-char: P Planned / B As-Built / D Dormant). On save, DA<Entity> defaults it to "P" if empty. The form shows it via Utility.MiscHelper.GetNetworkStatus(network_status.ToUpper()), and edit permission is gated by status (Utility.MiscHelper.GetLayerEditPermission(system_id, …, network_status, …)) — e.g. As-Built may be locked from casual edits.
3.6 Save mapping
On submit, JS serializes the dynamic section to JSON into hidden #hdnOtherInfo (AdditionalAttributesUtility.SetJsonValue(...) in Content/js/Utility.js) and POSTs to the layer’s save_entity_url (e.g. Library/SavePole). <Controller>.Save<Entity>(model) → BL<Entity>.Save<Entity>Entity → DA<Entity> writes the fixed columns to att_details_<entity> (e.g. att_details_pole, att_details_spliceclosure, att_details_building) and stores the EAV blob in the entity’s other_info JSON column; masters resolve to item_template_* / drop-down master tables. The geometry is written to point_master / line_master.
4. Live capture attempt (read-only)
Re-logged in fresh (admin / Demo@2023 → /Products/main), enumerated si.* (735 fns) and splicing.* (80 fns), and exercised the JS entry points. No form was submitted; no Save/Delete/Update clicked. Screenshots saved under references/ui-exploration/shots/detail/. Capture scripts: capture_three_screens.py, capture_pass2.py, capture_pass3.py, capture_pass4.py, capture_pass5.py (findings JSON alongside).
| Screen | Captured | What it shows |
|---|---|---|
| Splice entity panel | splice-03-entitypanel.png | Real _Splicing partial: Cable-to-Equipment / CPE-to-Customer modes, cable pickers, Selected/ISP-Equipment/Virtual legend, Splice button |
| Connection Path Finder | splice-01-pathfinder.png | Splicing/ConnectionPathFinder modal (splicing.SinglePathFind) |
| Bulk Splicing upload | splice-02-bulkupload.png | Splicing/UploadConnection modal |
| OLT Patching editor | olt-04-connectioneditor.png | Real _ConnectionEditor scaffold (“Select the equipment to view the connections” + Filter). |
| OLT Patching nav / admin | olt-02-patching.png, olt-03-adminhome.png | Admin nav showing top-level OLT Patching (href="#"), Equipment Builder, Core/Port Status |
| NE Library / layer tree | entform-04-nelibrary.png (+ entform-01/02, ne-01-library.png) | Left “NETWORK LAYERS” tree = the add-entity palette; full data-href/data-save-url/data-istemplate contract per layer read from the DOM |
Unreachable live (and why):
- The fully-rendered jsPlumb splice diagram (cores connected to ports): needs a real cable+equipment pair with ports; the demo has no project data at the demo extent (Select-All loaded no WMS feature tiles), so the diagram body renders empty. The entry panel was captured; the diagram structure is documented from
_CableToCable.cshtml/Splicing.js. - The OLT patch matrix populated with ports: same reason —
_ConnectionEditorshows only the “select equipment” prompt; no equipment models exist to select. Scaffold captured. - The populated entity add/edit form:
Library/Add<Entity>is a POST-only partial bound to a drawn geometry/system_id; callingsi.SetEntityAttributes('Pole')opens an empty dialog (no geometry), and a direct GET returns an Error page. The form’s exact field set is documented from_AdditionalAttributesForm.cshtml+layer_details+ the livedata-*contract instead.
5. Implications for the new platform
- Replace the jsPlumb-over-Razor splice editor with a real graph-backed splice editor. Today the diagram is reconstructed in the browser from server-rendered DOM nodes whose connectivity is re-derived (
getConnections()readsdata-is-connected-to-same), and persisted through a 405-linefn_splicing_save_connections+ a trigger that mutates two other tables. The new platform should drive the editor directly off a typed(node, edge)graph: ports are first-class nodes (cable strand =att_details_cable_infogranularity preserved), splices are edges with provenance (splicing_source,fat_process_id), and the editor reads/writes the graph API rather than HTML. Keep the through-connection and A/B cable-end concepts as edge metadata. - Model ports/patching as a typed component+port template system. The
Equipment→Chassis→Slot→Card→Port→Trayhierarchy and theisp_model_*parent/child rules are sound config-driven concepts — carry them forward as a component/port-template catalogue, but enforce port direction (I/O), capacity, and “splicing allowed” as constraints, not the current free-varcharport_status+ function-only checks. OLT patching and OSP splicing should be one connection model with different endpoint types, not two parallel code paths (ConnectionEditorvs_CableToCable) over the sameconnection_infotable. - Make the entity form genuinely schema-driven and decouple it from .cshtml partials. The good bones already exist:
layer_details(form URL, save URL, flags) +dynamic_controlsEAV +_AdditionalAttributesForm.cshtml. But fixed fields still live in ~40 hand-written_Add<Entity>.cshtmlpartials, EAV values are dumped into an opaqueother_infoJSON blob, and labels are remapped per customer inlayer_details. The rewrite should serve one schema endpoint returning a full field manifest (fixed + dynamic, types, validation, masters, vendor/template pickers, barcode, attachments,network_statusrules) and render it with a single generic form renderer — eliminating per-entity views and the JSON-blob round-trip, while keepingnetwork_status(Planned/As-Built/Dormant) as a first-class lifecycle attribute with edit-gating.
Appendix — key source paths
- Splicing JS:
SmartInventory/Content/js/Splicing.js,OSPSplice.js,ISPSplice.js,SpliceTray.js;Content/js/room-view/ConnectionBuilder.js,EquipmentEditor.js,rack-manager.js,room-manager.js;Content/js/Splice/Js-Plumb-1.4.1.min.js. API app:SmartInventoryServices/Content/js/Splice/(Js-Plumb-1.4.1, html2canvas.js, canvg.min.js). - Splicing views:
SmartInventory/Views/Splicing/(_Splicing,_CableToCable,_ODFToCable,_CPEToCustomer,_ConnectionEditor,_ConnectionFilter,_ModelConnections,_ConnectionPathFinder,SchematicView,_OpticalLinkBudget,_UploadConnection,_ViewPortHistory, …). FAT:Views/FiberAllocationTool/_FAT_Allocation.cshtml. - Controllers:
Controllers/SplicingController.cs(Index, CableToCable, ODFToCable, CPEToCustomer, SaveConnectionInfo, deleteConnection, ConnectionEditor, FilterConnection, ModelConnections, SchematicView, GetConnectionInfo),Controllers/FiberAllocationToolController.cs,Controllers/LibraryController.cs,Controllers/ISPController.cs. - BL/DA:
BusinessLogics/BLOSPSplicing.cs,BLFATConnection.cs,BLSpliceTray.cs,BLDynamicAttributes.cs,BLPortStatus.cs/BLMisc.cs;DataAccess/DAOSPSplicing.cs,DAFATConnection.cs,DADynamicAttributes.cs. - Entity form:
Views/Shared/_AdditionalAttributesForm.cshtml,Views/ISP/_Add*.cshtml,Models/AdditionalAttributes.cs,Content/js/Utility.js(AdditionalAttributesUtility),Content/js/ISP.js,Content/js/DynamicForms/dynamic.js. - DB:
connection_info,fat_connection_info,att_details_cable_info,isp_port_info,att_details_spliceclosure,att_details_splice_tray,att_details_patchpanel,att_details_model,isp_model_*,item_template_*,att_details_<entity>,layer_details,dynamic_controls,dynamic_controls_dropdown_master. Procs:fn_splicing_get_entity,fn_splicing_get_connection,fn_get_connection_info,fn_get_schematic_view,fn_get_connection_info_path,fn_splicing_isp_model_get_connection,fn_get_equipement_port,fn_splicing_save_connections,fn_splicing_delete_connection,fn_validate_splicing,fn_trg_update_core_port_status,fn_fat_generate_splicing,fn_fat_getconnection_details,fn_fat_update_connection_status,fn_export_patching_report.