{
  "run_id": "T4-W05-20260831T090757Z",
  "overlay_version": "gt-w05-1.0",
  "fixture_base": "gt-core-b1.1",
  "certified_claim": false,
  "pass": true,
  "total": 16,
  "passed": 16,
  "failed": 0,
  "skipped": 0,
  "backend_sha": "cc2593eaa9cc5577be081129d9cdd8b5cea1e680",
  "frontend_sha": "2e78ebbba5472a762cb0f6e0383310200122355c",
  "ctx_ids": {
    "session_a": 335,
    "session_b": 336,
    "session_t2": 337,
    "student_a": 413,
    "student_b": 418,
    "student_t2": 419,
    "batch_a": 217,
    "batch_b": 218,
    "today": "2026-08-31",
    "sheet_a_id": 192,
    "sheet_b_id": 193
  },
  "seed": {
    "today": "2026-08-31",
    "faculty_a": 19,
    "faculty_b": 20,
    "faculty_t2": 21,
    "session_a": 335,
    "session_b": 336,
    "session_t2": 337,
    "batch_a": 217,
    "batch_b": 218,
    "batch_t2": 219,
    "student_a": 413,
    "student_b": 418,
    "student_t2": 419,
    "used_existing_session_a": false,
    "per_lesson_c20": true,
    "per_lesson_c22": true
  },
  "cleanup": {
    "sessions": 5,
    "correction_logs": 0,
    "sheets": 5,
    "lines": 5,
    "students": 2,
    "faculties": 0,
    "users_deactivated": 0,
    "partners": 2,
    "batches": 3,
    "registers": 3,
    "years": 1,
    "courses": 2,
    "subjects": 2
  },
  "cases": [
    {
      "case_id": "W05-CREATE-OK",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "POST /api/v1/attendance/faculty/session-sheet/save Student A Hadir",
      "expected": "sheet done, one per_lesson line, company 20",
      "actual": {
        "result": {
          "success": true,
          "data": {
            "session": {
              "id": 335,
              "batch": "W05 7A 90757Z",
              "subject": "W05 Matematika 90757Z",
              "batch_id": 217,
              "time": "09:00 - 09:45",
              "attendance_sheet_id": 192,
              "is_submitted": true,
              "state": "done"
            },
            "summary": {
              "present": 1,
              "excused": 0,
              "absent": 0,
              "late": 0
            },
            "students": [
              {
                "id": 413,
                "line_id": 164,
                "name": "GT Student S1",
                "nsn": "9059000443",
                "present": true,
                "late": false,
                "excused": false,
                "absent": false,
                "status": "Hadir",
                "remark": "Hadir",
                "proof_file": null,
                "proof_filename": null,
                "permit_status": null,
                "has_approved_leave": false,
                "leave_request_name": null,
                "permit_id": null,
                "permit_evidence_url": null,
                "permit_evidence_filename": null
              }
            ]
          }
        },
        "after": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": true,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": "Hadir"
        }
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 164,
        "present": true,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": "Hadir"
      },
      "notes": ""
    },
    {
      "case_id": "W05-UPDATE-OK",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "resave Present→Alpa on same sheet",
      "expected": "still one line; flags changed to absent",
      "actual": {
        "result": {
          "success": true,
          "data": {
            "session": {
              "id": 335,
              "batch": "W05 7A 90757Z",
              "subject": "W05 Matematika 90757Z",
              "batch_id": 217,
              "time": "09:00 - 09:45",
              "attendance_sheet_id": 192,
              "is_submitted": true,
              "state": "done"
            },
            "summary": {
              "present": 0,
              "excused": 0,
              "absent": 1,
              "late": 0
            },
            "students": [
              {
                "id": 413,
                "line_id": 164,
                "name": "GT Student S1",
                "nsn": "9059000443",
                "present": false,
                "late": false,
                "excused": false,
                "absent": true,
                "status": "Alpa",
                "remark": "Alpa",
                "proof_file": null,
                "proof_filename": null,
                "permit_status": null,
                "has_approved_leave": false,
                "leave_request_name": null,
                "permit_id": null,
                "permit_evidence_url": null,
                "permit_evidence_filename": null
              }
            ]
          }
        },
        "before": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": true,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": "Hadir"
        },
        "after": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": false,
          "late": false,
          "excused": false,
          "absent": true,
          "remark": "Alpa"
        }
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 164,
        "present": true,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": "Hadir"
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 164,
        "present": false,
        "late": false,
        "excused": false,
        "absent": true,
        "remark": "Alpa"
      },
      "notes": ""
    },
    {
      "case_id": "W05-DUP-RETRY",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "save twice same payload",
      "expected": "unique(student,sheet,date); one sheet",
      "actual": {
        "first": true,
        "second": true,
        "after": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": false,
          "late": false,
          "excused": false,
          "absent": true,
          "remark": "Alpa"
        }
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 164,
        "present": false,
        "late": false,
        "excused": false,
        "absent": true,
        "remark": "Alpa"
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 164,
        "present": false,
        "late": false,
        "excused": false,
        "absent": true,
        "remark": "Alpa"
      },
      "notes": ""
    },
    {
      "case_id": "W05-TEACHER-FOREIGN-SESSION",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "save on Teacher B session_id",
      "expected": "denied; no write",
      "actual": {
        "success": false,
        "error": "session_not_found",
        "message": "Sesi kehadiran tidak ditemukan.",
        "message_key": "api.attendance.session_not_found"
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "notes": ""
    },
    {
      "case_id": "W05-TEACHER-FOREIGN-STUDENT",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "save Student B on Teacher A session",
      "expected": "invalid_student; no line for B",
      "actual": {
        "success": false,
        "error": "invalid_student",
        "message": "Siswa di luar rombel sesi.",
        "message_key": "api.attendance.invalid_student"
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 192,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "notes": ""
    },
    {
      "case_id": "W05-TEACHER-FORGED-SHEET",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "supply attendance_sheet_id from session B on session A save",
      "expected": "denied; session A unchanged",
      "actual": {
        "own_save": {
          "success": true,
          "data": {
            "session": {
              "id": 336,
              "batch": "W05 7B 90757Z",
              "subject": "CM",
              "batch_id": 218,
              "time": "10:00 - 10:45",
              "attendance_sheet_id": 193,
              "is_submitted": true,
              "state": "done"
            },
            "summary": {
              "present": 1,
              "excused": 0,
              "absent": 0,
              "late": 0
            },
            "students": [
              {
                "id": 418,
                "line_id": 165,
                "name": "W05-StudentB 90757Z",
                "nsn": "9050907502",
                "present": true,
                "late": false,
                "excused": false,
                "absent": false,
                "status": "Hadir",
                "remark": "Hadir",
                "proof_file": null,
                "proof_filename": null,
                "permit_status": null,
                "has_approved_leave": false,
                "leave_request_name": null,
                "permit_id": null,
                "permit_evidence_url": null,
                "permit_evidence_filename": null
              }
            ]
          }
        },
        "forged": {
          "success": false,
          "error": "session_not_found",
          "message": "Sesi kehadiran tidak ditemukan.",
          "message_key": "api.attendance.session_not_found"
        },
        "sheet_b_id": 193
      },
      "before_state": {
        "session_a": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": false,
          "late": false,
          "excused": false,
          "absent": true,
          "remark": "Alpa"
        },
        "session_b": {
          "session_company": 20,
          "sheet_id": false,
          "sheet_state": false,
          "sheet_count": 0,
          "line_count_session": 0,
          "line_count_student": 0,
          "line_id": false,
          "present": false,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": false
        }
      },
      "after_state": {
        "session_a": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": false,
          "late": false,
          "excused": false,
          "absent": true,
          "remark": "Alpa"
        },
        "session_b": {
          "session_company": 20,
          "sheet_id": 193,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 165,
          "present": true,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": "Hadir"
        }
      },
      "notes": ""
    },
    {
      "case_id": "W05-TEACHER-READ-OTHER",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "POST /api/v1/attendance/faculty/session-sheet for Teacher B session",
      "expected": "denied / session_not_found",
      "actual": {
        "success": false,
        "error": "session_not_found",
        "message": "Sesi kehadiran tidak ditemukan.",
        "message_key": "api.attendance.session_not_found"
      },
      "before_state": null,
      "after_state": null,
      "notes": ""
    },
    {
      "case_id": "W05-ADMIN-CREATE-OK",
      "status": "PASS",
      "actor": "gt.school_admin",
      "precondition": null,
      "action": "POST /api/v1/attendance/admin/sheet/create own session",
      "expected": "sheet done with one line company 20",
      "actual": {
        "result": {
          "success": true,
          "data": {
            "attendance_sheet_id": 194,
            "students_count": 1
          }
        },
        "after": {
          "session_company": 20,
          "sheet_id": 194,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 166,
          "present": true,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": false
        }
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 194,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 166,
        "present": true,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "notes": ""
    },
    {
      "case_id": "W05-XTENANT-SESSION",
      "status": "PASS",
      "actor": "gt.teacher.assigned + gt.school_admin",
      "precondition": null,
      "action": "T1 teacher/admin save T2 session; T2 admin control",
      "expected": "T1 denied; no line until T2 admin",
      "actual": {
        "teacher": {
          "success": false,
          "error": "session_not_found",
          "message": "Sesi kehadiran tidak ditemukan.",
          "message_key": "api.attendance.session_not_found"
        },
        "admin": {
          "success": false,
          "error": "not_found",
          "message": "Register atau sesi tidak ditemukan."
        },
        "t2_admin": {
          "success": true,
          "data": {
            "attendance_sheet_id": 195,
            "students_count": 1
          }
        }
      },
      "before_state": {
        "session_company": 22,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "after_t1": {
          "session_company": 22,
          "sheet_id": false,
          "sheet_state": false,
          "sheet_count": 0,
          "line_count_session": 0,
          "line_count_student": 0,
          "line_id": false,
          "present": false,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": false
        },
        "after_t2": {
          "session_company": 22,
          "sheet_id": 195,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 167,
          "present": true,
          "late": false,
          "excused": false,
          "absent": false,
          "remark": false
        }
      },
      "notes": ""
    },
    {
      "case_id": "W05-PARENT-OWN",
      "status": "PASS",
      "actor": "gt.parent.p1",
      "precondition": null,
      "action": "POST /api/v1/attendance/parent/daily linked child",
      "expected": "daily payload includes per_lesson sessions for child A",
      "actual": {
        "bind": {
          "parent_id": 301,
          "student_id": 413
        },
        "success": true,
        "session_count": 2,
        "subjects": [
          "W05 Matematika 90757Z",
          "W05 Matematika 90757Z"
        ],
        "attendance_snap": {
          "session_company": 20,
          "sheet_id": 192,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 164,
          "present": false,
          "late": false,
          "excused": false,
          "absent": true,
          "remark": "Alpa"
        }
      },
      "before_state": null,
      "after_state": null,
      "notes": ""
    },
    {
      "case_id": "W05-PARENT-PEER",
      "status": "PASS",
      "actor": "gt.parent.p1",
      "precondition": null,
      "action": "POST /api/v1/attendance/parent/daily peer child B",
      "expected": "denied for unlinked same-tenant child",
      "actual": {
        "success": false,
        "error": "student_not_found",
        "message": "Siswa tidak ditemukan untuk akun orang tua ini.",
        "message_key": "api.attendance.parent_student_not_found"
      },
      "before_state": null,
      "after_state": null,
      "notes": ""
    },
    {
      "case_id": "W05-STUDENT-SELF",
      "status": "PASS",
      "actor": "gt.student.s1",
      "precondition": null,
      "action": "POST /api/v1/attendance/student/daily own profile",
      "expected": "success with own daily payload (sessions may be empty)",
      "actual": {
        "link": {
          "uid": 443,
          "student_id": 413
        },
        "success": true,
        "error": null,
        "session_count": 2
      },
      "before_state": null,
      "after_state": null,
      "notes": ""
    },
    {
      "case_id": "W05-STUDENT-PEER",
      "status": "PASS",
      "actor": "gt.student.s1",
      "precondition": null,
      "action": "RPC search_read peer lines + own daily",
      "expected": "no peer line exposure via RPC; own daily succeeds",
      "actual": {
        "rpc_error": false,
        "rpc_exposed": false,
        "rpc_result_len": 0,
        "daily_success": true,
        "daily_error": null
      },
      "before_state": null,
      "after_state": null,
      "notes": ""
    },
    {
      "case_id": "W05-RPC-TEACHER-CREATE-LINE",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "call_kw op.attendance.line.create",
      "expected": "denied or no unauthorized row",
      "actual": {
        "http": 200,
        "error": true,
        "result": null
      },
      "before_state": {
        "count": 1
      },
      "after_state": {
        "count": 1
      },
      "notes": ""
    },
    {
      "case_id": "W05-CONCURRENT-SAVE",
      "status": "PASS",
      "actor": "gt.teacher.assigned x2",
      "precondition": null,
      "action": "concurrent save Hadir vs Alpa same student/session",
      "expected": "deterministic end state: exactly one line",
      "actual": {
        "results": [
          {
            "success": false,
            "error": "odoo_server_error",
            "message": "The operation cannot be completed: Sheet must be unique per Register/Session.",
            "exception": "odoo.exceptions.ValidationError"
          },
          {
            "success": true,
            "data": {
              "session": {
                "id": 339,
                "batch": "W05 7A 90757Z",
                "subject": "W05 Matematika 90757Z",
                "batch_id": 217,
                "time": "15:00 - 15:45",
                "attendance_sheet_id": 196,
                "is_submitted": true,
                "state": "done"
              },
              "summary": {
                "present": 0,
                "excused": 0,
                "absent": 1,
                "late": 0
              },
              "students": [
                {
                  "id": 413,
                  "line_id": 168,
                  "name": "GT Student S1",
                  "nsn": "9059000443",
                  "present": false,
                  "late": false,
                  "excused": false,
                  "absent": true,
                  "status": "Alpa",
                  "remark": "Alpa",
                  "proof_file": null,
                  "proof_filename": null,
                  "permit_status": null,
                  "has_approved_leave": false,
                  "leave_request_name": null,
                  "permit_id": null,
                  "permit_evidence_url": null,
                  "permit_evidence_filename": null
                }
              ]
            }
          }
        ],
        "after": {
          "session_company": 20,
          "sheet_id": 196,
          "sheet_state": "done",
          "sheet_count": 1,
          "line_count_session": 1,
          "line_count_student": 1,
          "line_id": 168,
          "present": false,
          "late": false,
          "excused": false,
          "absent": true,
          "remark": "Alpa"
        }
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 196,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 168,
        "present": false,
        "late": false,
        "excused": false,
        "absent": true,
        "remark": "Alpa"
      },
      "notes": ""
    },
    {
      "case_id": "W05-COMBINED-OR-SINGLE-POLICY",
      "status": "PASS",
      "actor": "gt.teacher.assigned",
      "precondition": null,
      "action": "single-session partial roster save (subset students)",
      "expected": "partial upsert OK for allowed students; not full-roster required",
      "actual": {
        "setup": {
          "cleared": true
        },
        "batch_roster_size": 1,
        "saved_lines": 1,
        "policy": "single_session_partial_upsert_observed",
        "combined_session_full_roster_required": false
      },
      "before_state": {
        "session_company": 20,
        "sheet_id": false,
        "sheet_state": false,
        "sheet_count": 0,
        "line_count_session": 0,
        "line_count_student": 0,
        "line_id": false,
        "present": false,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": false
      },
      "after_state": {
        "session_company": 20,
        "sheet_id": 198,
        "sheet_state": "done",
        "sheet_count": 1,
        "line_count_session": 1,
        "line_count_student": 1,
        "line_id": 169,
        "present": true,
        "late": false,
        "excused": false,
        "absent": false,
        "remark": "Hadir"
      },
      "notes": "Combined sessions require full canonical roster; single session accepts subset."
    }
  ]
}
