Page 2 · Downstream Impact Map (v0.4)
v0.4: added Deck Segment (162) as a conditional component. Ordered by dependency — everything flows from the component master, so that goes first.
← Brief 1. Form 3. 2D Diagram 4. Pylon Types 5. Counting

What else breaks, and in what order

Build these in the order shown. Step 1 is foundational — nothing downstream works until the component IDs exist.

1

Component master — 4 new IDs, starting at 158

Next free ID is 158 (Miscellaneous = 157 is the current highest).

IDConfig keyDisplay nameUnitProgress model
158PylonLowerPylon (Lower)MtrHeight-based lifts
159PylonUpperPylon (Upper / Mast)MtrHeight-based lifts
160PylonCrossBeamPylon Cross BeamNosBinary (H / diamond / delta only)
161StayCableStay CableNos4-stage, per cable
162DeckSegmentDeck Segment CONDITIONALNosCast → Stressed (per segment)
Component 162 only exists if a span uses a cantilever or segment erection method

The new per-span erection_method field on the Super Structure form (page 1, change 4) decides this. A precast-launched span keeps the existing Girder cast → stress → launch model and needs nothing new. A form-traveller or precast-segment span has no discrete girders to count — the deck grows segment by segment as each stay cable is stressed — so it needs Deck Segment instead.

This is the CR's biggest cost fork, and making it a per-span field is what keeps it controllable. If Mindhola's four approach spans are precast-launched and only the three 150 m main spans are cantilevered, the segment model is confined to three spans rather than the whole bridge.

Cable stages reuse the existing Girder pseudo-ID pattern exactly
161_1  Anchorage Fixing 161_2  Cable Installation 161_3  Initial Tensioning 161_4  Final Stressing

Same shape as 18_1 / 18_2 / 18_3 for Girder cast/stress/launch. This pattern is already handled generically — BridgeComponentTargetServices splits on str_contains($componentId, '_'), and weightage keys are JSON strings. So cable stages need no schema change at all.

Three files must change together: config/constant/component.php · the matching function in ComponentSectionHelper.php · database/seeders/BridgeComponentSeeder.php. The config IDs are just auto-increment positions from the seeder, so they must stay in sync.
⚠ Open decision — which section do these belong to? It changes section-wise progress % and every report.
Our proposal: Pylon (both zones) → Substructure (a vertical support cast in lifts, like a pier) and Stay Cable → Superstructure (it's what carries the span).
No IRC code settles this — IRC:SP:65 covers segmental bridges, not cable-stayed. Client must choose.
2

Component plan generation — and a real bug risk

BridgesInventoryServices::updateBridgeInventory() needs a 5th bridge_pier_type branch. This is the only place that decides which components a bridge gets.

QUANTITIES READ FROM pile_details
Pylon Lower / Upper4
Pylon Cross Beam8
Stay Cable164
cables = Σ(cable_count_a1 + cable_count_a2) × planes
= (19 + 22 + 22 + 19) × 2 = 164
⚠ THE TRAP

Pier Wall quantity is currently hardcoded no_of_span - 1. On Mindhola that gives 8 pier walls — but only P1, P6, P7, P8 are actually piers.

Pier Wall = no_of_span - 1  → 8 ✗
Pier Wall = count(support_type == 'pier') → 4 ✓

Same for Pier Cap. Get this wrong and physical progress is permanently understated on every cable-stayed bridge.

3

Progress entry — two new screens

Both mirror something that already exists. Neither is built from scratch.

Pylon (Lower & Upper)Stay Cable
Progress modelHeight-based lifts — same as Pier WallItem + stage — same as Girder
Location keyp_2p_2
Item number—us_a1_cable_1
Stage column—reuse girder_step (int 1–4)
Closest existing screenprogressCreate/single_pier.blade.phpGirder 3-step form
Two components, one location

Lower and Upper pylon are two separate components at the same location p_2. That's new for BMS, but the schema already allows it.

Cable naming is permanent

plane → side → index. Lock it before any data entry. Renaming later is expensive — see how much of component.php exists purely for LHS/RHS variants.

Cables get re-stressed

Stay cables are routinely force-adjusted as adjacent deck advances. Stage 4 must not hard-lock the cable — allow repeat 161_4 entries with a remark.

Stressing is one operation per cable, not per end. Cables are jacked simultaneously at both ends, so a single progress entry covers the whole cable. No need to model deck-end and pylon-end separately.
4

Roll-ups — mostly "just include the new IDs"

THESE JUST NEED THE NEW IDS PRESENT — NOTHING MORE
getBridgeComponentsStatus() BridgeSectionProgressService::calculateOverall() BridgeComponentTargetServices FinancialDetailsService::computePhysicalPctAsOf() UpdateRunningBillProgressSnapshots::computePhysicalPct()
One exception needs real work

BridgeComponentProgressRepository::allCompletedItems() reshapes progress rows into five different shapes depending on component class. Two additions needed:

  • →Pylon (158, 159) joins the height-based branch, alongside AbutWall (3) and PierWall (5). Returns {'p_2': [3.5, 2.0, …]} — an array of incremental lifts.
  • →Stay Cable (161) needs a new step-based branch like Girder. Returns {'p_2': {'us_a1_cable_1': [1,2,3]}}.

Note: height entries are incremental pours, summed — not cumulative snapshots. Match the existing drawPier() math exactly.

5

Weightage

bridge_component_weights.weights is a JSONB blob keyed by component identifier string — so 161_1…161_4 slot straight in. No migration.

⚠ Sequencing matters more than the code here. On a cable-stayed bridge the pylons and cables are a large share of project cost. If weightage isn't signed off before progress entry starts, this bridge's physical progress % is wrong from day one and hard to correct retroactively.
6

Reports

  • Stay Cable Installation & Stressing Report — mirror GirderAgeingReportService. It's the established bulk-query pattern and maps almost one-to-one: planned / installed / tensioned / stressed counts plus a per-cable stage timeline.
  • Substructure Progress Report — extend for pylon, or add a parallel Pylon Progress Report.
  • Daily Progress Report, Custom PDF, Download Bridge Info — new components in filters and dropdowns.
  • PDF export resolves labels via dropdownLabel() against display-only config arrays — register pylon_shape there or it prints raw keys.
7

Mobile app

The mobile app has no screen for lift-wise pours or cable-stage updates. This is new scope, not a tweak, and should be estimated alongside the web work rather than after it.

Assumption: web-only for phase 1 — needs client confirmation.

8

Financial / Running Bill

Stay cables are typically a distinct, high-value BOQ line — often imported and specialist-subcontracted, with supply billed separately from installation.

Ask the client whether "cable procured / on site" needs tracking as a milestone separate from "installed & stressed" before the BOQ-to-component mapping is built.

Three traps found in the existing code

Plan rows are never deleted

Both updateBridgeInventory() and syncApproachComponents() only ever updateOrCreate. If a bridge's config changes so a component stops applying, the stale row persists and the component keeps appearing.

Plans only materialise on Final Submit

A "Save as Draft" bridge has zero component plan rows — so no components at all. Anyone testing this feature will hit it and think it's broken.

Unknown pier type renders a silently blank diagram

The SVG dispatch is an @if/@elseif chain with no @else, in two places. The moment someone sets a bridge to cable_stayed before the partial exists, they get an empty box with no error. Add a fallback branch first — it's a 5-minute fix that saves a confusing bug report.

Page 2 of 3 · Next: the 2D diagram →