Branch

Pending: 0 Building: 1 Running: 2 Failed: 259

[FIX] web_responsive: pin primary-variables bundle order CPython randomizes string hashing per process (PYTHONHASHSEED), so a Python set literal used as an assets bundle value iterates in a different order every time the Odoo server process starts. The "web._assets_primary_variables" bundle was declared as a set of two SCSS paths, making its file load order nondeterministic across deployments and restarts. Switch the bundle from a set literal to a list literal, keeping the exact same two files in the exact same order they were already written in: form_variable.scss first, then primary_variable.scss. Verified safe to keep this order: form_variable.scss defines only $o-form-renderer-max-width and $o-form-view-sheet-max-width, while primary_variable.scss defines only $app-menu-text-color, $app-menu-background-color, $app-menu-item-highlight, $app-menu-box-shadow and $app-menu-box-shadow-highlight, all with !default. The two files' variable namespaces are fully disjoint in both directions, so there was no dependency-driven "correct" order to choose - this order is now a deliberate, deterministic choice rather than an accident of hash seeding. Protected by the repo-wide regression guard added in the immediately preceding commit (viin_brand/tests/test_manifest_assets_no_set_literals.py), which was measured RED against exactly this bundle before this fix, and is now confirmed GREEN together with this fix on a real Odoo 18.0 instance (db odoo_18_0_standard_viindoo_18_t_cbeabf2d): odoo.tests.result: 0 failed, 0 error(s) of 6 tests. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [FIX] viin_brand_common, web_responsive, viin_brand_mail, to_backend_theme: keep brand CSS out of core test bundles

Committer: David Tran

PR State: open

age: up-time: Not finished

[FIX] viin_brand_onboarding: drop own SCSS from core's JS unit-test bundles viin_brand_onboarding was the one brand module the earlier four-module sweep missed. Its onboarding.scss reads five brand variables that only viin_brand_common defines - $brand-primary-light/-dark/-darker and $brand-secondary-light/-dark - and that web.assets_unit_tests_setup and web.tests_assets no longer carry now that viin_brand_common's own sweep removed them. So this leak did not merely pollute core's JS unit tests with Viindoo design tokens, it aborted the compile of the whole bundle with "Undefined variable". Remove this module's own stylesheet from those two TEST-ONLY bundles; web.assets_backend (the real webclient) is untouched and still serves the stylesheet with all 18 brand gradient declarations byte-identical. New tests guard both directions. Measured: before 7 failed of 21 tests (14 "Undefined variable" occurrences), after 1 failed of 21 (0 "Undefined variable"). The one remaining failure is unrelated and pre-existing: a sibling guard test that needs point_of_sale or hr_attendance installed to verify anything, and correctly refuses to pass vacuously when neither is. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [FIX] viin_brand_common, web_responsive, viin_brand_mail, to_backend_theme: keep brand CSS out of core test bundles

Committer: David Tran

PR State: open

age: up-time:

[FIX] viin_brand_common: guard overrides out of public bundles Lock in the separation the previous commit established, so it cannot quietly rot. This module's overrides of core files belong to the backend webclient and must stay out of the point-of-sale terminal, the public mail page, the embedded livechat widget and the attendance kiosk. The guard asserts that in both directions: it also asserts the emoji-picker override is still deliberately shared with the public mail page and the livechat embed, so a future cleanup that mistakes those two intentional declarations for part of the leak gets caught instead of silently stripping brand coverage. It further asserts every override still reaches the webclient, so nobody can turn the suite green by deleting the overrides outright. Verified: 22 tests pass on a live database, and the four brand-appearance tours each still complete all three steps. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [FIX] viin_brand_common, web_responsive, viin_brand_mail, to_backend_theme: keep brand CSS out of core test bundles

Committer: David Tran

PR State: open

age: up-time:

[FIX] web_responsive: guard responsive layout now unit tests carry no brand CSS The previous commits on this branch stripped web_responsive's own SCSS back out of core's Hoot/QUnit test bundles, which fixed core tests that were measuring this module's layout instead of core's own defaults - but also removed the only place a regression that silently drops this module's SCSS from the real webclient would have been noticed. Add test_brand_css_out_of_test_bundles.py (2 tests): assert web_responsive.scss is absent from web.assets_unit_tests_setup and web.tests_assets (what the prior commit fixed) while still present in web.assets_web, the bundle the real webclient is served from - so a future change cannot silently strip the responsive layout from production while the test bundles stay clean. The module marker is matched on the full SCSS-compiler comment path, not a bare module-name substring, since this database also carries viin_customizer_web_responsive whose own stylesheet legitimately sits in the test bundle and would otherwise report a false leak. Verified live on a real instance: baseline 0 failed of 18, an inversion that comments out this module's own ('remove', ...) manifest entry takes down this guard specifically, and a restore-verify pass returns to 0 failed with all tours succeeding.

PR: [FIX] viin_brand_common, web_responsive, viin_brand_mail, to_backend_theme: keep brand CSS out of core test bundles

Committer: David Tran

PR State: open

age: up-time:

[FIX] to_backend_theme: drop own SCSS from core's Hoot/QUnit bundles Both web.assets_unit_tests_setup (core's Hoot test-setup bundle) and web.tests_assets (the legacy QUnit bundle) carry ('include', 'web.assets_backend') and ('include', 'web.assets_backend_lazy'), declared in Odoo core's own addons/web/__manifest__.py. That pulled to_backend_theme's own backend-theme SCSS straight into core's own unit-test pages, so several of core's own tests were measuring to_backend_theme's styling instead of core's own defaults. Add explicit ('remove', <path>) entries for all 7 of this module's own SCSS files, spanning both source bundles (web.assets_backend / web.assets_backend_lazy), to both TEST-ONLY bundle keys in this module's own manifest. web.assets_backend and web.assets_backend_lazy themselves (the real webclient) are untouched - AssetPaths.remove() operates on the accumulated per-bundle path list, not on the source bundle that contributed it. Confirmed both statically (zero diff on either production bundle key) and live (the two test bundles now resolve zero of this module's SCSS paths while the production bundles still resolve all of them, unchanged, and both test bundles still compile clean with zero errors). Manifest-only change - this module has no test-page CSS shim to remove.

PR: [FIX] viin_brand_common, web_responsive, viin_brand_mail, to_backend_theme: keep brand CSS out of core test bundles

Committer: David Tran

PR State: open

age: up-time: Not finished

[FIX] web_responsive: fix apps-menu toggle dead-end and flash bug The apps-menu toggle button (button.o_grid_apps_menu__button) could go permanently dead. AppsMenuAction is registered under the "menu" client-action tag, so it can be mounted directly via doAction("menu"), bypassing the apps_menu service's own openMenu() (the overlay path) entirely. When that happens, the service's isOpening flag still turns true (AppsMenuScreen's mount effect fires unconditionally) but removeOverlay stays null, so the next click's closeMenu() finds nothing to remove and does nothing - the button stays dead until the action is dismissed some other way. A code comment claimed this path was "unreachable, no live path to test" - that was false: erponline-enterprise18/viin_customizer_web_responsive (auto_install: True) reaches it via its own isolated action service, and this module's own test suite already drives doAction("menu") through the real action service elsewhere. closeMenu() now falls back to the real "action" service: when the "menu" action is the current controller and something is underneath it (breadcrumbs already exclude "menu"-tagged controllers, so a non-empty array means a real prior screen), it restores that screen. With nothing underneath (a bare doAction("menu"), e.g. the boot fallback) the button stays a no-op by design - there is nothing to reveal. Separately, the previous commit's anti-flash fix (66a6a7d65d, passing `open` down as a prop so the app grid renders in the same cycle the screen mounts) was silently discarded for any upgraded user. AppsMenu.setup() called useState() a second time whenever session.apps_menu.is_redirect_home is true, recomputing `open` from the router's menu_id and overwriting the prop entirely. migrations/18.0.1.0.8/post-migration.py backfills is_redirect_home=True for every upgraded user with no action_id - the dominant real configuration, not an edge case - so any such user landing on a non-root menu (menu_id != 0) got the one-frame empty-overlay flash back. Collapsed to a single useState() call: the prop wins whenever the caller passes it; the is_redirect_home fallback only applies when AppsMenu is mounted without that prop. Also removed a dead `browser.localStorage.setItem("redirect_menuId", "")` write (and its now-unused import) - its only reader, onMenuClick, was deleted by 66a6a7d65d; no other reader exists anywhere across branding18, tvtmaaddons18, or erponline-enterprise18. Updated a stale test comment describing the retired bus-round-trip open mechanism, and dropped a stray blank line. Bumped the module version. Two RED-before-green Hoot tests were added protecting each fix, both confirmed failing on the pre-fix code and passing after, live on Hoot desktop preset: - "clicking the navbar apps button dismisses the menu action too, not only the overlay" - "the is_redirect_home branch never overrides the open prop AppsMenuScreen always passes" Before: filter=@web_responsive/apps_menu - 17 tests, 15 passed / 2 failed (both new tests red on the exact predicted assertions). After: same filter - 17/17 passed. Full @web_responsive tag - 17/17 passed. Also manually verified the ordinary overlay open/close flow live in the browser - no regression.

PR: [FIX] web_responsive: reach the apps menu the user actually opens

Committer: David Tran

PR State: merged

age: up-time: Not finished

[FIX] web_responsive: reach the apps menu the user actually opens e2e5205 split the apps-menu screen into two sibling classes - AppsMenuAction (still registered under the "menu" actions tag, the class third-party modules patch by name) and AppsMenuOverlay (what appsMenuService.toggleMenu() actually mounts for the user, via the overlay service). Because the overlay was a SIBLING of AppsMenuAction rather than a descendant, a module that does patch(AppsMenuAction.prototype, {...}) and separately extends the shared "web_responsive.AppsMenuAction" template by name - the real, shipped shape in erponline-enterprise/viin_customizer_web_responsive - never reached the class that renders for the user. Runbot build 224030 failed 71 of 83 tests with "TypeError: ctx.getAppCreatorItem is not a function at AppsMenuOverlay.slot2": every tour that opens the apps menu died. Make AppsMenuOverlay extend AppsMenuAction instead of the shared AppsMenuScreen base, so a prototype patch() applied to AppsMenuAction - by this module or any third party, in either load order - is inherited by the overlay too. Corrected what plain inheritance would otherwise get wrong on the new subclass: static props (an overlay's shape, not the action-service props it would otherwise inherit), coversNothing (the overlay has no env.config to read breadcrumbs from, so it falls back to the base class's own resolution), and left static target/displayName inherited-but-inert with a comment so a future reader does not "clean them up" and reopen this. Documented at the class declarations that AppsMenuAction is both the "menu" action- tag registrant and the patch target other modules reach for by name, so the next module that legally patches this class does not silently break again. This repairs a regression we shipped, already merged into 18.0 (origin/18.0 @ 2cfee94 contains e2e5205). The suite was NOT executed here: this fix was produced under a static-verification-only constraint (no instance, no odoo-bin, no database, no test run). RED was argued from source - traced against e2e5205's diff and the real external patcher/template-inheritor - and the fix confirmed by static reasoning over the JS prototype chain (AppsMenuOverlay.prototype's [[Prototype]] is a live reference to AppsMenuAction.prototype, so a patch() mutation to the latter is visible to overlay instances). Syntax-checked with node --input-type=module --check; no reachable project ESLint config to run further here - that gate runs later at the run's own pre-PR tail.

PR: [FIX] web_responsive: reach the apps menu the user actually opens

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_brand_common: stop prepending brand to every tab title Every real page title got "Viindoo - " prepended to it, because WebClient.setup() injected a PERMANENT titleParts entry (zopenerp: "Viindoo") whenever session.viin_brand is set. Core only ever composes the literal "Odoo" as the EMPTY-CASE FALLBACK - Object.values(titleParts).join(" - ") || "Odoo" in web/static/src/core/browser/title_service.js - it never appears beside a real title. website's SEO dialog rendered "Viindoo - Hello, world!" instead of "Hello, world!", failing core's own test_website_event_pages_seo tour (runbot 223907, target G1 of run tour-reenable-14456). Remove the permanent setParts() injection - webclient.js had no other purpose, so it is deleted - and instead patch core's "title" service itself (new static/src/core/browser/title_service.js) so ONLY the empty-case fallback is rebranded: core computes the title exactly as it always does, and only when core's own getParts() shows titleParts is empty does the patch replace the trailing "Odoo" with "Viindoo". A real title composed by core is never touched. Still gated on the server-stamped session.viin_brand marker (introduced by f35f41c) so core's own QUnit/Hoot suites, whose mock sessions lack the marker, keep asserting the plain "Odoo" title. NOT verified against a live Hoot/QUnit run: this environment has no spare RAM to build an instance (a foreign run owns the only live one). RED-today / green-after was argued by reading title_service.js's composition and hand-tracing titleParts for both scenarios in the companion test, never executed.

PR: [FIX] web_responsive, viin_brand_common: unbreak the tours #14456 re-enables

Committer: David Tran

PR State: merged

Delete Date:

age: up-time:

[FIX] web_responsive: drop the statusbar DropdownItem hotkey override DropdownItem no longer accepts a hotkey prop on 18.0, so grafting hotkey='shift+a' onto every statusbar dropdown item crashed the whole statusbar with an OwlError on small screens (where the buttons collapse into that dropdown). The override was pointless anyway — it assigned the same hotkey to every item.

PR: V18 fix web responsive

Committer: Roy Le

PR State: merged

age: up-time:

[FWD] forward-port 17.0 -> 18.0 (c676d5a..2fe943f, 8 commits) Single merge of origin/17.0 into 18.0. Every source commit enters the DAG with its own SHA intact, so the merge-base advances to 17.0's tip and none of these conflicts is ever re-resolved on a future run. Ported: 6aef9e0 8069ccc 221946b 4c0d67c f35f41c 0d6646d 33a11ec 2fe943f FOUR THINGS WOULD HAVE MERGED GREEN AND BEEN WRONG AT 18.0. Each is invisible in the diff, so they are named here. 1. 221946b's guard is deliberately NOT taken. Source gates _loadDefaultApp on registry.category("actions").contains("apps_menu"). At 18.0 the action registers under the tag "menu", so that condition is permanently false and would have silently disabled the apps-menu redirect for every user. The target already reaches the same no-throw outcome via its session marker. 2. 4c0d67c's isCheck does not exist at 18.0. The tour engine was rewritten; StepSchema declares no isCheck and validates through Owl validate(). `run` is optional-typed, so an explicit undefined is not the same as absent - the key is deleted, not set. 3. The AppsMenu tests are re-implemented on Hoot, not ported. 18.0 replaced QUnit and all three of this module's suites imported a helper 18.0 core does not ship - they were already dead on this branch. 18.0 also passes a BARE STRING to doAction("menu"), so a literal port of `step(`do-action:${action.tag}`)` reads .tag off a string, records "do-action:undefined", and passes while asserting nothing. The new tests step on the argument itself. 4. One CSS reset was not enough. 17.0 had one test page; 18.0 runs two. Both resets are declared under web.tests_assets AND web.assets_unit_tests. EVIDENCE. A/B on this tree - identical suite, brand absent from the addons path vs brand installed with the resets absent - returned 0 failures against 28, all pixel-geometry (11x column_widths, 4x daterange, 1x datetime, draggable, scroller, nested_sortable, 7x html_editor, 1x mail). With the resets in place that drops to 6, all in @html_editor/*. The 17.0 runbot ids and counts were deliberately not carried into the code - 18.0's suite has different names and numbers, and quoting the old ones would be fabricated evidence. Also verified on a live 18.0 build rooted on this tree: 10/10 new Hoot tests pass, 26/26 Python tests pass across the four modules, and WebSuite.test_check_suite now passes - it was erroring on 18.0 before this work, which is what 2fe943f fixes. TWO CHANGES BEYOND THE EIGHT COMMITS, both deliberate: - viin_brand_website's x_icon QWeb override is removed and replaced by a data-level default on website.favicon. The override was a position="replace" that, because locate_node resolves an xpath to the first document-order match, destroyed website's own favicon producer - so a customer who configured a favicon could never serve it. Removing it alone would have left new websites unbranded, so the brand image is now the field's default instead: branded out of the box, and the customer's own value survives once set. - Three local fixes were needed to make the ported tests actually run at 18.0: defineMailModels() for mail's mock models, componentEnv for env.config on a direct mount, and /web/offline -> /odoo/offline after core's route rename. KNOWN GAPS, not hidden: the design doc's test_asset_isolation.py leak-guard was not written; 6 @html_editor failures remain (brand-caused, pre-existing on 18.0, outside what the 17.0 commits addressed); test_qunit_desktop fails on viin_web_gantt, a module in a different repo; the colorpicker tour was adapted statically and not executed; cluster-wide acceptance was not run.

PR: [FWD] forward-port 8 commits from 17.0 (c676d5a..2fe943f)

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_brand_website: keep the brand favicon as a DATA default, not a layout override Removing the x_icon QWeb override earlier in this branch fixed the field being unusable, but lost something worth keeping: a website that had never configured a favicon fell back to core's website.favicon default, which is Odoo's own web/static/img/favicon.ico. A Viindoo deployment would have started unbranded on its public pages - the most visible place a customer looks. The override was not the right way to hold that. Because locate_node resolves an xpath to the first document-order match, the `position="replace"` landed on website's own `t-set x_icon` producer and destroyed it, so a customer who set their own favicon could never serve it. Brand-always-wins and customer-can-configure were mutually exclusive under that design. A data-level default gives both. `website.favicon` is redeclared with the brand image as its default, so a NEW website starts branded and any value the customer sets afterwards survives untouched. Redeclared rather than merely overriding _default_favicon: core binds the default to the function OBJECT (`default=_default_favicon`, evaluated at class-definition time), so overriding the method alone would never be picked up. to_base.res_company redeclares its own favicon field for exactly this reason. The image is read by addons path, not through a module dependency - viin_brand is auto_install and always present in a branded deployment, but this module declares no edge to it, so a missing file logs a warning and degrades to core's default rather than breaking website creation. Two tests lock the pair, because holding only one of them is the bug this commit exists to avoid repeating: a fresh website starts with the brand favicon, and a favicon the customer sets is not overwritten by the default. KNOWN LIMIT: a default applies at record CREATION. Databases whose website record already exists keep whatever favicon they have, which for an existing branded deployment is the correct outcome anyway (the old override was render-time, so nothing was ever stored). A deployment that wants existing website records re-branded needs a separate data step - not added here. Verified: 26 Python tests across the four modules, 0 failures, both new tests confirmed executed rather than skipped.

PR: [FWD] forward-port 8 commits from 17.0 (c676d5a..2fe943f)

Committer: David Tran

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_common+viin_brand_website: make 2fe943f's regression tests pass on 18.0 The two suites forward-ported with 2fe943f failed on their first real 18.0 run. Two distinct causes, both fixed here. 1. /web/offline was renamed to /odoo/offline at 18.0 (web/controllers/webmanifest.py), so two tests in test_web_layout.py got a 404 and never reached their assertions. Only the TEST was affected - viin_brand_common's own controller overrides the handler with a bare @http.route(), inherits core's path, and therefore followed the rename by itself. The path is now a module-level OFFLINE_URL constant so the next rename breaks in one obvious place. 2. viin_brand_website's layout carried an 18.0-only override that destroyed the website's own favicon: <xpath expr="//t[@t-set='x_icon']" position="replace"> <t t-set="x_icon" t-value="'/viin_brand/static/img/favicon.ico'"/> </xpath> locate_node resolves an xpath to the FIRST document-order match, which in the combined website.layout arch is website's own producer (t-set x_icon = website.image_url(website, 'favicon')). Replacing it meant a website that had configured its own favicon could never serve it - the brand path was substituted unconditionally, with no `or` guard. Adding a guard would not have helped: after the replace, x_icon is unset at that point, so `x_icon or <brand>` collapses to the brand every time. This is why the title survived while the favicon did not: only x_icon had a second, replace-based mutator. Title flows through website's own `t-if="not title"` guard untouched. SCOPE NOTE: that override is NOT one of the eight commits this wave forward-ports and predates it on 18.0 - 17.0 has no such block. It is removed rather than left red because the test 2fe943f brings across exists precisely to assert that the brand default never pre-empts a website's own value, and removing the override restores the 17.0 behaviour that test encodes. It does change observable behaviour: a website with its own configured favicon now serves that favicon on website pages instead of the brand one. Non-website pages are unaffected - they still take the brand default from viin_brand_common's own fallback. Flagged for review rather than buried. Verified: the four affected modules' Python suites now run 22 tests with zero failures on a live 18.0 build (was 3 failures).

PR: [FWD] forward-port 8 commits from 17.0 (c676d5a..2fe943f)

Committer: David Tran

PR State: merged

age: up-time: Not finished

[FIX] web_responsive: stop disabling the attachment side panel on every form form_renderer.esm.js patched FormRenderer.hasFile() to return false unconditionally, and the file is loaded in web.assets_backend for the whole backend. hasFile() is what mail's form compiler asks before rendering the "o_attachment_preview" hook (mail/chatter/web/form_renderer.js mailLayout(), which returns COMBO only when there is a file), so with it in place the attachment preview panel never rendered on ANY form at ANY screen size - no receipt beside an expense report, no PDF beside a vendor bill. The patch also has nothing left to do on 18.0: mailLayout() already gates the panel on SIZES.XXL, so narrow screens get the chatter at the bottom and no preview whether or not this override exists. It only removed the feature from the wide screens that are supposed to have it. The exported unpatchDisableFilePreview handle is never imported anywhere, so nothing ever put the behaviour back. Reproduced and verified on v18_full: hr_expense's test_show_expense_receipt_on_expense_line_click went from "1 failed of 1 tests" (step 8/12 "Check attachment" timing out after 10s because the panel was absent from the DOM) to "tour succeeded, 0 failed of 1 tests". A browser probe on the same database confirmed the cause was rendering, not data: the mail store held all three attachments with attachmentsInWebClientView = 3, uiService.size = 6 (XXL) and the chatter mounted, while .o_attachment_preview was absent entirely. No manifest version bump: the module declares its assets with the "views/form/*" glob, so the ir.asset rows in the database are unchanged and the bundle is rebuilt from the checksum of the files it resolves.

PR: [FIX] web_responsive: stop disabling the attachment side panel on every

Committer: Roy Le

PR State: merged

age: up-time:

[FIX] viin_brand_pos: make forward-ported POS navbar guard Hoot test runnable on 18.0 The Hoot test added with the a982703 forward-port statically imported the real @point_of_sale/app/navbar/navbar, which drags 9 transitive POS-app modules into the shared web.assets_unit_tests bundle and aborts the whole web unit suite at setup. Register a dependency-free stand-in under the same module name (core's own odoo.define idiom) so the real guard patch applies on top of it without pulling the POS UI tree into the shared bundle. Proven live on 18.0: passed 2/2 with the guard, and the guard test fails when the guard is reverted (confirm-by-toggle).

PR: [18.0][FWD] Forward-port 17.0 fixes: branded colorpicker tour, POS navbar guard, statusbar/chatter absorbs

Committer: David Tran

PR State: merged

age: up-time:

[FIX] web_responsive: correct a false idempotency comment + bind the session_info test Three review findings from the forward-port batch. The migration's comment claimed the is_redirect_home filter makes a re-run match nothing, so an opted-out user is never silently re-opted-in. The second half was false: an opted-out user holds False, which is exactly what the domain selects. Odoo compiles a boolean "= False" to (col IS NULL OR col = FALSE), so the domain provably cannot tell "never backfilled" from "deliberately opted out" - the manifest version gate is what makes this run once. The comment now says that. The domain and the logic are unchanged and correct: that same collapse is what lets the backfill match the NULL rows every pre-existing user actually has. test_session_info only ever exercised the preference at True, so a hardcoded True in the session_info transport would have passed it. It now also flips the preference to False and re-asserts, binding the assertion to the user's real stored value on both sides. The new JS test file carried an OCA sibling's copyright header; it is Viindoo's own 2026 file. The LGPL-3 license line stays - the module is OCA.

PR: [FWD] forward-port 17.0 -> 18.0: store URLs + web_responsive apps_menu guard + is_redirect_home restoration

Committer: David Tran

PR State: open

age: up-time:

Merge remote-tracking branch 'origin/17.0' into 18.0

PR: Fwd from 17 to 18 260630 01

Committer: David Tran

PR State: merged

age: up-time:

[IMP] viin_brand_website_sale: drop unverifiable "#1" claim from promo The eCommerce "Powered by" footer stated "The #1 Open Source eCommerce Software" (vi_VN: "... Mã nguồn mở số 1"), an unverifiable superiority ranking. Vietnam's advertising law forbids "#1"/"best" style claims without supporting evidence and penalises them heavily, so remove the ranking wording from both the template source and the Vietnamese translation. - views/templates.xml: drop the "#1" from the promo label and the standalone "The" text node so the label reads "Open Source eCommerce Software"; add a comment at the label noting the VN advertising-law constraint. - i18n/vi_VN.po and .pot: realign msgid to the new source string and drop the now-orphaned "The" term; msgstr "... Mã nguồn mở số 1" -> "... Mã nguồn mở". - bump module version 0.1 -> 0.2 so existing databases pick up the updated view and translation on upgrade.

PR: [IMP][13.0] viin_brand_website_sale: drop unverifiable "#1" claim from promo

Committer: SonCrits

PR State: open

age: up-time:

[IMP] gitignore: ignore node_modules and .odoo-ai Add node_modules/ (Node.js dependencies) and .odoo-ai/ (Odoo AI agent workspace) to .gitignore so these local build/tooling artifacts are never tracked.

PR: [IMP] gitignore: ignore node_modules and .odoo-ai

Committer: David Tran

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_auth_signup: Header values may not contain linefeed

PR: [ADD][16.0] viin_brand_auth_signup: Viindoo Branding for module Signup

Committer: Viinbot

PR State: open

age: up-time:

[IMP] viin_brand_auth_totp_mail: fix test pylint

PR: [IMP][16.0] viin_brand_auth_totp*: Viindoo debranding for module auth_totp*

Committer: Viinbot

PR State: open

age: up-time:

[IMP] viin_brand_calendar: fix test pylint

PR: [ADD][16.0] viin_brand_calendar: Calendar Branding For Viindoo

Committer: Viinbot

PR State: open

age: up-time:

Update viin_brand_hr_skills/__manifest__.py

PR: [IMP][16.0] viin_brand_hr*: replace odoo brand by viindoo

Committer: GitHub

PR State: open

age: up-time:

[FIX] web_responsive: mv text-input.scss to viin_brand_mail

PR: [FIX] web_responsive: mv text-input.scss to viin_brand_mail

Committer: David Tran

PR State: merged

age: up-time:

[FIX] web_responsive: fix show scroll in text input

PR: [FIX][16.0] web_responsive: fix show scroll in text input

Committer: TuyenTran

PR State: merged

age: up-time:

[FIX] web_responsive: fix show scroll in text input

PR: [FIX][16.0] web_responsive: fix show scroll in text input

Committer: TuyenTran

PR State: merged

age: up-time:

[FIX] web_chatter_position: Fixed an issue where form height was lost in the Note app.

PR: [FIX][16.0] web_chatter_position: Fixed an issue where form height was lost…

Committer: quyen

PR State: merged

age: up-time:

[FIX] web_chatter_position: Fixed an issue where form height was lost in the Note app.

PR: [FIX][16.0] web_chatter_position: Fixed an issue where form height was lost…

Committer: quyen

PR State: merged

age: Not finished up-time: Not finished

[FIX] web_chatter_position: Fixed an issue where form height was lost in the Note app.

PR: [FIX][16.0] web_chatter_position: Fixed an issue where form height was lost…

Committer: quyen

PR State: merged

age: up-time: Not finished

[FIX] web_chatter_position: Fixed an issue where form height was lost in the Note app.

PR: [FIX][16.0] web_chatter_position: Fixed an issue where form height was lost…

Committer: quyen

PR State: merged

age: up-time:

[FIX] viin_brand_mail: restore the test bot identity on update, not only on install data/res_partner_data.xml renames base.partner_root to ViindooBot and is not noupdate, so the rebranding is re-applied on EVERY module update. The guard that puts core's OdooBot identity back for test runs lived in post_init_hook, which odoo/modules/loading.py:244 calls only when the module's state is 'to install' (:178). The two were asymmetric - branding on every load, restore on the first one only - so any -u left the partner branded and every core test hardcoding odoobot@example.com failed. google_calendar alone contributed 12 of them, since the superuser is the implicit event organiser in its Odoo-to-Google payload comparisons. The restore now lives on res.partner and is driven from the same data file that applies the branding, so both are on one trigger; a function tag runs on update as well as install (odoo/tools/convert.py:279-281 skips it only under noupdate). post_init_hook is kept as a one-line delegation so the logic has a single home.

PR: [FIX] viin_brand_mail: restore the test bot identity on update, not only on install

Committer: David Tran

PR State: open

age: up-time:

[FIX] viin_brand_common: restore core's QUnit leak-guard on web.layout viin_brand_common anchored its web.layout brand title/favicon defaults on //title and //link[@type='image/x-icon']. Core's WebSuite._check_only_call (web/tests/test_js.py:104) rewrites web.layout's whole arch_db to a stub containing neither node, and that write revalidates every extension of web.layout. The recombination raised a ValidationError, leaving core's QUnit leak-guard - the guard that stops a stray QUnit.only() from silently disabling the whole JS suite - dead on every Viindoo 17 database. Replace the two position="attributes" xpaths with a single <xpath expr="//head/meta[last()]" position="after"> that sets both values as `or` fallbacks. {head, meta[@charset]} is exactly the node set present in both the real arch and core's stub, and meta[last()] is the latest reachable point in it, so the defaults bind after every upstream producer - notably website.layout's per-page title, its seo_object assignment and the OpenGraph block - and before <title>. An anchor placed before <head> instead lands outside it and pre-empts those producers. Bump the manifest version 0.3.1 -> 0.3.2: Viindoo SaaS auto-upgrade selects modules to -u by diffing the on-disk manifest version against the customer database's ir_module_module.latest_version, and a view change only reaches an existing database through -u. Without the bump the fix would reach fresh installs only. Add regression coverage: viin_brand_common/tests/test_web_layout.py (4 methods) locks the stub survival and the brand defaults; viin_brand_website gains tests/test_website_title_not_preempted.py (3 methods) owning the cross-module contract that the brand default never pre-empts a website title or its OpenGraph meta. Both suites were proven RED - the first against 33a11ec, the second against acc5474. Close https://github.com/Viindoo/branding/issues/654 Signed-off-by: David Tran <davidtran.hp@gmail.com>

PR: [FIX] viin_brand_common: anchor web.layout xpaths on //head so core's QUnit guard can run again

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_brand_common: anchor web.layout xpaths on //head, not //title/link Core's WebSuite.test_check_suite (web/tests/test_js.py::_check_only_call) replaces web.layout's entire arch_db with a minimal stand-in arch that has a <head> but no <title>/<link>, to validate no stray QUnit.only()/ QUnit.debug() was left in the JS test suite. Writing that stand-in fires ir.ui.view's arch_db constraint, which recombines every view inheriting web.layout - viin_brand_common's two xpaths (anchored on //title and //link[@type='image/x-icon']) cannot locate their anchor against the stand-in, raising ValidationError and leaving core's QUnit-guard dead on every Viindoo 17 database. Replace both element-anchored xpaths with a single xpath anchored on //head (which the stand-in does provide), inserting two <t t-set> nodes as previous siblings of <head> that set the `title`/`x_icon` QWeb variables to their Viindoo defaults via an `or` fallback chain (`title or 'Viindoo'`, `x_icon or '/viin_brand/static/img/favicon.ico'`). Core's own <title t-esc="title or 'Odoo'"/> and favicon <link t-att-href="x_icon or '/web/static/img/favicon.ico'"/> then pick up those pre-set values unchanged, so exactly one <title> renders and an explicit caller-supplied title/x_icon still wins. Bump version 0.3.1 -> 0.3.2 so existing databases reload arch_db on upgrade. Add tests/test_web_layout.py (wired into tests/__init__.py) with 4 HttpCase regression tests covering: survival of core's exact stub write (RED before this fix), default title/favicon still brand correctly with exactly one <title>, an explicit title still wins, and an explicit x_icon still wins. All 4 assert on rendered HTTP output, never the arch string. Close https://github.com/Viindoo/branding/issues/654

PR: [FIX] viin_brand_common: anchor web.layout xpaths on //head so core's QUnit guard can run again

Committer: David Tran

PR State: merged

age: up-time:

[IMP] viin_brand_website_sale: drop unverifiable "#1" claim from promo The eCommerce "Powered by" footer stated "The #1 Open Source eCommerce Software" (vi_VN: "... mã nguồn mở số 1"), an unverifiable superiority ranking. Vietnam's advertising law forbids "#1"/"best" style claims without supporting evidence and penalises them heavily, so remove the ranking wording from both the template source and the Vietnamese translation. - views/templates.xml: promo label "The #1 Open Source eCommerce Software" -> "Open Source eCommerce Software"; add a comment at the label noting the VN advertising-law constraint. - i18n/vi_VN.po and .pot: realign msgid to the new source string; msgstr "... mã nguồn mở số 1" -> "... mã nguồn mở". - bump module version 0.1 -> 0.2 so existing databases pick up the updated view and translation on upgrade.

PR: [IMP][17.0] viin_brand_website_sale: drop unverifiable "#1" claim from promo

Committer: SonCrits

PR State: merged

age: up-time:

[IMP] viin_brand_website_sale: drop unverifiable "#1" claim from promo The eCommerce "Powered by" footer stated "The #1 Open Source eCommerce Software" (vi_VN: "... mã nguồn mở số 1"), an unverifiable superiority ranking. Vietnam's advertising law forbids "#1"/"best" style claims without supporting evidence and penalises them heavily, so remove the ranking wording from both the template source and the Vietnamese translation. - views/templates.xml: promo label "The #1 Open Source eCommerce Software" -> "Open Source eCommerce Software"; document the inherited replace with a comment. - i18n/vi_VN.po and .pot: realign msgid to the new source string; msgstr "... mã nguồn mở số 1" -> "... mã nguồn mở". - bump module version 0.1 -> 0.2 so existing databases pick up the updated view and translation on upgrade.

PR: [IMP][17.0] viin_brand_website_sale: drop unverifiable "#1" claim from promo

Committer: SonCrits

PR State: merged

age: Not finished up-time: Not finished

[FIX] web_responsive: core checkbox metrics inside QUnit pages The 'big checkboxes' restyle (+10px margin-right, 1.5em box) widens the list record-selector column, shifting core pixel-width assertions by exactly those pixels (runbot 223235/396399: ListView 'column widths should depend on the content when there is data' 41->51 and 'editable list: resize column headers' 52->51). Load a web.tests_assets-only reset that pins the test page back to core metrics; the real webclient keeps big checkboxes.

PR: [FIX] viin_brand_common: apply brand palette/title only in genuine sessions; core metrics in QUnit

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_common: apply brand palette/title only in genuine sessions; core metrics in QUnit Three brand client tweaks broke core QUnit suites: the unconditional colors.getColor override failed 30 GraphView tests asserting the default palette; the 'Viindoo' window-title part failed 3 ActionManager title tests; and the 15px base font shifted pixel-geometry assertions (Draggable confinement, Scroller offsets, tour anchors) by fractions of a pixel (runbot 223219/396221 & 223235/396399). session_info now stamps a viin_brand marker: real sessions keep the brand palette and title, mock test sessions (marker absent) fall through to core behavior. A web.tests_assets-only CSS reset pins the test page back to the 14px core base font - the real webclient is untouched. Also fix the missing '#' on the last palette color (was an invalid CSS color).

PR: [FIX] viin_brand_common: apply brand palette/title only in genuine sessions; core metrics in QUnit

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_website: end the colorpicker tour override with a pure check step The override dropped the final RGBA assertion entirely, leaving the last step action-less -- web_tour warns "ignoring action (auto) of last step" on every run. Relax the step to a pure check (isCheck on .o_rgba_div) instead of dropping it: the tour still ends on a verification, only the hard-coded rgb assertion the brand palette invalidates is gone. Verify: /website:TestUi.test_32_website_background_colorpicker 0 failed, 0 "ignoring action" warnings (clean CE and v17_full).

PR: V17 fix test tour

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_common: keep statusbar arrows compact so 4 stages fit on mobile The brand raises $o-font-size-base to 15px (core default is 14px). That extra width on the status-flow arrows is enough that a 4-stage statusbar no longer fits one row on small screens: adjustVisibleItems detects the wrap and folds one arrow into the overflow dropdown. Core's mobile web StatusBarField QUnit tests assert every stage renders as an inline arrow (4 visible, a single "..." toggle, one disabled dropdown item), so they failed 3/... under the branded assets while passing on clean CE. Root-caused on v17_full by instrumenting core areItemsWrapping(): branded arrows measured 65px wide / 34.5px tall vs clean CE's 50-61px / 33px, tipping 4 arrows over the container width. Scope the arrows to $o-font-size-base-small (13px) - the framework's compact control size - so they match core's geometry and all four stages stay inline. Only the arrow chrome shrinks; stage labels remain legible. Verified on v17_full: web MobileWebSuite.test_mobile_js 0 failed (the three StatusBarField "small devices" / "extra small screens" / "clickable ... on mobile" cases now pass).

PR: [FIX] viin_brand_common: keep statusbar arrows compact so 4 stages fit on mobile

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] web_responsive: restore disabled binding on chatter Log Note button The web_responsive.Chatter template replaces the Log Note button but dropped its t-att-disabled binding (the sibling Send message button kept it). This left Log Note always enabled regardless of posting permission, breaking Odoo core's project_chatter_log_disabled tour (project/tests/test_project_ui.py), which logs in as a limited Project User and asserts the button is disabled. Restore the same disabled expression used by the Send message button.

PR: [FIX] web_responsive: keep upstream "Action" statusbar toggler on mobile

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_pos: guard company service in POS Navbar favicon patch The POS Navbar patch read this.env.services.company.currentCompany.id unconditionally in setup() to set the branded favicon. The company service is not registered in the bare point_of_sale QUnit test env, so this.env.services.company was undefined and .currentCompany threw "Cannot read properties of undefined (reading 'currentCompany')" in Navbar.setup -> the whole POS Chrome mount failed, failing point_of_sale:WebSuite.test_pos_js ("mount the Chrome"). Optional-chain the service and bail out when there is no current company (no branded favicon to set). Real POS is unaffected. Verified: point_of_sale:WebSuite.test_pos_js passes (0 failed) on a focused point_of_sale+viin_brand_pos install with the guard.

PR: [FIX] viin_brand_pos: guard company service in POS Navbar favicon patch

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] viin_brand_website: adapt website_background_colorpicker tour to branded palette viin_brand_common recolours the frontend theme palette (primary #7f4282), so the core website_background_colorpicker tour no longer holds: its custom-colour step targets a hard-coded swatch background-color:#65435C (= rgb(101,67,92)) that the recoloured palette never produces, and the following RGBA check asserts that exact rgb. That breaks website: TestUi.test_32_website_background_colorpicker. Re-register the tour (force) in web.assets_tests with the custom-colour step adapted to pick whatever the first custom swatch is, and drop only the hard-coded custom-colour rgb assertion. The gradient steps (a fixed preset) and their RGBA check are kept, so the tour still exercises the colorpicker.

PR: [FIX] viin_brand_website: adapt website_background_colorpicker tour to branded palette

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] viin_brand: repoint hr_contract link to the canonical 17.0 store URL to_base overrides a core module's manifest 'website' from this branding dict at load time (_get_brand_module_website -> _load_manifest_plus), so this value is what a Viindoo deployment actually displays for the core hr_contract module - it is shipped, not inert. The hr_contract entry was wrong twice over: it used the legacy /apps/app/ prefix (now only a permanent 301 shim), and it pinned version 15.0 inside the 17.0 branch, so 17.0 users were sent to a four-series-old store page. viin_hr_contract is published on the store at 17.0, so the canonical target resolves directly. The remaining entries are deliberately left alone: they map core Odoo modules to Viindoo marketing intro pages, which is the correct destination - a core Odoo module has no Viindoo store page under its own name. hr_contract is the only store link in this dict, and the only one that was stale.

PR: [IMP] *: point module manifests at their canonical App Store page

Committer: David Tran

PR State: merged

age: up-time:

[FIX] web_responsive: don't break core component tests when apps_menu is absent The NavBar and WebClient patches called useService("apps_menu") and the menu searchbar read session.apps_menu.search_type. Isolated core component tests (NavBar, BurgerMenu, mail mobile) do not start apps_menu nor set session.apps_menu, so these threw as soon as web_responsive is installed ("Service apps_menu is not available", "Cannot read properties of undefined (reading 'search_type')"). Read apps_menu from env.services (optional), fall back to super._loadDefaultApp(), and use session.apps_menu?.search_type.

PR: [FIX] web_responsive: don't break core component tests when apps_menu is

Committer: Roy Le

PR State: merged

age: up-time: Not finished

[FIX] web_responsive: use semantic SCSS tokens + guard apps_menu access

PR: [FIX] web_responsive: semantic SCSS tokens + guard apps_menu access

Committer: David Tran

PR State: merged

age: up-time:

[MISC] *: enrich demo data

PR: [MISC] *: enrich demo data

Committer: Roy Le

PR State: merged

age: up-time:

[FIX] viin_backend_theme: restyle core without rewriting it A theme may change how Odoo looks. This one had begun changing what Odoo says, what it does, and how it describes itself to assistive technology - and runbot batch 223955 was where that came due. The theme case-transformed two surfaces it does not own: core's command-palette category block and the list view's column headers. Rendered text is what Odoo's own automated checks, tour assertions, screen readers and a user's copy-paste all read back, so a purely cosmetic rule turned 102 core checks red at once ("Command#" read back as "COMMAND#"). Core already presents the palette's category label in capitals itself, so ours added nothing. It was also a defect users could see: the class it targeted is the block holding every command row, not the label, so its muted colour, 11px size, weight and letter-spacing were inherited by every row in the palette. Aiming the rule at the label alone restores the rows to core's typography. Odoo ends every font stack it ships with two safety nets: a small Noto subset for characters a system font lacks or renders badly, and the four emoji families. This theme replaced Odoo's stacks with its own and dropped both nets from headings and from body text, so an emoji or an uncommon script in ordinary backend text - a customer name, a chatter message, a product label - could land on a system with nothing able to draw it and render as an empty box. Both stacks are whole again and now end identically. The brand heading font was also reaching into the rich-text editor, where an outgoing email body inlines whatever font it is shown in, handing the recipient a Viindoo face their mail client does not have and which is not even vendored yet. Email bodies go back to the portable system stack; the backend keeps Montserrat. Clicking the navbar apps icon threw away whatever the user was working on. The icon opened the home menu as a full page, so an open record, a half filled form or a kanban the user had just filtered was torn down and had to be rebuilt on the way back. Odoo's own contract for that icon is that it shows the app list without navigating, and a large part of Odoo's test suite is written on that assumption: 57 test files click it, some to pick an app, others merely in passing before carrying on with the screen they were already on. The latter could not work here at all, and the former could not either, because our tiles were not the kind of element those tests look for. The icon now shows the same full-screen home menu over the untouched view. Pressing it again puts it away and the user is back where they were - instantly, because nothing was ever destroyed - and so does clicking the page behind it or pressing Escape, which the full-page version offered no way to do. The design is unchanged: one icon, one home menu, and the landing page shown at sign-in is untouched. App tiles are now real links, as they are in stock Odoo, so they can be opened in a new tab, copied, or announced sensibly. They had carried an explicit role telling a screen reader each tile is an item in a list, never that it is something the user can follow; because an explicit role replaces an element's own rather than adding to it, the tiles were also absent from links navigation, one of the main ways people using a screen reader move through a page. That role is gone, and the grid's own list role went with it, since a list is required to contain list items and keeping one alone would have left an empty, malformed list rather than a fix. Wrapping each tile to keep both was rejected: the tiles are laid out directly by the grid and are the elements the drag-to-reorder handles, so a wrapper breaks the layout and the reordering unless hidden by a CSS trick with its own record of removing elements from the accessibility tree. Nothing on screen changes, and keyboard navigation and drag-to-reorder are unaffected. Guards now fail the build if this theme case-transforms anything it did not author, if either font stack loses its fallback, or if a tile stops being announced as a link; the font guard reads the value the browser is actually handed rather than the source. One existing check was inverted rather than weakened: it asserted the previous view was gone after clicking the apps icon, which is the behaviour being fixed, and now asserts the view survives. Owner decisions D1, D2 and D3, 2026-08-17. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [FIX] viin_backend_theme, viin_brand_{web,mail,pos}: stop breaking core Odoo 19

Committer: David Tran

PR State: merged

Delete Date:

age: up-time:

[FIX] viin_backend_{web,theme}: remove redundant tests

PR: V19 fix imp viin brand cluster

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_backend_theme: remove redundant tests

PR: V19 fix imp viin brand cluster

Committer: David Tran

PR State: merged

age: up-time:

[IMP] viin_brand_web: remove border-radius override and link override

PR: V19 fix imp viin brand cluster

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_brand_base_setup, viin_brand_web: split the catalogue to follow the artefacts A stale #: reference silently DROPS the translation - the loader builds ir_model_data keys straight out of the occurrence string, finds no row, and skips the entry with no error and nothing red in any test suite. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [REF] viin_brand_common: split into viin_brand_web + viin_brand_base_setup

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_brand_website: brand the websites a field default cannot reach Removing the x_icon QWeb override was right - it resolved to website's own producer and destroyed it, so a configured favicon could never be served. But that override was also, incidentally, what made unconfigured websites look branded: it forced the brand path at render time for every website regardless of the stored field. With it gone the stored value renders, and for two populations that value is still Odoo's icon - website.default_website, which core creates while loading the website module, before this module's field extension exists, and any website predating this module's install. A field default fires only at record creation, so it reaches neither. So on every existing 19.0 database this branch, as it stood, silently swapped the Viindoo favicon for Odoo's. Reported by Codex on PR #664. Corrected once, from two entry points that share one implementation: post_init_hook for a fresh install, migrations/0.1.2 for a database where the module is already installed. Both rewrite ONLY records byte-identical to core's own default - those are provably nobody's choice - and leave every configured favicon exactly as it is, which is the whole point of having removed the override. Verified on clean databases: a fresh install and an upgrade both end with the default website branded, while a website whose owner set its own favicon keeps it byte-for-byte. UntouchedFaviconsGetBrandedTest locks both halves - doing nothing fails one assertion, overwriting everything fails the other.

PR: [FWD] forward-port 18.0 -> 19.0 (0dafec5..467ac60, 9 commits)

Committer: David Tran

PR State: merged

age: up-time:

[FWD] forward-port 18.0 -> 19.0 (0dafec5..467ac60, 9 commits) Absorbs every commit that landed on 18.0 since the last forward-port, so the merge-base advances and none of them is reconsidered next run. Three carry real behaviour to 19.0: * viin_brand_website no longer replaces website.layout's x_icon producer. That xpath resolved to core's own producer and destroyed it, so a customer who configured their own favicon could never serve it. Branding now comes from a field default in models/website.py: a new website starts branded, and the customer's value wins the moment they set one. Locked by tests/test_website_favicon_not_preempted.py. * viin_backend_theme guards _loadDefaultApp before diverting to the home menu, so an environment with a cleaned action registry falls back to the stock default app instead of throwing during boot. * viin_brand_website_sale drops the unverifiable "#1" ranking claim from the eCommerce promo, in the template and both translation catalogs. The rest are absorbed without adapt because 19.0 already moved past them: web_responsive is gone entirely, replaced by viin_backend_theme; QUnit is replaced by Hoot; the web.layout title/favicon fallback was deliberately re-homed onto that template's callers and must not be restored. One auto-merge carried a symbol that no longer exists here: the window-title branding arrived guarded by session.viin_brand, a marker stamped by an ir.http.session_info override 19.0 does not have, which would have left the title permanently unbranded with no error. Reverted to the 19.0 version. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [FWD] forward-port 18.0 -> 19.0 (0dafec5..467ac60, 9 commits)

Committer: David Tran

PR State: merged

age: up-time:

[FIX] viin_backend_theme: realign radius invariant to owner decision D5 viin_brand_common's brand_variables.scss restores a pre-19 square-corners token ($o-border-radius: 0) in the previous commit; this file's cluster-wide "zero radius overrides anywhere" invariant predates that restore and read it as the exact regression it exists to catch. Owner decision D5 keeps the restore, so the guard is updated to treat that single base-rung declaration as a pinned, SSOT-read exception (-sm/-lg remain unchanged and must still equal core's own scale exactly) instead of a violation. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [19.0][UPG] viin_brand_*: upgrade to 19

Committer: David Tran

PR State: merged

age: up-time:

[UPG] viin_brand*: upgrade to version 19.0

PR: [19.0][UPG] viin_brand_*: upgrade to 19

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time:

[REM] web_responsive: drop OCA responsive backend (superseded by viin_backend_theme's native mobile/rail redesign) Was the legacy to_backend_theme's dependency; nothing else in the repo/tvtmaaddons/core depends on it. Signed-off-by: David Tran <david.tran@tvtmarine.com>

PR: [UPG] branding-base cluster (5 modules) to Odoo 19.0 + de-brand/teal SSOT

Committer: David Tran

PR State: merged

age: up-time: