[CLAUDE] App+Api+Docs: Chunk E1 — List endpoint + Bypass-review + Notify TPB + chốt session 8
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m15s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m15s
3 endpoint mới + Notify TPB + Docs update để chốt session 8.
Application:
- PurchaseEvaluationDepartmentApprovalFeatures.cs (NEW):
* ListPeDepartmentApprovalsQuery + DTO PeDepartmentApprovalDto
* Join Departments (lấy Name) + lookup Users.FullName denorm cho FE timeline
- UserFeatures.cs: SetUserBypassReviewCommand + Handler dùng UserManager.UpdateAsync
- IApplicationDbContext: thêm DbSet<User> Users + DbSet<Role> Roles (cần cho lookup)
Api:
- PurchaseEvaluationsController: GET /api/purchase-evaluations/{id}/department-approvals
- UsersController: PATCH /api/users/{id}/bypass-review (Authorize Users.Update)
Infra:
- PurchaseEvaluationWorkflowService: notify TPB cùng dept khi NV review.
Query db.Users.Where(DeptId match + IsActive) → UserManager.GetRolesAsync
filter DeptManager → notifications.NotifyAsync. Best effort fail non-critical.
Docs:
- STATUS.md: Recently Done thêm row session 8 + Phase header update
count 52→55 tables, 15→16 migrations, 128→131 endpoints
- HANDOFF.md: TL;DR session 8 + 8 cảnh báo session 9 (FE chưa làm,
test flow anh Kiệt, smart reject test, lock edit test, ...)
- migration-todos.md: Phase 9 done section đầy đủ 3 ràng buộc + pending Chunk E-bis
- CLAUDE.md: count 52→55 + migration 16 description
- session log: 2026-05-04-1230-chot-session-8-2-stage-dept-approval.md (full report)
Verify final:
- Build pass 0 warning 0 error
- 77 unit test pass (54 Domain + 23 Infra)
- Migration 16 applied LocalDB OK + schema verified
Total session 8 cumulative: 5 commit per-chunk:
- 5fe61cc (A: Migration 16 schema)
- 14f3c9f (B: Lock edit guards 17 handler)
- 9747f8c (C: Smart reject + Resume 3 module)
- a532ba6 (D: PE 2-stage logic)
- (current E1: List + Notify + Bypass + Docs)
Pending Chunk E-bis (defer cho session 9 sau UAT PE):
- FE Workflow Panel hiển thị 2-stage timeline
- FE UserManager toggle CanBypassReview
- HĐ + Budget 2-stage extension
- Tests Phase 3 mini cho 2-stage Service-layer logic
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -157,6 +157,35 @@ Session log: `2026-04-28-chot-session-4-budget.md`.
|
||||
|
||||
## 📝 Phase 9 — UAT + Ops + carry over (Session 6+ active)
|
||||
|
||||
### ✅ Session 8 done (2026-05-04) — Migration 16: 2-stage dept approval + smart reject + lock edit
|
||||
|
||||
**Bối cảnh:** Anh Kiệt (FDC) báo bug PE workflow: NV.PRO tạo phiếu → duyệt được hết phase. Phân quyền sai vì policy chỉ check role, không check Stage 2-cấp.
|
||||
|
||||
**3 ràng buộc gộp 1 migration:**
|
||||
|
||||
- [x] **Lock edit khi Phase != DangSoanThao** — 17 handler thêm guard (Contract Detail × 15 qua helper `EnsureContractType`, PE Detail × 5 qua helper mới `PurchaseEvaluationDraftGuard`, Budget Detail × 3 inline). KHÔNG lock Comment + Attachment + Opinion (workflow design intent).
|
||||
- [x] **Smart reject + Resume** — `Decision=Reject` → `entity.RejectedFromPhase = currentPhase` + force `targetPhase=DangSoanThao`. Resume: `Drafter trình từ DangSoanThao + RejectedFromPhase != null → jump tới phase đã reject + clear field`. Bypass policy guard ở resume.
|
||||
- [x] **2-stage dept approval (PE only v1)** — User.DepartmentId != null + role guard:
|
||||
- DeptManager (TPB) → Stage=Confirm trực tiếp
|
||||
- User.CanBypassReview=true → Stage=Confirm + IsBypassed=true
|
||||
- Else (NV) → Stage=Review only, BLOCK transition cho đến khi TPB confirm
|
||||
- Schema: 3 bảng `*DepartmentApprovals` UNIQUE (TargetId, Phase, Dept, Stage)
|
||||
|
||||
- [x] **Migration 16** `AddTwoStageDeptApprovalAndSmartReject` — 4 ALTER + 3 CREATE TABLE + 12 indexes + FK Cascade
|
||||
- [x] **Endpoint mới**: `GET /api/purchase-evaluations/{id}/department-approvals` (List), `PATCH /api/users/{id}/bypass-review` (toggle)
|
||||
- [x] **Notify TPB cùng dept** khi NV review (best effort, fail non-critical)
|
||||
- [x] **Verify**: Build pass + 77 test pass + Migration applied LocalDB OK + schema verified qua sqlcmd
|
||||
- [x] 5 commit per-chunk: `5fe61cc` (A) · `14f3c9f` (B) · `9747f8c` (C) · `a532ba6` (D) · current (E1)
|
||||
|
||||
Session log: `2026-05-04-1230-chot-session-8-2-stage-dept-approval.md`.
|
||||
|
||||
**Pending Chunk E-bis (defer):**
|
||||
- [ ] FE Workflow Panel hiển thị progress 2-stage timeline
|
||||
- [ ] FE UserManager toggle `CanBypassReview` checkbox
|
||||
- [ ] HĐ 2-stage mở rộng (`ContractWorkflowService` thêm 2-stage logic + endpoint List)
|
||||
- [ ] Budget 2-stage mở rộng (low priority)
|
||||
- [ ] Tests 2-stage logic Service-layer (cần UserManager DI helper)
|
||||
|
||||
### ✅ Session 6 done (2026-04-30 — pure docs work)
|
||||
|
||||
- [x] **MD audit + compact** — STATUS -27%, HANDOFF -32%, migration-todos -35%, archive 51 row Phase 0-7 cũ
|
||||
|
||||
@ -0,0 +1,273 @@
|
||||
# Session log — 2026-05-04 chốt session 8 — 2-stage dept approval + smart reject + lock edit
|
||||
|
||||
**Topic:** Migration 16 đóng bug anh Kiệt (FDC) báo: "tạo NV.PRO mới + tạo phiếu PE + duyệt gì duyệt được hết = phân quyền sai". Schema + logic 2-stage approval + smart reject + lock edit guards.
|
||||
|
||||
**Dev:** Claude (Opus 4.7) + user (pqhuy1987@gmail.com)
|
||||
**Duration:** ~5 giờ (gồm Chunk A-D + verify LocalDB + Chunk E1 BE).
|
||||
**Base commit:** `dfb43fc` (chốt session 7).
|
||||
|
||||
## Bối cảnh
|
||||
|
||||
User chia sẻ screenshot chat FDC-Anh Kiệt (Zalo):
|
||||
- Anh Kiệt: "tạo tài khoản mới với vai trò là nhân viên, tạo phiếu mới, duyệt gì duyệt được hết — do anh phân quyền ko đúng hay sao em? user long.chau"
|
||||
- User: "để e check" + "thêm 1 tầng nữa"
|
||||
|
||||
Ngầm yêu cầu: thêm 2-cấp duyệt mỗi phòng ban (NV Review → TPB Confirm) + setting bypass cho NV.
|
||||
|
||||
Cộng thêm 2 ràng buộc khác:
|
||||
- "khi đưa lên duyệt thì không thay đổi được thông tin được nhé"
|
||||
- "khi nào reject điều chỉnh lại thì trả về người trình và quay lại bước duyệt"
|
||||
|
||||
## Approach final (sau 4 vòng iterate plan)
|
||||
|
||||
User đề xuất "tách bảng riêng để lưu trạng thái duyệt của từng phòng ban" — đây là cách hay hơn 3 option Claude đề xuất ban đầu vì:
|
||||
- KHÔNG touch workflow versioned hiện tại
|
||||
- KHÔNG cần migrate HĐ/PE cũ
|
||||
- Pattern mirror `PurchaseEvaluationDepartmentOpinion` (Migration 15) đã proven
|
||||
|
||||
3 ràng buộc gộp vào 1 migration để rollback atomic.
|
||||
|
||||
## Commits session 8
|
||||
|
||||
5 commit per-chunk theo plan:
|
||||
|
||||
- `5fe61cc` — Chunk A: Migration 16 schema (Domain + Infra)
|
||||
- `14f3c9f` — Chunk B: Lock edit guards 17 handler (App)
|
||||
- `9747f8c` — Chunk C: Smart reject + Resume after reject (3 module)
|
||||
- `a532ba6` — Chunk D: PE 2-stage dept approval logic (Infra)
|
||||
- (current) — Chunk E1: BE List endpoint + Notify TPB + Bypass-review toggle + Docs
|
||||
|
||||
## A. Schema — Migration 16
|
||||
|
||||
### 4 ALTER + 3 CREATE TABLE
|
||||
|
||||
```sql
|
||||
-- Smart reject (3 bảng)
|
||||
ALTER Contracts ADD RejectedFromPhase int NULL
|
||||
ALTER PurchaseEvaluations ADD RejectedFromPhase int NULL
|
||||
ALTER Budgets ADD RejectedFromPhase int NULL
|
||||
|
||||
-- Bypass per-user
|
||||
ALTER Users ADD CanBypassReview bit NOT NULL DEFAULT 0
|
||||
|
||||
-- 3 bảng DepartmentApprovals (mirror schema)
|
||||
CREATE TABLE ContractDepartmentApprovals (...)
|
||||
CREATE TABLE PurchaseEvaluationDepartmentApprovals (...)
|
||||
CREATE TABLE BudgetDepartmentApprovals (...)
|
||||
UNIQUE (TargetId, PhaseAtApproval, DepartmentId, Stage)
|
||||
Columns: ApproverUserId, ApproverRoleSnapshot, Comment, ApprovedAt,
|
||||
IsBypassed bit + AuditableEntity (CreatedAt/By/...)
|
||||
```
|
||||
|
||||
### Domain entities mới
|
||||
|
||||
- `Common/ApprovalStage` enum (1=Review NV, 2=Confirm TPB)
|
||||
- `Contracts/ContractDepartmentApproval`
|
||||
- `PurchaseEvaluations/PurchaseEvaluationDepartmentApproval`
|
||||
- `Budgets/BudgetDepartmentApproval`
|
||||
|
||||
LƯU Ý: KHÁC `PurchaseEvaluationDepartmentOpinion` (Migration 15) — Opinion là sign-off block "Ý kiến 4 phòng ban" trên header phiếu. DepartmentApproval mới là 2-stage approval workflow per phase.
|
||||
|
||||
## B. Lock edit guards — 17 handler
|
||||
|
||||
| Module | Handler | Pattern |
|
||||
|---|---|---|
|
||||
| Contract | 15 (7 Add + 7 Update Detail × 7 type + 1 Delete) | Helper `EnsureContractType` extended |
|
||||
| PE | 5 (Add/Update/Delete Detail + Upsert/Delete Quote) | Helper mới `PurchaseEvaluationDraftGuard` |
|
||||
| Budget | 3 (Add/Update/Delete Detail) | Inline guard |
|
||||
|
||||
**KHÔNG lock** (intentional, đúng workflow):
|
||||
- Contract Comment (cần được trong DangGopY phase 3)
|
||||
- Contract Attachment Upload/Delete (Drafter scan ký ở DangInKy phase 5)
|
||||
- PE OpinionUpsert (Ý kiến 4 PB là sign-off, có thể nhập sau khi trình)
|
||||
- PE Attachment (báo giá NCC upload xuyên suốt workflow)
|
||||
|
||||
## C. Smart reject + Resume
|
||||
|
||||
### Reject
|
||||
```csharp
|
||||
if (decision == Reject) {
|
||||
entity.RejectedFromPhase = currentPhase; // snapshot phase đang reject
|
||||
targetPhase = DangSoanThao; // force về Drafter
|
||||
}
|
||||
// Approval row: FromPhase=X, ToPhase=DangSoanThao, Decision=Reject
|
||||
```
|
||||
|
||||
### Resume after reject
|
||||
```csharp
|
||||
if (decision == Approve
|
||||
&& fromPhase == DangSoanThao
|
||||
&& entity.RejectedFromPhase != null) {
|
||||
targetPhase = entity.RejectedFromPhase!.Value; // jump straight
|
||||
entity.RejectedFromPhase = null; // clear flag
|
||||
// Skip policy guard (Drafter đã trình lại sau khi sửa)
|
||||
}
|
||||
```
|
||||
|
||||
Approval history giờ track đầy đủ cycle reject→sửa→resume:
|
||||
1. `Approval 1`: DangGopY → DangSoanThao, Decision=Reject (CCM reject)
|
||||
2. (Drafter sửa Header/Detail)
|
||||
3. `Approval 2`: DangSoanThao → DangGopY, Decision=Approve (Drafter resume)
|
||||
|
||||
## D. PE 2-stage dept approval logic
|
||||
|
||||
**Logic flow trong `PurchaseEvaluationWorkflowService.TransitionAsync`:**
|
||||
|
||||
1. Detect approving phase với role thuộc phòng ban:
|
||||
- `decision == Approve` + `target != DangSoanThao && != TuChoi`
|
||||
- Không reject + không resume + không admin/system
|
||||
- `actorUserId != null` + `actor.DepartmentId != null`
|
||||
|
||||
2. Stage detection:
|
||||
- `DeptManager` (TPB) → `Stage=Confirm` trực tiếp
|
||||
- `User.CanBypassReview=true` → `Stage=Confirm` + `IsBypassed=true`
|
||||
- Else (NV) → `Stage=Review` only
|
||||
|
||||
3. Upsert `PurchaseEvaluationDepartmentApproval` row (UNIQUE (PEId, Phase, Dept, Stage))
|
||||
|
||||
4. Check `Stage=Confirm` tồn tại cho `(PEId, fromPhase, deptId)`:
|
||||
- Yes → tiếp tục normal phase transition logic (phase đổi)
|
||||
- No → BLOCK transition:
|
||||
* Insert PEApproval row (FromPhase=ToPhase=fromPhase, Decision=Approve, Comment="[Review NV] ...")
|
||||
* Insert Changelog "NV X đã review phase Y, chờ TPB confirm"
|
||||
* Notify TPB cùng dept (best effort)
|
||||
* Return early — Phase KHÔNG đổi
|
||||
|
||||
5. Skip 2-stage hoàn toàn khi:
|
||||
- Decision=Reject (Chunk C đã handle)
|
||||
- Resume after reject (target đã pinned)
|
||||
- Admin role hoặc System (auto-approve)
|
||||
- actorUserId == null hoặc actor.DepartmentId == null
|
||||
|
||||
### Bug fix verified theo flow anh Kiệt
|
||||
- User `long.chau` (NV.PRO, role=Procurement, DepartmentId=PRO) duyệt phase ChoPurchasing:
|
||||
- role=Procurement (không có DeptManager) → Stage=Review
|
||||
- hasConfirm=false → BLOCK transition ✅
|
||||
- TPB.PRO (`tra.bui` có role DeptManager + DeptId=PRO) duyệt:
|
||||
- role=DeptManager → Stage=Confirm
|
||||
- hasConfirm=true → ALLOW transition ✅
|
||||
|
||||
## E. Endpoint mới
|
||||
|
||||
### List PE Department Approvals
|
||||
```http
|
||||
GET /api/purchase-evaluations/{id}/department-approvals
|
||||
Response: List<PeDepartmentApprovalDto> (Id, PhaseAtApproval, DepartmentId,
|
||||
DepartmentName, Stage, ApproverUserId, ApproverName,
|
||||
ApproverRoleSnapshot ("TPB"/"NV"/"NV(bypass)"), Comment,
|
||||
ApprovedAt, IsBypassed)
|
||||
```
|
||||
|
||||
FE Workflow Panel sẽ render dạng timeline 2-stage progress.
|
||||
|
||||
### Set User Bypass Review
|
||||
```http
|
||||
PATCH /api/users/{id}/bypass-review
|
||||
Body: { canBypassReview: true|false }
|
||||
[Authorize(Policy = "Users.Update")]
|
||||
```
|
||||
|
||||
Admin toggle cho 1 user. Khi `true`, NV được duyệt thay TPB ở 2-stage (skip Stage Review, đẩy thẳng Stage Confirm).
|
||||
|
||||
## F. Notify TPB cùng dept
|
||||
|
||||
Khi NV insert `Stage=Review` mà chưa có Confirm → service query `db.Users` filter `DepartmentId == deptId && IsActive`, dùng `UserManager.GetRolesAsync` filter role `DeptManager`, push notification "Phiếu chờ TPB confirm" (best effort, fail non-critical).
|
||||
|
||||
## G. Verify thực tế
|
||||
|
||||
```
|
||||
✓ Build pass mỗi commit (2 warning DocxRenderer cũ)
|
||||
✓ 77 unit test pass mỗi commit (54 Domain + 23 Infra)
|
||||
✓ Migration 16 applied LocalDB SolutionErp_Design OK
|
||||
✓ Schema verified qua sqlcmd:
|
||||
- 3 bảng mới: ContractDepartmentApprovals, PEDepartmentApprovals, BudgetDepartmentApprovals
|
||||
- 4 cột mới: Users.CanBypassReview (bit) + 3 RejectedFromPhase (int)
|
||||
✓ API startup không error (warning query filter là pattern intentional)
|
||||
✓ Push 6 commit lên Gitea (2 docs session 7 + 4 code session 8)
|
||||
```
|
||||
|
||||
## H. Files touched session 8
|
||||
|
||||
```
|
||||
src/Backend/SolutionErp.Domain/Common/ApprovalStage.cs (NEW)
|
||||
src/Backend/SolutionErp.Domain/Contracts/ContractDepartmentApproval.cs (NEW)
|
||||
src/Backend/SolutionErp.Domain/PurchaseEvaluations/PurchaseEvaluationDepartmentApproval.cs (NEW)
|
||||
src/Backend/SolutionErp.Domain/Budgets/BudgetDepartmentApproval.cs (NEW)
|
||||
src/Backend/SolutionErp.Domain/Contracts/Contract.cs (mod: +RejectedFromPhase + nav)
|
||||
src/Backend/SolutionErp.Domain/PurchaseEvaluations/PurchaseEvaluation.cs (mod: +RejectedFromPhase + nav)
|
||||
src/Backend/SolutionErp.Domain/Budgets/Budget.cs (mod: +RejectedFromPhase + nav)
|
||||
src/Backend/SolutionErp.Domain/Identity/User.cs (mod: +CanBypassReview)
|
||||
|
||||
src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/
|
||||
20260504051025_AddTwoStageDeptApprovalAndSmartReject.cs (NEW migration)
|
||||
*.Designer.cs + ApplicationDbContextModelSnapshot.cs (3-file rule)
|
||||
src/Backend/SolutionErp.Infrastructure/Persistence/ApplicationDbContext.cs (mod: +3 DbSet)
|
||||
src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/
|
||||
DepartmentApprovalsConfiguration.cs (NEW: 3 config)
|
||||
ContractConfiguration.cs / PurchaseEvaluationConfiguration.cs / BudgetConfiguration.cs
|
||||
(mod: +RejectedFromPhase HasConversion)
|
||||
|
||||
src/Backend/SolutionErp.Application/Common/Interfaces/IApplicationDbContext.cs (mod: +5 DbSet)
|
||||
src/Backend/SolutionErp.Application/Contracts/ContractDetailsFeatures.cs (mod: helper Phase guard)
|
||||
src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationDetailFeatures.cs (mod: helper Phase guard)
|
||||
src/Backend/SolutionErp.Application/Budgets/BudgetFeatures.cs (mod: 3 inline Phase guard + smart reject Budget)
|
||||
src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationDepartmentApprovalFeatures.cs (NEW)
|
||||
src/Backend/SolutionErp.Application/Users/UserFeatures.cs (mod: +SetUserBypassReviewCommand)
|
||||
|
||||
src/Backend/SolutionErp.Infrastructure/Services/ContractWorkflowService.cs (mod: smart reject + resume)
|
||||
src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs (mod: smart reject + 2-stage logic + notify TPB)
|
||||
|
||||
src/Backend/SolutionErp.Api/Controllers/PurchaseEvaluationsController.cs (mod: +1 endpoint)
|
||||
src/Backend/SolutionErp.Api/Controllers/UsersController.cs (mod: +1 endpoint)
|
||||
|
||||
docs/STATUS.md (mod: Recently Done + Phase header)
|
||||
docs/HANDOFF.md (mod: cảnh báo session 9)
|
||||
docs/changelog/migration-todos.md (mod: Phase 9 done section)
|
||||
docs/CLAUDE.md (mod: count 52→55, 15→16)
|
||||
docs/changelog/sessions/2026-05-04-1230-chot-session-8-*.md (NEW: file này)
|
||||
```
|
||||
|
||||
## I. Cảnh báo session 9
|
||||
|
||||
1. **Bug fix anh Kiệt** chỉ áp PE workflow. HĐ + Budget 2-stage scope **defer** cho khi UAT PE OK.
|
||||
2. **FE Workflow Panel** chưa update — workflow vẫn hoạt động đúng (BE block transition khi NV review chưa có TPB confirm), nhưng UX chưa hiển thị 2-stage progress. User test sẽ thấy phase không đổi mà không biết tại sao.
|
||||
3. **FE UserManager toggle CanBypassReview** chưa làm — admin SET qua Postman/curl tạm:
|
||||
```
|
||||
PATCH /api/users/{id}/bypass-review
|
||||
Authorization: Bearer <admin token>
|
||||
Content-Type: application/json
|
||||
{ "canBypassReview": true }
|
||||
```
|
||||
4. **Notify TPB cùng dept** dùng `UserManager.GetRolesAsync` filter `DeptManager`. Cần verify với production user có role DeptManager đúng không.
|
||||
5. **Tests Phase 1 (Domain) chưa update** — không có Domain policy thay đổi. Tests Service-layer 2-stage logic cần `UserManager` + `IDateTime` DI helper, defer Phase 3 mini.
|
||||
6. **Cron audit định kỳ 2026-05-01** đã quá hạn 3 ngày, vẫn EMPTY runtime (CronList trống). Cần manual trigger hoặc recreate cron.
|
||||
|
||||
## J. Lessons learned
|
||||
|
||||
1. **Iterate plan với user trước khi code lớn** — 4 vòng review (Claude propose → user push back "tách bảng riêng") tránh implement sai approach. Schema kết quả simple hơn cả 3 option Claude đề xuất.
|
||||
|
||||
2. **Per-chunk commit pattern** — 5 chunk small commits (A-B-C-D-E1) thay vì 1 commit monolithic giúp:
|
||||
- Build + test pass mỗi chunk → bug khu trú dễ
|
||||
- Rollback granular nếu chunk nào sai
|
||||
- Code review easier (each commit < 100 LOC change)
|
||||
|
||||
3. **Smart reject với jump-back** đơn giản hơn dự đoán — chỉ thêm 1 nullable field `RejectedFromPhase` + 2 if branch trong service. Bypass policy guard ở resume case là key.
|
||||
|
||||
4. **Helper extract pattern (EnsureContractType extend)** — 14 handler share 1 guard logic. DRY + 1 nơi maintain.
|
||||
|
||||
5. **2 file `User` ở 2 namespace** — Domain.Identity.User vs SolutionErp.Domain.Identity.User — cần explicit `Domain.Identity.User` khi disambiguate.
|
||||
|
||||
## K. Stats sau session 8
|
||||
|
||||
| | Trước S8 | Sau S8 |
|
||||
|---|---:|---:|
|
||||
| BE LOC | ~13050 | ~13750 (+700) |
|
||||
| DB tables | 52 | **55** (+3 DepartmentApprovals) |
|
||||
| Migrations | 15 | **16** |
|
||||
| API endpoints | ~128 | **~131** (+3) |
|
||||
| FE pages | ~31 | ~31 (FE chưa update) |
|
||||
| Tests | 77 | 77 (chưa thêm) |
|
||||
| Gotchas | 41 | 41 |
|
||||
| Demo user | 30 | 30 |
|
||||
| Commits S8 | 0 | **5** (A-B-C-D-E1) |
|
||||
| Session log | 18 | **19** |
|
||||
Reference in New Issue
Block a user