Add a new "Банкетное меню" catalog tab (category 6) alongside Боксы/ Премиум/Посуда for composing wedding/banquet/anniversary menus. Unlike the other tabs, dishes here are priced and weighed per guest, grouped by menu section (catalogSection), and clicking a checkbox doesn't add to the order directly -- it toggles inclusion in a live summary panel showing a running per-guest price table for the whole composed menu. The item editor gets two new fields (menu section, weight per guest) shown only for this category, reusing the existing generic item CRUD (editBox/saveBox) rather than building a parallel admin UI. Also re-bumped index.html's script cache-busting query string, which the previous whitelist-fix commit changed the content of app-runtime.js without updating -- the same stale-cache bug fixed earlier in the session, now closed for directly-tagged scripts too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
55 lines
9.8 KiB
JavaScript
55 lines
9.8 KiB
JavaScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
const root=process.cwd();
|
|
const pub=path.join(root,'public');
|
|
const readPub=p=>fs.readFileSync(path.join(pub,p),'utf8');
|
|
const readRoot=p=>fs.readFileSync(path.join(root,p),'utf8');
|
|
const fail=m=>{console.error('FAIL:',m);process.exitCode=1};
|
|
const ok=m=>console.log('OK:',m);
|
|
const html=readPub('index.html'),legacy=readPub('legacy/bootstrap.js'),runtime=readPub('app-runtime.js'),safe=readPub('core/sun-safe.js'),sw=readPub('service-worker.js'),performance=readPub('core/performance.js'),dataLayer=readPub('core/data-layer-v1773.js'),serverAutomation=readPub('core/server-automation-v1770.js'),ops=readPub('core/ops-ux-v1762.js'),hotfix=readPub('core/hotfix-v1763.js'),ux=readPub('core/ux-fixes-v1764.js'),classic=readPub('core/classic-offer-pdf-v1767.js'),developerUX=readPub('core/developer-console-v1768.js'),offerWorkspace=readPub('core/offer-workspace-v1769.js');
|
|
if(!html.includes('core/sun-safe.js'))fail('SunSafe must load before legacy modules');else ok('shared SunSafe loaded');
|
|
if(html.includes('offer-gallery-data.js')||fs.existsSync(path.join(pub,'offer-gallery-data.js')))fail('blocking offer-gallery-data.js still present');else ok('base64 gallery removed');
|
|
for(const raw of ['<span>${b.name}</span>','<span>${o.event}</span>','<span>${o.address||','value="${x[0]}"','value="${x[2]}"']) if(legacy.includes(raw)) fail(`legacy bootstrap contains raw HTML interpolation ${raw}`);
|
|
if(!legacy.includes('sunEsc(')||!legacy.includes('sunAttr('))fail('legacy bootstrap is not using shared escaping');else ok('legacy bootstrap escapes text and attributes');
|
|
if(!legacy.includes("persistOrders('order.save')")||!legacy.includes("persistOrders('order.status')")||!legacy.includes("persistOrders('order.delete')")||!legacy.includes("persistCatalog('catalog.save')")||!legacy.includes("persistCatalog('catalog.delete')"))fail('legacy CRUD is not routed through data layer');else ok('legacy CRUD routes through data layer');
|
|
const duplicateEsc=[html,runtime].join('\n').split('\n').filter(line=>/\b(?:const|let)\s+esc\b/.test(line)&&line.includes('.replace('));
|
|
if(duplicateEsc.length)fail(`duplicate esc implementations remain: ${duplicateEsc.length}`);else ok('local esc aliases delegate to SunSafe');
|
|
if(runtime.includes('/Type /Catalog'))fail('manual PDF writer remains in app-runtime.js');else ok('PDF packing removed from runtime');
|
|
if(!readPub('core/pdf-engine.js').includes('/Type /Catalog'))fail('shared PDF engine missing');else ok('single shared PDF engine present');
|
|
const employeeEdge=path.join(root,'supabase/functions/caterium-create-employee/index.ts');
|
|
if(!fs.existsSync(employeeEdge))fail('production employee Edge Function source missing');else ok('production employee Edge Function versioned');
|
|
const edge=readRoot('supabase/functions/caterium-create-employee/index.ts');
|
|
if(/service_role\s*[:=]\s*['"][A-Za-z0-9._-]{20,}/i.test(edge)||/eyJ[a-zA-Z0-9_-]{30,}/.test(edge))fail('possible hard-coded secret in Edge Function');else ok('no hard-coded service key detected');
|
|
if(!safe.includes('reference.parentNode===parent'))fail('safe insertBefore guard missing');else ok('safe DOM insertion guard present');
|
|
const files=fs.readdirSync(path.join(pub,'catalog'));
|
|
const current=files.filter(x=>/^current-\d{3}\.jpg$/i.test(x)).length;
|
|
const legacyCount=files.filter(x=>/^\d{3}\.jpg$/i.test(x)).length;
|
|
if(current!==113)fail(`current catalog photo count ${current}, expected 113`);else ok('113 current catalog photos');
|
|
if(legacyCount!==60)fail(`legacy catalog photo count ${legacyCount}, expected 60`);else ok('60 legacy catalog photos');
|
|
const gallery=fs.readdirSync(path.join(pub,'offer-gallery')).filter(x=>/\.jpg$/i.test(x));
|
|
if(gallery.length!==2)fail(`offer gallery contains ${gallery.length} jpg files, expected 2`);else ok('offer gallery trimmed');
|
|
if(!sw.includes('20260912-account-center-loader')||!sw.includes('login-signature-v1776.js')||!sw.includes('data-layer-v1773.js')||!sw.includes('server-automation-v1770.js')||!sw.includes('offer-workspace-v1769.js')||sw.includes('offer-gallery-data.js'))fail('service worker cache is stale');else ok('PWA cache updated for login refresh');
|
|
if(html.includes('20260907-v17-6-0-stability-security')||html.includes('20260909-v17-7-3-clients-server-read')||!html.includes('20260916-v18-1-2-banquet-menu-tab')||!html.includes('classic-offer-pdf-v1767.js'))fail('index still serves stale core asset version');else ok('index cache-busting is current');
|
|
if(!performance.includes('SunAttachmentGuard')||!performance.includes('MAX_SIDE=2048'))fail('chat photo compression guard missing');else ok('chat photo compression guard present');
|
|
if(!performance.includes("rpc('sun_dev_dashboard')")||!performance.includes('storage_size')||!performance.includes('server_size'))fail('Developer Console memory counters missing');else ok('Developer Console memory counters present');
|
|
if(performance.includes('records.forEach(r=>r.addedNodes.forEach(n=>{if(n.nodeType===1)scan(n)}));enhanceDeveloperMemory()'))fail('Developer Console memory refresh is still coupled to MutationObserver');else ok('Developer Console memory refresh loop removed');
|
|
if(!performance.includes('MEMORY_REFRESH_MS=30000')||!performance.includes('MEMORY_TIMEOUT_MS=8000')||!performance.includes('memoryPromise'))fail('Developer Console bounded refresh controls missing');else ok('Developer Console bounded refresh controls present');
|
|
if(!performance.includes('pendingImageRoots')||!performance.includes('queueImageScan'))fail('batched image mutation scanning missing');else ok('image mutation scanning is batched');
|
|
if(!performance.includes('loadDataLayer')||!performance.includes('data-layer-v1773.js')||!performance.includes('loadServerAutomation'))fail('v17.7.1 data layer loaders missing');else ok('v17.7.1 data layer loaders present');
|
|
if(!dataLayer.includes("const VERSION='17.7.3'")||!dataLayer.includes('ordersRepo')||!dataLayer.includes('catalogRepo')||!dataLayer.includes('clientsRepo')||!dataLayer.includes('sun_v17_save_client_v1772')||!dataLayer.includes('sun_v17_clients_snapshot_v1773')||!dataLayer.includes('refreshServerClients')||!dataLayer.includes('CateriumDataV1772=api'))fail('v17.7.3 data layer missing');else ok('v17.7.3 data layer present');
|
|
if(!serverAutomation.includes("const VERSION='17.7.0'")||!serverAutomation.includes("rpc('sun_run_order_automation'")||!serverAutomation.includes('applyServerChanges'))fail('v17.7.0 server automation client missing');else ok('v17.7.0 server automation client present');
|
|
if(!performance.includes('ux-fixes-v1764.js')||!performance.includes('SunUXFixV1764'))fail('UX fix loader missing');else ok('UX fix loader present');
|
|
if(!performance.includes('hotfix-v1763.js')||!performance.includes('SunHotfixV1763'))fail('v17.6.3 hotfix loader missing');else ok('v17.6.3 hotfix loader present');
|
|
if(!performance.includes('ops-ux-v1762.js')||!performance.includes('SunOpsUXV1762'))fail('ops UX loader missing');else ok('ops UX loader present');
|
|
for(const marker of ['patchDeveloperOpen','enhanceDeveloperGate','data-saas-admin','stopImmediatePropagation','instanceof HTMLElement']) if(!hotfix.includes(marker))fail(`developer/SaaS hotfix marker missing: ${marker}`);else ok(`developer/SaaS hotfix marker: ${marker}`);
|
|
for(const marker of ['SUPPORT_POLL_MS=20000','supportReadPermission','refreshSupportWorkspace','sun-menu-editor-v1762','showCalendarDay',"ROUTE_BASE_KEY='sunRouteBaseV1'",'showRouteOrder','routeOpenYandex']) if(!ops.includes(marker)) fail(`ops UX marker missing: ${marker}`); else ok(`ops UX marker: ${marker}`);
|
|
for(const marker of ["AUTO_DELAY_MS=60*1000","order.prepayment=total","order.status='Отдан заказчику'",'sunAutoCompletedAt','classificationDate','persistOfferTemplate','clientOfferTemplateId','offerTemplateId','sun-v1764-menu-icon','CateriumServerAutomationV1770?.enabled']) if(!ux.includes(marker))fail(`UX compatibility marker missing: ${marker}`);else ok(`UX compatibility marker: ${marker}`);
|
|
for(const marker of ['CLOUD_RPC_TIMEOUT_MS=12000','CLOUD_CONFLICT_MAX_RETRIES=4','refreshSupportWorkspace',"const VERSION = '17.7.3'",'ERROR_DEDUPE_MS=5*60*1000','DEV_ADMIN_TTL_MS=30000']) if(!runtime.includes(marker))fail(`stability marker missing: ${marker}`);else ok(`stability marker: ${marker}`);
|
|
if(!hotfix.includes('checkPlatformAdmin?.(false)')||!hotfix.includes('},10000);'))fail('Developer fallback polling is still aggressive');else ok('Developer fallback polling is throttled');
|
|
if(!ux.includes('sunMenuIconV1766')||!ux.includes('sun-offer-template-mini-editorial-grid')||!runtime.includes('explicitTemplate'))fail('v17.6.6 proposal/menu markers missing');else ok('v17.6.6 proposal/menu markers present');
|
|
if(!classic.includes("const VERSION='17.6.7'")||!classic.includes('CLASSIC_IDS')||!classic.includes('ARCHIVE_IDS')||!classic.includes('renderPages'))fail('v17.6.7 classic PDF module missing');else ok('v17.6.7 classic PDF module present');
|
|
if(!developerUX.includes("const VERSION='17.6.8'")||!developerUX.includes('sun_dev_delete_company_v1768')||!developerUX.includes('sun_dev_error_groups_v1768')||!developerUX.includes('selectedAccountsWorkspace')||!developerUX.includes('sun-dev-plan-matrix')||!developerUX.includes('KNOWN_DOM_RACE'))fail('v17.6.8 Developer Console UX module missing');else ok('v17.6.8 Developer Console UX module present');
|
|
if(!offerWorkspace.includes("const VERSION='17.6.9'")||!offerWorkspace.includes('data-offer-workspace-tab=\"templates\"')||!offerWorkspace.includes('data-offer-gallery-slot')||!offerWorkspace.includes('sunOfferGalleryOverridesV1769'))fail('v17.6.9 offer workspace module missing');else ok('v17.6.9 offer workspace module present');
|
|
if(/service_role\s*[:=]\s*['"][A-Za-z0-9._-]{20,}/i.test(ops+hotfix+ux+classic+developerUX+offerWorkspace+dataLayer+serverAutomation)||/eyJ[a-zA-Z0-9_-]{30,}/.test(ops+hotfix+ux+classic+developerUX+offerWorkspace+dataLayer+serverAutomation))fail('possible secret in client modules');else ok('client modules have no hard-coded secret');
|
|
if(process.exitCode)process.exit(process.exitCode);
|