- Replace the Phase-0 "content to be completed" placeholder Usage section in every community_* README.rst with the actual features built across Phases 1-6 (routes, crons, portal pages). - Add CHANGELOG.rst (19.0.1.0.0) to every community_* module. - Note independent-vs-bundled module relationships in the root README. - Fix HANDOFF.md: Phase 8 was already committed (9a24691) and a git remote is configured, contrary to what it still said; record 9-A progress and the open gaps (missing banner.png assets, live --test-enable suite not re-run this session, no v1.0.0 tag yet).
12 KiB
Handoff / Resume Notes
Read this first if you're picking this project back up — whether that's
Claude Code in a future session or a human developer. The phase-by-phase
build plan is in CommunityOS_Implementation_Plan_for_Claude_Code.md; this
file is the "where things actually stand" companion to it.
Status at a glance
| Phase | What it is | Status |
|---|---|---|
| 0 | Repo scaffold, Docker dev stack, CI + brand-leak guardrails | ✅ Done, committed |
| 1 | community_membership |
✅ Done, committed |
| 2 | event_qr_ticketing |
✅ Done, committed |
| 3 | community_school |
✅ Done, committed |
| 4 | community_classifieds + community_benefits |
✅ Done, committed |
| 5 | community_interac (Interac e-Transfer payment provider) |
✅ Done, committed |
| 6 | community_theme_base + community_portal |
✅ Done, committed |
| 7 | tncsc_deployment (client config layer) |
✅ Done, committed |
| 8 | TNCSC data migration scripts | ✅ Done, committed (9a24691) |
| 9 | Packaging for resale + production go-live | 🟡 9-A in progress (see below); 9-B not started |
Every phase 0–7 commit was verified against a live Odoo 19 + Postgres 16
container before being committed — not just written and assumed to work.
Run git log --oneline for the full commit list; each commit message
documents what was built and how it was verified, including several real
Odoo 19 API changes that don't match older docs/tutorials (see "Gotchas"
below for the index).
Git remote is configured: origin -> https://git.metatroncube.in/admin/TNCSC_Odoo.git.
Resuming the dev environment
cd deploy
docker compose up -d
- Odoo: http://localhost:8069, database
communityos_dev, loginadmin/ passwordadmin. - This dev database has been used for all testing across every phase —
it has real posted accounting entries in it (from Interac transaction
confirmations, membership invoices, etc.). That's why Phase 7's
tncsc_deploymentmodule can't be installed on it directly (Odoo correctly refuses to change a company's currency once journal entries exist) — it was instead verified on throwaway fresh databases (tncsc_freshN, all dropped after verification). A real TNCSC production database should be a genuinely fresh install, not this dev one. - After any module code change, the running
deploy-odoo-1container has a stale in-memory registry until you either upgrade the module (-u) and restart the container, or just restart it:
This bit repeatedly during development — don't skip it when testing.docker compose restart odoo
Phase 8 — done, committed (9a24691)
All three migration scripts exist, are committed, and have been verified against a live Odoo instance (see "How each was tested" below).
scripts/_migration_common.py— shared JSON-RPC helpers (auth, execute_kw, CSV normalization, aMigrationReportclass) for the migration scripts.scripts/migrate_members.py— idempotent upsert by email, dry-run flag, tier lookup by code, report CSV.scripts/migrate_students.py— idempotent upsert of parent partner (by email, reusing a partner created bymigrate_members.pyif one exists)- child partner +
community.school.student, matched by (parent, student name) since students don't have their own email in the source data. Enrolls into the matching class in the current open term (matched bycommunity.school.levelcode) when one exists; otherwise still creates/updates the student record and reports why no enrollment happened.
- child partner +
scripts/migrate_opening_balances.py— posts oneaccount.movein the Miscellaneous Operations journal, dated the last fiscal year-end (computed fromres.company.fiscalyear_last_day/month, or--dateoverride). Refuses to post anything if the CSV doesn't balance (sum(debit) != sum(credit)) or references an unknown account code — checked before any Odoo write happens. Idempotent via a fixedref("Opening Balances Import"): re-running finds the existing posted entry and does nothing.
How each was tested
Followed the same pattern as scripts/migrate_classroom.py (Phase 3):
dry-run first, then a real run, then a second real run to prove
idempotency — against a fresh database, not communityos_dev. See
"Why a fresh DB, not communityos_dev" below for why.
docker compose up -d, then created a throwaway DB with both product modules and the client layer:odoo -d tncsc_migration_test -i community_membership,tncsc_deployment --stop-after-init(installingtncsc_deploymentalone pulls incommunity_schooland everything else as dependencies). Restarted the container afterward.migrate_members.py: synthetic CSV atdata/raw/members_export_sample.csv(gitignored, left in place as a fixture) with 4 valid rows + 2 deliberately-bad rows (missing email, unknown tier code). Dry-run matched real-run output; second real run reportedupdatednotcreatedfor all 4; confirmed via RPC that exactly oneres.partnerper email existed after both runs andmembership_statewasactive.migrate_students.py: needed acommunity.school.term(state=open),community.school.level(code=BEG), andcommunity.school.classseeded first (the fresh DB has none) — also had to grant theadminuser the School Coordinator group, since a fresh install doesn't put admin in it. Synthetic CSV atdata/raw/students_export_sample.csvwith 3 valid rows (2 matching the open term's class, 1 with nolevel_code) + 1 deliberately-bad row (missing parent). Confirmed via RPC after 2 runs: exactly 3community.school.studentrecords, exactly 2community.school.enrollmentrecords (no duplicates), parent partners correctly reused from step 2 instead of duplicated.migrate_opening_balances.py: synthetic CSV atdata/raw/opening_balances_sample.csvusing real account codes from the fresh DB's TNCSC chart of accounts (111100 Cash, 112110 Trade AR, 322000 Retained Earnings as the balancing line). Verified the out-of-balance guard refuses to post (tested with a deliberately mismatched debit/credit CSV). Real run posted one balanced, postedaccount.move; second run detected the existing entry and did nothing. Confirmed via RPC: exactly one move, three correctly-valued lines, AR line correctly linked to the migrated Ravi Kumar partner.
Real TNCSC member/student/trial-balance data doesn't exist yet — all three scripts were intentionally designed against a documented, assumed CSV schema (see each script's docstring) since the real export formats aren't known yet. Confirm the assumed column names match the real exports before relying on them, or adjust the scripts to match.
Why a fresh DB, not communityos_dev
communityos_dev doesn't have tncsc_deployment installed (see the top of
this file — it can't be, since it already has posted journal entries and
Odoo refuses to change a company's currency once those exist). Testing the
Phase 8 scripts there would exercise generic community_membership/
community_school behavior, not the actual TNCSC-configured target
(TNCSC's real chart of accounts, company currency, groups). Since Phase 8's
entire purpose is rehearsing the real TNCSC data load, a fresh DB with
tncsc_deployment installed is the more representative target — and it
avoids adding more synthetic test data to the one long-lived dev DB used
across every other phase. tncsc_migration_test was not dropped after
this session (unlike the Phase 7 tncsc_freshN throwaways) — it's left in
place in case the next session wants to keep testing against it; drop it
before it's mistaken for anything resembling real data.
To pick this back up
Either wait for real TNCSC export samples to validate the assumed CSV schemas against, or move on to Phase 9.
Phase 9 — 9-A in progress, 9-B not started
Two sub-parts with very different risk profiles:
- 9-A (productize): safe to do autonomously. Done so far — every
community_*module hasstatic/description/index.html, a realREADME.rst(Usage sections filled in past the Phase-0 placeholder), and aCHANGELOG.rst; manifests passscripts/check_manifests.py. Still open:- Every product manifest's
imageskey points atstatic/description/banner.png, but no module actually has that file — the Apps-list/App-Store banner image doesn't exist yet. Needs a real designed asset per module, not a placeholder. - No
v1.0.0git tag yet, and no release report — holding off on both until the banner-image gap above is resolved and the full--test-enablesuite has actually been run against live Odoo (this session had no Docker available, so only the static checks — brand-leak grep, manifest completeness — were re-verified, not the live module install/tests). - No role guides (admin/treasurer/teacher/parent) written yet.
- Every product manifest's
- 9-B (go-live): not started.
deploy/odoo.confis still dev config (list_db = True,proxy_mode = False, noworkers) anddeploy/nginx-communityos.confis an explicit "development skeleton" — SSL, DNS cutover, firewall rules, and backups on a real production server all remain. This needs a human in the loop with actual server access/credentials — don't let an agent run this unattended.
Gotchas discovered this build (Odoo 19 API drift + environment quirks)
This Odoo 19 build (19.0-20260817, essentially a nightly) diverges from
older tutorials/docs in several places that cost real debugging time. Each
is documented in detail in the commit message where it was found — this is
just the index so you know to search git log for it instead of
re-discovering it:
res.groups.category_id→ replaced byprivilege_id→res.groups.privilege.category_id(Session 1-A commit).- Settings pages use a new
<app>/<block>/<setting>structure inherited frombase.res_config_settings_view_form, not the old raw-div layout (Session 1-A commit). ir.crondroppednumbercallentirely (Session 1-B commit).event.eventhas nostatefield anymore (replaced by astage_id/event.stagekanban system) (Phase 2 commit).- Route
type='json'should betype='jsonrpc'('json'still works but is deprecated) (Phase 2 commit). - Search-view
<group>elements for "Group By" sections no longer accept astringattribute, onlyname(Phase 3 / Phase 4 commits). res.groups.users→ renamed touser_ids(Phase 4 commit).res.config.settingsfields backed byconfig_parameter=only support boolean/integer/float/char/selection/many2one/datetime — notBinary. Using it on a Binary field breaks every Settings tab, not just the one you're adding, since they share one model (fix:commit after Phase 6).- Anonymous visitors hitting an
auth='user'+website=Trueroute in this specific build crash with a raw 500 instead of a clean redirect to/web/login(Request._serve_db'sfinally: self.env = Noneruns before the website error handler tries to build the redirect). Worked around by switching those routes toauth='public'with a manualif request.env.user._is_public(): return request.redirect(...)check (fix:commit after Phase 6 — this is the fix to reach for if you add new member-only pages later, don't reintroduceauth='user'on awebsite=Trueroute without it). - Setting
res.company.country_idon a brand-new company auto-schedules this build's own chart-template installer via a precommit hook, which races an explicittry_loading()call made in the same install transaction and silently reverts it afterwards.ir.croncode execution is also sandboxed and forbids direct attribute assignment (STORE_ATTR) — use.write(...). Both fully explained in the Phase 7 commit message, fix pattern is inaddons/tncsc_deployment/models/res_company.py.
Handing off to a team
- Repo is already pushed to
origin(see above) — confirm the team has access togit.metatroncube.in. - Point them at
CommunityOS_Implementation_Plan_for_Claude_Code.md(the plan) and this file (current status). - They'll need Docker Desktop (or equivalent) to run
deploy/docker-compose.ymllocally — no other local dependencies. - If they're using Claude Code to continue: just point it at this repo and this file. It doesn't need conversation history — everything load-bearing is either in a commit message or in this document.