Add BIM/VDC work packages, platform links, and AWP traceability
SOP tool: - "Load BIM / VDC template" (Step 4): one click sets BIM deliverable types, install-phase disciplines, BIM release-gate constraints (with EN06 citations), the BIM process sequence, reference sources, BIM sign-off roles, and MWP##-[Area]-[PHASE] numbering. Tags the SOP mode as 'bim'. - Step 3 required sign-off role titles are now editable (default Superintendent/Foreman); the BIM template sets them to BIM Coordinator and Construction Lead (CRS). - Step 7: capture a project-homepage link for the chosen tracking and commissioning platforms. Work Package Creator: - BIM mode (SOP.mode==='bim'): hides controls.dev Assets, Material List, and Kitting/MIMO; shows a BIM Details card (LOD, model area, clash / coordination status, linked scan). - Project tracking/commissioning links are copied onto every WP and shown in the WP output. - "Enabled by - BIM package(s)" field links a field IWP back to the BIM package that enabled it (EWP -> IWP traceability). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ function onSizePresetChange(){
|
||||
}
|
||||
|
||||
let state = {
|
||||
mode: 'standard', // 'standard' (field IWP) | 'bim' (BIM/VDC EWP) — set by the BIM template
|
||||
project: {name:'', number:'', client:'', division:'', site:''},
|
||||
team: {pm:'', apm:'', cm:'', qm:''},
|
||||
teamMembers: [],
|
||||
@@ -31,7 +32,7 @@ let state = {
|
||||
wpTypes: [],
|
||||
governance: {woformat:'', wosize:'', issuance:[], disciplines:['Mechanical','Electrical','Tech'], discMode:'choice', instanceSuffix:'letter', sizeHoursMax:''},
|
||||
quality: {qcreq:'', photo:'', hold:''},
|
||||
platforms: {tracking:'CxAlloy', commissioning:'CxAlloy'},
|
||||
platforms: {tracking:'CxAlloy', commissioning:'CxAlloy', trackingUrl:'', commissioningUrl:''},
|
||||
sequence: [],
|
||||
constraints: [],
|
||||
sources: []
|
||||
@@ -92,7 +93,14 @@ const OPTIONAL_ROLES = [
|
||||
'Quality Representative',
|
||||
'Planner',
|
||||
'Safety Manager',
|
||||
'Project Controls Manager'
|
||||
'Project Controls Manager',
|
||||
// BIM / VDC roles (used by the BIM template; also selectable on any SOP)
|
||||
'BIM Coordinator',
|
||||
'BIM Modeler / Detailer',
|
||||
'VDC Manager',
|
||||
'Construction Lead (CRS)',
|
||||
'Field Lead',
|
||||
'General Contractor'
|
||||
];
|
||||
|
||||
const LABOR_COST_CODES = [
|
||||
@@ -137,6 +145,101 @@ const LABOR_COST_CODES = [
|
||||
'9000|Administration'
|
||||
];
|
||||
|
||||
// ── BIM / VDC TEMPLATE ──────────────────────────────────────────────────────────
|
||||
// The BIM/VDC department also produces work packages under Advanced Work Packaging —
|
||||
// model & engineering deliverables (EWPs) that feed the field's install packages.
|
||||
// These defaults are drawn from the EN06 SOP + work instructions and are applied by
|
||||
// loadBIMTemplate() (the "Load BIM / VDC template" button on Step 4). Everything
|
||||
// remains editable afterward.
|
||||
const BIM_WP_TYPES = [
|
||||
'Model Area Package', 'Conduit Routing Package', 'Coordination / Clash Package',
|
||||
'First-of-Kind (FOK) Package', '2D Installation Sheet Set', 'Field Detailing / Markup Package',
|
||||
'Laser Scan Package', 'As-Built Model / Drawings'
|
||||
];
|
||||
// BIM "disciplines" are the install phases work is broken into (EN06-SOP §4.1.2.5).
|
||||
const BIM_PHASES = [
|
||||
'Cable Tray & Hangers', 'Conduits & Hangers', 'Wall & Slab Penetrations',
|
||||
'Panels & Instrument Racks', 'In-wall Instruments & Stud-ups'
|
||||
];
|
||||
const BIM_TEMPLATE_ROLES = [
|
||||
'BIM Coordinator', 'BIM Modeler / Detailer', 'VDC Manager',
|
||||
'Construction Lead (CRS)', 'Field Lead', 'General Contractor'
|
||||
];
|
||||
// Release-gate constraints for a BIM/model package (the BIM equivalent of the field's
|
||||
// AWP constraints). Citations point back to the EN06 documents.
|
||||
const BIM_CONSTRAINTS = [
|
||||
{name:'Required Docs Received (IO list, P&IDs, drawings, models, specs)', description:'Project-start inputs available — EN06-SOP §3.1'},
|
||||
{name:'Conduit Schedule & Schematic Redlines Received', description:'Hard gate: no conduit modeled without these — EN06-SOP §3'},
|
||||
{name:'LOD Defined & Agreed', description:'Level of detail set at kick-off — EN06-G-01'},
|
||||
{name:'Field Coordination / Laser Scan Complete', description:'Field walk or scan done — EN06-WI-01 / WI-03'},
|
||||
{name:'Clash-Free / Coordinated with GC & Trades', description:'Coordination complete — EN06-SOP §8.1'},
|
||||
{name:'Constructability Review (CRS) Signed', description:'Internal construction-lead sign-off before GC — EN06-SOP §8.4'},
|
||||
{name:'GC / Trade Sign-Off', description:'GC review and approval — EN06-SOP §8.2'},
|
||||
{name:'Issued-For-Fabrication (IFF) Granted', description:'Model approved for field use — EN06-SOP §9.4'}
|
||||
];
|
||||
const BIM_SEQUENCE = [
|
||||
'Project start — gather required docs', 'Kick-off (LOD, schedule, cost code)',
|
||||
'Field coordination / laser scan', 'Model racks, instruments & panels',
|
||||
'Model conduit (after schedule + redlines)', 'BIM coordination / clash with GC & trades',
|
||||
'Constructability review (CRS)', 'GC submission & sign-off (IFF)',
|
||||
'2D installation sheets', 'As-built (scan / redlines)'
|
||||
];
|
||||
const BIM_SOURCES = [
|
||||
{label:'IO List (Point Matrix DB)', ph:'controls.dev / SharePoint'},
|
||||
{label:'P&IDs', ph:'Procore / SharePoint'},
|
||||
{label:'Contract / Design Drawings', ph:'Procore / Bluebeam'},
|
||||
{label:'Navisworks / Revit Models', ph:'BIM360 / SharePoint'},
|
||||
{label:'Specs & Submittals', ph:'client portal'},
|
||||
{label:'Conduit Schedule', ph:'Excel on SharePoint'},
|
||||
{label:'Bluebeam Project', ph:'Bluebeam Studio'},
|
||||
{label:'Pre-Construction Tracker', ph:'SharePoint'},
|
||||
{label:'Constructability Review Sheet (CRS)', ph:'SharePoint'}
|
||||
];
|
||||
|
||||
function loadBIMTemplate(){
|
||||
if(!confirm('Load the BIM / VDC template?\n\nThis sets the WP types, release-gate constraints, sign-off roles, construction sequence, reference sources, disciplines (install phases) and numbering format to BIM/VDC defaults from the EN06 SOPs. Your project details (Step 1) and team (Step 2) are left alone, and you can edit everything afterward.')) return;
|
||||
|
||||
state.mode = 'bim'; // flags the Creator to show BIM fields / hide field-only sections
|
||||
|
||||
// Step 4 — deliverable package types
|
||||
state.wpTypes = BIM_WP_TYPES.map(n => ({name:n, enabled:true, notes:'', approval:''}));
|
||||
renderWPTypes();
|
||||
|
||||
// Step 5 — disciplines become install phases; multi-discipline; model numbering
|
||||
state.governance.disciplines = BIM_PHASES.slice();
|
||||
state.governance.discMode = 'multi';
|
||||
state.governance.woformat = 'MWP##-[Area]-[PHASE]';
|
||||
const setVal = (id, v) => { const el = document.getElementById(id); if(el) el.value = v; };
|
||||
setVal('gov_disciplines', BIM_PHASES.join(', '));
|
||||
setVal('gov_discmode', 'multi');
|
||||
setVal('gov_woformat', 'MWP##-[Area]-[PHASE]');
|
||||
|
||||
// Step 3 — set the two required roles to BIM titles, then add the rest as optional
|
||||
state.signoffRoles[0] = {role:'BIM Coordinator', name: (state.signoffRoles[0] && state.signoffRoles[0].name) || ''};
|
||||
state.signoffRoles[1] = {role:'Construction Lead (CRS)', name: (state.signoffRoles[1] && state.signoffRoles[1].name) || ''};
|
||||
setVal('role_super_title', 'BIM Coordinator');
|
||||
setVal('role_foreman_title', 'Construction Lead (CRS)');
|
||||
BIM_TEMPLATE_ROLES.filter(r => r !== 'BIM Coordinator' && r !== 'Construction Lead (CRS)')
|
||||
.forEach(r => { if(!state.signoffRoles.some(x => x.role === r)) state.signoffRoles.push({role:r, name:''}); });
|
||||
renderOptionalRoles();
|
||||
|
||||
// Step 9 — BIM release-gate constraints (replaces the field's standard 10)
|
||||
state.constraints = BIM_CONSTRAINTS.map(c => ({...c}));
|
||||
_constraintsSeeded = true;
|
||||
renderStandardConstraints();
|
||||
|
||||
// Step 8 — BIM process sequence
|
||||
state.sequence = BIM_SEQUENCE.map(s => ({label:s, kind:'step'}));
|
||||
renderSequenceSteps();
|
||||
|
||||
// Step 10 — reference sources
|
||||
state.sources = BIM_SOURCES.map(s => ({label:s.label, system:'', notes:'', link:'', ph:s.ph, preset:true}));
|
||||
renderSources();
|
||||
|
||||
track('bim_template_loaded');
|
||||
alert('BIM / VDC template loaded.\n\nReview Step 5 (disciplines are now the install phases; numbering = MWP##-[Area]-[PHASE]) and Step 3 (BIM Coordinator + Construction Lead were added; leave the built-in Superintendent/Foreman blank if not used). Adjust anything as needed, then finish the SOP.');
|
||||
}
|
||||
|
||||
// ── INITIALIZATION ────────────────────────────────────────────────────────────
|
||||
window.addEventListener('DOMContentLoaded',()=>{
|
||||
initializeWPTypes();
|
||||
@@ -204,7 +307,12 @@ function loadSampleData(){
|
||||
document.getElementById('proj_cm').value = 'K. Boyd';
|
||||
document.getElementById('proj_qm').value = 'D. Nguyen';
|
||||
|
||||
// Step 3 already has defaults
|
||||
// Step 3 — standard required roles
|
||||
state.mode = 'standard';
|
||||
if(state.signoffRoles[0]) state.signoffRoles[0].role = 'Superintendent';
|
||||
if(state.signoffRoles[1]) state.signoffRoles[1].role = 'Foreman';
|
||||
const stEl = document.getElementById('role_super_title'); if(stEl) stEl.value = 'Superintendent';
|
||||
const ftEl = document.getElementById('role_foreman_title'); if(ftEl) ftEl.value = 'Foreman';
|
||||
document.getElementById('role_super_name').value = 'John Smith';
|
||||
document.getElementById('role_foreman_name').value = 'Mike Jones';
|
||||
|
||||
@@ -272,8 +380,8 @@ function repopulateForm(){
|
||||
set('proj_apm', state.team.apm);
|
||||
set('proj_cm', state.team.cm);
|
||||
set('proj_qm', state.team.qm);
|
||||
if(state.signoffRoles[0]) set('role_super_name', state.signoffRoles[0].name);
|
||||
if(state.signoffRoles[1]) set('role_foreman_name', state.signoffRoles[1].name);
|
||||
if(state.signoffRoles[0]){ set('role_super_title', state.signoffRoles[0].role); set('role_super_name', state.signoffRoles[0].name); }
|
||||
if(state.signoffRoles[1]){ set('role_foreman_title', state.signoffRoles[1].role); set('role_foreman_name', state.signoffRoles[1].name); }
|
||||
set('gov_woformat', state.governance.woformat);
|
||||
// gov_wosize is now a <select>; if a saved value isn't one of the presets
|
||||
// (e.g. legacy free text), add it as an option so the round-trip preserves it.
|
||||
@@ -290,6 +398,8 @@ function repopulateForm(){
|
||||
set('qual_hold', state.quality.hold);
|
||||
set('plat_tracking', state.platforms.tracking);
|
||||
set('plat_commissioning', state.platforms.commissioning);
|
||||
set('plat_tracking_url', state.platforms.trackingUrl);
|
||||
set('plat_commissioning_url', state.platforms.commissioningUrl);
|
||||
}
|
||||
|
||||
// ── TOOL SWITCHING ────────────────────────────────────────────────────────────
|
||||
@@ -412,8 +522,9 @@ function renderWPTypes(){
|
||||
container.appendChild(row);
|
||||
});
|
||||
const addRow = document.createElement('div');
|
||||
addRow.style.cssText = 'margin-top:0.85rem;';
|
||||
addRow.innerHTML = `<button onclick="addCustomWPType()" style="background:var(--primary,#0f62fe); color:#fff; border:none; padding:0.55rem 1rem; border-radius:4px; font-weight:600; cursor:pointer; font-size:13px;">+ Add Custom Type</button>`;
|
||||
addRow.style.cssText = 'margin-top:0.85rem; display:flex; gap:0.5rem; flex-wrap:wrap;';
|
||||
addRow.innerHTML = `<button onclick="addCustomWPType()" style="background:var(--primary,#0f62fe); color:#fff; border:none; padding:0.55rem 1rem; border-radius:4px; font-weight:600; cursor:pointer; font-size:13px;">+ Add Custom Type</button>
|
||||
<button onclick="loadBIMTemplate()" title="Configure this SOP for the BIM / VDC team's model & engineering work packages" style="background:var(--bg); color:var(--text); border:1px solid var(--border); padding:0.55rem 1rem; border-radius:4px; font-weight:600; cursor:pointer; font-size:13px;">Load BIM / VDC template</button>`;
|
||||
container.appendChild(addRow);
|
||||
}
|
||||
|
||||
@@ -461,7 +572,8 @@ function removeTeamMember(i){
|
||||
|
||||
function renderOptionalRoles(){
|
||||
const container = document.getElementById('optional-roles-list');
|
||||
const current = state.signoffRoles.filter(r=>r.role!=='Superintendent'&&r.role!=='Foreman');
|
||||
// The first two entries are the required (editable-title) roles; the rest are optional.
|
||||
const current = state.signoffRoles.slice(2);
|
||||
container.innerHTML = current.map((r,i)=>`
|
||||
<div style="display:grid; grid-template-columns:1fr 200px 30px; gap:1rem; align-items:center; padding:0.75rem; background:var(--bg); border-radius:6px; margin-bottom:0.5rem; border:1px solid var(--border);">
|
||||
<select onchange="state.signoffRoles[${state.signoffRoles.indexOf(r)}].role=this.value">
|
||||
@@ -732,7 +844,10 @@ function collectStepData(){
|
||||
state.team.qm = document.getElementById('proj_qm').value;
|
||||
break;
|
||||
case 3:
|
||||
// The two required roles now have editable titles (default Superintendent/Foreman).
|
||||
state.signoffRoles[0].role = (document.getElementById('role_super_title').value || 'Role 1').trim();
|
||||
state.signoffRoles[0].name = document.getElementById('role_super_name').value;
|
||||
state.signoffRoles[1].role = (document.getElementById('role_foreman_title').value || 'Role 2').trim();
|
||||
state.signoffRoles[1].name = document.getElementById('role_foreman_name').value;
|
||||
break;
|
||||
case 5:
|
||||
@@ -753,6 +868,8 @@ function collectStepData(){
|
||||
case 7:
|
||||
state.platforms.tracking = document.getElementById('plat_tracking').value;
|
||||
state.platforms.commissioning = document.getElementById('plat_commissioning').value;
|
||||
state.platforms.trackingUrl = (document.getElementById('plat_tracking_url').value || '').trim();
|
||||
state.platforms.commissioningUrl = (document.getElementById('plat_commissioning_url').value || '').trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -783,6 +900,7 @@ function completeSOP(){
|
||||
|
||||
sop = {
|
||||
meta: {tool:'Work Package Configuration', sample:false},
|
||||
mode: state.mode || 'standard', // 'bim' hides field-only sections + shows BIM fields in the Creator
|
||||
project: {
|
||||
name: state.project.name,
|
||||
number: state.project.number,
|
||||
@@ -813,8 +931,14 @@ function completeSOP(){
|
||||
approval: t.approval || ''
|
||||
})),
|
||||
sources: state.sources.filter(s=>s.label),
|
||||
field: {trackPlatform: state.platforms.tracking},
|
||||
commissioning: {tool: state.platforms.commissioning},
|
||||
field: {trackPlatform: state.platforms.tracking, trackPlatformUrl: state.platforms.trackingUrl || ''},
|
||||
commissioning: {tool: state.platforms.commissioning, toolUrl: state.platforms.commissioningUrl || ''},
|
||||
// Project homepage links in the tracking / commissioning systems. The Creator
|
||||
// copies these onto every Work Package created for this project.
|
||||
projectLinks: [
|
||||
state.platforms.trackingUrl ? {label:'Tracking — '+state.platforms.tracking, system:state.platforms.tracking, url:state.platforms.trackingUrl} : null,
|
||||
state.platforms.commissioningUrl ? {label:'Commissioning — '+state.platforms.commissioning, system:state.platforms.commissioning, url:state.platforms.commissioningUrl} : null
|
||||
].filter(Boolean),
|
||||
quality: {
|
||||
qcReq: state.quality.qcreq,
|
||||
photo: state.quality.photo,
|
||||
|
||||
Reference in New Issue
Block a user