docs: add standalone HTML version of the TNCSC handbook
Same content as TNCSC_Handbook.md, styled to match the version published as a shareable Artifact web page. Self-contained (Google Fonts is the only external dependency) so it works opened directly in a browser or served from any static host, without relying on the Artifact platform.
This commit is contained in:
parent
91c4580ae2
commit
35e62e8c61
846
docs/TNCSC_Handbook.html
Normal file
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>
|
||||
Loading…
x
Reference in New Issue
Block a user