Ship three fully-wired admin areas end-to-end with APIs, seeds, tests and docs. Backend (new `encoach_lms_api` addon + existing addons): - Institutional: academic years/terms, departments, admission registers & admissions, courses/batches, lessons, fees (terms + student fees + invoicing with income-account auto-wiring), gradebook (assignments/grades), library, facilities (encoach.asset), student leave, result templates + marksheets (incl. delete-with-cascade). - Support: `encoach.ticket` model + CRUD/assignee routes; payment records derived from `op.student.fees.details` and `account.move`; platform settings backed by `encoach.code` and `ir.config_parameter` (packages + grading config). - Training: `encoach.vocab.item` + `encoach.grammar.rule` (plus progress models) with CRUD, pagination, search/level filters, and upsert-style progress endpoints. Odoo 19 compatibility: `_sql_constraints` replaced with `@api.constrains`; `ValidationError`/`UserError` mapped to HTTP 400. Frontend: - Rewire institutional admin pages (Academic Year Manager, Admissions, Courses, Lessons, Fees, Gradebook, Library, Facilities, Student Leave, Marksheets, Taxonomy, Resources) to real APIs with React Query invalidation and dialogs. - New typed services: `payments.service.ts`, `platformSettings.service.ts`, `training.service.ts`. Updated `fees/gradebook/lms/courseware/taxonomy/ resources/student-progress/generation` services + related types. - Rewrite `VocabularyPage`, `GrammarPage`, `PaymentRecordPage`, `SettingsPage`, `TicketsPage` to consume live data with search/filter/progress/CRUD flows. - New shared components: `TaxonomyCascade`, `MaterialViewer`, `teacher/TeacherLibrary`. - Favicons/branding assets and misc. UX polish across teacher/student pages. Tooling & QA: - Seeders: `seed_demo.py`, `seed_demo_data.py`, `seed_institutional.py` (idempotent, covers institutional + support + training fixtures incl. income-account wiring). - API write-flow test suites: `test_write_flows.py` (institutional), `test_support_flows.py` (support), `test_training_flows.py` (training), `test_ai_full.py`. All suites pass end-to-end. - Docs: add `docs/PROJECT_SUMMARY.md` with per-section scope, artifacts and QA. - `.gitignore`: ignore `pgdata_bak_*/`, `frontend/.vite/`, `frontend/dist/`, `frontend/node_modules/`. Made-with: Cursor
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
import { api } from "@/lib/api-client";
|
|
|
|
export interface RegistrationCode {
|
|
id: number;
|
|
code: string;
|
|
code_type: "individual" | "corporate";
|
|
user_type: "student" | "teacher" | "corporate";
|
|
max_uses: number;
|
|
uses: number;
|
|
used: boolean;
|
|
expiry_date: string;
|
|
created: string;
|
|
entity_id: number | null;
|
|
}
|
|
|
|
export interface GeneratePayload {
|
|
count?: number;
|
|
code_type?: "individual" | "corporate";
|
|
user_type?: "student" | "teacher" | "corporate";
|
|
max_uses?: number;
|
|
expiry_date?: string;
|
|
}
|
|
|
|
export interface PlatformPackage {
|
|
id: number;
|
|
name: string;
|
|
price: number;
|
|
duration: string;
|
|
discount: number;
|
|
}
|
|
|
|
export interface GradingConfig {
|
|
min_score: number;
|
|
max_score: number;
|
|
increment: number;
|
|
}
|
|
|
|
export const platformSettingsService = {
|
|
listCodes: () =>
|
|
api.get<{ items: RegistrationCode[]; total: number }>("/codes"),
|
|
generateCodes: (payload: GeneratePayload) =>
|
|
api.post<{ data: RegistrationCode[]; count: number }>(
|
|
"/codes/generate",
|
|
payload,
|
|
),
|
|
deleteCode: (id: number) => api.delete<{ success: boolean }>(`/codes/${id}`),
|
|
|
|
listPackages: () =>
|
|
api.get<{ items: PlatformPackage[]; total: number }>("/packages"),
|
|
createPackage: (p: Omit<PlatformPackage, "id">) =>
|
|
api.post<PlatformPackage>("/packages", p),
|
|
updatePackage: (id: number, p: Partial<PlatformPackage>) =>
|
|
api.patch<PlatformPackage>(`/packages/${id}`, p),
|
|
deletePackage: (id: number) =>
|
|
api.delete<{ success: boolean }>(`/packages/${id}`),
|
|
|
|
getGrading: () => api.get<GradingConfig>("/grading-config"),
|
|
setGrading: (cfg: GradingConfig) => api.patch<GradingConfig>("/grading-config", cfg),
|
|
};
|