# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
# Development
cd /home/moonui/public_html/moon-erp
npx ng serve                              # Dev server at http://localhost:4200
npx ng build --base-href /app/            # Production build

# Deploy (clean old chunks first!)
rm -f /home/moonui/public_html/app/*.js /home/moonui/public_html/app/*.css /home/moonui/public_html/app/*.html /home/moonui/public_html/app/*.ico
\cp -rf /home/moonui/public_html/moon-erp/dist/moon-erp/browser/* /home/moonui/public_html/app/

# Generate
npx ng generate component features/<name> --standalone --style=scss --skip-tests
```

Tests are disabled (skipTests: true in angular.json). No test runner configured.

## Architecture

Moon ERP — Angular 21 standalone-component ERP with NgRx state management, PrimeNG UI, and RTL-first bilingual support (Arabic/English).

### Directory Layout (src/app/)

- **core/services/** — 65+ API services (one per resource, `providedIn: 'root'`)
- **core/store/** — 27 NgRx feature slices (actions, reducer, effects per feature)
- **core/models/** — TypeScript interfaces for all API entities
- **core/interceptors/** — `auth.interceptor.ts` (adds `X-Authorization` header)
- **core/guards/** — `authGuard`, `guestGuard`, `permissionGuard`
- **features/** — 60+ standalone feature components (lazy-loaded via routes)
- **layout/** — `main-layout`, `sidebar`, `topbar`
- **shared/components/** — `data-table`, `form-dialog`, `page-header`, `module-nav`

### Data Flow Pattern

Every CRUD feature follows: **Component → NgRx Action → Effect → Service → API → Effect → Reducer → Selector → Component**

Each NgRx slice uses `@ngrx/entity` with this state shape:
```typescript
interface FeatureState extends EntityState<Model> {
  meta: PaginationMeta | null;
  loading: boolean;
  saving: boolean;
  error: string | null;
  loaded: boolean;
}
```

### Component Pattern

- Standalone components with explicit imports (no NgModules)
- Angular `signal()` for UI state (dialog visibility, editing item)
- NgRx `store.select()` observables for data state
- Reactive forms via `FormBuilder`
- PrimeNG `MessageService` for toast notifications, `ConfirmationService` for delete confirmations

### Routing

`app.routes.ts` — all routes lazy-loaded. Two main route groups under auth guard:
- `/core/*` — core & inventory features
- `/accounting/*` — all accounting features

Permission guard uses prefix matching with route data: `{ permissions: ['core.users'] }`. Super admin (empty roles/permissions arrays) bypasses all checks.

## Backend Documentation

Check these before any major feature work:

- **Documentation Portal (primary)**: https://moon-support.elbaset.com/portal/moon-erp-4EIy8R
- **Changelog**: https://moon-erp.elbaset.com/documentation/changelog-app.html
- **API Explorer**: https://moon-erp.elbaset.com/documentation/api-explorer.html
- **OpenAPI Spec**: https://moon-erp.elbaset.com/documentation/openapi.yaml

### Current Version: 0.6.0 (Unreleased)

Key recent changes (from changelog):
- **LIS-078**: Status sync, panel dedup, kanban cleanup (4-issue batch)
- **LIS-075**: Accounting and pricing 13-issue fix
- **LIS-074**: Flow and accounting comprehensive fix (12-issue batch)
- **LIS-063**: Result types and formula auto-calculation engine
- **HRM-019**: HR reports (6 types: workforce, attendance, leave, payroll, loans, turnover)
- **SUP-067**: Support V2 professional task management (complete rewrite)
- **ACC-045**: Journal entry partner_id linking

## Critical API Details

- **Auth header**: `X-Authorization: Bearer <token>` — NOT standard `Authorization` header. Standard header returns 401. ⚠️ Official docs say `Authorization` but reality is `X-Authorization`.
- **Pagination**: Official docs say `per_page` default=15, but API ignores `per_page` and returns max 25 items. All services use `listAll()` to auto-paginate via `forkJoin`.
- **Login response**: Token at `response.token` (not `response.data.token`).
- **API base**: `https://moon-erp.elbaset.com/api`
- **URL pattern**: `/api/{module}/{resource}` — IDs are integer auto-incrementing PKs.
- **Interceptor skip**: Auth interceptor must skip `/assets/` requests (translation JSONs).
- **Dates**: ISO 8601 with UTC (`2026-02-16T10:30:00.000000Z`). Accepts `YYYY-MM-DD` in requests.
- **Money**: Returned as numbers (not strings), `decimal(12,3)` in DB.
- **Soft deletes**: DELETE returns 200 with `{"message": "Deleted"}`.
- **Localization**: `Accept-Language: ar|en` header controls response language.
- **Tokens**: No expiry — valid until explicit logout.

### Error Responses
| Code | Meaning | Body |
|------|---------|------|
| 401 | Unauthenticated | `{"message": "Unauthenticated."}` |
| 403 | Forbidden | `{"message": "This action is unauthorized."}` |
| 404 | Not Found | `{"message": "Resource not found."}` |
| 422 | Validation | `{"message": "...", "errors": {"field": ["msg"]}}` |
| 500 | Server Error | Generic message (no stack in production) |

### API Scale (from OpenAPI spec)
- **Total**: 500+ endpoints across 10 modules
- Auth (7), Core (~80), Accounting (~95), Inventory (~40), Sales (~50), Purchases (~45), HRM (~70), POS (~30), LIS (~120), Support V2 (~80)

## Framework Gotchas

- **PrimeNG v21**: `OverlayPanel` renamed to `Popover` (import from `primeng/popover`). Checkbox `label` property removed — use separate `<label>` element.
- **PrimeNG theme**: Use `@primeuix/themes/aura` (NOT `@primeng/themes` which is deprecated).
- **ngx-translate v17**: `provideTranslateHttpLoader()` must be INSIDE `provideTranslateService({ loader: ... })`. Use `fallbackLang` not `defaultLanguage`.
- **zone.js**: Must be in angular.json polyfills (not included by default in Angular 21).
- **Tailwind CSS 4**: Uses `@tailwindcss/postcss` — no tailwind.config.js file.

## Deployment Gotchas

- Always clean old JS/CSS/HTML files before copying build output — old chunks accumulate.
- Use `\cp -rf` to bypass cp alias prompts on this cPanel server.
- `.htaccess` in `/app/` uses `%{REQUEST_FILENAME}` not `%{DOCUMENT_ROOT}/app%{REQUEST_URI}` for SPA fallback.
- Apache `mod_proxy` is NOT available in `.htaccess` on this cPanel hosting.

## LIS Flow (Laboratory Information System)

### Test Types
- **Single test**: one value
- **Panel** (e.g. CBC = 14 values): appears as single test everywhere EXCEPT result entry where all values show for input

### External Lab — Two Roles

**Role 1: Client (inbound — they send us tests)**
- `external_lab_id` on request = this lab is a CLIENT
- Normal workflow: collection → kanban → results → approval
- Only difference: billing goes to the external lab's account
- NO referrals, NO portal — purely internal work

**Role 2: Service Provider (outbound — we send them tests)**
Two cases trigger this:
1. **Investigation has `is_outsourced=true`** + `default_external_lab_id` — outsourced from the start
2. **Internal test sent out from kanban** — gets new barcode, returns to collection

After collection, outbound tests:
1. Go to **Referrals page directly** — NEVER enter kanban
2. Appear in **Results page** immediately (waiting for value)
3. Get sent to external lab
4. Results can come from 3 places: portal (receive-results), referrals page, results page
5. All 3 sources sync to results page
6. From results page: edit or approve

### Internal Flow
1. Create request (for normal client OR external lab as client)
2. Collection — samples auto-split by type and section
3. Internal tests → kanban | Outsourced tests → separate barcode
4. After collection: internal → kanban, outsourced → referrals

### Kanban (3 stages: received, in-progress, completed)
**Received/In-progress actions:**
- Reject test → new barcode → back to collection → normal flow
- Send out → new barcode → back to collection → after collection goes to referrals (NOT kanban)
- Enter result → test marked completed

**Completed actions:**
- Re-test → new barcode → back to collection. Old result preserved. Marked for comparison.

### Results Page
- Shows ALL tests (internal + external)
- Internal tests appear after entering kanban
- External tests appear after collection (waiting for value)
- Can enter/edit/approve results
- Panels show all values for entry
- Re-tested items show previous result for comparison

## Feature Documentation

Each major module has its own CLAUDE.md with detailed architecture, workflows, signals, API endpoints, and gotchas. **Read the relevant feature CLAUDE.md before working on any module:**

| Module | File | Lines | Coverage |
|--------|------|-------|----------|
| **Core Architecture** | `src/app/core/CLAUDE.md` | 256 | Services pattern, auth, guards, NgRx, shared components, theming, i18n |
| **LIS (Lab)** | `src/app/features/lis/CLAUDE.md` | 630 | 33 sub-modules, request wizard, kanban, results, referrals, print/PDF, external portal |
| **Accounting** | `src/app/features/accounting/CLAUDE.md` | 533 | 33 features, chart of accounts, journals, banking, reconciliation, year-end closing |
| **HR** | `src/app/features/hr/CLAUDE.md` | 454 | 19 sub-modules, payroll, attendance, leave, recruitment, performance |
| **Sales** | `src/app/features/sales/CLAUDE.md` | 390 | Quotation→Order→Delivery→Invoice→Payment flow, commissions, approvals |
| **Purchases** | `src/app/features/purchases/CLAUDE.md` | 386 | Request→Order→GRN→Bill→Payment flow, supplier pricing |
| **Inventory** | `src/app/features/inventory/CLAUDE.md` | 300 | 14 features, stock movements, warehouses, counts, adjustments, reorder alerts |
| **POS** | `src/app/features/pos/CLAUDE.md` | 281 | Cart, sessions, offline mode, receipt printing, terminal config |

## Code Style

Prettier configured in package.json: `printWidth: 100`, `singleQuote: true`, Angular HTML parser.

Translation keys follow pattern: `FEATURE_NAME.FIELD` (e.g., `BRANCHES.NAME_AR`, `COMMON.SAVE`). Translation files at `src/assets/i18n/{ar,en}.json`.

Bilingual entity fields use `name_ar`/`name_en` (or `title_ar`/`title_en`) convention.
