> ## Documentation Index
> Fetch the complete documentation index at: https://human-resource-docs.ha-consultancy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture Overview

> The three components of BC Human Resource — AL extension, ASP.NET API, and React roster add-in — how they fit together, trust boundaries, and data flow.

BC Human Resource is delivered as three components that share data through well-defined contracts. You can deploy just the AL extension if all you need is HR inside BC, or layer the API and React control add-in for richer scheduling and self-service.

```mermaid theme={null}
graph TB
    subgraph BC["☁️ Business Central Tenant — SaaS or on-prem"]
        subgraph AL["BC Human Resource AL Extension (AppSource app)"]
            T["Tables / Page extensions"]
            P["Pages, reports, codeunits"]
            PS["Permission set: Human Resource HAC"]
            WS["Published web services (OData)"]
            subgraph RB["Roster Board page"]
                RC["React control add-in\n(iframe · /scripts/assets)"]
            end
        end
    end

    subgraph HRAPI["HR.API — ASP.NET Core 9"]
        DB[("SQL DB\n(Clients table)")]
    end

    subgraph Clients["Portal / Mobile clients"]
        MOB["📱 Mobile app or web portal"]
    end

    MOB -->|"HTTPS · tenant-id header"| HRAPI
    HRAPI -->|"BC OData v4 · OAuth 2.0 client credentials"| AL
```

## The three layers

### 1. AL extension — the source of truth

Lives in **`BC-Human-Resource-AL/`** and ships as a `.app` file installed on a Business Central tenant. Every piece of HR data lives in BC tables defined here (or in the standard `Employee` table extended by this app). All business rules — accrual, deduction, installment generation, approval flow, salary breakdown, EOS calculation — run as AL codeunits inside BC.

The extension also publishes a set of bound OData actions on codeunits so external systems can read and write HR data without writing AL.

This component can be installed **stand-alone** and provides a complete HR back-office workflow without any other component.

### 2. ASP.NET API — the mobile / portal gateway

Lives in **`HR.API/`**. It is a thin OAuth-protected pass-through: every endpoint takes a `tenant-id` header, looks up the matching BC environment in its local `Clients` SQL table, obtains an OAuth 2.0 access token from Entra ID, and forwards the call to one of BC's bound OData actions.

What this layer adds on top of calling BC directly: a stable documented JSON contract, a simpler authentication story for mobile apps, and multi-tenant routing so one deployed API can serve many BC environments.

It does **not** cache HR data, store any HR records locally, or implement its own user management. This component is **optional**.

### 3. React control add-in — the Visual Roster Board

Lives in **`react-roster-shift-board/`** and is **built into the AL extension** at compile time: Vite writes the bundled `js/base.js` and `app.css` to `../BC-Human-Resource-AL/scripts/assets/`. The AL control add-in then references those files, so when you ship the `.app` you ship the React bundle inside it.

At runtime the React app runs inside an iframe that BC injects into the **Visual Roster Board** page (70003175). It talks to BC exclusively through the control add-in extensibility bridge — there is **no HTTP** between the React app and BC, and **no dependency** on the HR.API for the Roster Board to function.

## Data flow per scenario

### HR consultant building a roster

```mermaid theme={null}
graph TD
    A["👤 HR user"] --> B["BC Roster Board page (70003175)"]
    B --> C["Loads iframe → React app boots"]
    C --> D["React calls GetResources via control add-in bridge"]
    D --> E["AL trigger reads BC tables → returns data to React"]
    E --> F["User drags employee onto a shift slot"]
    F --> G["React calls SaveRosterEntry"]
    G --> H["AL trigger writes to Employee Roster HAC table"]
```

### Employee submitting a leave request from a phone app

```mermaid theme={null}
sequenceDiagram
    participant M as 📱 Mobile app
    participant A as HR.API
    participant E as Entra ID
    participant B as Business Central

    M->>A: POST /api/leave/request-leave<br/>(tenant-id header)
    A->>A: ApiKeyAttribute resolves tenant → BC environment
    A->>E: Client credentials grant
    E-->>A: OAuth bearer token
    A->>B: POST APIManagementLeave_RequestLeave (OData)
    B->>B: Runs validation — same as in-BC leave page
    B->>B: Writes to Leave Journal HAC / Employee Leave HAC
    B-->>A: Response payload
    A-->>M: JSON response
```

## Trust boundaries

| Boundary                 | What crosses it                | Protected by                                                                                 |
| ------------------------ | ------------------------------ | -------------------------------------------------------------------------------------------- |
| Mobile/portal ↔ HR.API   | JSON, `tenant-id` header       | TLS, the `[ApiKey]` filter validating tenant-id against the local `Clients` table            |
| HR.API ↔ BC OData        | JSON, OAuth Bearer             | TLS, Entra ID client credentials per-tenant                                                  |
| React iframe ↔ AL page   | JSON via control-add-in bridge | Same origin within BC web client; bridge is provided by Microsoft and is not network-exposed |
| AL extension ↔ BC tables | Standard BC permission set     | The `Human Resource HAC` permission set, plus standard BC role hierarchy                     |

## Technology map

| Technology                       | Where                               | Why                                                        |
| -------------------------------- | ----------------------------------- | ---------------------------------------------------------- |
| AL                               | `BC-Human-Resource-AL/src/`         | Native BC extension language                               |
| ASP.NET Core 9 / C#              | `HR.API/HR.API/`, `HR.API/HR.Core/` | Web API host + service library                             |
| Entity Framework Core 9          | `HR.API/HR.Core/Data/`              | One DB context, one table (`Clients`)                      |
| SQL Server                       | External                            | EF migrations target SQL Server                            |
| RestSharp                        | `HR.API/HR.Core/Services/`          | Outbound HTTP to BC OData                                  |
| React 19 / TypeScript 5 / Vite 7 | `react-roster-shift-board/src/`     | Roster Board UI                                            |
| Syncfusion EJ2                   | `react-roster-shift-board/`         | `ScheduleComponent`, `GanttComponent` — commercial license |

## Build-time coupling

The React project's Vite config writes its build output directly into the AL extension's scripts directory:

```ts theme={null}
// react-roster-shift-board/vite.config.ts
build: {
  outDir: '../BC-Human-Resource-AL/scripts/assets',
  rollupOptions: {
    output: {
      entryFileNames: 'js/base.js',
      assetFileNames: '[name].[ext]',
    },
  },
}
```

<Warning>Always run `npm run build` in `react-roster-shift-board/` before publishing the AL extension — otherwise the iframe will load a stale bundle.</Warning>

CI should run, in order:

```bash theme={null}
cd react-roster-shift-board && npm ci && npm run build
cd ../BC-Human-Resource-AL && al-compiler ...
```
