3 Commits

Author SHA1 Message Date
metatroncubeswdev
ff96bf0f81 O9: a real public website - Metatroncube's marketing homepage, and a second Odoo branding leak found while building it
CLAUDE.md's own O9 spec says branding applies to "backend, portal,
website and every QWeb report" - the website part was never actually
built. The public side of the site was still bare stock Odoo: an
empty homepage (website.homepage ships as a literal
`<div id="wrap" class="oe_structure oe_empty"/>`) and the admission
form as the only real content anywhere a visitor could land.

Per discussion: this is Metatroncube's own product marketing page, not
the fictional school's site - it stays on a fixed brand (navy/indigo,
Manrope + Work Sans, an illustrative dashboard preview panel), not the
per-company colours the admission form and portal already read from
res.company. Swapping the demo company for the O9 closing beat
re-skins the product's own screens; it must not also repaint
Metatroncube's own marketing collateral.

Real second bug found building this, not related to the homepage
content itself: rendering it surfaced a second, separate "Powered by
Odoo" badge - web.brand_promotion, called from web.frontend_layout's
shared footer - that is completely different from the one
mc_education_theme already hid on the portal sidebar (different
template, different markup, an <img> logo rather than text). This one
sits in the footer of every website AND portal page and had been live
on the admission form this whole time; nobody had reason to scroll to
the bottom of that page and look. Neutralizing the shared, reusable
template rather than website.layout specifically means every current
and future caller of web.brand_promotion is covered by one fix.

New dependencies this actually needs and the spec's one-line
"Depends: mc_education_base" missed: `website` (to inherit
website.homepage) and `web` (to inherit web.brand_promotion) - on top
of `portal`, already added for the same reason last time. Flagging
per CLAUDE.md's closing instruction rather than working around it
quietly again.

Testing note worth recording: website.homepage resolves through a
per-website "copy-on-write" view, and Odoo auto-creates a default
website (COW'd immediately) before this module even loads. Checking
that per-website combination via _get_combined_arch() inside a
--test-enable run that installs and tests everything in one
transaction can see a stale, pre-COW empty result purely from cache
timing internal to that one transaction - confirmed NOT a real
defect by checking the same thing as a fresh request against the
actual long-running server, which renders correctly every time.
Tests here check what's actually deterministic (this module's own
authored view content) plus a live HTTP round trip proving the route
itself serves successfully, rather than chase that harness artifact.

Full suite (all 9 modules + web_responsive) re-verified together:
0 failed, 0 error(s) of 85 tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 18:39:40 -04:00
metatroncubeswdev
bd9b449ded fix: create the four backend demo logins the demo script actually needs
shared/DEMO_SCRIPT.md's cast table names six logins. Two - the parent
and student portal accounts - were created in mc_education_portal.
The other four (Principal, Front Office, Teacher, Accountant) were
explicitly punted to O9: mc_education_base's demo/mc_teacher_demo.xml
says outright "res.users/login creation is O9's job (demo rehearsal),
not this base module." That job was never actually done - found only
now, while writing a demo handbook that needed to print real, working
credentials and I checked them against a live container before
printing anything.

Concretely this means a from-scratch rehearsal of the demo script
would have stalled at Scene 1: there was no way to log in as Rekha
Nair, Sunitha R, or David Fernandes at all, and logging in as
"Arun Prakash" would have meant either sharing the admin account or
creating an unlinked user that fails Scene 4's actual point - a
teacher seeing only their own batch, which the attendance record rule
resolves through batch_id.class_teacher_id.user_id. Arun's login is
now attached to the same hr.employee record mc_education_base's own
demo data already made Grade 8-A's class teacher, not a fresh one.

Real Odoo behaviour learned fixing this, worth recording since it
will bite again: demo data loads with noupdate=True so a school's own
edits survive a later module update, and that guard is checked by
xmlid, not by which file is doing the writing - a <record> in this
module trying to set an existing mc_education_base demo record's
field was silently skipped, no error, nothing in the log. <function>
calls the ORM directly and is the correct tool, but carries the same
guard one level up in Odoo's loader (convert.py's _tag_function skips
entirely unless the module is being freshly installed, mode == 'init'
- an update on an already-installed database is a no-op). That is
exactly the real story this product cares about (a clean machine,
installing the whole suite once), so it's the right fix going
forward - verified on a from-scratch install of all nine modules
together. The one already-running database that had this module
installed before this fix existed needed a one-off manual correction
outside the codebase, not a workaround inside it.

Added a regression test asserting all four logins exist in the right
group and that Arun's employee record and Grade 8-A's class_teacher_id
actually resolve to the same person - not just "a teacher login
exists somewhere."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 15:06:31 -04:00
metatroncubeswdev
736c0e8c10 O9: mc_education_theme - per-company branding, the closing beat
Serves O9's acceptance test directly: swap to the second demo school
by switching the active company. Every branding field this module
configures - logo, primary/secondary colour, name, currency (on the
brand-new company only, see below), address - already exists on stock
res.company; this module adds zero new model fields, only demo data
and one view override. Two full companies exist because
shared/DEMO_SCRIPT.md names both by design: St. Aloysius Public
School (Coimbatore, the rebranded default company) and Waterloo
Heights Academy (Ontario, a fresh second company).

Removed the one concrete, spec-named piece of visible Odoo branding:
portal.portal_record_sidebar's "Powered by Odoo" logo, which renders
on every portal document page including the fee invoices
mc_education_portal links to - inherited the template and dropped
that div. Verified by actually rendering the template
(ir.qweb._render) and asserting the string is gone, not just that the
xpath applied without error.

Vendored OCA web_responsive per CLAUDE.md sec 2 ("pin every
third-party addon to a commit SHA, never a branch") - pinned to
b96307a8953f3bae075b8f7d94f40f00c2e63d1f on OCA/web's 19.0 branch.
Correcting my own third_party/README.md from O0 while doing this:
`git subtree add` on the whole OCA/web repo pulls every addon in that
monorepo (23MB+) for the sake of one - updated the instructions there
to fetch the pinned commit and extract just the one addon's directory
instead. Verified installable standalone against the live container
before vendoring it into the suite.

Real finding from testing the full 9-module suite installed together,
not this module in isolation: mc_education_fees's chart-of-accounts
setup (via `account`) posts journal items for the main company before
this module's demo data runs, and account.company.write() hard-blocks
a currency change once journal items exist - correctly so, you cannot
retroactively change a currency after transactions are posted in it.
Company currency belongs at true initial setup, before any financial
module has run, never as a later "apply a theme" change; dropped the
currency_id change on the rebranded main company accordingly (the
brand-new second company has no such history, so its currency is set
safely at creation). This is exactly why this session tests each
module against a real container, then the whole suite together before
calling anything done - this specific bug only exists when multiple
modules' demo data compose, and was invisible testing this module
alone.

Full-suite verification: all 9 mc_education_* modules plus
web_responsive installed together in one database, 81 tests across 8
of the 9 modules (mc_education_admission has none - a known gap, it
was verified by hand via curl/shell against the live container
instead, see its own commit), 0 failed, 0 errors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 14:24:05 -04:00