# Task 1 report — printing the stock receipt (إذن الإضافة)

**Date:** 2026-08-08 · **Branch:** `hazemdev2` (both repos, verified before and at commit time)
**Status:** DONE — implemented, type-checked, built, committed. Not pushed, not merged, not deployed to `/app`.

**Commits**
- FE `moon-erp`: `6375c8edfc24546082cce20fc38daf93647ff5ce` — *feat: print the stock receipt (إذن إضافة) with costs and a two-party signature block*
- BE `moon-erp-be`: `32f7ee8842e11da7cbbbcdf9a91d9f0a19dc0593` — *docs: changelog — printable stock receipt (إذن الإضافة)*

---

## What was built

| File | Change |
|---|---|
| `src/app/features/stock-receipts/stock-receipt-print.config.ts` | **new** (157 lines) — `STOCK_RECEIPT_PRINT_CONFIG`, mirroring `stock-issue-print.config.ts` |
| `src/app/features/stock-receipts/stock-receipts.component.ts` | +16 lines — inject `PrintService`, `companyInfo` signal seeded from `getCompanyWithLogo()` in `ngOnInit`, `printStockReceipt(item)` |
| `src/app/features/stock-receipts/stock-receipts.component.html` | +1 line — `pi pi-print` row action, immediately after the eye/view button |
| `src/app/shared/print/signature-section.ts` | **shared file, additive** — optional `parties` option on `buildSignatureSection` |

`documentType: 'stock_receipt'` and `settingKeyPrefix: 'print.stock_receipt'`, so the receipt reads
`print.stock_receipt.active_template` / `.custom_templates` through exactly the same
`PrintService.print()` machinery the issue uses. Icon `pi pi-sign-in` (the issue's is `pi pi-sign-out`).

`printStockReceipt()` calls `stockReceiptService.getById(item.id)` first — the list endpoint does not
eager-load `items` — then `printService.print(CONFIG, res.data, this.companyInfo())`, with the
existing `showError` on failure. Identical shape to `printStockIssue()` at
`stock-issues.component.ts:1279`.

**i18n: zero new keys.** The config reuses `PRINT.UNIT_COST` (already present in both `ar.json` and
`en.json`) and otherwise uses inline bilingual literals exactly as the issue config does
(`lang === 'ar' ? 'المخزن' : 'Warehouse'`). Neither `ar.json` nor `en.json` was touched at all —
no `git checkout`/`restore`/`stash` went anywhere near them.

**On-screen behaviour unchanged.** The only visible difference on the receipts screen is one extra
icon button in the actions cell. No column, form, dialog or data-loading change.

---

## The judgement call: the printed receipt SHOWS values

**Decision: yes — unit cost, line total and document total are printed** (`priceLabel:
t('PRINT.UNIT_COST')`, `subtotal = total = doc.total_cost`).

Reasons, in order of weight:

1. **The document's whole job is reconciliation against a priced counterpart.** The storekeeper
   checks the receipt line by line against the supplier's delivery note / invoice. A quantities-only
   receipt cannot perform the check it exists to perform.
2. **The cost on this document is the cost that lands in the ledger.** The receipt's `unit_cost`
   drives stock valuation and the resulting GL entry. Printing the paper record of a valuation
   event without the values makes the paper record non-authoritative.
3. **Precedent inside this codebase.** The GRN (`grn-print.config.ts`) — the *other* goods-in
   printout in Moon ERP — prints `PRINT.UNIT_COST` and totals. Two goods-in documents that print
   differently would be an inconsistency, not a design.
4. **The screen already shows them.** The receipts list has a «إجمالي التكلفة» column and the line
   grid has `unit_cost` / `total_cost` columns. A printout that silently drops them contradicts the
   screen the user just looked at.
5. **The reason the issue hides prices does not transfer.** An issue slip is often handed to a
   customer or to production; showing *our* cost there leaks margin. A receipt is either kept
   internally or handed back to the supplier, whose own prices these are. There is nothing to leak.

**Currency:** the receipt resource has no `currency_code`, so the config uses
`doc.currency_code || company?.currency || ''` rather than the hard-coded `'SAR'` fallback the issue
and delivery-note configs use. Since this document now prints money, a wrong hard-coded currency
symbol is worse than a blank one; `DashboardCompanySummary.currency` is the right source and is
already present on the object `PrintService` passes in.

---

## Signature block — shared helper reused, not forked

`buildSignatureSection(receivedBy?, options?)` gained an optional second parameter:

```ts
buildSignatureSection(undefined, {
  title: 'التسليم والاستلام / Delivery & Receipt',
  parties: [{ role: 'المسلِّم / Delivered by' }, { role: 'المستلم / Received by' }],
})
```

One section, two role-captioned rows (Name / Signature / Date each), one company-stamp box — rather
than two full sections, which would have printed two stamp boxes.

**Backward compatibility was verified empirically, not assumed.** The previous version of the file
was compiled from `git show HEAD:…` alongside the new one and both were called with `undefined`,
`''` and a name; the emitted `{title, html}` is **byte-identical** in all three cases. The two
existing callers (`delivery-note-print.config.ts`, `stock-issue-print.config.ts`) are therefore
unaffected — which matters, because `stock-issue-print.config.ts` belongs to the agent working
Task 2 in parallel.

Both name lines are left **blank** on real documents — `partner_name` is the organisation, not the
person signing, the same reasoning the issue config already documents. Names are pre-filled only in
`sampleData()`, i.e. in the Print Settings preview.

### Shared files touched — declared as required by the brief

`src/app/shared/print/signature-section.ts` is the **only** shared file changed, and the change is
purely additive (a new optional parameter + an exported interface). I did not touch
`stock-issues/*`, `InventoryIssueItemResource`, or `doc-config.service.ts`. No backend code was
changed at all; the only BE file edited is `docs/moonstack/CHANGELOG.md`.

---

## Verification

- `npx tsc --noEmit` — clean, no output, no new errors.
- `npx ng build --base-href /app/` — **green**, output written to `dist/moon-erp`. Only the
  pre-existing CommonJS-bailout warnings (`qrcode`, `file-saver`, `html2canvas`) appear; none of
  them relate to this change.
- Legacy signature-section output diffed byte-for-byte against the pre-change implementation
  (see above).
- Every edited file `chown moonui2:moonui2`.
- **NOT deployed to `/app`** — the orchestrator deploys.

### What I could not verify

**I cannot open a browser, so the printed output was never looked at.** Nothing in this report is a
claim about how the page renders. What is actually verified is: it compiles, it builds, the config
object matches the shape `PrintService`/`GENERIC_TEMPLATES` consume, and the shared helper's
existing output is unchanged. The rendered A4/A5 result — column widths with the cost column added,
where the two-row signature block falls relative to a page break, RTL alignment of the money
columns — needs one human print preview.

---

## Notes / open items

1. **Print Settings parity gap (pre-existing, not introduced here).** `print-settings.component.ts`
   registers sales, purchases and accounting configs only — the stock **issue** is not registered
   there either. So neither the issue nor the receipt gets a template-picker card in
   Settings → Print, and both fall back to the `classic` template unless
   `print.stock_receipt.active_template` is set some other way. Registering the receipt alone would
   have exceeded issue-parity and touched another shared file for no acceptance criterion, so I did
   not. If the owner wants template selection for warehouse documents, the right fix is a new
   "المخزون / Inventory" group in `print-settings.component.ts` carrying **both** configs — one
   small follow-up, not part of this task.
2. **No reference number on the printed receipt.** `InventoryReceiptResource` exposes
   `reference_type` / `reference_type_label` / `reference_id` but — unlike `InventoryIssueResource`
   — no resolved `reference_number`. The printout therefore shows «نوع المرجع / Reference Type»
   only; I did not invent a number. If the owner wants the source document number (the PO / GRN /
   bill a receipt came from) on the paper, that needs a BE change to
   `InventoryReceiptResource` mirroring the issue's `referenceNumber()` resolver — worth raising,
   but out of scope here.
3. **The print button carries no `*appCan` permission directive**, matching the issue's print
   button exactly. Anyone who can see the receipts screen can print a receipt. If receipt costs
   should be permission-gated, that is a deliberate decision to take for both documents at once,
   not a per-screen one.
