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:
@@ -92,12 +92,24 @@ function applySOP(){
|
||||
lockQuality('wp_qc'); lockQuality('wp_photo'); lockQuality('wp_hold');
|
||||
const hint=document.getElementById('wp_number_hint'); hint.textContent = SOP.governance&&SOP.governance.woFormat ? 'auto-built · format: '+SOP.governance.woFormat : '';
|
||||
buildConstraints(); buildSignoffs();
|
||||
applyBimMode();
|
||||
if(!pkgMaterials.length){ pkgMaterials=[{qty:'',unit:'',desc:''}]; buildMaterials(); }
|
||||
if(!pkgAttach.length){ pkgAttach=[{doc:'',rev:'',link:''}]; buildAttach(); }
|
||||
if(!pkgAssets.length){ pkgAssets=[{tag:'',desc:'',link:''}]; buildAssets(); }
|
||||
if(!pkgWorkSteps.length){ pkgWorkSteps=['']; buildWorkSteps(); }
|
||||
updateNumber(); updateReleaseBanner();
|
||||
}
|
||||
// In a BIM/VDC SOP, hide the field-only sections (controls.dev assets, materials,
|
||||
// kitting/MIMO) and reveal the BIM Details card. Driven by SOP.mode==='bim'.
|
||||
function isBimSOP(){ return !!(SOP && SOP.mode === 'bim'); }
|
||||
function applyBimMode(){
|
||||
const bim = isBimSOP();
|
||||
const show = (id, on) => { const el = document.getElementById(id); if(el) el.style.display = on ? '' : 'none'; };
|
||||
show('bim-card', bim);
|
||||
show('asset-card', !bim);
|
||||
show('material-card', !bim);
|
||||
show('mimo-card', !bim);
|
||||
}
|
||||
function buildCostCodes(){
|
||||
const sel=document.getElementById('wp_cost'); const cur=sel.value;
|
||||
sel.innerHTML=`<option value="">Select cost code…</option>`+COST_CODES.map(c=>{const [code,desc]=c.split('|'); return `<option value="${code}">${code} — ${esc(desc)}</option>`;}).join('');
|
||||
@@ -677,7 +689,14 @@ function collectPackage(){
|
||||
signoffs:pkgSignoffs.map(s=>({role:s.role,name:s.name,date:s.date,signed:s.signed,dateReason:s.dateReason||''})),
|
||||
holds:pkgHolds.map(h=>({...h})),
|
||||
actualHrs:gv('wp_actual_hrs'), installedQty:gv('wp_installed_qty'), redlines:gv('wp_redlines'), lessons:gv('wp_lessons'),
|
||||
// AWP traceability: which BIM/model package(s) enabled this install package.
|
||||
bimlink:gv('wp_bimlink'),
|
||||
// BIM/VDC package details (only meaningful on a BIM SOP).
|
||||
lod:gv('wp_lod'), modelArea:gv('wp_model_area'), clash:gv('wp_clash'), scanLink:gv('wp_scan_link'),
|
||||
project:(SOP&&SOP.project&&SOP.project.name)||'', track:(SOP&&SOP.field&&SOP.field.trackPlatform)||'',
|
||||
// Project homepage links in the tracking / commissioning systems, copied from the
|
||||
// SOP so they travel with every Work Package created for this project.
|
||||
projectLinks:(SOP&&SOP.projectLinks)?SOP.projectLinks.map(l=>({...l})):[],
|
||||
updatedAt:new Date().toISOString()
|
||||
};
|
||||
}
|
||||
@@ -696,6 +715,8 @@ function renderPackage(pkg){
|
||||
let h=`<h1>${esc(pkg.number||'(no number)')} — Work Package</h1>
|
||||
<div class="doc-subtitle">${esc(pkg.project)} · TYPE: ${esc(pkg.type).toUpperCase()} · STATUS: ${esc(pkg.status).toUpperCase()} · ${readyTxt}</div>`;
|
||||
const costDesc = (COST_CODES.find(c=>c.split('|')[0]===pkg.cost)||'').split('|')[1];
|
||||
// Project system links travel with the WP; fall back to the live SOP for older packages.
|
||||
const plinks = (pkg.projectLinks&&pkg.projectLinks.length) ? pkg.projectLinks : ((SOP&&SOP.projectLinks)||[]);
|
||||
h+=`<h2>1.0 General Information</h2><table><tbody>
|
||||
<tr><th style="width:200px">WP Number</th><td>${cell(pkg.number)}</td></tr>
|
||||
<tr><th>Subject</th><td>${cell(pkg.subject)}</td></tr>
|
||||
@@ -710,6 +731,9 @@ function renderPackage(pkg){
|
||||
<tr><th>Due Date</th><td>${cell(pkg.due)}</td></tr>
|
||||
<tr><th>Specification Section</th><td>${cell(pkg.spec)}</td></tr>
|
||||
<tr><th>Description</th><td>${cell(pkg.desc)}</td></tr>
|
||||
${plinks.length?`<tr><th>Project Systems</th><td>${plinks.map(l=>esc(l.label)+': '+linkify(l.url)).join('<br>')}</td></tr>`:''}
|
||||
${pkg.bimlink?`<tr><th>Enabled by (BIM)</th><td>${/^https?:\/\//i.test(pkg.bimlink)?linkify(pkg.bimlink):cell(pkg.bimlink)}</td></tr>`:''}
|
||||
${(pkg.lod||pkg.modelArea||pkg.clash||pkg.scanLink)?`<tr><th>BIM / Model</th><td>${[pkg.lod?'LOD: '+esc(pkg.lod):'', pkg.modelArea?'Area: '+esc(pkg.modelArea):'', pkg.clash?'Coordination: '+esc(pkg.clash):'', pkg.scanLink?'Scan: '+linkify(pkg.scanLink):''].filter(Boolean).join('<br>')}</td></tr>`:''}
|
||||
</tbody></table>`;
|
||||
if(pkg.assets&&pkg.assets.length){ h+=`<h2>2.0 Assets (controls.dev)</h2><table><thead><tr><th style="width:180px">Asset Tag / ID</th><th>Description</th><th>controls.dev Link</th></tr></thead><tbody>`;
|
||||
pkg.assets.forEach(a=>h+=`<tr><td>${cell(a.tag)}</td><td>${cell(a.desc)}</td><td>${a.link?linkify(a.link):ns()}</td></tr>`); h+=`</tbody></table>`; }
|
||||
@@ -857,6 +881,8 @@ function loadPackageIntoForm(p){
|
||||
set('wp_due',p.due); set('wp_spec',p.spec); set('wp_desc',p.desc); set('wp_hours',p.hours);
|
||||
set('wp_kit_owner',p.kitOwner); set('wp_kit_date',p.kitDate); set('wp_mimo_time',p.mimoTime); set('wp_mimo_loc',p.mimoLoc);
|
||||
set('wp_actual_hrs',p.actualHrs); set('wp_installed_qty',p.installedQty); set('wp_redlines',p.redlines); set('wp_lessons',p.lessons);
|
||||
set('wp_bimlink',p.bimlink); set('wp_lod',p.lod); set('wp_model_area',p.modelArea); set('wp_clash',p.clash); set('wp_scan_link',p.scanLink);
|
||||
applyBimMode();
|
||||
buildTypePicker(); document.getElementById('wp_type').value=p.type||'';
|
||||
buildCostCodes(); document.getElementById('wp_cost').value=p.cost||'';
|
||||
set('wp_wbs',p.wbs);
|
||||
@@ -923,8 +949,10 @@ function duplicateWP(){
|
||||
|
||||
function newPackage(){
|
||||
editingId=null;
|
||||
['wp_subject','wp_system','wp_location','wp_wbs','wp_assignees','wp_distribution','wp_due','wp_spec','wp_desc','wp_hours','wp_kit_owner','wp_kit_date','wp_mimo_time','wp_mimo_loc','wp_actual_hrs','wp_installed_qty','wp_redlines','wp_lessons'].forEach(id=>{const el=document.getElementById(id); if(el) el.value='';});
|
||||
['wp_subject','wp_system','wp_location','wp_wbs','wp_assignees','wp_distribution','wp_due','wp_spec','wp_desc','wp_hours','wp_kit_owner','wp_kit_date','wp_mimo_time','wp_mimo_loc','wp_actual_hrs','wp_installed_qty','wp_redlines','wp_lessons','wp_bimlink','wp_model_area','wp_scan_link'].forEach(id=>{const el=document.getElementById(id); if(el) el.value='';});
|
||||
document.getElementById('wp_type').value=''; document.getElementById('wp_kit_status').value=''; document.getElementById('wp_cost').value='';
|
||||
['wp_lod','wp_clash'].forEach(id=>{const el=document.getElementById(id); if(el) el.value='';});
|
||||
applyBimMode();
|
||||
setRadio('status','Draft');
|
||||
numberDims={}; buildNumberDims();
|
||||
pkgDisciplines=[]; pkgScope={}; pkgDiscStatus={}; buildDisciplinePicker(); renderScope(); onHoursChange();
|
||||
|
||||
Reference in New Issue
Block a user