# WP1 — Fix `*appCan` directive + gate Purchases action buttons

## Goal
Make the FE actually hide action controls a user wasn't granted, starting with the **Purchases** module (the owner's named example). First fix the `*appCan` directive so action-level strings work correctly (today it uses EXACT `can()`, which breaks the prefix/trailing-dot form and can't express "has this exact action"). Then add `*appCan` to every action control in every Purchases screen, keyed to the EXISTING catalog permission for that action — including `purchases.orders.approve` on the **Approve purchase-order** button (the owner's example).

## Files
- **Fix directive:** `src/app/shared/directives/can.directive.ts` — change its check from exact `PermissionService.can(p)` to the **prefix-aware** `PermissionService.hasAnyPermission([p])` (which uses `permissionMatches`: an owned `resource` or exact `resource.action` grant matches; a *different* action like `.view` correctly does NOT match `.approve`; super-admin bypass preserved). This fixes trailing-dot usages AND makes exact action strings work. Verify `hasAnyPermission` is public on `permission.service.ts`; if not, expose a small `canDo(p)` that does the prefix match and use it.
- **Gate Purchases screens** (add `*appCan="'purchases.<resource>.<action>'"` to each create/edit/delete/approve/confirm/cancel/post/etc. control, and import `CanDirective` in each standalone component's `imports`):
  - `src/app/features/purchases/requests/requests.component.html` — New (`purchases.requests.create`), row Edit (`.update`), Delete (`.delete`), Approve (`.approve`).
  - `src/app/features/purchases/orders/orders.component.html` — New (`purchases.orders.create`), Edit (`.update`), Delete (`.delete`), **Approve (`purchases.orders.approve`)**, Confirm (`.confirm`).
  - `src/app/features/purchases/bills/bills.component.html` — create/create_direct/update/delete/approve/post/cancel.
  - `src/app/features/purchases/grns/grns.component.html` — create/update/delete/approve/cancel/quality_check.
  - `src/app/features/purchases/payments/payments.component.html` — create/update/delete/post/cancel.
  - `src/app/features/purchases/returns/returns.component.html` — create/update/delete/approve/post/cancel.
  - `src/app/features/purchases/supplier-prices/supplier-prices.component.html` — create/update/delete.
  - (also their `.component.ts` `imports:` arrays for `CanDirective`, and any edit/view detail components if they carry action buttons.)
- Grep each screen for the buttons: `grep -nE "p-button|pButton|(onClick)=" <file>` and map each to its action. Use the EXACT strings from the catalog (verified present): `purchases.requests.{create,update,delete,approve}`, `purchases.orders.{create,update,delete,approve,confirm}`, `purchases.bills.{create,create_direct,update,delete,approve,post,cancel}`, `purchases.grns.{create,update,delete,approve,cancel,quality_check}`, `purchases.payments.{create,update,delete,post,cancel}`, `purchases.returns.{create,update,delete,approve,post,cancel}`, `purchases.supplier-prices.{create,update,delete}`.

## Interfaces (for later WPs)
- The established pattern: `<button ... *appCan="'module.resource.action'">`. `CanDirective` (selector `[appCan]`) is imported per standalone component. `PermissionService.hasAnyPermission([p])` is the prefix-aware gate. Later WPs (Sales/Inventory/etc.) reuse this exact pattern + the fixed directive.

## Acceptance criteria
- `can.directive.ts` uses the prefix-aware check; a user with only `purchases.requests.view` → the New/Edit/Delete/Approve buttons on Purchases screens are HIDDEN; a user with `purchases.orders.approve` → the Approve button on purchase orders SHOWS; super-admin sees everything (bypass intact).
- Every action control on all 7 Purchases screens carries an `*appCan` with the correct existing permission string (no typos — must match the catalog exactly).
- No non-action / navigation / "view" controls are hidden (view is the baseline for reaching the screen).
- `ng build --base-href /app/` stays GREEN.

## Tests
- FE gate = `ng build` green. (No FE unit runner in this repo.) Spot-verify by reasoning: a `.view`-only owned set does not match `.create/.update/.delete/.approve` via `permissionMatches`.

## Flags
- Not [FIN]. No migration. FE-only.

## Out of scope
- Do NOT change route guards, the menu/sidebar, or the roles-management screen.
- Do NOT touch Sales/Inventory/etc. (later WPs).
- Do NOT add or rename any BE permission (all Purchases action perms already exist).
- Do NOT deploy or commit-to-main.
