Compare commits
6 Commits
8dd97dec9b
...
35e62e8c61
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35e62e8c61 | ||
|
|
91c4580ae2 | ||
|
|
5596f41377 | ||
|
|
745e147de9 | ||
|
|
aeeb355948 | ||
|
|
24be6360e2 |
105
HANDOFF.md
@ -16,7 +16,7 @@ file is the "where things actually stand" companion to it.
|
||||
| 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 |
|
||||
| 7 | `tncsc_deployment` (client config layer) | ✅ Done, committed. Website pages content migrated from live tncsc.com in a later session — see "TNCSC website migration" below |
|
||||
| 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 |
|
||||
|
||||
@ -46,6 +46,12 @@ docker compose up -d
|
||||
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.
|
||||
- `tncsc_site` is another fresh DB (with `tncsc_deployment` installed), used
|
||||
for the website content migration below — kept around this time (not
|
||||
dropped) since it's the one with the real seeded event/tiers to look at.
|
||||
Since multiple DBs coexist, a plain `http://localhost:8069/` won't know
|
||||
which to serve — select one explicitly first, e.g.
|
||||
`http://localhost:8069/web?db=tncsc_site`, then it's remembered by cookie.
|
||||
- **After any module code change**, the *running* `deploy-odoo-1` container
|
||||
has a stale in-memory registry until you either upgrade the module (`-u`)
|
||||
and restart the container, or just restart it:
|
||||
@ -159,11 +165,10 @@ Two sub-parts with very different risk profiles:
|
||||
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.0` git tag yet, and no release report — holding off on both
|
||||
until the banner-image gap above is resolved and the full
|
||||
`--test-enable` suite 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).
|
||||
until the banner-image gap above is resolved. (A later session did run
|
||||
`--test-enable` for `tncsc_deployment` specifically against live Odoo
|
||||
while doing the website migration below — 9/9 passing — but that
|
||||
wasn't a full suite-wide run across every `community_*` module.)
|
||||
- No role guides (admin/treasurer/teacher/parent) written yet.
|
||||
- **9-B (go-live)**: not started. `deploy/odoo.conf` is still dev config
|
||||
(`list_db = True`, `proxy_mode = False`, no `workers`) and
|
||||
@ -172,6 +177,59 @@ Two sub-parts with very different risk profiles:
|
||||
server** all remain. This needs a human in the loop with actual server
|
||||
access/credentials — don't let an agent run this unattended.
|
||||
|
||||
## TNCSC website migration (from live tncsc.com, WordPress -> Odoo)
|
||||
|
||||
`addons/tncsc_deployment/views/website_pages.xml` was rewritten from the
|
||||
Phase 7 placeholder pages ("content to be finalized") into the real site
|
||||
content, adapted from tncsc.com (captured 2026-08-20). Tested against a
|
||||
dedicated fresh database, `tncsc_site` (not `communityos_dev` or
|
||||
`tncsc_migration_test`) — `docker compose exec odoo odoo -d tncsc_site -i
|
||||
tncsc_deployment --stop-after-init` recreates it from scratch.
|
||||
|
||||
- Real pages built: Home, About, About/Tamil Nadu (bilingual EN/Tamil),
|
||||
About/Board of Directors (12 real named members + photos), Membership
|
||||
hub, Membership Benefits (real 8-point benefit copy), Tamil Class,
|
||||
Contact, plus the pre-existing Sponsors placeholder. Nav restructured to
|
||||
match tncsc.com's real structure (Home / About dropdown / Events /
|
||||
Membership dropdown / Tamil Class / Contact) instead of the old flat
|
||||
Classifieds/Benefits/Sponsors list.
|
||||
- Real assets pulled from tncsc.com and committed under
|
||||
`addons/tncsc_deployment/static/src/img/` (~1.1MB: logo, board photos,
|
||||
section imagery) rather than hotlinking the WordPress site.
|
||||
- Events, Membership, and Tamil Class are wired to the real product
|
||||
modules (`event.event` for the homepage's "Upcoming Events", live
|
||||
`community.membership.tier` records for pricing, `/school/register` for
|
||||
Tamil Class signup) instead of being static copies — see each page's
|
||||
QWeb for the exact query.
|
||||
- One real event was seeded (`data/events_data.xml`): TNCSC's Summer
|
||||
Picnic 2026, matching what's live on tncsc.com/events.
|
||||
- **Deliberately not reproduced**, because it isn't real: tncsc.com's own
|
||||
Sponsors page (generic `client-01..09` stock logos, dead links) and its
|
||||
Contact page phone number (`+7 (800) 123 45 69`, a non-Canadian WordPress
|
||||
theme demo placeholder) are themselves unmigrated theme demo content on
|
||||
the live site, not real TNCSC data — confirmed by inspecting alt
|
||||
text/hrefs, not assumed. Contact page ships with the real, verified
|
||||
email (`support@tncsc.ca`) and social links (Facebook/YouTube/Instagram)
|
||||
instead.
|
||||
- **Real gap, not paved over**: `community_membership` has no public
|
||||
self-service "join online" flow (portal only handles renewal for
|
||||
partners a staff member already created) — every "Become a Member" CTA
|
||||
points at `/contact` rather than a fake/broken signup link. Building
|
||||
that flow is follow-on work, not done here.
|
||||
- **Known cosmetic leftover**: Odoo's own stock header/footer snippets
|
||||
ship a placeholder phone number (`+1 555-555-5556`) baked into core
|
||||
`website` module views (`website.header_text_element`,
|
||||
`website.footer_custom`, `website.s_contact_info`), independent of
|
||||
anything in this module. It's normal, editable-in-the-website-builder
|
||||
content on any fresh Odoo site, not something this module introduced —
|
||||
left for whoever does the go-live content pass to delete via the
|
||||
Website editor (Edit -> click the text -> delete), rather than patched
|
||||
with a defensive XML override here.
|
||||
- Text throughout was reconstructed via automated extraction from the live
|
||||
pages, not copy-pasted from raw HTML — treat it as a faithful draft.
|
||||
**Have TNCSC proofread the migrated copy against the original site
|
||||
before go-live.**
|
||||
|
||||
## Gotchas discovered this build (Odoo 19 API drift + environment quirks)
|
||||
|
||||
This Odoo 19 build (`19.0-20260817`, essentially a nightly) diverges from
|
||||
@ -214,6 +272,41 @@ re-discovering it:
|
||||
is also sandboxed and forbids direct attribute assignment (`STORE_ATTR`)
|
||||
— use `.write(...)`. Both fully explained in the Phase 7 commit message,
|
||||
fix pattern is in `addons/tncsc_deployment/models/res_company.py`.
|
||||
- Not version drift, but a real trap worth indexing here since it cost
|
||||
significant debugging time during the website migration: the `website`
|
||||
module auto-forks its own website-bound ("Copy-On-Write") copy of both
|
||||
the homepage (`website.homepage`) and the top nav tree (`website.menu_id`)
|
||||
the first time a website exists. A generic (`website_id`-unset) page or
|
||||
menu record renders fine at ordinary URLs, but is silently ignored for
|
||||
the homepage route and the rendered nav specifically — those two routes
|
||||
only resolve records explicitly bound to the current `website_id`, and on
|
||||
a same-URL tie the auto-forked stock copy wins over a same-priority
|
||||
custom one by insertion order. Confirmed empirically against a live
|
||||
container (not from docs). Fix pattern — explicitly bind `website_id`,
|
||||
and where a stock auto-forked duplicate exists, remove it — is in
|
||||
`addons/tncsc_deployment/__init__.py` (`_remove_stock_homepage_page`,
|
||||
`_fix_website_menus`), both run from `post_init_hook`. Relevant if you
|
||||
add more top-level pages/menu items later.
|
||||
- Each product module's backend app (Membership, School, Benefits,
|
||||
Classifieds, Interac Payments) has its root `ir.ui.menu` restricted to
|
||||
its own manager/coordinator group, and a fresh `tncsc_deployment`
|
||||
install doesn't put the `admin` user in any of them by default. Result:
|
||||
admin's backend app switcher only shows stock apps (Events, eLearning,
|
||||
Settings, ...) and none of the CommunityOS ones, which looks exactly
|
||||
like "the modules aren't installed" even though
|
||||
`ir.module.module.state` is `installed` for all of them — confirmed
|
||||
by checking `env['ir.ui.menu'].with_user(admin).search([('parent_id',
|
||||
'=', False)])`, which is the right way to check what a user actually
|
||||
sees (menu visibility is group-based, not just install state). Fixed
|
||||
by adding `admin` to `tncsc_deployment.group_tncsc_board_admin` in
|
||||
`security/tncsc_roles.xml` (that group's `implied_ids` already covers
|
||||
every product manager group) — this used to be the manual per-group
|
||||
step described above for Phase 8's School Coordinator grant; it's now
|
||||
automatic on any fresh install. Note `res.groups.implied_ids` doesn't
|
||||
populate the implied group's own `user_ids` — checking membership via
|
||||
`user in group.user_ids` will wrongly say "no" for an implied group;
|
||||
use `user.has_group('module.xml_id')` instead, which does resolve the
|
||||
transitive closure correctly.
|
||||
|
||||
## Handing off to a team
|
||||
|
||||
|
||||
@ -35,6 +35,6 @@ entitled per membership tier:
|
||||
],
|
||||
'demo': [],
|
||||
'images': ['static/description/banner.png'],
|
||||
'application': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@ -36,6 +36,6 @@ Soft-detects Community OS Membership; runs standalone without it.
|
||||
],
|
||||
'demo': [],
|
||||
'images': ['static/description/banner.png'],
|
||||
'application': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@ -38,6 +38,6 @@ Sellable to any Canadian organization accepting Interac e-Transfer.
|
||||
],
|
||||
'demo': [],
|
||||
'images': ['static/description/banner.png'],
|
||||
'application': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@ -31,6 +31,6 @@ a missing module:
|
||||
],
|
||||
'demo': [],
|
||||
'images': ['static/description/banner.png'],
|
||||
'application': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@ -31,6 +31,6 @@ layout that reads these tokens.
|
||||
],
|
||||
'demo': [],
|
||||
'images': ['static/description/banner.png'],
|
||||
'application': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ OS product module required.
|
||||
],
|
||||
},
|
||||
'images': ['static/description/banner.png'],
|
||||
'application': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
'external_dependencies': {
|
||||
'python': ['qrcode'],
|
||||
|
||||
@ -9,3 +9,80 @@ def post_init_hook(env):
|
||||
transaction isn't reliable on this Odoo build.
|
||||
"""
|
||||
env.company._tncsc_setup_accounting()
|
||||
_remove_stock_homepage_page(env)
|
||||
_fix_website_menus(env)
|
||||
|
||||
|
||||
def _remove_stock_homepage_page(env):
|
||||
"""The website module auto-creates its own website-bound "homepage"
|
||||
page/view (key 'website.homepage') for every website, independently of
|
||||
this module. That page ties on priority with data/../views/website_pages.xml's
|
||||
own website-bound page_home record (same url "/", same website_id) -
|
||||
confirmed empirically against a live container that the url "/" route
|
||||
(unlike every other page url) only resolves a website-bound page, so an
|
||||
unbound generic page or an inherited view has no effect here, and on a
|
||||
tie the stock page wins by insertion order (it's created before this
|
||||
module installs). Removing it is what makes page_home actually serve.
|
||||
"""
|
||||
website = env.ref('website.default_website', raise_if_not_found=False)
|
||||
if not website:
|
||||
return
|
||||
stock_view = env['ir.ui.view'].sudo().search([
|
||||
('key', '=', 'website.homepage'),
|
||||
('website_id', '=', website.id),
|
||||
])
|
||||
stock_page = env['website.page'].sudo().search([
|
||||
('url', '=', '/'),
|
||||
('website_id', '=', website.id),
|
||||
('view_id', 'in', stock_view.ids),
|
||||
])
|
||||
# unlinking the page cascades to its underlying view - unlinking the
|
||||
# (already-cascaded) view afterward would raise a MissingError.
|
||||
stock_page.unlink()
|
||||
|
||||
|
||||
# xmlid (without module prefix) of each top-level nav entry -> xmlids of its
|
||||
# children, as declared in views/website_pages.xml.
|
||||
_MENU_TREE = {
|
||||
'menu_home': [],
|
||||
'menu_about': ['menu_about_tamil_nadu', 'menu_about_board'],
|
||||
'menu_events': [],
|
||||
'menu_membership': ['menu_membership_benefits', 'menu_membership_registration'],
|
||||
'menu_tamil_class': [],
|
||||
'menu_contact': [],
|
||||
}
|
||||
|
||||
|
||||
def _fix_website_menus(env):
|
||||
"""Same Copy-On-Write pattern as _remove_stock_homepage_page, applied to
|
||||
website.menu: the website module auto-forks its own website-bound copy
|
||||
of the top nav tree (a "Top Menu for Website <n>" record, referenced by
|
||||
website.menu_id) independently of this module. website_pages.xml's menu
|
||||
records attach to the generic tree (website.main_menu) instead, so they
|
||||
never render, while Odoo's auto-forked copy renders as flat top-level
|
||||
items with none of our children - confirmed empirically against a live
|
||||
container. Fix: re-parent our records onto the actual rendered tree, and
|
||||
drop every other child Odoo forked there so only ours show.
|
||||
"""
|
||||
website = env.ref('website.default_website', raise_if_not_found=False)
|
||||
if not website:
|
||||
return
|
||||
root = website.menu_id
|
||||
if not root:
|
||||
return
|
||||
|
||||
mine = env['website.menu']
|
||||
for top_xmlid, child_xmlids in _MENU_TREE.items():
|
||||
top_menu = env.ref(f'tncsc_deployment.{top_xmlid}', raise_if_not_found=False)
|
||||
if not top_menu:
|
||||
continue
|
||||
top_menu.write({'website_id': website.id, 'parent_id': root.id})
|
||||
mine |= top_menu
|
||||
for child_xmlid in child_xmlids:
|
||||
child_menu = env.ref(f'tncsc_deployment.{child_xmlid}', raise_if_not_found=False)
|
||||
if child_menu:
|
||||
child_menu.write({'website_id': website.id, 'parent_id': top_menu.id})
|
||||
mine |= child_menu
|
||||
|
||||
stray = env['website.menu'].sudo().search([('parent_id', '=', root.id), ('id', 'not in', mine.ids)])
|
||||
stray.unlink()
|
||||
|
||||
@ -42,6 +42,7 @@ that applies to the community_* product modules.
|
||||
'data/theme_data.xml',
|
||||
'data/membership_data.xml',
|
||||
'data/mail_template_overrides.xml',
|
||||
'data/events_data.xml',
|
||||
'data/ir_cron.xml',
|
||||
'views/website_pages.xml',
|
||||
],
|
||||
|
||||
19
addons/tncsc_deployment/data/events_data.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<!-- Real upcoming event, matching what's live on tncsc.com/events (2026-08-20).
|
||||
Update/replace once TNCSC confirms the venue address. -->
|
||||
<record id="partner_summer_picnic_venue" model="res.partner">
|
||||
<field name="name">Mississauga, Ontario</field>
|
||||
<field name="city">Mississauga</field>
|
||||
<field name="state_id" ref="base.state_ca_on"/>
|
||||
<field name="country_id" ref="base.ca"/>
|
||||
<field name="type">other</field>
|
||||
</record>
|
||||
<record id="event_summer_picnic_2026" model="event.event">
|
||||
<field name="name">TNCSC's Summer Picnic 2026</field>
|
||||
<field name="date_begin" eval="'2026-07-11 14:00:00'"/>
|
||||
<field name="date_end" eval="'2026-07-11 20:00:00'"/>
|
||||
<field name="address_id" ref="partner_summer_picnic_venue"/>
|
||||
<field name="website_published">True</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@ -14,8 +14,25 @@
|
||||
suppresses that auto-trigger so only our explicit load runs. -->
|
||||
<record id="base.main_company" model="res.company">
|
||||
<field name="name">Tamil Nadu Cultural Society of Canada</field>
|
||||
<field name="email">info@tncsc.example.org</field>
|
||||
<field name="website">https://www.tncsc.example.org</field>
|
||||
<field name="email">support@tncsc.ca</field>
|
||||
<field name="website">https://tncsc.com</field>
|
||||
<field name="logo" type="base64" file="tncsc_deployment/static/src/img/brand/logo.png"/>
|
||||
</record>
|
||||
|
||||
<!-- Public social links, confirmed live on tncsc.com/contact (2026-08-20).
|
||||
No street address or phone number is set: tncsc.com does not publish
|
||||
either (its "Contact" page phone number is unmigrated WordPress
|
||||
theme demo content, not a real TNCSC number) - add both here once
|
||||
TNCSC provides them. -->
|
||||
<record id="website.default_website" model="website">
|
||||
<field name="name">Tamil Nadu Cultural Society of Canada</field>
|
||||
<field name="social_facebook">https://www.facebook.com/TNCSCCanada/</field>
|
||||
<field name="social_youtube">https://www.youtube.com/@tamilnaduculturalsocietyof5866</field>
|
||||
<field name="social_instagram">https://www.instagram.com/tncsc_canada</field>
|
||||
<!-- website.logo is its own stored field (defaults to Odoo's own
|
||||
placeholder logo), not a related/computed fallback to
|
||||
res.company.logo - both need to be set explicitly. -->
|
||||
<field name="logo" type="base64" file="tncsc_deployment/static/src/img/brand/logo.png"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@ -27,6 +27,16 @@
|
||||
(4, ref('community_interac.group_interac_verifier')),
|
||||
(4, ref('event.group_event_manager')),
|
||||
]"/>
|
||||
<!-- Without this, a fresh install leaves the installing admin user
|
||||
out of every product-module manager group, so their backend
|
||||
app switcher only shows stock apps (Events, eLearning, ...)
|
||||
and none of the CommunityOS ones - each app's root menu is
|
||||
group-restricted and admin isn't a member of any of those
|
||||
groups by default. Confirmed empirically against a live
|
||||
container; this is the automated fix for the manual step
|
||||
HANDOFF.md previously described doing by hand for the School
|
||||
Coordinator group alone. -->
|
||||
<field name="user_ids" eval="[(4, ref('base.user_admin'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="group_tncsc_treasurer" model="res.groups">
|
||||
|
||||
BIN
addons/tncsc_deployment/static/src/img/about/discover.webp
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
addons/tncsc_deployment/static/src/img/about/join.webp
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
addons/tncsc_deployment/static/src/img/about/tamil-heritage.webp
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
addons/tncsc_deployment/static/src/img/about/unity.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/amirtha.webp
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/anand.webp
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/asraph.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/brindha.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/karuna.webp
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/mari.webp
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/murugan.webp
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/nandhini.webp
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/palani.webp
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/rachel.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/sekar.webp
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
addons/tncsc_deployment/static/src/img/board/shanmuga.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
addons/tncsc_deployment/static/src/img/brand/logo.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
addons/tncsc_deployment/static/src/img/events/about-01-1.webp
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
addons/tncsc_deployment/static/src/img/events/about-02-1.webp
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
addons/tncsc_deployment/static/src/img/events/about-03-1.webp
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
addons/tncsc_deployment/static/src/img/events/about-04-1.webp
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
addons/tncsc_deployment/static/src/img/hero/slide-1.webp
Normal file
|
After Width: | Height: | Size: 922 KiB |
BIN
addons/tncsc_deployment/static/src/img/hero/slide-2.webp
Normal file
|
After Width: | Height: | Size: 660 KiB |
BIN
addons/tncsc_deployment/static/src/img/hero/slide-3.webp
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
addons/tncsc_deployment/static/src/img/hero/slide-4.webp
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
addons/tncsc_deployment/static/src/img/home/about-01.webp
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
addons/tncsc_deployment/static/src/img/home/about-02.webp
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
addons/tncsc_deployment/static/src/img/home/about-03.webp
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
addons/tncsc_deployment/static/src/img/home/about-04.webp
Normal file
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
BIN
addons/tncsc_deployment/static/src/img/home/hero.webp
Normal file
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 76 KiB |
@ -67,7 +67,12 @@ class TestTncscDeployment(TransactionCase):
|
||||
self.assertEqual(tier.product_id.property_account_income_id, dues_account)
|
||||
|
||||
def test_website_pages_published(self):
|
||||
for url in ('/', '/about', '/tamil-school', '/sponsors', '/contact'):
|
||||
urls = (
|
||||
'/', '/about', '/about/tamil-nadu', '/about/board-of-directors',
|
||||
'/membership', '/membership/benefits', '/tamil-school',
|
||||
'/sponsors', '/contact',
|
||||
)
|
||||
for url in urls:
|
||||
page = self.env['website.page'].search([('url', '=', url)], limit=1)
|
||||
self.assertTrue(page, f"Expected a website.page for {url}")
|
||||
self.assertTrue(page.is_published)
|
||||
|
||||
@ -1,21 +1,325 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<!-- ================================================================
|
||||
Content on this page is adapted from the live tncsc.com site
|
||||
(captured 2026-08-20) as part of migrating it into this Odoo
|
||||
website. It should be proofread by TNCSC against the original
|
||||
before go-live - text was reconstructed via automated extraction,
|
||||
not copy-pasted from raw HTML, so treat it as a faithful draft,
|
||||
not a byte-exact mirror. Two known gaps, deliberately not
|
||||
fabricated here:
|
||||
- No public self-service "join online" flow exists yet in
|
||||
community_membership (portal only handles renewal for partners
|
||||
already created by staff) - every "Become a Member" CTA below
|
||||
points at the /contact form instead of a broken/fake signup link.
|
||||
- tncsc.com's own Sponsors page and Contact-page phone number are
|
||||
unmigrated WordPress theme demo placeholders (generic
|
||||
"client-01..09" logos, a non-Canadian demo phone number) with no
|
||||
real data behind them - neither is reproduced here.
|
||||
================================================================ -->
|
||||
|
||||
<!-- Home -->
|
||||
<!-- Home. The website module's homepage route ("/") is special-cased:
|
||||
it only serves a website.page whose website_id explicitly matches
|
||||
the current website. A generic (website_id-unset) page at "/"
|
||||
renders fine at every OTHER url but is silently ignored for the
|
||||
homepage specifically, and inheriting the stock "website.homepage"
|
||||
view has no effect either, because Odoo already auto-forks a
|
||||
website-specific copy of that view (Copy-On-Write) with no
|
||||
inherit_id of its own the first time the website is customized -
|
||||
confirmed empirically against a live container. So both records
|
||||
below explicitly bind website_id to the default website, matching
|
||||
what the homepage route actually looks up. -->
|
||||
<record id="view_page_home" model="ir.ui.view">
|
||||
<field name="name">TNCSC Home</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">tncsc_deployment.page_home</field>
|
||||
<field name="website_id" ref="website.default_website"/>
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_home">
|
||||
<t t-call="website.layout">
|
||||
<div class="container" style="margin-top: 40px; margin-bottom: 60px;">
|
||||
<h1>Tamil Nadu Cultural Society of Canada</h1>
|
||||
<p class="lead">Celebrating Tamil language, arts, and culture in Canada.</p>
|
||||
<p>Content to be finalized by TNCSC - this is a placeholder home page
|
||||
generated by the deployment layer.</p>
|
||||
<a href="/school/register" class="btn btn-primary me-2">Register for Tamil School</a>
|
||||
<a href="/classifieds" class="btn btn-outline-secondary">Browse Classifieds</a>
|
||||
<div id="wrap">
|
||||
<!-- Hero: 4-slide carousel, matching tncsc.com's real slider content/order. -->
|
||||
<section id="tncscHero" class="carousel slide carousel-fade" data-bs-ride="carousel">
|
||||
<div class="carousel-indicators">
|
||||
<button type="button" data-bs-target="#tncscHero" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"/>
|
||||
<button type="button" data-bs-target="#tncscHero" data-bs-slide-to="1" aria-label="Slide 2"/>
|
||||
<button type="button" data-bs-target="#tncscHero" data-bs-slide-to="2" aria-label="Slide 3"/>
|
||||
<button type="button" data-bs-target="#tncscHero" data-bs-slide-to="3" aria-label="Slide 4"/>
|
||||
</div>
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active">
|
||||
<div class="d-flex align-items-center text-white" style="min-height: 480px; background: linear-gradient(135deg, rgba(5,9,30,0.88) 0%, rgba(16,25,63,0.82) 100%), url('/tncsc_deployment/static/src/img/hero/slide-1.webp') center/cover;">
|
||||
<div class="container text-center py-5">
|
||||
<h1 class="display-4 fw-bold">Connecting Tamil Hearts Across Canada</h1>
|
||||
<p class="lead">Join Canada's Largest Tamil Nadu Cultural Community</p>
|
||||
<a href="/about" class="btn btn-lg" style="background-color: var(--community-secondary); color: #fff;">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<div class="d-flex align-items-center text-white" style="min-height: 480px; background: linear-gradient(135deg, rgba(5,9,30,0.88) 0%, rgba(16,25,63,0.82) 100%), url('/tncsc_deployment/static/src/img/hero/slide-2.webp') center/cover;">
|
||||
<div class="container text-center py-5">
|
||||
<h1 class="display-4 fw-bold">Honouring Our Roots, Growing Together</h1>
|
||||
<p class="lead">Where Tamil Culture Thrives Across Generations</p>
|
||||
<a href="/tamil-school" class="btn btn-lg" style="background-color: var(--community-secondary); color: #fff;">Explore Our Community</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<div class="d-flex align-items-center text-white" style="min-height: 480px; background: linear-gradient(135deg, rgba(5,9,30,0.88) 0%, rgba(16,25,63,0.82) 100%), url('/tncsc_deployment/static/src/img/hero/slide-3.webp') center/cover;">
|
||||
<div class="container text-center py-5">
|
||||
<h1 class="display-4 fw-bold">Celebrating 28+ Years of Culture & Connection</h1>
|
||||
<p class="lead">Canada's Home for Tamil Tradition, Unity & Pride</p>
|
||||
<a href="/event" class="btn btn-lg" style="background-color: var(--community-secondary); color: #fff;">Book Now</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<div class="d-flex align-items-center text-white" style="min-height: 480px; background: linear-gradient(135deg, rgba(5,9,30,0.88) 0%, rgba(16,25,63,0.82) 100%), url('/tncsc_deployment/static/src/img/hero/slide-4.webp') center/cover;">
|
||||
<div class="container text-center py-5">
|
||||
<h1 class="display-4 fw-bold">Join Canada's Tamil Cultural Heartbeat</h1>
|
||||
<p class="lead">Tradition unites, heritage shines globally.</p>
|
||||
<a href="/contact" class="btn btn-lg" style="background-color: var(--community-secondary); color: #fff;">Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="carousel-control-prev" type="button" data-bs-target="#tncscHero" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"/>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</button>
|
||||
<button class="carousel-control-next" type="button" data-bs-target="#tncscHero" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"/>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<section class="pt56 pb56">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-4">
|
||||
<div class="col-lg-6">
|
||||
<span class="text-uppercase fw-bold" style="color: var(--community-accent);">Celebrating Cultural Excellence</span>
|
||||
<h2>About TNCSC</h2>
|
||||
<h3 class="h4">Canada's Largest Tamil Cultural Organization — Bridging Heritage & Community Since 1997</h3>
|
||||
<p>
|
||||
The Tamil Nadu Cultural Society of Canada (TNCSC) has been a cornerstone of the
|
||||
Tamil community since 1997, connecting generations of Tamil families through
|
||||
culture, education, and service.
|
||||
</p>
|
||||
<p>
|
||||
As a registered non-profit organization, TNCSC preserves the rich heritage of
|
||||
Tamil Nadu while fostering a sense of belonging among Tamil Canadians across
|
||||
provinces. From vibrant Pongal festivals to Tamil language schools, every
|
||||
initiative is a celebration of identity, resilience, and community spirit.
|
||||
</p>
|
||||
<p>
|
||||
With programs designed for youth, seniors, newcomers, and families, TNCSC
|
||||
continues to build a vibrant cultural bridge between Tamil traditions and
|
||||
Canadian values.
|
||||
</p>
|
||||
<a href="/about" class="btn btn-outline-primary">Learn More</a>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row g-2">
|
||||
<div class="col-6"><img src="/tncsc_deployment/static/src/img/home/about-01.webp" class="img-fluid rounded" alt="TNCSC community"/></div>
|
||||
<div class="col-6"><img src="/tncsc_deployment/static/src/img/home/about-02.webp" class="img-fluid rounded" alt="TNCSC community"/></div>
|
||||
<div class="col-6"><img src="/tncsc_deployment/static/src/img/home/about-03.webp" class="img-fluid rounded" alt="TNCSC community"/></div>
|
||||
<div class="col-6"><img src="/tncsc_deployment/static/src/img/home/about-04.webp" class="img-fluid rounded" alt="TNCSC community"/></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="pt56 pb56 bg-light">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-4">
|
||||
<div class="col-lg-6">
|
||||
<div class="row g-2">
|
||||
<div class="col-6"><img src="/tncsc_deployment/static/src/img/home/about-01.webp" class="img-fluid rounded" alt="TNCSC story"/></div>
|
||||
<div class="col-6"><img src="/tncsc_deployment/static/src/img/home/about-03.webp" class="img-fluid rounded mt-4" alt="TNCSC story"/></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<span class="text-uppercase fw-bold" style="color: var(--community-accent);">Watch Our Story</span>
|
||||
<h2>Proudly Celebrating Tamil Heritage in Canada</h2>
|
||||
<p class="lead">
|
||||
From Pongal Festivals to Youth Empowerment — Experience Culture That Connects
|
||||
Generations.
|
||||
</p>
|
||||
<p>
|
||||
For over 28+ years, TNCSC has brought together Tamil families from all across
|
||||
Canada to preserve, celebrate, and pass on the vibrant culture of Tamil Nadu.
|
||||
</p>
|
||||
<p>
|
||||
Through traditional festivals, language education, youth leadership, and
|
||||
community support, our organization is more than just a gathering — it's a
|
||||
living, growing cultural legacy.
|
||||
</p>
|
||||
<p class="fw-bold">Discover the heartbeat of our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="pt56 pb56">
|
||||
<div class="container">
|
||||
<div class="row g-4 text-center">
|
||||
<div class="col-md-4">
|
||||
<img src="/tncsc_deployment/static/src/img/home/cultural-events-icon.webp" alt="" style="height:64px;"/>
|
||||
<h4 class="mt-3">Cultural Networking Events</h4>
|
||||
<p>
|
||||
Connect with fellow Tamil professionals, entrepreneurs, artists, and families
|
||||
through curated meetups and celebrations that strengthen our cultural bond and
|
||||
open new doors in Canada.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<img src="/tncsc_deployment/static/src/img/home/youth-mentorship.webp" alt="" style="height:64px;"/>
|
||||
<h4 class="mt-3">Youth & Career Mentorship</h4>
|
||||
<p>
|
||||
Our mentorship program pairs talented students and young professionals with
|
||||
experienced Tamil-Canadian leaders who provide valuable guidance in education,
|
||||
career, leadership, and life skills.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<img src="/tncsc_deployment/static/src/img/home/frends-gathering.webp" alt="" style="height:64px;"/>
|
||||
<h4 class="mt-3">Festivals & Family Gatherings</h4>
|
||||
<p>
|
||||
From Pongal feasts to Deepavali musical nights and summer picnics, TNCSC
|
||||
events go beyond formality — they bring vibrant joy, rich culture, and true
|
||||
community spirit into every celebration.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="pt56 pb56 bg-light">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-4">
|
||||
<div class="col-lg-5">
|
||||
<span class="text-uppercase fw-bold" style="color: var(--community-accent);">Get Involved</span>
|
||||
<h2>Why Join TNCSC?</h2>
|
||||
<p class="lead">Experience Culture, Connection & Community — All Year Round.</p>
|
||||
<img src="/tncsc_deployment/static/src/img/home/hero.webp" class="img-fluid rounded d-none d-lg-block" alt="TNCSC community"/>
|
||||
</div>
|
||||
<div class="col-lg-7">
|
||||
<div class="accordion" id="tncscWhyJoin">
|
||||
<div class="accordion-item">
|
||||
<h3 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#tncscFaqWhere">
|
||||
Where Is TNCSC Based?
|
||||
</button>
|
||||
</h3>
|
||||
<div id="tncscFaqWhere" class="accordion-collapse collapse show" data-bs-parent="#tncscWhyJoin">
|
||||
<div class="accordion-body">
|
||||
Tamil Nadu Cultural Society of Canada — Community Centre, Ontario,
|
||||
Canada, with regional chapters across major Canadian cities.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h3 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#tncscFaqJoin">
|
||||
How Can I Join?
|
||||
</button>
|
||||
</h3>
|
||||
<div id="tncscFaqJoin" class="accordion-collapse collapse" data-bs-parent="#tncscWhyJoin">
|
||||
<div class="accordion-body">
|
||||
Membership is open year-round! Choose from annual, lifetime, or
|
||||
family plans. Join today and be part of our vibrant upcoming
|
||||
celebrations and events.
|
||||
<a href="/membership" class="d-block mt-2">See membership plans →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<t t-set="upcoming_events" t-value="env['event.event'].sudo().search([('website_published', '=', True)], order='date_begin', limit=3)"/>
|
||||
<section class="pt56 pb56" t-if="upcoming_events">
|
||||
<div class="container">
|
||||
<h2 class="text-center mb-4">Upcoming Events & Celebrations</h2>
|
||||
<div class="row g-2 mb-5 d-none d-md-flex">
|
||||
<div class="col-3"><img src="/tncsc_deployment/static/src/img/events/about-01-1.webp" class="img-fluid rounded" alt="TNCSC event"/></div>
|
||||
<div class="col-3"><img src="/tncsc_deployment/static/src/img/events/about-02-1.webp" class="img-fluid rounded" alt="TNCSC event"/></div>
|
||||
<div class="col-3"><img src="/tncsc_deployment/static/src/img/events/about-03-1.webp" class="img-fluid rounded" alt="TNCSC event"/></div>
|
||||
<div class="col-3"><img src="/tncsc_deployment/static/src/img/events/about-04-1.webp" class="img-fluid rounded" alt="TNCSC event"/></div>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
<t t-foreach="upcoming_events" t-as="upcoming_event">
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<p class="text-uppercase small fw-bold mb-1" style="color: var(--community-accent);">Events</p>
|
||||
<h5 class="card-title" t-out="upcoming_event.name"/>
|
||||
<p class="card-text text-muted mb-1" t-field="upcoming_event.date_begin" t-options="{'widget': 'date'}"/>
|
||||
<p class="card-text" t-if="upcoming_event.address_id" t-out="upcoming_event.address_id.city"/>
|
||||
<a t-attf-href="/event/#{ slug(upcoming_event) }" class="btn btn-outline-primary btn-sm">Book Now</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="pt56 pb56 bg-light">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-4">
|
||||
<div class="col-lg-6">
|
||||
<span class="text-uppercase fw-bold" style="color: var(--community-accent);">Language & Culture</span>
|
||||
<h2>Speak the Language of Your Heritage</h2>
|
||||
<p>At TNCSC, our mission is to pass the beauty of Tamil to every generation in Canada.</p>
|
||||
<p>
|
||||
Whether you're a parent hoping to pass on your language, a student preparing
|
||||
for cultural competitions, or a newcomer eager to connect — TNCSC offers
|
||||
welcoming, effective Tamil learning programs for all ages.
|
||||
</p>
|
||||
<p>
|
||||
Our community-led classes are designed to blend traditional Tamil values with
|
||||
modern teaching methods. From the alphabet to ancient poetry, from
|
||||
conversational Tamil to cultural idioms — we make language learning fun,
|
||||
meaningful, and rooted in real community connection.
|
||||
</p>
|
||||
<p class="fst-italic">Because to speak Tamil… is to feel Tamil.</p>
|
||||
<a href="/tamil-school" class="btn btn-primary">Start Learning Today</a>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<img src="/tncsc_deployment/static/src/img/tamil_class/tamil_class.webp" class="img-fluid rounded" alt="Tamil class"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="pt56 pb56 text-white text-center" style="background-color: var(--community-primary);">
|
||||
<div class="container">
|
||||
<h2>Be a Part of the Legacy</h2>
|
||||
<p class="lead" style="max-width: 720px; margin-left: auto; margin-right: auto;">
|
||||
Join the Tamil Nadu Cultural Society of Canada and help preserve Tamil heritage,
|
||||
empower youth, and bring our vibrant culture to life in every corner of Canada. Your
|
||||
support keeps our language, traditions, and community thriving.
|
||||
</p>
|
||||
<a href="/membership" class="btn btn-lg mt-2 mb-4" style="background-color: var(--community-secondary); color: #fff;">Join TNCSC Today</a>
|
||||
<div class="row justify-content-center g-3">
|
||||
<t t-foreach="env['community.membership.tier'].sudo().search([('active', '=', True)], order='sequence')" t-as="tier">
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="card bg-transparent border-light text-white h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" t-out="tier.name"/>
|
||||
<p class="card-text" t-out="'%s %s' % (tier.currency_id.symbol, int(tier.price))"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
@ -24,6 +328,7 @@
|
||||
<record id="page_home" model="website.page">
|
||||
<field name="url">/</field>
|
||||
<field name="view_id" ref="view_page_home"/>
|
||||
<field name="website_id" ref="website.default_website"/>
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
@ -35,10 +340,55 @@
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_about">
|
||||
<t t-call="website.layout">
|
||||
<div class="container" style="margin-top: 40px; margin-bottom: 60px;">
|
||||
<h1>About Us</h1>
|
||||
<p>Placeholder content - to be filled in with TNCSC's real history, mission,
|
||||
and board information.</p>
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>Celebrating Community, Culture, and Connection Since 1997</h1>
|
||||
<h2 class="h4 text-muted">Tamil Nadu Cultural Society of Canada</h2>
|
||||
<p class="lead">
|
||||
TNCSC is a one and only largest Indian Tamil Organisation in Canada for the
|
||||
people of Tamilnadu as a whole.
|
||||
</p>
|
||||
<p>
|
||||
Tamil Nadu Cultural Society of Canada (TNCSC) is a Not-for-Profit Ontario
|
||||
Corporation serving Indian Tamils in Canada. It was established in May 1997
|
||||
on an informal basis as an association of like minded Indian Tamils. It was
|
||||
registered in February 1998 as a not-for-profit corporation in the province
|
||||
of Ontario to connect Tamil Diasporas of Indian Tamils in Canada.
|
||||
</p>
|
||||
<h3 class="mt-5">Preserving Tamil Heritage</h3>
|
||||
<p>
|
||||
The purpose is to serve Tamils of Indian origin in Canada and preserve and
|
||||
promote the heritage of our culture in Canada by celebrating festivals like
|
||||
Pongal combined with Christmas and English New Year, Tamil New Year and
|
||||
Deepavali combined with Eid. This will facilitate the people of Tamil Nadu
|
||||
from different religion to feel Canada as a home away from home. We also help
|
||||
Tamil kids of Indo-Canadian Tamils to understand our rich heritage and the
|
||||
culture. Association is also assisting the new immigrants from Tamilnadu to
|
||||
settle down fast in Canada by providing necessary information relating to
|
||||
Canadian society, settlement, job search and community support by means of
|
||||
networking.
|
||||
</p>
|
||||
<div class="row g-4 mt-4">
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<img src="/tncsc_deployment/static/src/img/tamil_nadu/tamilnadu-1.webp" class="card-img-top" alt="Tamil Nadu"/>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Tamil Nadu</h4>
|
||||
<p class="card-text">The land whose heritage and language TNCSC exists to celebrate.</p>
|
||||
<a href="/about/tamil-nadu" class="btn btn-outline-primary">Discover Tamil Nadu</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<img src="/tncsc_deployment/static/src/img/about/unity.webp" class="card-img-top" alt="Board of Directors"/>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Board of Directors</h4>
|
||||
<p class="card-text">Meet the volunteers leading TNCSC.</p>
|
||||
<a href="/about/board-of-directors" class="btn btn-outline-primary">Meet the Board</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
@ -50,7 +400,203 @@
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Tamil School -->
|
||||
<!-- About / Tamil Nadu -->
|
||||
<record id="view_page_tamil_nadu" model="ir.ui.view">
|
||||
<field name="name">TNCSC Tamil Nadu</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">tncsc_deployment.page_tamil_nadu</field>
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_tamil_nadu">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>தமிழ்நாடு <small class="text-muted">/ Tamil Nadu</small></h1>
|
||||
<p class="lead" lang="ta">
|
||||
தமிழ்நாடு — தமிழர்களின் ஆன்மாவும் அடையாளமும்! இது ஆயிரக்கணக்கான ஆண்டுகள்
|
||||
பழமை வாய்ந்த வரலாற்றைக் கொண்ட நிலம்.
|
||||
</p>
|
||||
<img src="/tncsc_deployment/static/src/img/tamil_nadu/tamilnadu-1.webp" class="img-fluid rounded my-4" alt="Tamil Nadu coastline"/>
|
||||
<p>
|
||||
Tamil Nadu is the land of the Tamils, and it has a history that dates back
|
||||
several thousand years. It is an enchanting and ancient Dravidian land in the
|
||||
extreme south of peninsular India, where traditions and culture blend and
|
||||
continue to live in harmony — from its temples and sculptures to its living
|
||||
classical language.
|
||||
</p>
|
||||
<p>
|
||||
The state's coastline runs nearly 1,000 km along the Coromandel Coast and the
|
||||
Bay of Bengal, dotted with coconut palms, fishing villages, and rich maritime
|
||||
wildlife. It is this land — its language, its coast, its temples, and its
|
||||
people — that TNCSC exists to keep alive for Tamil families across Canada.
|
||||
</p>
|
||||
<img src="/tncsc_deployment/static/src/img/tamil_nadu/tamilnadu-2.webp" class="img-fluid rounded my-4" alt="Tamil Nadu heritage"/>
|
||||
<a href="/about" class="btn btn-outline-secondary">Back to About</a>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
<record id="page_tamil_nadu" model="website.page">
|
||||
<field name="url">/about/tamil-nadu</field>
|
||||
<field name="view_id" ref="view_page_tamil_nadu"/>
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- About / Board of Directors -->
|
||||
<record id="view_page_board" model="ir.ui.view">
|
||||
<field name="name">TNCSC Board of Directors</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">tncsc_deployment.page_board</field>
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_board">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>Board of Directors</h1>
|
||||
<p class="lead">The volunteers currently leading TNCSC.</p>
|
||||
<t t-set="board_members" t-value="[
|
||||
{'name': 'Anand Babu Gurusamy', 'title': 'President', 'img': 'anand.webp'},
|
||||
{'name': 'Rachel Daniel', 'title': 'Vice President', 'img': 'rachel.webp'},
|
||||
{'name': 'Murugan Sriramulu', 'title': 'Secretary', 'img': 'murugan.webp'},
|
||||
{'name': 'Palanimurugan Palanichamy', 'title': 'Treasurer', 'img': 'palani.webp'},
|
||||
{'name': 'Karunamoorthy Samu', 'title': 'Joint Secretary', 'img': 'karuna.webp'},
|
||||
{'name': 'Nandhini Senthil Kumar', 'title': 'Joint Treasurer', 'img': 'nandhini.webp'},
|
||||
{'name': 'Amirthavarshini Thirugnanasambandam', 'title': 'Director, Muthamizh Paadasaalai', 'img': 'amirtha.webp'},
|
||||
{'name': 'Ashraph Sulaiman', 'title': 'Director, IT Wing', 'img': 'asraph.webp'},
|
||||
{'name': 'Brindha Rajamanickam', 'title': 'Director, Muthamizh Paadasaalai', 'img': 'brindha.webp'},
|
||||
{'name': 'Mari Mutharasan', 'title': 'Director, Muthamizh Paadasaalai', 'img': 'mari.webp'},
|
||||
{'name': 'Shanmuga', 'title': 'Director, IT Wing', 'img': 'shanmuga.webp'},
|
||||
{'name': 'Sekar Karuppan', 'title': 'Director, IT Wing', 'img': 'sekar.webp'},
|
||||
]"/>
|
||||
<div class="row g-4">
|
||||
<t t-foreach="board_members" t-as="member">
|
||||
<div class="col-6 col-md-3 text-center">
|
||||
<img t-attf-src="/tncsc_deployment/static/src/img/board/#{member['img']}" class="rounded-circle mb-2" style="width:120px;height:120px;object-fit:cover;" t-att-alt="member['name']"/>
|
||||
<h5 t-out="member['name']"/>
|
||||
<p class="text-muted small" t-out="member['title']"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<a href="/about" class="btn btn-outline-secondary mt-4">Back to About</a>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
<record id="page_board" model="website.page">
|
||||
<field name="url">/about/board-of-directors</field>
|
||||
<field name="view_id" ref="view_page_board"/>
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Membership hub -->
|
||||
<record id="view_page_membership" model="ir.ui.view">
|
||||
<field name="name">TNCSC Membership</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">tncsc_deployment.page_membership</field>
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_membership">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>Membership</h1>
|
||||
<p class="lead">
|
||||
For over 28+ years, TNCSC has been a pillar for Tamil families across
|
||||
Canada — preserving language, celebrating tradition, and uniting generations
|
||||
through community events and cultural programs.
|
||||
</p>
|
||||
<div class="row g-4 my-2">
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<img src="/tncsc_deployment/static/src/img/membership/membership-benefits.webp" class="card-img-top" alt="Membership benefits"/>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Membership Benefits</h4>
|
||||
<p class="card-text">Festivals, networking, Tamil school priority, and more.</p>
|
||||
<a href="/membership/benefits" class="btn btn-outline-primary">See Benefits</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<img src="/tncsc_deployment/static/src/img/membership/membership-registration.webp" class="card-img-top" alt="Become a member"/>
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Become a Member</h4>
|
||||
<p class="card-text">Online sign-up is launching soon — for now, contact us to get started.</p>
|
||||
<a href="/contact" class="btn btn-primary">Contact Us to Join</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="mt-5">Membership Plans</h3>
|
||||
<div class="row g-3">
|
||||
<t t-foreach="env['community.membership.tier'].sudo().search([('active', '=', True)], order='sequence')" t-as="tier">
|
||||
<div class="col-6 col-lg-2 col-md-4">
|
||||
<div class="card h-100 text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" t-out="tier.name"/>
|
||||
<p class="card-text fw-bold" t-out="'%s %s' % (tier.currency_id.symbol, int(tier.price))"/>
|
||||
<p class="card-text text-muted small" t-out="dict(tier._fields['period'].selection).get(tier.period)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<p class="text-muted small mt-3">Already a member? <a href="/my/membership">Manage your membership</a>.</p>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
<record id="page_membership" model="website.page">
|
||||
<field name="url">/membership</field>
|
||||
<field name="view_id" ref="view_page_membership"/>
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Membership benefits -->
|
||||
<record id="view_page_membership_benefits" model="ir.ui.view">
|
||||
<field name="name">TNCSC Membership Benefits</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">tncsc_deployment.page_membership_benefits</field>
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_membership_benefits">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>Membership Benefits</h1>
|
||||
<h2 class="h5 text-muted">TNCSC Memberships</h2>
|
||||
<p class="lead">Join Hands to Keep Our Tamil Heritage Alive — Right Here in Canada!</p>
|
||||
<p>
|
||||
Becoming a member of Tamil Nadu Cultural Society of Canada (TNCSC) is more
|
||||
than just signing up — it's becoming part of a family that celebrates Tamil
|
||||
identity, language, and culture in every heartbeat.
|
||||
</p>
|
||||
<div class="row g-4 align-items-center">
|
||||
<div class="col-md-6">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">Experience the joy of celebrating Tamil festivals like Pongal, Tamil New Year, and Deepavali just the way we do back home.</li>
|
||||
<li class="list-group-item">Meet new friends, families, and professionals who share your values and heritage.</li>
|
||||
<li class="list-group-item">Our community events bring together people from all walks of life — from entrepreneurs to IT professionals to artists.</li>
|
||||
<li class="list-group-item">Members' children get priority access to our Muthamizh Padasaalai, where they learn Tamil reading, writing, and speaking.</li>
|
||||
<li class="list-group-item">Every member is welcome to participate as a volunteer in TNCSC events.</li>
|
||||
<li class="list-group-item">Enjoy free or discounted entry to select TNCSC programs, workshops, and cultural events.</li>
|
||||
<li class="list-group-item">Voting rights and board election participation privileges.</li>
|
||||
<li class="list-group-item">Your membership keeps Tamil culture alive — your involvement keeps our community strong.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<img src="/tncsc_deployment/static/src/img/membership/members-img.webp" class="img-fluid rounded" alt="TNCSC members"/>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/contact" class="btn btn-primary btn-lg mt-4">Become a Member</a>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
<record id="page_membership_benefits" model="website.page">
|
||||
<field name="url">/membership/benefits</field>
|
||||
<field name="view_id" ref="view_page_membership_benefits"/>
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Tamil School / Tamil Class -->
|
||||
<record id="view_page_tamil_school" model="ir.ui.view">
|
||||
<field name="name">TNCSC Tamil School</field>
|
||||
<field name="type">qweb</field>
|
||||
@ -58,11 +604,29 @@
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_tamil_school">
|
||||
<t t-call="website.layout">
|
||||
<div class="container" style="margin-top: 40px; margin-bottom: 60px;">
|
||||
<h1>Tamil School</h1>
|
||||
<p>Weekend Tamil language classes for children and youth. See current terms,
|
||||
levels, and class schedules below.</p>
|
||||
<a href="/school/register" class="btn btn-primary">Register</a>
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>Tamil Class</h1>
|
||||
<h2 class="h5 text-muted">முத்தமிழ் பாடசாலை</h2>
|
||||
<div class="row g-4 align-items-center">
|
||||
<div class="col-md-6">
|
||||
<p class="lead">
|
||||
தமிழ்மொழி, தமிழ்க் கலாச்சாரம், தமிழ் மரபு — the Tamil language, culture,
|
||||
and heritage form the identity and foundation of our community.
|
||||
</p>
|
||||
<p>
|
||||
Operating since 2013, our Tamil classes serve children ages 4 and older,
|
||||
building speaking, reading, and writing skills through a curriculum based
|
||||
on Tamil Nadu's own education system, taught from custom textbooks
|
||||
developed for accessibility abroad. Our teachers are experienced educators
|
||||
from Tamil Nadu who bring language, history, culture, and tradition into
|
||||
every class.
|
||||
</p>
|
||||
<a href="/school/register" class="btn btn-primary">Register</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<img src="/tncsc_deployment/static/src/img/tamil_class/tamil_class.webp" class="img-fluid rounded" alt="Tamil class"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
@ -74,7 +638,10 @@
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Sponsors -->
|
||||
<!-- Sponsors: tncsc.com's own Sponsors page is unmigrated WordPress
|
||||
theme demo content (generic client-01..09 stock logos, dead links,
|
||||
no real sponsor names) - left as a placeholder, deliberately not
|
||||
linked from the main nav, until TNCSC provides real sponsor data. -->
|
||||
<record id="view_page_sponsors" model="ir.ui.view">
|
||||
<field name="name">TNCSC Sponsors</field>
|
||||
<field name="type">qweb</field>
|
||||
@ -105,10 +672,51 @@
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="tncsc_deployment.page_contact">
|
||||
<t t-call="website.layout">
|
||||
<div class="container" style="margin-top: 40px; margin-bottom: 60px;">
|
||||
<div id="wrap" class="container pt56 pb56">
|
||||
<h1>Contact Us</h1>
|
||||
<p>Email: <t t-out="env.company.email or ''"/></p>
|
||||
<p>Placeholder content - add a real address, phone number, and contact form.</p>
|
||||
<p class="lead">We'd Love to Hear From You</p>
|
||||
<div class="row g-5">
|
||||
<div class="col-lg-5">
|
||||
<h5>Visit / Call Us Anytime</h5>
|
||||
<p>
|
||||
Email:
|
||||
<a t-attf-href="mailto:#{env.company.email}" t-out="env.company.email"/>
|
||||
</p>
|
||||
<p class="text-muted small">
|
||||
No public phone line or street address is published yet — email or
|
||||
social media is the fastest way to reach us.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://www.facebook.com/TNCSCCanada/" target="_blank" class="me-3">Facebook</a>
|
||||
<a href="https://www.youtube.com/@tamilnaduculturalsocietyof5866" target="_blank" class="me-3">YouTube</a>
|
||||
<a href="https://www.instagram.com/tncsc_canada" target="_blank">Instagram</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-7">
|
||||
<section class="s_website_form" data-snippet="s_website_form">
|
||||
<form id="contactus_form" action="/website/form/" method="post" enctype="multipart/form-data" class="o_mark_required" data-mark="*" data-model_name="mail.mail" data-success-mode="redirect" data-success-page="/contactus-thank-you">
|
||||
<input type="hidden" name="email_to" t-att-value="env.company.email"/>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contact_name">Name <span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" name="name" id="contact_name" required="1"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contact_email">Email <span class="text-danger">*</span></label>
|
||||
<input type="email" class="form-control" name="email_from" id="contact_email" required="1"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contact_subject">Subject</label>
|
||||
<input type="text" class="form-control" name="subject" id="contact_subject"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="contact_description">Message <span class="text-danger">*</span></label>
|
||||
<textarea class="form-control" name="description" id="contact_description" rows="5" required="1"/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Submit Now</button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
@ -120,41 +728,72 @@
|
||||
<field name="is_published">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Main nav menu entries -->
|
||||
<!-- Main nav menu, matching tncsc.com's real structure:
|
||||
Home / About (Tamil Nadu, Board Of Directors) / Events /
|
||||
Membership (Membership Benefits, Membership Registration) /
|
||||
Tamil Class / Contact.
|
||||
Classifieds and the vendor Benefits directory are still fully
|
||||
functional CommunityOS features - they're reachable from the
|
||||
member portal (/my), just not on the public marketing nav, matching
|
||||
tncsc.com's own structure. -->
|
||||
<record id="menu_home" model="website.menu">
|
||||
<field name="name">Home</field>
|
||||
<field name="url">/</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">5</field>
|
||||
</record>
|
||||
<record id="menu_about" model="website.menu">
|
||||
<field name="name">About</field>
|
||||
<field name="url">/about</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
<record id="menu_tamil_school" model="website.menu">
|
||||
<field name="name">Tamil School</field>
|
||||
<field name="url">/tamil-school</field>
|
||||
<record id="menu_about_tamil_nadu" model="website.menu">
|
||||
<field name="name">Tamil Nadu</field>
|
||||
<field name="url">/about/tamil-nadu</field>
|
||||
<field name="parent_id" ref="menu_about"/>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
<record id="menu_about_board" model="website.menu">
|
||||
<field name="name">Board Of Directors</field>
|
||||
<field name="url">/about/board-of-directors</field>
|
||||
<field name="parent_id" ref="menu_about"/>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
<record id="menu_events" model="website.menu">
|
||||
<field name="name">Events</field>
|
||||
<field name="url">/event</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
<record id="menu_classifieds" model="website.menu">
|
||||
<field name="name">Classifieds</field>
|
||||
<field name="url">/classifieds</field>
|
||||
<record id="menu_membership" model="website.menu">
|
||||
<field name="name">Membership</field>
|
||||
<field name="url">/membership</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">30</field>
|
||||
</record>
|
||||
<record id="menu_benefits" model="website.menu">
|
||||
<field name="name">Benefits</field>
|
||||
<field name="url">/benefits</field>
|
||||
<record id="menu_membership_benefits" model="website.menu">
|
||||
<field name="name">Membership Benefits</field>
|
||||
<field name="url">/membership/benefits</field>
|
||||
<field name="parent_id" ref="menu_membership"/>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
<record id="menu_membership_registration" model="website.menu">
|
||||
<field name="name">Membership Registration</field>
|
||||
<field name="url">/contact</field>
|
||||
<field name="parent_id" ref="menu_membership"/>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
<record id="menu_tamil_class" model="website.menu">
|
||||
<field name="name">Tamil Class</field>
|
||||
<field name="url">/tamil-school</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">40</field>
|
||||
</record>
|
||||
<record id="menu_sponsors" model="website.menu">
|
||||
<field name="name">Sponsors</field>
|
||||
<field name="url">/sponsors</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">50</field>
|
||||
</record>
|
||||
<record id="menu_contact" model="website.menu">
|
||||
<field name="name">Contact</field>
|
||||
<field name="url">/contact</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence">60</field>
|
||||
<field name="sequence">50</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
846
docs/TNCSC_Handbook.html
Normal file
@ -0,0 +1,846 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="A settings and day-to-day operations guide for TNCSC board members and volunteers running their CommunityOS system.">
|
||||
<title>TNCSC Handbook</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Zilla+Slab:wght@400;500;600;700&family=Inter:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Mono:wght@500;600&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
h1, h2, h3, h4, p, ul, ol { margin: 0; }
|
||||
|
||||
:root {
|
||||
--ink: #0c1230;
|
||||
--ink-soft: #333a5c;
|
||||
--muted: #5b6280;
|
||||
--paper: #f4f5fb;
|
||||
--surface: #ffffff;
|
||||
--surface-2: #eef0fa;
|
||||
--border: #dfe2f0;
|
||||
--border-soft: #ebedf7;
|
||||
--accent: #0d7fd6;
|
||||
--accent-ink: #ffffff;
|
||||
--accent-soft: #e6f2fd;
|
||||
--warn: #c2550a;
|
||||
--warn-soft: #fdece0;
|
||||
--code-surface: #eef0fa;
|
||||
--code-ink: #2a2f52;
|
||||
--shadow: 0 1px 2px rgba(12, 18, 48, 0.04), 0 8px 24px -12px rgba(12, 18, 48, 0.18);
|
||||
--focus: #0d7fd6;
|
||||
|
||||
--font-display: "Zilla Slab", Georgia, "Times New Roman", serif;
|
||||
--font-body: "Inter", -apple-system, "Segoe UI", sans-serif;
|
||||
--font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
--ink: #e9ebfa;
|
||||
--ink-soft: #c3c7e6;
|
||||
--muted: #9599c0;
|
||||
--paper: #0a0e24;
|
||||
--surface: #11162f;
|
||||
--surface-2: #171d3d;
|
||||
--border: #262c4f;
|
||||
--border-soft: #1b2142;
|
||||
--accent: #4fb2ff;
|
||||
--accent-ink: #05121f;
|
||||
--accent-soft: #12233b;
|
||||
--warn: #ff9d5c;
|
||||
--warn-soft: #2e1c10;
|
||||
--code-surface: #171d3d;
|
||||
--code-ink: #cfd3f2;
|
||||
--shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 12px 28px -14px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--ink: #e9ebfa;
|
||||
--ink-soft: #c3c7e6;
|
||||
--muted: #9599c0;
|
||||
--paper: #0a0e24;
|
||||
--surface: #11162f;
|
||||
--surface-2: #171d3d;
|
||||
--border: #262c4f;
|
||||
--border-soft: #1b2142;
|
||||
--accent: #4fb2ff;
|
||||
--accent-ink: #05121f;
|
||||
--accent-soft: #12233b;
|
||||
--warn: #ff9d5c;
|
||||
--warn-soft: #2e1c10;
|
||||
--code-surface: #171d3d;
|
||||
--code-ink: #cfd3f2;
|
||||
--shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 12px 28px -14px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--paper);
|
||||
color: var(--ink);
|
||||
font-family: var(--font-body);
|
||||
font-size: 16.5px;
|
||||
line-height: 1.65;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
a { color: var(--accent); text-decoration-thickness: 1.5px; text-underline-offset: 2px; }
|
||||
a:focus-visible, button:focus-visible, summary:focus-visible {
|
||||
outline: 2.5px solid var(--focus);
|
||||
outline-offset: 2px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
text-wrap: balance;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
p { margin: 0 0 1.05em; max-width: 66ch; }
|
||||
ul, ol { max-width: 66ch; padding-left: 1.35em; }
|
||||
li { margin-bottom: 0.45em; }
|
||||
li:last-child { margin-bottom: 0; }
|
||||
li > ul, li > ol { margin-top: 0.45em; }
|
||||
|
||||
/* ---------- Masthead ---------- */
|
||||
|
||||
.masthead {
|
||||
border-bottom: 1px solid var(--border);
|
||||
background:
|
||||
radial-gradient(1100px 420px at 12% -20%, var(--accent-soft), transparent 60%),
|
||||
var(--surface);
|
||||
}
|
||||
|
||||
.masthead-inner {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
padding: 3.4rem 2rem 2.6rem;
|
||||
}
|
||||
|
||||
.kicker {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 0.6em;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.kicker::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 1.6em;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
h1.title {
|
||||
font-size: clamp(2.2rem, 4.4vw, 3.15rem);
|
||||
margin: 0 0 0.55em;
|
||||
max-width: 16ch;
|
||||
}
|
||||
|
||||
.dek {
|
||||
font-size: 1.14rem;
|
||||
color: var(--ink-soft);
|
||||
max-width: 56ch;
|
||||
margin: 0 0 1.6rem;
|
||||
}
|
||||
|
||||
.login-note {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.65em;
|
||||
background: var(--surface-2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
padding: 0.65em 1em;
|
||||
font-size: 0.92rem;
|
||||
color: var(--ink-soft);
|
||||
max-width: 66ch;
|
||||
}
|
||||
|
||||
.login-note b { color: var(--ink); }
|
||||
|
||||
/* ---------- App grid on masthead ---------- */
|
||||
|
||||
.app-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 0.6rem;
|
||||
margin-top: 2.2rem;
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.app-chip {
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
border-radius: 10px;
|
||||
padding: 0.7em 0.85em;
|
||||
font-size: 0.86rem;
|
||||
font-weight: 600;
|
||||
color: var(--ink-soft);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ---------- Layout ---------- */
|
||||
|
||||
.layout {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
padding: 2.6rem 2rem 6rem;
|
||||
display: grid;
|
||||
grid-template-columns: 240px minmax(0, 1fr);
|
||||
gap: 3.2rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
nav.toc {
|
||||
position: sticky;
|
||||
top: 1.6rem;
|
||||
align-self: start;
|
||||
font-size: 0.89rem;
|
||||
}
|
||||
|
||||
nav.toc .toc-label {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.72rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
margin-bottom: 0.9rem;
|
||||
}
|
||||
|
||||
nav.toc ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
counter-reset: toc;
|
||||
border-left: 1px solid var(--border);
|
||||
}
|
||||
|
||||
nav.toc li { margin: 0; }
|
||||
|
||||
nav.toc a {
|
||||
counter-increment: toc;
|
||||
display: flex;
|
||||
gap: 0.65em;
|
||||
align-items: baseline;
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
margin-left: -1px;
|
||||
border-left: 2px solid transparent;
|
||||
color: var(--ink-soft);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav.toc a::before {
|
||||
content: counter(toc, decimal-leading-zero);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.76rem;
|
||||
color: var(--muted);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
nav.toc a:hover { color: var(--accent); border-left-color: var(--border); }
|
||||
nav.toc a.active { color: var(--accent); border-left-color: var(--accent); font-weight: 600; }
|
||||
|
||||
main { min-width: 0; }
|
||||
|
||||
section.chapter {
|
||||
padding-top: 0.4rem;
|
||||
margin-bottom: 3.6rem;
|
||||
scroll-margin-top: 1.4rem;
|
||||
}
|
||||
|
||||
section.chapter:last-child { margin-bottom: 0; }
|
||||
|
||||
.chapter-head {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.85rem;
|
||||
margin-bottom: 1.3rem;
|
||||
padding-bottom: 1.1rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.chapter-num {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
h2.chapter-title {
|
||||
font-size: clamp(1.5rem, 2.6vw, 1.9rem);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h3.sub {
|
||||
font-size: 1.12rem;
|
||||
margin: 1.9rem 0 0.75rem;
|
||||
}
|
||||
section.chapter > h3.sub:first-of-type,
|
||||
.chapter-body > h3.sub:first-child { margin-top: 0.4rem; }
|
||||
|
||||
h4.microhead {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.76rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
margin: 1.6rem 0 0.6rem;
|
||||
}
|
||||
|
||||
/* ---------- Menu path chips ---------- */
|
||||
|
||||
.path {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.86em;
|
||||
font-weight: 500;
|
||||
background: var(--code-surface);
|
||||
color: var(--code-ink);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 7px;
|
||||
padding: 0.18em 0.15em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.path span { padding: 0.05em 0.5em; white-space: nowrap; }
|
||||
.path span:not(:last-child)::after {
|
||||
content: "›";
|
||||
margin-left: 0.55em;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
p .path, li .path { margin: 0.15em 0; }
|
||||
p:has(> .path:only-child) { max-width: none; }
|
||||
|
||||
.field {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.86em;
|
||||
background: var(--surface-2);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 5px;
|
||||
padding: 0.08em 0.4em;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
/* ---------- Cards / role & app tables ---------- */
|
||||
|
||||
.card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
|
||||
gap: 0.85rem;
|
||||
margin: 1.2rem 0 1.6rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
border-radius: 12px;
|
||||
padding: 1.1rem 1.15rem;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.card b {
|
||||
display: block;
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.02rem;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.card p { margin: 0; font-size: 0.92rem; color: var(--ink-soft); max-width: none; }
|
||||
|
||||
table.roles {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1.2rem 0 1.6rem;
|
||||
font-size: 0.94rem;
|
||||
}
|
||||
|
||||
table.roles th, table.roles td {
|
||||
text-align: left;
|
||||
padding: 0.75em 0.9em;
|
||||
border-bottom: 1px solid var(--border);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.roles th {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.74rem;
|
||||
letter-spacing: 0.07em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
table.roles td:first-child, table.roles th:first-child { font-weight: 600; white-space: nowrap; }
|
||||
table.roles tr:last-child td { border-bottom: none; }
|
||||
|
||||
.role-badge {
|
||||
display: inline-block;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.72rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.03em;
|
||||
padding: 0.22em 0.6em;
|
||||
border-radius: 999px;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ---------- Steps ---------- */
|
||||
|
||||
ol.steps {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 1.1rem 0 1.6rem;
|
||||
counter-reset: step;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.9rem;
|
||||
}
|
||||
|
||||
ol.steps li {
|
||||
counter-increment: step;
|
||||
display: grid;
|
||||
grid-template-columns: 2rem 1fr;
|
||||
gap: 0.9rem;
|
||||
margin: 0;
|
||||
max-width: 66ch;
|
||||
}
|
||||
|
||||
ol.steps li::before {
|
||||
content: counter(step);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: 50%;
|
||||
background: var(--surface-2);
|
||||
color: var(--accent);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ---------- Callouts ---------- */
|
||||
|
||||
.callout {
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--accent);
|
||||
background: var(--accent-soft);
|
||||
border-radius: 0 10px 10px 0;
|
||||
padding: 0.9em 1.15em;
|
||||
margin: 1.3rem 0;
|
||||
font-size: 0.94rem;
|
||||
}
|
||||
.callout p { margin: 0; max-width: none; color: var(--ink-soft); }
|
||||
.callout p + p { margin-top: 0.6em; }
|
||||
.callout b { color: var(--ink); }
|
||||
|
||||
.callout.warn {
|
||||
border-left-color: var(--warn);
|
||||
background: var(--warn-soft);
|
||||
}
|
||||
|
||||
.callout-label {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.09em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
display: block;
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
.callout.warn .callout-label { color: var(--warn); }
|
||||
|
||||
/* ---------- Troubleshooting table ---------- */
|
||||
|
||||
table.trouble {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1.2rem 0 0.4rem;
|
||||
font-size: 0.93rem;
|
||||
}
|
||||
|
||||
table.trouble th {
|
||||
text-align: left;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.07em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
font-weight: 600;
|
||||
padding: 0 0.9em 0.6em 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
table.trouble td {
|
||||
padding: 0.95em 0.9em 0.95em 0;
|
||||
border-bottom: 1px solid var(--border-soft);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.trouble td:first-child { font-weight: 600; width: 34%; }
|
||||
table.trouble tr:last-child td { border-bottom: none; }
|
||||
|
||||
/* ---------- Footer ---------- */
|
||||
|
||||
footer.colophon {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
padding: 2.2rem 2rem 3.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
color: var(--muted);
|
||||
font-size: 0.88rem;
|
||||
}
|
||||
|
||||
/* ---------- Responsive ---------- */
|
||||
|
||||
@media (max-width: 880px) {
|
||||
.layout { grid-template-columns: 1fr; }
|
||||
nav.toc {
|
||||
position: static;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 1rem 1.2rem;
|
||||
background: var(--surface);
|
||||
}
|
||||
nav.toc ol { border-left: none; }
|
||||
nav.toc a { padding-left: 0; margin-left: 0; border-left: none; }
|
||||
.app-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
body { overflow-x: hidden; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html { scroll-behavior: auto; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="masthead">
|
||||
<div class="masthead-inner">
|
||||
<span class="kicker">Community OS · Operations Guide</span>
|
||||
<h1 class="title">TNCSC Handbook</h1>
|
||||
<p class="dek">How the Tamil Nadu Cultural Society of Canada configures, runs, and troubleshoots its own system — written for board members and volunteers, not developers.</p>
|
||||
<div class="login-note">📍 <span><b>Where to log in:</b> your production site's <span class="field">/web/login</span> page. Ask your technical contact for the exact address if you don't have it.</span></div>
|
||||
<div class="app-grid">
|
||||
<div class="app-chip">Membership</div>
|
||||
<div class="app-chip">Events</div>
|
||||
<div class="app-chip">School</div>
|
||||
<div class="app-chip">Classifieds</div>
|
||||
<div class="app-chip">Benefits</div>
|
||||
<div class="app-chip">Interac Payments</div>
|
||||
<div class="app-chip">Website</div>
|
||||
<div class="app-chip">Settings</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="layout">
|
||||
<nav class="toc" aria-label="Table of contents">
|
||||
<div class="toc-label">Contents</div>
|
||||
<ol>
|
||||
<li><a href="#understanding">Understanding the system</a></li>
|
||||
<li><a href="#roles">User roles</a></li>
|
||||
<li><a href="#branding">Branding</a></li>
|
||||
<li><a href="#membership">Membership</a></li>
|
||||
<li><a href="#events">Events</a></li>
|
||||
<li><a href="#school">Tamil Class (School)</a></li>
|
||||
<li><a href="#classifieds">Classifieds</a></li>
|
||||
<li><a href="#benefits">Benefits</a></li>
|
||||
<li><a href="#interac">Interac Payments</a></li>
|
||||
<li><a href="#website">Website content</a></li>
|
||||
<li><a href="#accounting">Accounting basics</a></li>
|
||||
<li><a href="#troubleshooting">Troubleshooting</a></li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
|
||||
<section class="chapter" id="understanding">
|
||||
<div class="chapter-head"><span class="chapter-num">01</span><h2 class="chapter-title">Understanding the system</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p>Once you log in, you'll see an <b>app switcher</b> — a grid of icons, one per area of the system. Each app is where a specific part of TNCSC's work lives:</p>
|
||||
|
||||
<div class="card-grid">
|
||||
<div class="card"><b>Membership</b><p>Members, tiers/pricing, renewals</p></div>
|
||||
<div class="card"><b>Events</b><p>Creating events, ticketing, check-in</p></div>
|
||||
<div class="card"><b>School</b><p>Tamil Class terms, classes, attendance</p></div>
|
||||
<div class="card"><b>Classifieds</b><p>The member board and its moderation queue</p></div>
|
||||
<div class="card"><b>Benefits</b><p>Benefit centres and member perks</p></div>
|
||||
<div class="card"><b>Interac Payments</b><p>Confirming e-Transfer payments</p></div>
|
||||
<div class="card"><b>Website</b><p>The public website — pages, menus, content</p></div>
|
||||
<div class="card"><b>Settings</b><p>Branding, org configuration, user accounts</p></div>
|
||||
</div>
|
||||
|
||||
<div class="callout">
|
||||
<span class="callout-label">If an app is missing</span>
|
||||
<p>It's almost always a permissions issue, not a broken install. See <a href="#roles">User roles</a> and <a href="#troubleshooting">Troubleshooting</a> below.</p>
|
||||
</div>
|
||||
|
||||
<p>Two databases exist during development/testing (<span class="field">tncsc_migration_test</span>, <span class="field">tncsc_site</span>) — your technical contact will tell you which one is live production once you go live. Everything in this guide applies the same way regardless of which database you're in.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="roles">
|
||||
<div class="chapter-head"><span class="chapter-num">02</span><h2 class="chapter-title">User roles — who can do what</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p>Go to <span class="path"><span>Settings</span><span>Users & Companies</span><span>Users</span></span>, click a person's name, and under their groups you'll find <b>TNCSC Roles</b>. Check the box for the role that matches what they do:</p>
|
||||
|
||||
<table class="roles">
|
||||
<tr><th>Role</th><th>Grants</th></tr>
|
||||
<tr><td><span class="role-badge">Board Admin</span></td><td>Everything — membership, school, classifieds, benefits, events, and Interac payments. Give this only to whoever runs the system day-to-day.</td></tr>
|
||||
<tr><td><span class="role-badge">Treasurer</span></td><td>Confirms Interac payments and has invoicing access.</td></tr>
|
||||
<tr><td><span class="role-badge">Events Officer</span></td><td>Creates/manages events and staffs check-in.</td></tr>
|
||||
<tr><td><span class="role-badge">School Coordinator</span></td><td>Manages Tamil Class terms, classes, students, enrollment.</td></tr>
|
||||
<tr><td><span class="role-badge">Teacher</span></td><td>Can only take attendance for their own classes.</td></tr>
|
||||
<tr><td><span class="role-badge">Classifieds Moderator</span></td><td>Reviews and publishes classified listings.</td></tr>
|
||||
</table>
|
||||
|
||||
<p>A person can hold more than one role — e.g. someone can be both <b>School Coordinator</b> and <b>Teacher</b>. Members themselves don't need a role checked here at all: once someone is a member, they get their own self-service <b>member portal</b> automatically (see <a href="#membership">Membership</a>) — separate from these backend roles, and it doesn't require a staff login.</p>
|
||||
|
||||
<h4 class="microhead">Adding a new staff or volunteer account</h4>
|
||||
<ol class="steps">
|
||||
<li>Go to <span class="path"><span>Settings</span><span>Users & Companies</span><span>Users</span><span>New</span></span></li>
|
||||
<li>Fill in their name and email, then save.</li>
|
||||
<li>Check the role(s) above for them. They'll get an email to set their own password.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="branding">
|
||||
<div class="chapter-head"><span class="chapter-num">03</span><h2 class="chapter-title">Branding: colours, logo, fonts</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p><span class="path"><span>Settings</span><span>General Settings</span><span>Theme</span></span> (left-hand tab list).</p>
|
||||
<ul>
|
||||
<li><span class="field">Primary / Secondary / Accent Colour</span> — enter a colour as a hex code (e.g. <span class="field">#05091E</span>). These apply instantly across the website, the member portal, and PDF documents like the membership card — no other setting to touch.</li>
|
||||
<li><span class="field">Logo</span> — upload the image file to use in the site header and on generated PDFs. If left blank, the company logo (<span class="path"><span>Settings</span><span>General Settings</span><span>Companies</span></span>) is used instead.</li>
|
||||
<li><span class="field">Heading Font / Body Font</span> — enter a font name, e.g. <span class="field">Inter, sans-serif</span>. Needs to be a font available to browsers — ask your technical contact before entering something unusual.</li>
|
||||
</ul>
|
||||
<p>Click <b>Save</b> at the top of the page after any change.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="membership">
|
||||
<div class="chapter-head"><span class="chapter-num">04</span><h2 class="chapter-title">Membership</h2></div>
|
||||
<div class="chapter-body">
|
||||
|
||||
<h3 class="sub">Settings</h3>
|
||||
<p><span class="path"><span>Settings</span><span>General Settings</span><span>Membership</span></span></p>
|
||||
<ul>
|
||||
<li><span class="field">Organization Name</span> — used in renewal emails and the membership card.</li>
|
||||
<li><span class="field">Member ID Format</span> — the pattern new member IDs follow, e.g. <span class="field">TNCSC-{year}-{seq}</span> produces <span class="field">TNCSC-2026-014</span>. Don't change the placeholders unless your technical contact confirms it's safe — they drive the auto-numbering.</li>
|
||||
<li><span class="field">Renewal Reminder Offsets</span> — comma-separated days-before-expiry to send reminders, e.g. <span class="field">30,14,7</span>.</li>
|
||||
<li><span class="field">Member Portal</span> — toggle the self-service portal on or off site-wide.</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="sub">Membership tiers and pricing</h3>
|
||||
<p><span class="path"><span>Membership</span><span>Configuration</span><span>Membership Tiers</span></span></p>
|
||||
<p>Each row is a plan (Individual, Family, Student, Senior, Life, or whatever TNCSC offers). To <b>change a price</b>, open the tier and edit <span class="field">Price</span> — this is the only place pricing lives. To <b>add a new tier</b>, click New and fill in:</p>
|
||||
<ul>
|
||||
<li><span class="field">Name</span> — shown to members, e.g. "Corporate Sponsor"</li>
|
||||
<li><span class="field">Code</span> — a short internal code, e.g. <span class="field">CORP</span> (no spaces)</li>
|
||||
<li><span class="field">Price</span> and <span class="field">Currency</span></li>
|
||||
<li><span class="field">Period</span> — Annual, One-Time, or Monthly</li>
|
||||
<li><span class="field">Sequence</span> — controls display order (lower numbers show first)</li>
|
||||
</ul>
|
||||
<p>Deactivating a tier (rather than deleting it) keeps historical records intact for members who already hold it — use the tier's kebab (⋮) menu → <b>Archive</b>, instead of deleting.</p>
|
||||
|
||||
<h3 class="sub">Day-to-day membership work</h3>
|
||||
<ul>
|
||||
<li><span class="path"><span>Membership</span><span>Members</span></span> — the full member list. Open a member to see their tier, status, and expiry date.</li>
|
||||
<li>Renewal reminders and draft renewal invoices are generated <b>automatically</b> by a daily background job — nothing to run manually. What you do need to do periodically: check <span class="path"><span>Invoicing</span><span>Customer Invoices</span></span> for draft renewal invoices and confirm/send them once payment is expected.</li>
|
||||
<li>Each member can view their status, download their QR membership card, and renew from <span class="field">/my/membership</span> once logged into the website — no need to email cards out manually.</li>
|
||||
<li>The membership card's QR code links to a public verification page (<span class="field">/membership/verify/<member ID></span>) — anyone scanning it sees only "valid" / "expired" / "not found," never personal details.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="events">
|
||||
<div class="chapter-head"><span class="chapter-num">05</span><h2 class="chapter-title">Events</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p><span class="path"><span>Events</span><span>Events</span><span>New</span></span> — this is standard Odoo event creation:</p>
|
||||
<ol class="steps">
|
||||
<li>Name, start/end date and time, location.</li>
|
||||
<li>Under <b>Website</b>, check <span class="field">Is Published</span> to make it visible on the public Events page and the homepage's "Upcoming Events" section — <b>unpublished events won't appear anywhere on the public site</b>, even though they exist in the system.</li>
|
||||
<li>Add ticket types under the event's <b>Registration</b> tab if you're charging for entry (e.g. "General $0–$30").</li>
|
||||
</ol>
|
||||
<p>Every registration automatically gets a signed QR ticket, emailed with the confirmation. At the door, staff with the <span class="role-badge">Events Officer</span> role use <span class="path"><span>Events</span><span>Registration Desk</span></span> to scan tickets (or type the ticket reference manually) — it shows valid / already checked-in / invalid, and a live count of registered vs. checked-in.</p>
|
||||
<p><span class="path"><span>Events</span><span>Reporting</span><span>Attendees / Revenues</span></span> gives you numbers after the fact without any setup.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="school">
|
||||
<div class="chapter-head"><span class="chapter-num">06</span><h2 class="chapter-title">Tamil Class (School)</h2></div>
|
||||
<div class="chapter-body">
|
||||
|
||||
<h3 class="sub">Settings</h3>
|
||||
<p><span class="path"><span>Settings</span><span>General Settings</span><span>School</span></span>: <span class="field">At-Risk Attendance Threshold</span> — the attendance percentage below which a student is flagged "at-risk" in the report.</p>
|
||||
|
||||
<h3 class="sub">Configuration — set these up before each school year</h3>
|
||||
<ul>
|
||||
<li><span class="path"><span>School</span><span>Configuration</span><span>Terms</span></span> — create a term (e.g. "2026-27"), set start/end dates, and open it (<span class="field">State = Open</span>) once registration should begin. Only one term should normally be open at a time.</li>
|
||||
<li><span class="path"><span>School</span><span>Configuration</span><span>Levels</span></span> — define your levels however TNCSC teaches (e.g. "Beginner" through "Advanced", or "Grade 1" through "Grade 12"). Each needs a short <span class="field">Code</span> and optional min/max age.</li>
|
||||
<li><b>Classes</b> aren't under Configuration — create them from <span class="path"><span>School</span><span>Classes</span><span>New</span></span>: pick the term, level, teacher, weekday, time, location, and max students. This is what shows up as an option when a parent registers online.</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="sub">Day-to-day</h3>
|
||||
<ul>
|
||||
<li><span class="path"><span>School</span><span>Students / Enrollments</span></span> — see who's enrolled where.</li>
|
||||
<li><span class="path"><span>School</span><span>Attendance Report</span></span> — a pivot table of attendance by class.</li>
|
||||
<li><span class="path"><span>School</span><span>At-Risk Students</span></span> — students below the configured threshold, so you can follow up.</li>
|
||||
<li>Teachers take attendance themselves from their own portal page (<span class="field">/school/attendance</span>) — a roster with a batch Present/Absent/Late/Excused save. An absence automatically emails the parent. Teachers only see their own classes.</li>
|
||||
<li>Parents register their child at <span class="field">/school/register</span> on the public website, in three steps. A full class waitlists the student automatically and notifies them when a seat frees up — no manual waitlist management needed.</li>
|
||||
<li>Each class auto-creates and manages its own online course/materials channel — enrolling or withdrawing a student automatically enrols/unenrols them there too.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="classifieds">
|
||||
<div class="chapter-head"><span class="chapter-num">07</span><h2 class="chapter-title">Classifieds</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p><span class="path"><span>Settings</span><span>General Settings</span><span>Classifieds</span></span>: <span class="field">Listing Duration</span> — how many days a published listing stays live before auto-expiring.</p>
|
||||
<p><span class="path"><span>Classifieds</span><span>Moderation</span></span> is where every new submission lands first (state: Pending Review). Open one to <b>Publish</b> or <b>Reject</b> it — only published listings appear on the public <span class="field">/classifieds</span> board. Posting requires the member to be logged in with an active membership, so this queue should only ever contain genuine member submissions.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="benefits">
|
||||
<div class="chapter-head"><span class="chapter-num">08</span><h2 class="chapter-title">Benefits</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p>Two things to set up, then one thing to log ongoing:</p>
|
||||
<ul>
|
||||
<li><span class="path"><span>Benefits</span><span>Benefit Centres</span></span> — the businesses/organizations offering a member benefit. Add their name, category, description, and logo.</li>
|
||||
<li><span class="path"><span>Benefits</span><span>Benefits</span></span> — the actual discount/perk, linked to one or more <b>Membership Tiers</b> (only members holding one of those tiers will see it). Set the discount type and validity dates.</li>
|
||||
<li><span class="path"><span>Benefits</span><span>Redemptions</span></span> — a log a benefit centre (or staff) creates when a member actually uses a benefit, after confirming the member is active. Mostly for your own record-keeping, not something to set up in advance.</li>
|
||||
</ul>
|
||||
<p>Members see only what their own tier qualifies them for at <span class="field">/my/benefits</span>; the public directory of participating centres is at <span class="field">/benefits</span>.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="interac">
|
||||
<div class="chapter-head"><span class="chapter-num">09</span><h2 class="chapter-title">Interac e-Transfer Payments</h2></div>
|
||||
<div class="chapter-body">
|
||||
|
||||
<h3 class="sub">One-time setup</h3>
|
||||
<p><span class="path"><span>Invoicing</span><span>Configuration</span><span>Online Payments</span><span>Payment Providers</span></span> → open <b>Interac e-Transfer</b>:</p>
|
||||
<ul>
|
||||
<li><span class="field">Interac Recipient Email</span> — the real e-transfer address payments should be sent to.</li>
|
||||
<li><span class="field">Interac Deadline Hours</span> — how long an unconfirmed payment stays pending before it's auto-cancelled (defaults to 48 hours if left blank).</li>
|
||||
<li>Set the provider's <span class="field">State</span> to <span class="field">Enabled</span> so it appears as a checkout option.</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="sub">Day-to-day <span style="font-weight:400;color:var(--muted);font-family:var(--font-body);font-size:0.72em;">— Treasurer role</span></h3>
|
||||
<p>When someone chooses Interac at checkout, they're emailed instructions (recipient address, amount, a reference code, and the deadline) automatically — nothing for you to send.</p>
|
||||
<p>Once you actually receive the e-transfer in your real bank account, go to <span class="path"><span>Interac Payments</span><span>Pending Payments</span></span>, find the matching transaction (match by amount and reference code), and click <b>Payment Received</b>. This confirms the linked invoice/registration/order. If nobody confirms it before the deadline, it auto-cancels and the payer is notified by email.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="website">
|
||||
<div class="chapter-head"><span class="chapter-num">10</span><h2 class="chapter-title">Website content</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p>The <b>Website</b> app, then click <b>Edit</b> on any page while viewing it on the public site to change text, images, and layout directly (drag-and-drop editor) — no code for routine copy changes. <span class="path"><span>Site</span><span>Menu Editor</span></span> lets you add, remove, or reorder navigation items.</p>
|
||||
|
||||
<div class="callout warn">
|
||||
<span class="callout-label">Known placeholder content</span>
|
||||
<p>The <b>Sponsors</b> page and a few header/footer text blocks (e.g. a placeholder phone number) still carry content from the original site design — safe to edit or delete through the Website editor whenever real sponsor logos or a real phone number are ready.</p>
|
||||
</div>
|
||||
|
||||
<div class="callout warn">
|
||||
<span class="callout-label">No public signup yet</span>
|
||||
<p><b>"Become a Member" buttons currently point to the Contact page</b>, not a self-service signup form — TNCSC doesn't have public online membership signup yet (only renewal, for existing members). Don't redirect these to a form that doesn't exist; talk to your technical contact if/when online signup becomes a priority.</p>
|
||||
</div>
|
||||
|
||||
<p>For anything beyond content edits — new page types, new sections with custom behaviour, structural changes — that's a developer task, not a Website-editor task.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="accounting">
|
||||
<div class="chapter-head"><span class="chapter-num">11</span><h2 class="chapter-title">Accounting basics</h2></div>
|
||||
<div class="chapter-body">
|
||||
<p>The chart of accounts, tax setup, and journals were seeded for a Canadian non-profit when the system was set up, including dedicated revenue accounts (Membership Dues, Event Revenue, Sponsorship, School Fees, Donations) and a <b>Donations</b> journal. You generally don't need to create new accounts for normal operations — membership tiers, event tickets, and school fees are already wired to the right ones.</p>
|
||||
<div class="callout warn">
|
||||
<span class="callout-label">Don't, without sign-off</span>
|
||||
<p>Rename or delete existing accounts, or change the company's currency/country, without your accountant <i>and</i> technical contact both signing off — several of these are load-bearing for other parts of the system (e.g. renaming the dues account could silently break where membership payments post to).</p>
|
||||
</div>
|
||||
<p>Day-to-day invoicing/payment work happens under the <b>Invoicing</b> app as normal.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="troubleshooting">
|
||||
<div class="chapter-head"><span class="chapter-num">12</span><h2 class="chapter-title">Troubleshooting & getting help</h2></div>
|
||||
<div class="chapter-body">
|
||||
<table class="trouble">
|
||||
<tr><th>Symptom</th><th>Likely cause / fix</th></tr>
|
||||
<tr><td>An app I should have access to isn't in my switcher</td><td>You're missing the matching role — see <a href="#roles">User roles</a>. Ask a Board Admin to check the box for you.</td></tr>
|
||||
<tr><td>I changed a setting and nothing changed on the site</td><td>Make sure you clicked <b>Save</b>. If it still looks wrong after a minute, it may need a technical restart — contact support rather than repeating the change.</td></tr>
|
||||
<tr><td>A member says their QR card doesn't work</td><td>Check their membership <b>state</b> on their member record — the verify page only shows "valid" for members currently <i>active</i>.</td></tr>
|
||||
<tr><td>An event isn't showing on the website</td><td>Confirm <span class="field">Is Published</span> is checked on the event — unpublished events are invisible on the public site by design.</td></tr>
|
||||
<tr><td>A parent can't register for a class</td><td>Check the term is <b>Open</b> and the class isn't already full — full classes waitlist automatically rather than blocking registration outright.</td></tr>
|
||||
<tr><td>An Interac payment doesn't confirm</td><td>Double-check the reference code and amount match exactly before clicking Payment Received — mismatches usually mean it's a different transaction.</td></tr>
|
||||
</table>
|
||||
<p style="margin-top:1.4rem;">For anything not covered here — a genuine error message, something that looks broken rather than misconfigured, or a request for new functionality — contact your technical support contact rather than experimenting on the live site. Screenshots and the exact steps you took help them fix it faster.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="colophon">
|
||||
This handbook covers the CommunityOS suite as configured for TNCSC. It does not cover server maintenance, backups, or deployment — those remain your technical contact's responsibility.
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var links = Array.prototype.slice.call(document.querySelectorAll('nav.toc a'));
|
||||
var sections = links.map(function (a) {
|
||||
return document.getElementById(a.getAttribute('href').slice(1));
|
||||
});
|
||||
|
||||
function onScroll() {
|
||||
var pos = window.scrollY + 140;
|
||||
var activeIndex = 0;
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i] && sections[i].offsetTop <= pos) activeIndex = i;
|
||||
}
|
||||
links.forEach(function (a, i) {
|
||||
a.classList.toggle('active', i === activeIndex);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('scroll', onScroll, { passive: true });
|
||||
onScroll();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
359
docs/TNCSC_Handbook.md
Normal file
@ -0,0 +1,359 @@
|
||||
# TNCSC CommunityOS Handbook
|
||||
|
||||
A plain-language guide for TNCSC board members and volunteers to configure
|
||||
settings and run the system day-to-day — no developer required for any of
|
||||
this. If something isn't covered here, or doesn't work the way this guide
|
||||
describes, that's a question for your technical support contact, not
|
||||
something to guess at.
|
||||
|
||||
**Where to log in:** your production site's `/web/login` page (ask your
|
||||
technical contact for the exact address if you don't have it). Use the
|
||||
account and password you were given.
|
||||
|
||||
---
|
||||
|
||||
## Contents
|
||||
|
||||
1. [Understanding the system](#1-understanding-the-system)
|
||||
2. [User roles — who can do what](#2-user-roles--who-can-do-what)
|
||||
3. [Branding: colours, logo, fonts](#3-branding-colours-logo-fonts)
|
||||
4. [Membership](#4-membership)
|
||||
5. [Events](#5-events)
|
||||
6. [Tamil Class (School)](#6-tamil-class-school)
|
||||
7. [Classifieds](#7-classifieds)
|
||||
8. [Benefits](#8-benefits)
|
||||
9. [Interac e-Transfer Payments](#9-interac-e-transfer-payments)
|
||||
10. [Website content](#10-website-content)
|
||||
11. [Accounting basics](#11-accounting-basics)
|
||||
12. [Troubleshooting & getting help](#12-troubleshooting--getting-help)
|
||||
|
||||
---
|
||||
|
||||
## 1. Understanding the system
|
||||
|
||||
Once you log in, you'll see an **app switcher** — a grid of icons, one per
|
||||
area of the system:
|
||||
|
||||
| App | What it's for |
|
||||
|---|---|
|
||||
| **Membership** | Members, tiers/pricing, renewals |
|
||||
| **Events** | Creating events, ticketing, check-in |
|
||||
| **School** | Tamil Class terms, classes, students, attendance |
|
||||
| **Classifieds** | The member classifieds board and its moderation queue |
|
||||
| **Benefits** | Benefit centres (partner businesses) and member benefits |
|
||||
| **Interac Payments** | Confirming e-Transfer payments |
|
||||
| **Website** | The public website — pages, menus, content |
|
||||
| **Settings** | Branding, org-wide configuration, user accounts |
|
||||
|
||||
**If an app is missing from your switcher**, it's almost always a
|
||||
permissions issue, not a broken install — see
|
||||
[section 2](#2-user-roles--who-can-do-what) and
|
||||
[troubleshooting](#12-troubleshooting--getting-help).
|
||||
|
||||
Two databases exist during development/testing (`tncsc_migration_test`,
|
||||
`tncsc_site`) — your technical contact will tell you which one is live
|
||||
production once you go live. Everything in this guide applies the same way
|
||||
regardless of which database you're in.
|
||||
|
||||
---
|
||||
|
||||
## 2. User roles — who can do what
|
||||
|
||||
Go to **Settings → Users & Companies → Users**, click a person's name, and
|
||||
under their groups you'll find **TNCSC Roles**. Check the box for the role
|
||||
that matches what they do:
|
||||
|
||||
| Role | What it grants |
|
||||
|---|---|
|
||||
| **Board Admin** | Everything — membership, school, classifieds, benefits, events, and Interac payments. Give this only to whoever runs the system day-to-day. |
|
||||
| **Treasurer** | Confirms Interac payments and has invoicing access. |
|
||||
| **Events Officer** | Creates/manages events and staffs check-in. |
|
||||
| **School Coordinator** | Manages Tamil Class terms, classes, students, enrollment. |
|
||||
| **Teacher** | Can only take attendance for their own classes. |
|
||||
| **Classifieds Moderator** | Reviews and publishes classified listings. |
|
||||
|
||||
A person can hold more than one role — e.g. someone can be both **School
|
||||
Coordinator** and **Teacher**. Members themselves don't need a role
|
||||
checked here at all: once someone is a member, they get their own
|
||||
self-service **member portal** automatically (see
|
||||
[section 4](#4-membership)) — that's separate from these backend roles,
|
||||
and doesn't require a staff login.
|
||||
|
||||
**Adding a new staff/volunteer account:** Settings → Users & Companies →
|
||||
Users → **New**, fill in their name and email, save, then check the
|
||||
role(s) above. They'll get an email to set their own password.
|
||||
|
||||
---
|
||||
|
||||
## 3. Branding: colours, logo, fonts
|
||||
|
||||
**Settings → General Settings → Theme** (left-hand tab list).
|
||||
|
||||
- **Primary / Secondary / Accent Colour** — enter a colour as a hex code
|
||||
(e.g. `#05091E`). These apply instantly across the website, the member
|
||||
portal, and PDF documents like the membership card — no other setting
|
||||
to touch.
|
||||
- **Logo** — upload the image file to use in the site header and on
|
||||
generated PDFs. If left blank, the company logo (Settings → General
|
||||
Settings → Companies) is used instead.
|
||||
- **Heading Font / Body Font** — enter a font name, e.g. `Inter,
|
||||
sans-serif`. Needs to be a font available to browsers (a "web-safe"
|
||||
font, or one already loaded via Google Fonts) — ask your technical
|
||||
contact before entering something unusual.
|
||||
|
||||
Click **Save** at the top of the page after any change.
|
||||
|
||||
---
|
||||
|
||||
## 4. Membership
|
||||
|
||||
### 4.1 Settings
|
||||
|
||||
**Settings → General Settings → Membership**:
|
||||
|
||||
- **Organization Name** — used in renewal emails and the membership card.
|
||||
- **Member ID Format** — the pattern new member IDs follow, e.g.
|
||||
`TNCSC-{year}-{seq}` produces `TNCSC-2026-014`. Don't change the
|
||||
`{year}`/`{seq}` placeholders unless your technical contact confirms
|
||||
the change is safe — they drive the auto-numbering.
|
||||
- **Renewal Reminder Offsets** — comma-separated days-before-expiry to
|
||||
send reminder emails, e.g. `30,14,7` sends reminders 30, 14, and 7 days
|
||||
before a membership expires.
|
||||
- **Member Portal** — toggle to turn the self-service portal (`/my/membership`)
|
||||
on or off site-wide.
|
||||
|
||||
### 4.2 Membership tiers and pricing
|
||||
|
||||
**Membership → Configuration → Membership Tiers.**
|
||||
|
||||
Each row is a plan (Individual, Family, Student, Senior, Life, or
|
||||
whatever TNCSC offers). To **change a price**, open the tier and edit
|
||||
**Price** — this is the only place pricing lives; there's no separate
|
||||
price to update anywhere else. To **add a new tier**, click New and fill
|
||||
in:
|
||||
|
||||
- **Name** — shown to members, e.g. "Corporate Sponsor"
|
||||
- **Code** — a short internal code, e.g. `CORP` (no spaces)
|
||||
- **Price** and **Currency**
|
||||
- **Period** — Annual, One-Time, or Monthly
|
||||
- **Sequence** — controls display order (lower numbers show first)
|
||||
|
||||
Deactivating a tier (rather than deleting it) keeps historical records
|
||||
intact for members who already hold it — use the **Active** toggle,
|
||||
found via the tier's kebab (⋮) menu → "Archive", instead of deleting.
|
||||
|
||||
### 4.3 Day-to-day membership work
|
||||
|
||||
- **Membership → Members** — the full member list. Open a member to see
|
||||
their tier, status (active/renewal due/expired), and expiry date.
|
||||
- Renewal reminders and draft renewal invoices are generated
|
||||
**automatically** by a daily background job — you don't need to run
|
||||
anything manually. What you *do* need to do periodically: check
|
||||
**Invoicing → Customer Invoices** for draft renewal invoices and
|
||||
confirm/send them once payment is expected.
|
||||
- Each member can view their status, download their QR membership card,
|
||||
and renew from `/my/membership` once logged into the website — you
|
||||
don't need to email cards out manually.
|
||||
- The membership card's QR code links to a public verification page
|
||||
(`/membership/verify/<member ID>`) — anyone scanning it (e.g. at an
|
||||
event door) sees only "valid" / "expired" / "not found," never personal
|
||||
details.
|
||||
|
||||
---
|
||||
|
||||
## 5. Events
|
||||
|
||||
**Events → Events → New.** This is standard Odoo event creation:
|
||||
|
||||
1. Name, start/end date and time, location.
|
||||
2. Under **Website**, check **Is Published** to make it visible on the
|
||||
public Events page and the homepage's "Upcoming Events" section —
|
||||
*unpublished events won't appear anywhere on the public site,* even
|
||||
though they exist in the system.
|
||||
3. Add ticket types under the event's **Registration** tab if you're
|
||||
charging for entry (e.g. "General $0–$30").
|
||||
|
||||
Every registration automatically gets a signed QR ticket, emailed with
|
||||
the confirmation. At the door, staff with the **Events Officer** role use
|
||||
**Events → Registration Desk** to scan tickets (or type the ticket
|
||||
reference manually) — it shows valid / already checked-in / invalid, and
|
||||
a live count of registered vs. checked-in.
|
||||
|
||||
**Events → Reporting → Attendees / Revenues** gives you numbers after the
|
||||
fact without any setup.
|
||||
|
||||
---
|
||||
|
||||
## 6. Tamil Class (School)
|
||||
|
||||
### 6.1 Settings
|
||||
|
||||
**Settings → General Settings → School**: **At-Risk Attendance
|
||||
Threshold** — the attendance percentage below which a student is flagged
|
||||
"at-risk" in the report (see below).
|
||||
|
||||
### 6.2 Configuration — set these up before each school year
|
||||
|
||||
**School → Configuration → Terms** — create a term (e.g. "2026-27"),
|
||||
set start/end dates, and open it (**State = Open**) once registration
|
||||
should begin. Only one term should normally be open at a time.
|
||||
|
||||
**School → Configuration → Levels** — define your levels however TNCSC
|
||||
teaches (e.g. "Beginner" through "Advanced", or "Grade 1" through "Grade
|
||||
12"). Each needs a short **Code** (e.g. `BEG`) and optional min/max age.
|
||||
|
||||
**Classes** aren't under Configuration — create them directly from
|
||||
**School → Classes → New**: pick the term, level, teacher, weekday,
|
||||
time, location, and max students. This is what shows up as an option
|
||||
when a parent registers online.
|
||||
|
||||
### 6.3 Day-to-day
|
||||
|
||||
- **School → Students / Enrollments** — see who's enrolled where.
|
||||
- **School → Attendance Report** — a pivot table of attendance by class.
|
||||
- **School → At-Risk Students** — students below the configured
|
||||
attendance threshold, so you can follow up.
|
||||
- Teachers take attendance themselves from their own portal page
|
||||
(`/school/attendance`) — a roster of today's/this-week's classes with a
|
||||
batch Present/Absent/Late/Excused save. An absence automatically emails
|
||||
the parent. Teachers only see their own classes there.
|
||||
- Parents register their child at `/school/register` on the public
|
||||
website (parent → student → class + payment, in three steps). If a
|
||||
class is full, the student is waitlisted and notified automatically
|
||||
when a seat frees up — no manual waitlist management needed.
|
||||
- Each class auto-creates and manages its own online course/materials
|
||||
channel — enrolling or withdrawing a student automatically
|
||||
enrols/unenrols them there too.
|
||||
|
||||
---
|
||||
|
||||
## 7. Classifieds
|
||||
|
||||
**Settings → General Settings → Classifieds**: **Listing Duration** — how
|
||||
many days a published listing stays live before auto-expiring.
|
||||
|
||||
**Classifieds → Moderation** is where every new submission lands first
|
||||
(state: Pending Review). Open one to **Publish** or **Reject** it — only
|
||||
published listings appear on the public `/classifieds` board. Posting
|
||||
requires the member to be logged in with an active membership, so this
|
||||
queue should only ever contain genuine member submissions.
|
||||
|
||||
---
|
||||
|
||||
## 8. Benefits
|
||||
|
||||
Two things to set up, then one thing to log ongoing:
|
||||
|
||||
- **Benefits → Benefit Centres** — the businesses/organizations offering
|
||||
a member benefit. Add their name, category, description, and logo.
|
||||
- **Benefits → Benefits** — the actual discount/perk, linked to one or
|
||||
more **Membership Tiers** (only members holding one of those tiers will
|
||||
see it). Set the discount type (percent / fixed amount / perk) and
|
||||
validity dates.
|
||||
- **Benefits → Redemptions** — a log a benefit centre (or staff) creates
|
||||
when a member actually uses a benefit, after confirming the member is
|
||||
active. This is mostly for your own record-keeping of usage, not
|
||||
something you need to set up in advance.
|
||||
|
||||
Members see only what their own tier qualifies them for at
|
||||
`/my/benefits`; the public directory of participating centres is at
|
||||
`/benefits`.
|
||||
|
||||
---
|
||||
|
||||
## 9. Interac e-Transfer Payments
|
||||
|
||||
### 9.1 One-time setup
|
||||
|
||||
**Invoicing → Configuration → Online Payments → Payment Providers** →
|
||||
open **Interac e-Transfer**:
|
||||
|
||||
- **Interac Recipient Email** — the real e-transfer address payments
|
||||
should be sent to.
|
||||
- **Interac Deadline Hours** — how long an unconfirmed payment stays
|
||||
pending before it's automatically cancelled (defaults to 48 hours if
|
||||
left blank).
|
||||
- Set the provider's **State** to **Enabled** so it appears as a
|
||||
checkout option.
|
||||
|
||||
### 9.2 Day-to-day (Treasurer role)
|
||||
|
||||
When someone chooses Interac at checkout, they're emailed instructions
|
||||
(recipient address, amount, a reference code, and the deadline) — this
|
||||
happens automatically, nothing for you to send.
|
||||
|
||||
Once you actually receive the e-transfer in your real bank/e-transfer
|
||||
account, go to **Interac Payments → Pending Payments**, find the matching
|
||||
transaction (match by amount and reference code), and click **Payment
|
||||
Received**. This confirms the linked invoice/registration/order. If
|
||||
nobody confirms it before the deadline, it auto-cancels and the payer is
|
||||
notified by email.
|
||||
|
||||
---
|
||||
|
||||
## 10. Website content
|
||||
|
||||
**Website** app, then click **Edit** on any page while viewing it on the
|
||||
public site to change text, images, and layout directly (drag-and-drop
|
||||
editor) — no code involved for routine copy changes. **Site → Menu
|
||||
Editor** lets you add, remove, or reorder navigation items.
|
||||
|
||||
Two things worth knowing about the current site before you edit it:
|
||||
|
||||
- The **Sponsors** page and a few header/footer text blocks (e.g. a
|
||||
placeholder phone number) still contain placeholder content carried
|
||||
over from the original site design — safe to edit or delete through
|
||||
the Website editor whenever real sponsor logos or a real phone number
|
||||
are ready.
|
||||
- **"Become a Member" buttons currently point to the Contact page**, not
|
||||
a self-service signup form — TNCSC doesn't have public online
|
||||
membership signup yet (only renewal, for existing members). Don't
|
||||
redirect these to a form that doesn't exist; talk to your technical
|
||||
contact if/when online signup becomes a priority.
|
||||
|
||||
For anything beyond content edits — new page types, new sections with
|
||||
custom behaviour, structural changes — that's a developer task, not a
|
||||
Website-editor task.
|
||||
|
||||
---
|
||||
|
||||
## 11. Accounting basics
|
||||
|
||||
The chart of accounts, tax setup, and journals were seeded for a Canadian
|
||||
non-profit when the system was set up, including dedicated revenue
|
||||
accounts (Membership Dues, Event Revenue, Sponsorship, School Fees,
|
||||
Donations) and a **Donations** journal. You generally don't need to
|
||||
create new accounts for normal operations — membership tiers, event
|
||||
tickets, and school fees are already wired to the right ones.
|
||||
|
||||
**Do not** rename or delete existing accounts, or change the company's
|
||||
currency/country, without your accountant and technical contact both
|
||||
signing off — several of these are load-bearing for other parts of the
|
||||
system (e.g. renaming the dues account could silently break where
|
||||
membership payments post to). Day-to-day invoicing/payment work happens
|
||||
under the **Invoicing** app as normal.
|
||||
|
||||
---
|
||||
|
||||
## 12. Troubleshooting & getting help
|
||||
|
||||
| Symptom | Likely cause / fix |
|
||||
|---|---|
|
||||
| An app I should have access to isn't in my switcher | You're missing the matching role — see [section 2](#2-user-roles--who-can-do-what). Ask a Board Admin to check the box for you. |
|
||||
| I changed a setting and nothing changed on the site | Make sure you clicked **Save**. If it still looks wrong after a minute, it may need a technical restart — contact support rather than repeating the change. |
|
||||
| A member says their QR card doesn't work | Check their membership **state** on their member record — the verify page only shows "valid" for members currently in the *active* state. |
|
||||
| An event isn't showing on the website | Confirm **Is Published** is checked on the event (see [section 5](#5-events)) — unpublished events are invisible on the public site by design. |
|
||||
| A parent can't register for a class | Check the term is **Open** and the class isn't already full (School → Classes) — full classes waitlist automatically rather than blocking registration outright. |
|
||||
| An Interac payment doesn't confirm | Double-check the reference code and amount match exactly before clicking Payment Received — mismatches usually mean it's a different transaction. |
|
||||
|
||||
For anything not covered here — a genuine error message, something that
|
||||
looks broken rather than misconfigured, or a request for new
|
||||
functionality — contact your technical support contact rather than
|
||||
experimenting on the live site. Screenshots and the exact steps you took
|
||||
help them fix it faster.
|
||||
|
||||
---
|
||||
|
||||
*This handbook covers the CommunityOS suite as configured for TNCSC. It
|
||||
does not cover server maintenance, backups, or deployment — those remain
|
||||
your technical contact's responsibility.*
|
||||