Odoo_Dance_SCL/scripts/seed_demo.py
2026-09-28 11:03:02 +05:30

419 lines
15 KiB
Python

# ============================================================
# Rhythm & Grace Dance Academy — DEMO DATA SEED
# Run with: docker exec -i odoo_dance odoo shell -d dance_school_erp \
# --no-http < scripts/seed_demo.py
# ============================================================
import random
from datetime import date, timedelta
random.seed(42)
today = date.today()
PWD = "Dance@2026"
def section(title):
print("\n" + "=" * 60)
print(" " + title)
print("=" * 60)
Employee = env["hr.employee"]
Users = env["res.users"]
Partner = env["res.partner"]
Batch = env["dance.batch"]
Enrollment = env["dance.enrollment"]
Session = env["dance.session"]
Attendance = env["dance.attendance"]
Move = env["account.move"]
Request = env["dance.enrollment.request"]
internal_group = env.ref("base.group_user")
portal_group = env.ref("base.group_portal")
# ------------------------------------------------------------
# 1. TEACHERS — employee + internal user login
# ------------------------------------------------------------
section("TEACHERS")
teacher_specs = [
("Ananya Rao", "ananya.teacher@demo.com", "Senior Bharatanatyam Instructor"),
("Rahul Menon", "rahul.teacher@demo.com", "Hip-Hop Instructor"),
("Sophia Williams", "sophia.teacher@demo.com", "Contemporary Instructor"),
("Meera Iyer", "meera.teacher@demo.com", "Kathak & Zumba Instructor"),
]
teachers = {}
for name, login, title in teacher_specs:
emp = Employee.search([("name", "=", name)], limit=1)
if not emp:
emp = Employee.create({"name": name, "job_title": title})
else:
emp.job_title = title
user = Users.search([("login", "=", login)], limit=1)
if not user:
user = Users.with_context(no_reset_password=True).create(
{
"name": name,
"login": login,
"email": login,
"password": PWD,
"groups_id": [(6, 0, [internal_group.id])],
}
)
if not emp.user_id:
emp.user_id = user.id
if not emp.work_email:
emp.work_email = login
teachers[name] = emp
print(" teacher:", name, "->", login)
env.cr.commit()
# ------------------------------------------------------------
# 2. PARENTS — partner + portal user login
# ------------------------------------------------------------
section("PARENTS")
parent_specs = [
("Priya Sharma", "priya.parent@demo.com", "+1 555 0101"),
("Marcus Johnson", "marcus.parent@demo.com", "+1 555 0102"),
("Aisha Patel", "aisha.parent@demo.com", "+1 555 0103"),
("David Chen", "david.parent@demo.com", "+1 555 0104"),
]
parents = {}
for name, login, phone in parent_specs:
partner = Partner.search([("email", "=", login)], limit=1)
if not partner:
partner = Partner.create(
{"name": name, "email": login, "phone": phone, "is_student": False}
)
user = Users.search([("login", "=", login)], limit=1)
if not user:
user = Users.with_context(no_reset_password=True).create(
{
"name": name,
"login": login,
"email": login,
"password": PWD,
"partner_id": partner.id,
"groups_id": [(6, 0, [portal_group.id])],
}
)
parents[name] = partner
print(" parent:", name, "->", login)
env.cr.commit()
# ------------------------------------------------------------
# 3. STUDENTS
# ------------------------------------------------------------
section("STUDENTS")
student_specs = [
("Diya Sharma", "Priya Sharma", "bharatanatyam", "intermediate", date(2014, 3, 12)),
("Arjun Sharma", "Priya Sharma", "hiphop", "beginner", date(2016, 7, 5)),
("Liam Johnson", "Marcus Johnson", "hiphop", "advanced", date(2011, 1, 22)),
("Emma Johnson", "Marcus Johnson", "contemporary", "intermediate", date(2013, 9, 9)),
("Zara Patel", "Aisha Patel", "kathak", "beginner", date(2017, 5, 2)),
("Aryan Patel", "Aisha Patel", "bharatanatyam", "beginner", date(2015, 11, 30)),
("Lucas Chen", "David Chen", "contemporary", "advanced", date(2010, 6, 18)),
("Mia Chen", "David Chen", "zumba", "intermediate", date(2012, 2, 14)),
]
students = {}
for name, parent_name, style, level, dob in student_specs:
s = Partner.search([("name", "=", name), ("is_student", "=", True)], limit=1)
if not s:
s = Partner.create(
{
"name": name,
"is_student": True,
"guardian_id": parents[parent_name].id,
"guardian_ids": [(4, parents[parent_name].id)],
"dance_style": style,
"level": level,
"date_of_birth": dob,
"student_status": "active",
"join_date": today - timedelta(days=random.randint(120, 600)),
}
)
students[name] = s
print(" student:", name, "(", s.student_code or "-", ") guardian", parent_name)
env.cr.commit()
# ------------------------------------------------------------
# 4. BATCHES
# ------------------------------------------------------------
section("BATCHES")
# name, style, level, teacher, room, start, end, days
batch_specs = [
("Bharatanatyam — Intermediate", "bharatanatyam", "intermediate",
"Ananya Rao", "Studio A", 16.0, 17.5, "Mon/Wed"),
("Hip-Hop — Juniors", "hiphop", "beginner",
"Rahul Menon", "Studio B", 17.5, 18.5, "Tue/Thu"),
("Hip-Hop — Advanced", "hiphop", "advanced",
"Rahul Menon", "Studio B", 18.5, 20.0, "Tue/Thu"),
("Contemporary — All Levels", "contemporary", "intermediate",
"Sophia Williams", "Studio C", 17.0, 18.5, "Wed/Fri"),
("Kathak — Beginners", "kathak", "beginner",
"Meera Iyer", "Studio D", 16.0, 17.0, "Sat"),
("Zumba Fitness", "zumba", "intermediate",
"Meera Iyer", "Studio E", 18.0, 19.0, "Sat"),
]
batch_days = {
"Bharatanatyam — Intermediate": [0, 2],
"Hip-Hop — Juniors": [1, 3],
"Hip-Hop — Advanced": [1, 3],
"Contemporary — All Levels": [2, 4],
"Kathak — Beginners": [5],
"Zumba Fitness": [5],
}
batches = {}
for name, style, level, teacher, room, st, et, days in batch_specs:
b = Batch.search([("name", "=", name)], limit=1)
if not b:
b = Batch.create(
{
"name": name,
"dance_style": style,
"level": level,
"instructor_id": teachers[teacher].id,
"room": room,
"capacity": 16,
"start_date": today - timedelta(days=180),
"end_date": today + timedelta(days=180),
"start_time": st,
"end_time": et,
"schedule_days": days,
"status": "active",
}
)
batches[name] = b
print(" batch:", name, "-", teacher)
env.cr.commit()
# ------------------------------------------------------------
# 5. ENROLLMENTS
# ------------------------------------------------------------
section("ENROLLMENTS")
enroll_map = [
("Diya Sharma", "Bharatanatyam — Intermediate"),
("Diya Sharma", "Contemporary — All Levels"),
("Arjun Sharma", "Hip-Hop — Juniors"),
("Liam Johnson", "Hip-Hop — Advanced"),
("Liam Johnson", "Zumba Fitness"),
("Emma Johnson", "Contemporary — All Levels"),
("Zara Patel", "Kathak — Beginners"),
("Aryan Patel", "Bharatanatyam — Intermediate"),
("Lucas Chen", "Contemporary — All Levels"),
("Mia Chen", "Zumba Fitness"),
("Mia Chen", "Kathak — Beginners"),
]
batch_students = {}
for sname, bname in enroll_map:
s, b = students[sname], batches[bname]
e = Enrollment.search(
[("student_id", "=", s.id), ("batch_id", "=", b.id)], limit=1
)
if not e:
e = Enrollment.create(
{
"student_id": s.id,
"batch_id": b.id,
"status": "active",
"enrollment_date": today - timedelta(days=random.randint(60, 300)),
}
)
batch_students.setdefault(bname, []).append(s)
print(" enrolled:", sname, "in", bname)
env.cr.commit()
# ------------------------------------------------------------
# 6. SESSIONS (6 weeks past .. 3 weeks ahead)
# ------------------------------------------------------------
section("SESSIONS")
sessions_by_batch = {}
created_sessions = 0
for bname, b in batches.items():
days = batch_days[bname]
recs = []
d = today - timedelta(days=42)
horizon = today + timedelta(days=21)
while d <= horizon:
if d.weekday() in days:
existing = Session.search(
[("batch_id", "=", b.id), ("date", "=", d)], limit=1
)
if existing:
recs.append(existing)
else:
status = "completed" if d < today else "scheduled"
try:
rec = Session.create(
{"batch_id": b.id, "date": d, "status": status}
)
recs.append(rec)
created_sessions += 1
except Exception as ex:
print(" ! skipped session", bname, d, "-", ex)
d += timedelta(days=1)
sessions_by_batch[bname] = recs
print(" sessions created:", created_sessions)
env.cr.commit()
# ------------------------------------------------------------
# 7. ATTENDANCE (completed sessions only)
# ------------------------------------------------------------
section("ATTENDANCE")
att_created = 0
for bname, recs in sessions_by_batch.items():
studs = batch_students.get(bname, [])
for sess in recs:
if sess.status != "completed":
continue
for stud in studs:
if Attendance.search(
[("session_id", "=", sess.id), ("student_id", "=", stud.id)],
limit=1,
):
continue
roll = random.random()
status = "present" if roll < 0.82 else ("late" if roll < 0.92 else "absent")
try:
Attendance.create(
{
"session_id": sess.id,
"student_id": stud.id,
"status": status,
}
)
att_created += 1
except Exception as ex:
print(" ! skipped attendance", "-", ex)
# mark completed sessions done
for sess in recs:
if sess.status == "completed" and sess.status != "completed":
pass
print(" attendance records created:", att_created)
env.cr.commit()
# ------------------------------------------------------------
# 8. FEE INVOICES (3 months: 2 paid, current month mixed)
# ------------------------------------------------------------
section("FEE INVOICES")
income = env["account.account"].search([("account_type", "=", "income")], limit=1)
fee_by_level = {"beginner": 80.0, "intermediate": 110.0, "advanced": 140.0}
this_month = today.replace(day=1)
m1 = (this_month - timedelta(days=1)).replace(day=1)
m2 = (m1 - timedelta(days=1)).replace(day=1)
invoice_months = [(m2, True), (m1, True), (this_month, None)] # None = random
paid_count = open_count = 0
for sname, bname in enroll_map:
student, batch = students[sname], batches[bname]
amount = fee_by_level.get(batch.level, 100.0)
for inv_date, pay in invoice_months:
dup = Move.search(
[
("move_type", "=", "out_invoice"),
("partner_id", "=", student.id),
("invoice_date", "=", inv_date),
("dance_batch_id", "=", batch.id),
],
limit=1,
)
if dup:
continue
line = {
"name": "Monthly Tuition — %s" % batch.name,
"quantity": 1,
"price_unit": amount,
"tax_ids": [(6, 0, [])],
}
if income:
line["account_id"] = income.id
try:
move = Move.create(
{
"move_type": "out_invoice",
"partner_id": student.id,
"dance_student_id": student.id,
"dance_batch_id": batch.id,
"invoice_date": inv_date,
"invoice_line_ids": [(0, 0, line)],
}
)
move.action_post()
except Exception as ex:
print(" ! invoice failed", sname, inv_date, "-", ex)
continue
should_pay = pay if pay is not None else (random.random() < 0.5)
if should_pay:
try:
wiz = (
env["account.payment.register"]
.with_context(
active_model="account.move", active_ids=move.ids
)
.create({})
)
wiz.action_create_payments()
paid_count += 1
except Exception as ex:
print(" ! payment failed", sname, "-", ex)
open_count += 1
else:
open_count += 1
env.cr.commit()
print(" invoices paid:", paid_count, " open:", open_count)
# report payment states
states = {}
for mv in Move.search(
[("move_type", "=", "out_invoice"), ("dance_student_id", "!=", False)]
):
states[mv.payment_state] = states.get(mv.payment_state, 0) + 1
print(" invoice payment_state breakdown:", states)
# ------------------------------------------------------------
# 9. WEBSITE ENROLLMENT REQUESTS (approval pipeline demo)
# ------------------------------------------------------------
section("ENROLLMENT REQUESTS")
req_specs = [
("Noah Williams", "Jessica Williams", "jessica.w@example.com",
"+1 555 0201", "hiphop", "beginner", "new"),
("Ava Martinez", "Carlos Martinez", "carlos.m@example.com",
"+1 555 0202", "contemporary", "intermediate", "contacted"),
("Sofia Kapoor", "Anjali Kapoor", "anjali.k@example.com",
"+1 555 0203", "bharatanatyam", "beginner", "approved"),
("Ethan Brown", "Laura Brown", "laura.b@example.com",
"+1 555 0204", "zumba", "intermediate", "new"),
]
for sn, gn, ge, gp, style, lvl, state in req_specs:
if Request.search([("student_name", "=", sn)], limit=1):
continue
r = Request.create(
{
"student_name": sn,
"guardian_name": gn,
"guardian_email": ge,
"guardian_phone": gp,
"dance_style": style,
"preferred_level": lvl,
"message": "Submitted via the website Enroll Now form.",
}
)
if state == "contacted":
r.action_mark_contacted()
elif state == "approved":
r.action_approve()
print(" request:", sn, "[", state, "]", r.reference)
env.cr.commit()
# ------------------------------------------------------------
section("DONE — SUMMARY")
print(" students :", Partner.search_count([("is_student", "=", True)]))
print(" batches :", Batch.search_count([]))
print(" enrollments :", Enrollment.search_count([]))
print(" sessions :", Session.search_count([]))
print(" attendance :", Attendance.search_count([]))
print(" invoices :", Move.search_count(
[("move_type", "=", "out_invoice"), ("dance_student_id", "!=", False)]))
print(" requests :", Request.search_count([]))
print("\n All demo logins use password:", PWD)
env.cr.commit()
print("\nSEED COMPLETE.\n")