From e8cb28602d623b006aa8678ac26cc707827d18bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 10:06:29 +0000 Subject: [PATCH] Apply Caterium v17.7.0 architecture foundation --- docs/release-manifest.json | 21 +++++++++++++++------ docs/releases/V17.7.0-CHANGES.txt | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 4 ++-- public/app-runtime.js | 4 ++-- public/core/performance.js | 16 ++++++++++++---- public/core/ux-fixes-v1764.js | 1 + public/index.html | 4 ++-- public/service-worker.js | 6 +++--- tests/app.spec.mjs | 17 +++++++++++++++++ tests/release-check.mjs | 8 ++++++++ 11 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 docs/releases/V17.7.0-CHANGES.txt diff --git a/docs/release-manifest.json b/docs/release-manifest.json index 61ff13a..704c887 100644 --- a/docs/release-manifest.json +++ b/docs/release-manifest.json @@ -1,6 +1,6 @@ { "app": "Caterium", - "version": "v17.6.9", + "version": "v17.7.0", "channel": "production", "schema": 17, "legacyStateKept": true, @@ -11,7 +11,7 @@ "serverReady": true, "workspaceAutoDiscovery": true, "invitesTemporarilyDisabled": false, - "pwaCache": "v74-20260908-v17-6-9-offer-pdf-tabs-gallery", + "pwaCache": "v75-20260908-v17-7-0-architecture-foundation", "fullOfferDescriptions": true, "dynamicOfferRows": true, "pdfOfferDescriptionFix": true, @@ -108,7 +108,7 @@ "catalogCompositionTildaEndpoint": "getproduct", "catalogCompositionPremiumForceRefresh": true, "catalogCompositionCacheRequiresPremium": true, - "notes": "Client offer workspace: PDF preview, editor and PDF templates separated into tabs; editor scroll restored; two per-offer final gallery photos can be uploaded and are used in preview/PDF.", + "notes": "Architecture foundation: explicit data layer, server-side order automation with legacy/cloud compatibility, telemetry hygiene, current stability version, regression checks.", "catalogPhotoSources": 113, "catalogPhotosStoredInCatalog": true, "catalogLegacyPhotosInCatalog": 60, @@ -246,7 +246,7 @@ "signupTrial": "14-day Full", "developerMfaInputSelectorFixed": true, "developerMfaRepeatedValidationToastsFixed": true, - "release": "20260908-v17-6-9-offer-pdf-tabs-gallery", + "release": "20260908-v17-7-0-architecture-foundation", "registrationFlow": "email-password-confirm-company-auto-login", "emailConfirmationRequired": false, "employeeInviteLinks": false, @@ -327,7 +327,7 @@ "cloudConflictMaxRetries": 4, "errorLogDedupMinutes": 5, "networkFailureBackoff": true, - "stabilityLoggerVersion": "17.6.5", + "stabilityLoggerVersion": "17.7.0", "developerAdminCheckTtlMs": 30000, "supportRefreshLightweight": true, "supportRefreshIntervalMs": 20000, @@ -358,5 +358,14 @@ "offerTemplatesSeparateTab": true, "offerEditorScrollable": true, "offerTwoCustomGalleryPhotos": true, - "offerWorkspaceModule": "core/offer-workspace-v1769.js" + "offerWorkspaceModule": "core/offer-workspace-v1769.js", + "architectureFoundation": true, + "dataLayer": "core/data-layer-v1770.js", + "serverOrderAutomation": true, + "serverOrderAutomationCron": "every minute", + "serverOrderTimezoneColumn": true, + "browserOrderAutomationCloudDisabled": true, + "errorTelemetryRejectsLocalFile": true, + "errorTelemetryServerDedupMinutes": 5, + "errorTelemetryRetentionDays": 30 } diff --git a/docs/releases/V17.7.0-CHANGES.txt b/docs/releases/V17.7.0-CHANGES.txt new file mode 100644 index 0000000..59b9352 --- /dev/null +++ b/docs/releases/V17.7.0-CHANGES.txt @@ -0,0 +1,12 @@ +Caterium v17.7.0 — Architecture Foundation +Date: 2026-09-08 + +1. Introduces core/data-layer-v1770.js as the first explicit application data layer. Orders and storage access can migrate away from direct globals/localStorage without a rewrite. +2. Order auto-completion is now a server business rule. PostgreSQL cron runs every minute and marks due orders fully paid/completed. +3. The server updates both normalized sun_v17_orders and the legacy sun_app_state sunOrders payload so existing clients remain compatible during migration. +4. Signed-in cloud clients no longer execute browser-side auto-completion; the old code remains only as local/offline fallback. +5. Client server-automation module can request an immediate run on startup/focus and applies changed normalized orders through the data layer. +6. Error telemetry rejects file:// events, deduplicates identical events for five minutes, and retains only 30 days. Historical file:// events are removed. +7. Stability logger version is synchronized to 17.7.0. +8. PWA cache v75 includes data-layer and server-automation modules. +9. This is phase 1 of the architecture migration; legacy state remains intentionally enabled until subsequent domain-by-domain extraction is complete. diff --git a/package-lock.json b/package-lock.json index 2a66a82..d67ce2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "caterium-app", - "version": "17.6.9", + "version": "17.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "caterium-app", - "version": "17.6.9", + "version": "17.7.0", "devDependencies": { "@playwright/test": "^1.51.0", "http-server": "^14.1.1", diff --git a/package.json b/package.json index f682db8..e5f6448 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "caterium-app", "private": true, - "version": "17.6.9", + "version": "17.7.0", "type": "module", "scripts": { - "check:syntax": "node --check public/app-runtime.js && node --check public/service-worker.js && node --check public/legacy/bootstrap.js && node --check public/core/sun-safe.js && node --check public/core/performance.js && node --check public/core/hotfix-v1763.js && node --check public/core/ops-ux-v1762.js && node --check public/core/ux-fixes-v1764.js && node --check public/core/pdf-engine.js && node --check public/core/classic-offer-pdf-v1767.js && node --check public/core/developer-console-v1768.js && node --check public/core/offer-workspace-v1769.js", + "check:syntax": "node --check public/app-runtime.js && node --check public/service-worker.js && node --check public/legacy/bootstrap.js && node --check public/core/sun-safe.js && node --check public/core/performance.js && node --check public/core/data-layer-v1770.js && node --check public/core/server-automation-v1770.js && node --check public/core/hotfix-v1763.js && node --check public/core/ops-ux-v1762.js && node --check public/core/ux-fixes-v1764.js && node --check public/core/pdf-engine.js && node --check public/core/classic-offer-pdf-v1767.js && node --check public/core/developer-console-v1768.js && node --check public/core/offer-workspace-v1769.js", "test:static": "node tests/static-security.mjs", "check:release": "node tests/release-check.mjs", "check:deploy": "npm run check:syntax && npm run test:static && npm run check:release", diff --git a/public/app-runtime.js b/public/app-runtime.js index c1ac52b..1411297 100644 --- a/public/app-runtime.js +++ b/public/app-runtime.js @@ -4221,8 +4221,8 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс 'use strict'; if (window.SunStabilityV17) return; - const VERSION = '17.6.5'; - const RELEASE = 'v17.6.5 Stability'; + const VERSION = '17.7.0'; + const RELEASE = 'v17.7.0 Architecture Foundation'; const DB_NAME = 'SunStabilityV17'; const DB_VERSION = 1; const DAILY_KEY = 'sunV17DailyBackup'; diff --git a/public/core/performance.js b/public/core/performance.js index 409d158..bbbfe11 100644 --- a/public/core/performance.js +++ b/public/core/performance.js @@ -1,7 +1,7 @@ (()=>{ 'use strict'; - const VERSION='17.6.9'; - const RELEASE='20260908-v17-6-9-offer-pdf-tabs-gallery'; + const VERSION='17.7.0'; + const RELEASE='20260908-v17-7-0-architecture-foundation'; const critical=img=>img.closest('header,.brand,#sunCloudAuthGate,.sun-auth-gate')||img.id==='sunLoginLogo'||img.classList.contains('sun-live-catalog-logo'); const tune=img=>{ if(!(img instanceof HTMLImageElement)||critical(img))return; @@ -91,6 +91,14 @@ function scheduleMemoryRefresh(delay=80,force=false){setTimeout(()=>{if(developerVisible())enhanceDeveloperMemory({force}).catch(()=>{})},delay)} function startMemoryTimer(){if(memoryTimer)return;memoryTimer=setInterval(()=>{if(!document.hidden&&developerVisible())enhanceDeveloperMemory({force:true}).catch(()=>{})},MEMORY_REFRESH_MS)} + function loadDataLayer(){ + if(window.CateriumDataV1770||document.getElementById('cateriumDataV1770Script'))return; + const script=document.createElement('script');script.id='cateriumDataV1770Script';script.src=`core/data-layer-v1770.js?v=${RELEASE}`;script.async=false;script.onerror=()=>console.error('[Caterium] Не загрузился data-layer-v1770.js');document.head.appendChild(script); + } + function loadServerAutomation(){ + if(window.CateriumServerAutomationV1770||document.getElementById('cateriumServerAutomationV1770Script'))return; + const script=document.createElement('script');script.id='cateriumServerAutomationV1770Script';script.src=`core/server-automation-v1770.js?v=${RELEASE}`;script.async=true;script.onerror=()=>console.error('[Caterium] Не загрузился server-automation-v1770.js');document.head.appendChild(script); + } function loadHotfix(){ if(window.SunHotfixV1763||document.getElementById('sunHotfixV1763Script'))return; const script=document.createElement('script');script.id='sunHotfixV1763Script';script.src=`core/hotfix-v1763.js?v=${RELEASE}`;script.async=true;script.onerror=()=>console.error('[Caterium] Не загрузился модуль hotfix-v1763.js');document.head.appendChild(script); @@ -112,13 +120,13 @@ const script=document.createElement('script');script.id='sunOfferWorkspaceV1769Script';script.src=`core/offer-workspace-v1769.js?v=${RELEASE}`;script.async=true;script.onerror=()=>console.error('[Caterium] Не загрузился модуль offer-workspace-v1769.js');document.head.appendChild(script); } const start=()=>{ - loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();scan(document);startMemoryTimer(); + loadDataLayer();loadServerAutomation();loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();scan(document);startMemoryTimer(); const mo=new MutationObserver(records=>{records.forEach(r=>r.addedNodes.forEach(n=>{if(n.nodeType===1)queueImageScan(n)}));}); mo.observe(document.documentElement,{childList:true,subtree:true}); document.addEventListener('click',e=>{if(e.target.closest('#sunDeveloperNavV22,[data-dev-tab],#sunDevRefresh'))scheduleMemoryRefresh(100,true)},true); window.addEventListener('sun:cloud-state-applied',()=>scheduleMemoryRefresh(180,true)); document.addEventListener('visibilitychange',()=>{if(!document.hidden&&developerVisible())scheduleMemoryRefresh(50,false)}); - window.SunPerformance={VERSION,scanImages:()=>scan(document),refreshDeveloperMemory:(force=true)=>enhanceDeveloperMemory({force}),loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,disconnect:()=>{mo.disconnect();if(memoryTimer){clearInterval(memoryTimer);memoryTimer=0}if(imageScanTimer){clearTimeout(imageScanTimer);imageScanTimer=0}pendingImageRoots.clear();}}; + window.SunPerformance={VERSION,scanImages:()=>scan(document),refreshDeveloperMemory:(force=true)=>enhanceDeveloperMemory({force}),loadDataLayer,loadServerAutomation,loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,disconnect:()=>{mo.disconnect();if(memoryTimer){clearInterval(memoryTimer);memoryTimer=0}if(imageScanTimer){clearTimeout(imageScanTimer);imageScanTimer=0}pendingImageRoots.clear();}}; }; if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',start,{once:true});else start(); })(); diff --git a/public/core/ux-fixes-v1764.js b/public/core/ux-fixes-v1764.js index f795069..67252ce 100644 --- a/public/core/ux-fixes-v1764.js +++ b/public/core/ux-fixes-v1764.js @@ -44,6 +44,7 @@ try{ const signed=Boolean(cloud?.getSession?.()?.user); if(!signed)return true; + if(window.CateriumServerAutomationV1770?.enabled)return false; if(typeof cloud?.hasPermission==='function')return cloud.hasPermission('orders.edit')||cloud.hasPermission('app.write'); }catch(_){} return true; diff --git a/public/index.html b/public/index.html index 044c2f1..b864e91 100644 --- a/public/index.html +++ b/public/index.html @@ -71,7 +71,7 @@ button{touch-action:manipulation} #sunGlobalSearchBtn kbd{display:none!important} #sunSyncSettingsCard>div[style*="grid-template-columns"]{grid-template-columns:1fr!important} -}
Солнце Кейтеринг

Стоимость позиций0 ₽

Предоплата0 ₽

К оплате0 ₽

Заказы

МероприятиеДата и времяАдресСуммаСтатусДействия

Нажмите «Изменить», чтобы открыть заказ. Сумма, предоплата и остаток сохраняются вместе с заказом.

Склад

В этой версии каталог продуктов пополняется из составов боксов. Остатки и цены добавим следующим шагом.

Статистика

- + diff --git a/public/service-worker.js b/public/service-worker.js index 1d4607a..9654b06 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,8 +1,8 @@ -const CACHE='sun-catering-pwa-v74-20260908-v17-6-9-offer-pdf-tabs-gallery'; -const VERSION='20260908-v17-6-9-offer-pdf-tabs-gallery'; +const CACHE='sun-catering-pwa-v75-20260908-v17-7-0-architecture-foundation'; +const VERSION='20260908-v17-7-0-architecture-foundation'; const CORE=[ './','./index.html', - `./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/hotfix-v1763.js?v=${VERSION}`,`./core/ops-ux-v1762.js?v=${VERSION}`,`./core/ux-fixes-v1764.js?v=${VERSION}`,`./core/pdf-engine.js?v=${VERSION}`,`./core/classic-offer-pdf-v1767.js?v=${VERSION}`,`./core/developer-console-v1768.js?v=${VERSION}`,`./core/offer-workspace-v1769.js?v=${VERSION}`,`./legacy/bootstrap.js?v=${VERSION}`,`./app-runtime.js?v=${VERSION}`, + `./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/data-layer-v1770.js?v=${VERSION}`,`./core/server-automation-v1770.js?v=${VERSION}`,`./core/hotfix-v1763.js?v=${VERSION}`,`./core/ops-ux-v1762.js?v=${VERSION}`,`./core/ux-fixes-v1764.js?v=${VERSION}`,`./core/pdf-engine.js?v=${VERSION}`,`./core/classic-offer-pdf-v1767.js?v=${VERSION}`,`./core/developer-console-v1768.js?v=${VERSION}`,`./core/offer-workspace-v1769.js?v=${VERSION}`,`./legacy/bootstrap.js?v=${VERSION}`,`./app-runtime.js?v=${VERSION}`, './offer-gallery/001.jpg','./offer-gallery/002.jpg', './catalog/001.jpg','./catalog/002.jpg','./catalog/003.jpg', './sun-logo.png','./caterium-login-logo.png','./pwa-icon-192.png','./pwa-icon-512.png','./manifest.webmanifest', diff --git a/tests/app.spec.mjs b/tests/app.spec.mjs index c6d5c74..364e773 100644 --- a/tests/app.spec.mjs +++ b/tests/app.spec.mjs @@ -257,3 +257,20 @@ test('v17.6.9 offer workspace module boots', async ({ page }) => { expect(result.tabs).toBe(true); expect(await page.locator('[data-offer-gallery-slot]').count()).toBe(2); }); + + +test('v17.7.0 data layer can update orders without direct UI globals', async ({ page }) => { + await page.goto('/index.html',{waitUntil:'domcontentloaded'}); + const source=fs.readFileSync(path.join(process.cwd(),'public','core','data-layer-v1770.js'),'utf8');await page.addScriptTag({content:source}); + await page.evaluate(()=>localStorage.setItem('sunOrders',JSON.stringify([{id:77,status:'Новый',total:1000}]))); + const result=await page.evaluate(()=>{const before=window.CateriumDataV1770.orders.get(77);window.CateriumDataV1770.orders.update(77,o=>({...o,status:'Тест'}));return {before:before.status,after:window.CateriumDataV1770.orders.get(77).status,version:window.CateriumDataV1770.VERSION}}); + expect(result).toEqual({before:'Новый',after:'Тест',version:'17.7.0'}); +}); + +test('v17.7.0 server automation applies returned normalized orders through data layer', async ({ page }) => { + await page.goto('/index.html',{waitUntil:'domcontentloaded'}); + await page.evaluate(()=>{window.__applied=[];window.CateriumDataV1770={isSupportReadOnly:()=>false,diagnostics:{measure:async(_n,fn)=>fn()},orders:{applyServerChanges:(orders)=>window.__applied.push(...orders)}};window.CateriumData=window.CateriumDataV1770;window.SunCloudV2={getSession:()=>({user:{id:'u'}}),getWorkspace:()=>({id:'w'}),getClient:()=>({rpc:async()=>({data:{changed:1,orders:[{id:8,status:'Отдан заказчику'}]},error:null})})};}); + const source=fs.readFileSync(path.join(process.cwd(),'public','core','server-automation-v1770.js'),'utf8');await page.addScriptTag({content:source}); + await page.waitForFunction(()=>Boolean(window.CateriumServerAutomationV1770));await page.evaluate(()=>window.CateriumServerAutomationV1770.run({force:true})); + expect(await page.evaluate(()=>window.__applied)).toEqual([{id:8,status:'Отдан заказчику'}]); +}); diff --git a/tests/release-check.mjs b/tests/release-check.mjs index 583b954..b2c532e 100644 --- a/tests/release-check.mjs +++ b/tests/release-check.mjs @@ -65,3 +65,11 @@ check(offerWorkspace.includes('PDF и предпросмотр')&&offerWorkspace check(offerWorkspace.includes('SunClassicOfferPDFV1767')&&offerWorkspace.includes('finalGallery=galleryFor'),'custom gallery is injected into PDF renderer'); check(releaseManifest.offerWorkspaceTabs===true&&releaseManifest.offerTemplatesSeparateTab===true&&releaseManifest.offerTwoCustomGalleryPhotos===true,'release manifest records offer workspace changes'); if(bad)process.exit(1); + +check(pkg.version==='17.7.0','package version is v17.7.0'); +check(index.includes('20260908-v17-7-0-architecture-foundation'),'index cache bust is v17.7.0'); +check(sw.includes('v75-20260908-v17-7-0-architecture-foundation')&&sw.includes('data-layer-v1770.js')&&sw.includes('server-automation-v1770.js'),'PWA caches architecture foundation modules'); +check(fs.existsSync(path.join(root,'public/core/data-layer-v1770.js'))&&fs.existsSync(path.join(root,'public/core/server-automation-v1770.js')),'data layer and server automation modules exist'); +check(ux.includes('CateriumServerAutomationV1770?.enabled'),'cloud browser auto completion is disabled when server automation is active'); +check(runtime.includes("const VERSION = '17.7.0'")&&runtime.includes("v17.7.0 Architecture Foundation"),'stability logger reports v17.7.0'); +check(fs.existsSync(path.join(root,'ops/sql/SUPABASE-V17.7.0-SERVER-ORDER-AUTOMATION.sql'))&&fs.existsSync(path.join(root,'ops/sql/SUPABASE-V17.7.0-ERROR-TELEMETRY-HYGIENE.sql')),'v17.7.0 server migrations are versioned');