# Commissioning Repositories vs `CODING-STANDARD.md` §9 (proposal only, no code changed)

**Status:** analysis + proposal. No repository has been modified.
**Scope:** the 10 repositories in `Modules/Commissioning/app/Repositories/` only.
**Approved direction:** option (b) — align the Commissioning module, not all 87 repositories.

---

## 1. What the standard says

`AI/RULES/CODING-STANDARD.md` §9:

> Repositories MUST inject the Eloquent model in the constructor and access it only through `$this->model`.
> Do NOT call the model class directly inside repositories.

with `Model::create(...)`, `Model::where(...)`, `Model::query()->paginate()` listed as wrong and
`$this->model->...` as correct. `AI/SKILLS/database-standard/SKILL.md` adds no repository rule.

## 2. What the code actually does

All 10 Commissioning repositories, measured:

| Repository | ctor | `Model::query()` | other `Model::` static | `DB::table()` | `$this->model` |
|---|---|---|---|---|---|
| CommissioningAdjustmentRepository | 0 | 3 | 0 | 0 | 0 |
| CommissioningAllocationRepository | 0 | 5 | 0 | 0 | 0 |
| CommissioningFundRepository | 0 | 4 | 0 | 0 | 0 |
| CommissioningFundUnlockRepository | 0 | 4 | 0 | 0 | 0 |
| CommissioningLedgerRepository | 0 | 4 | 0 | 0 | 0 |
| CommissioningRedistributionRepository | 0 | 3 | 0 | 0 | 0 |
| CommissioningRuleRepository | 0 | 4 | 0 | 0 | 0 |
| CommissioningRunRepository | 0 | 6 | 0 | 0 | 0 |
| CommissioningSettlementRepository | 0 | 3 | 0 | 0 | 0 |
| ContractCommissionConfigurationRepository | 0 | 9 | 0 | 4 | 0 |
| **total** | **0** | **45** | **0** | **4** | **0** |

The module is perfectly consistent with itself: no constructors, every model touched through
`Model::query()`, never a bare `Model::create()`/`Model::where()`. So the actual pattern is
"static entry, builder chain" — a narrower and more uniform habit than the standard's prohibition
suggests, and `ContractCommissionConfigurationRepository` (written during this program) simply
followed its nine siblings.

Codebase-wide, for context: 87 repositories, 14 use `$this->model` (Project 7/26, Attendance 4/11,
Payroll 2/14, Configuration 1/16, Employee 0/20, Commissioning 0/10). The standard describes roughly
16% of the code.

### The four `DB::table()` calls are not the same question

In `ContractCommissionConfigurationRepository` they are cross-table reads whose root table is **not**
this repository's model:

| Line | Root table | Purpose |
|---|---|---|
| 132 | `contracts` | unbound-contract report (joins shares, members, configurations) |
| 210 | `contracts` | `paginateSummaries` (joins clients, configurations, rules) |
| 306 | `contract_commission_shares` | active share per contract |
| 341 | `contract_members` | active member counts |

`$this->model` cannot express these — the model is `ContractCommissionConfiguration`, and these
queries start from Project-owned tables. Any alignment must keep them as query-builder reads.

## 3. Options considered

| Option | Effect | Cost | Risk |
|---|---|---|---|
| Leave as is, correct the doc | doc matches reality; code untouched | ~10 doc lines | none |
| **Align the 10 repositories (approved)** | module matches the standard | 10 files, 45 call sites, 10 new constructors | low but non-zero: every repository is resolved by the container, so a wrong constructor breaks the whole module at boot |
| Align all 87 | codebase matches the standard | 87 files, ~5 modules | high churn, no functional gain, large review surface |

## 4. Proposed change — code

Per repository, one mechanical edit:

```php
class CommissioningRunRepository implements CommissioningRunRepositoryInterface
{
    protected CommissioningRun $model;

    public function __construct(CommissioningRun $model)
    {
        $this->model = $model;
    }

    // Model::query()  →  $this->model->query()   (45 sites across 10 files)
}
```

Notes that make this safe:

- Every repository maps to exactly one model, so the injection target is unambiguous.
- Interfaces are bound in `CommissioningServiceProvider` with `bind(Interface::class, Class::class)`; Laravel autowires the model, so no provider change is needed.
- `$this->model->query()` is behaviourally identical to `Model::query()`, including the `BelongsToCompany` trait and any global scopes.
- The 4 `DB::table()` calls stay as they are (§2).
- Nothing else changes: no method signatures, no query semantics, no service or controller edits.

Style note: the project's own example in §9 uses an untyped `protected $model;`. Typed properties are
better, but matching the documented example keeps the diff uncontroversial — pick one and apply it to
all 10 identically.

## 5. Proposed change — documentation

`CODING-STANDARD.md` §9 is silent on the cross-table case, which every reporting repository hits.
Minimal addition after the "Correct" block:

```markdown
Queries whose root table is not the repository's own model (reporting joins across
modules, aggregate counts) may use the query builder directly. Keep them in the
repository layer — they must not leak into services.
```

Optionally record the current reality so the next audit does not read as a violation:

```markdown
Existing repositories predating this rule may still use `Model::query()`. Align them
when a module is already being worked on; do not open cross-module refactors for it.
```

## 6. Verification plan for the implementation block

1. `php artisan test Modules/Commissioning` — expect 130 passed, unchanged.
2. `php artisan about` or any container resolve — catches a mis-typed constructor at boot.
3. `git diff --stat` — expect exactly 10 files, additions only in constructors, plus the 45 substitutions.
4. No test edits. If a test needs changing, the refactor changed behaviour and must be reverted.

## 7. Recommendation

Do §5 (doc correction) regardless — it is true either way and costs nothing.

§4 is safe but is pure churn: it improves conformance to a rule the codebase mostly ignores, and
touches 10 files that are currently correct, consistent and fully covered. Worth doing only as its
own small block with nothing else in flight, so the diff is trivially reviewable. It is explicitly
**not** worth bundling into a feature branch.

**No code changed. Awaiting an implementation block for §4, and approval for §5.**
