diff --git a/docs/MODULE_DATA_FLOW.html b/docs/MODULE_DATA_FLOW.html
index e7a2ac7..8197f48 100644
--- a/docs/MODULE_DATA_FLOW.html
+++ b/docs/MODULE_DATA_FLOW.html
@@ -892,7 +892,7 @@ flowchart TD
end
PREVIEW --> CALC[calculateDepreciation]
- CREATE --> STORE[(assets: method, rate, cost, salvage, life, purchase_date)]
+ CREATE --> STORE[(assets: method, rate, cost, salvage, life, commencement/purchase date)]
STORE --> READ["GET /assets/:id"]
READ --> CALC
@@ -903,19 +903,92 @@ flowchart TD
OTHER --> CALC
+
+
Input fields used in calculation
- | Method | Rate auto-calc? | Formula concept |
+ | Field | Meaning | Role in formula |
- | SLM | Yes (if rate omitted) | Equal yearly depreciation on original cost |
- | WDV | Yes (if rate omitted) | Depreciation on reducing book value year-by-year |
- | OTHER | No — user must send depreciation_rate | Custom % on cost |
+ purchase_cost | Asset cost / amount | Starting book value; base for rate & annual dep |
+ salvage_value | Residual value at end of life | Floor for book value; used in rate auto-calc |
+ useful_life_years | Expected life in years | Rate auto-calc + cap on years elapsed |
+ commencement_date | Usage / put-to-use date | Primary start date for years elapsed |
+ purchase_date | Purchase date | Fallback start date if commencement is null |
+ depreciation_method | SLM / WDV / OTHER | Which formula path to run |
+ depreciation_rate | % per year | Optional for SLM/WDV (auto); required for OTHER |
+ as_of_date | Calculate as of (preview only) | Defaults to today |
+
+ Date → years elapsed
+ depreciation_start_date = commencement_date || purchase_date
+years_elapsed = (as_of_date − depreciation_start_date) / 365.25 days
+capped_years = min(years_elapsed, useful_life_years) // if life is set
+
+ Accumulated depreciation uses capped_years so it never exceeds useful life.
+
+ Method 1 — SLM (Straight Line)
+ Equal depreciation every year on original cost, never below salvage.
+ Auto rate (when depreciation_rate omitted):
+ depreciable_amount = max(purchase_cost − salvage_value, 0)
+depreciation_rate = (depreciable_amount / purchase_cost / useful_life_years) × 100
+
+ Amounts:
+ annual_depreciation = purchase_cost × rate / 100
+accumulated_depreciation = min(annual_depreciation × capped_years, purchase_cost − salvage_value)
+book_value = max(purchase_cost − accumulated_depreciation, salvage_value)
+
+ Example: cost = ₹1,00,000 · salvage = ₹10,000 · life = 10 years · start = 1 year ago
+
+ - Rate = ((100000−10000)/100000/10)×100 = 9%
+ - Annual = 100000 × 9% = ₹9,000
+ - Accumulated (1 yr) = ₹9,000
+ - Book value = ₹91,000
+
+
+ Method 2 — WDV (Written Down Value)
+ Depreciation each year on the reducing book value (not original cost). Book value never goes below salvage.
+ Auto rate (when depreciation_rate omitted; needs salvage > 0 and < cost):
+ depreciation_rate = (1 − (salvage_value / purchase_cost)^(1 / useful_life_years)) × 100
+
+ Amounts (year-by-year):
+ book_value = purchase_cost
+for each full year in capped_years:
+ year_dep = book_value × rate / 100
+ book_value = max(book_value − year_dep, salvage_value)
+if fractional year remains:
+ year_dep = (book_value × rate / 100) × fraction
+ book_value = max(book_value − year_dep, salvage_value)
+
+accumulated_depreciation = purchase_cost − book_value
+annual_depreciation = book_value × rate / 100 // next year's dep on current WDV
+
+ Example: cost = ₹1,00,000 · salvage = ₹10,000 · life = 10 years · start = 1 year ago
+
+ - Rate ≈ (1 − (10000/100000)^(1/10)) × 100 ≈ 20.57%
+ - Year 1 dep ≈ 100000 × 20.57% ≈ ₹20,570
+ - Book value ≈ ₹79,430
+ - Accumulated ≈ ₹20,570
+ - Next annual (on WDV) ≈ 79430 × 20.57% ≈ ₹16,340
+
+
+ OTHER method
+ Same accumulation style as SLM, but depreciation_rate is mandatory (no auto-calc).
+
+
+ | Method | Rate auto-calc? | Depreciates on | Salvage role |
+
+ | SLM | Yes (if rate omitted) | Original purchase_cost every year | In rate formula + book-value floor |
+ | WDV | Yes (if rate omitted) | Reducing book value each year | In rate formula + book-value floor |
+ | OTHER | No — send depreciation_rate | Original cost × rate (like SLM) | Book-value floor only |
+
+
+
FE usage:
- Live preview →
POST /assets/depreciation/calculate (no save)
- Saved asset view →
GET /assets/:id → data.depreciation object
- Method dropdown →
GET /assets/depreciation-methods
+ - Prefer sending
commencement_date; backend falls back to purchase_date
12. Alerts flow (cross-asset dashboards)
diff --git a/docs/MODULE_DATA_FLOW.md b/docs/MODULE_DATA_FLOW.md
index fff00fe..6b4a66b 100644
--- a/docs/MODULE_DATA_FLOW.md
+++ b/docs/MODULE_DATA_FLOW.md
@@ -501,7 +501,7 @@ flowchart TD
end
PREVIEW --> CALC[calculateDepreciation]
- CREATE --> STORE[(assets: method, rate, cost, salvage, life, purchase_date)]
+ CREATE --> STORE[(assets: method, rate, cost, salvage, life, commencement/purchase date)]
STORE --> READ["GET /assets/:id"]
READ --> CALC
@@ -512,17 +512,104 @@ flowchart TD
OTHER --> CALC
```
-| Method | Rate auto-calc? | Formula concept |
+### Input fields used in calculation
+
+| Field | Meaning | Role in formula |
|---|---|---|
-| **SLM** | Yes (if rate omitted) | Equal yearly depreciation on original cost |
-| **WDV** | Yes (if rate omitted) | Depreciation on reducing book value year-by-year |
-| **OTHER** | No — user must send `depreciation_rate` | Custom % on cost |
+| `purchase_cost` | Asset cost / amount | Starting book value; base for rate & annual dep |
+| `salvage_value` | Residual value at end of life | Floor for book value; used in rate auto-calc |
+| `useful_life_years` | Expected life in years | Rate auto-calc + cap on years elapsed |
+| `commencement_date` | Usage / put-to-use date | **Primary** start date for years elapsed |
+| `purchase_date` | Purchase date | Fallback start date if commencement is null |
+| `depreciation_method` | `SLM` / `WDV` / `OTHER` | Which formula path to run |
+| `depreciation_rate` | % per year | Optional for SLM/WDV (auto); required for OTHER |
+| `as_of_date` | Calculate as of (preview only) | Defaults to today |
+
+### Date → years elapsed
+
+```
+depreciation_start_date = commencement_date || purchase_date
+years_elapsed = (as_of_date − depreciation_start_date) / 365.25 days
+capped_years = min(years_elapsed, useful_life_years) // if life is set
+```
+
+Accumulated depreciation uses `capped_years` so it never exceeds useful life.
+
+### Method 1 — SLM (Straight Line)
+
+Equal depreciation every year on **original cost**, never below salvage.
+
+**Auto rate** (when `depreciation_rate` omitted):
+
+```
+depreciable_amount = max(purchase_cost − salvage_value, 0)
+depreciation_rate = (depreciable_amount / purchase_cost / useful_life_years) × 100
+```
+
+**Amounts:**
+
+```
+annual_depreciation = purchase_cost × rate / 100
+accumulated_depreciation = min(annual_depreciation × capped_years, purchase_cost − salvage_value)
+book_value = max(purchase_cost − accumulated_depreciation, salvage_value)
+```
+
+**Example:** cost = ₹1,00,000 · salvage = ₹10,000 · life = 10 years · start = 1 year ago
+
+- Rate = ((100000−10000)/100000/10)×100 = **9%**
+- Annual = 100000 × 9% = **₹9,000**
+- Accumulated (1 yr) = **₹9,000**
+- Book value = **₹91,000**
+
+### Method 2 — WDV (Written Down Value)
+
+Depreciation each year on the **reducing book value**. Book value never goes below salvage.
+
+**Auto rate** (when `depreciation_rate` omitted; needs salvage > 0 and < cost):
+
+```
+depreciation_rate = (1 − (salvage_value / purchase_cost)^(1 / useful_life_years)) × 100
+```
+
+**Amounts (year-by-year):**
+
+```
+book_value = purchase_cost
+for each full year in capped_years:
+ year_dep = book_value × rate / 100
+ book_value = max(book_value − year_dep, salvage_value)
+if fractional year remains:
+ year_dep = (book_value × rate / 100) × fraction
+ book_value = max(book_value − year_dep, salvage_value)
+
+accumulated_depreciation = purchase_cost − book_value
+annual_depreciation = book_value × rate / 100 // next year's dep on current WDV
+```
+
+**Example:** cost = ₹1,00,000 · salvage = ₹10,000 · life = 10 years · start = 1 year ago
+
+- Rate ≈ (1 − (10000/100000)^(1/10)) × 100 ≈ **20.57%**
+- Year 1 dep ≈ 100000 × 20.57% ≈ **₹20,570**
+- Book value ≈ **₹79,430**
+- Accumulated ≈ **₹20,570**
+- Next annual (on WDV) ≈ 79430 × 20.57% ≈ **₹16,340**
+
+### OTHER method
+
+Same accumulation style as SLM, but `depreciation_rate` is **mandatory** (no auto-calc).
+
+| Method | Rate auto-calc? | Depreciates on | Salvage role |
+|---|---|---|---|
+| **SLM** | Yes (if rate omitted) | Original `purchase_cost` every year | In rate formula + book-value floor |
+| **WDV** | Yes (if rate omitted) | Reducing book value each year | In rate formula + book-value floor |
+| **OTHER** | No — send `depreciation_rate` | Original cost × rate (like SLM) | Book-value floor only |
**FE usage:**
- **Live preview** → `POST /assets/depreciation/calculate` (no save)
- **Saved asset view** → `GET /assets/:id` → `data.depreciation` object
- **Method dropdown** → `GET /assets/depreciation-methods`
+- Prefer sending `commencement_date`; backend falls back to `purchase_date`
---
diff --git a/src/docs/assets-routes.yaml b/src/docs/assets-routes.yaml
index 0a4ae31..8ed260d 100644
--- a/src/docs/assets-routes.yaml
+++ b/src/docs/assets-routes.yaml
@@ -509,6 +509,9 @@ paths:
get:
tags: [Assets]
summary: List assets
+ description: >
+ Each item includes purchase_cost, current_value (book value after depreciation),
+ and a depreciation summary object (method, rate, annual, accumulated, book_value, years_elapsed).
parameters:
- { name: page, in: query, schema: { type: integer } }
- { name: limit, in: query, schema: { type: integer } }
diff --git a/src/modules/assets/assets.service.js b/src/modules/assets/assets.service.js
index b610278..e97d60c 100644
--- a/src/modules/assets/assets.service.js
+++ b/src/modules/assets/assets.service.js
@@ -148,12 +148,24 @@ const sanitizeAsset = (asset) => {
? Number(rest.depreciation_rate)
: null;
+ const depreciation = calculateDepreciation({
+ depreciation_method: rest.depreciation_method,
+ depreciation_rate: depreciationRate,
+ purchase_cost: purchaseCost,
+ salvage_value: salvageValue,
+ useful_life_years: rest.useful_life_years,
+ commencement_date: rest.commencement_date,
+ purchase_date: rest.purchase_date,
+ });
+
return {
...rest,
maintenance_checklist_json: presentChecklistTemplate(rest.maintenance_checklist_json),
purchase_cost: purchaseCost,
salvage_value: salvageValue,
depreciation_rate: depreciationRate,
+ // Current written-down / book value after depreciation (same as depreciation.book_value)
+ current_value: depreciation.book_value,
item_category: item_categories || null,
item_subcategory: item_subcategories || null,
location: location || null,
@@ -167,15 +179,10 @@ const sanitizeAsset = (asset) => {
created_by_user: users_assets_created_byTousers || null,
updated_by_user: users_assets_updated_byTousers || null,
attachments: (asset_attachments || []).map(sanitizeAttachment),
- depreciation: calculateDepreciation({
- depreciation_method: rest.depreciation_method,
- depreciation_rate: depreciationRate,
- purchase_cost: purchaseCost,
- salvage_value: salvageValue,
- useful_life_years: rest.useful_life_years,
- commencement_date: rest.commencement_date,
- purchase_date: rest.purchase_date,
- }),
+ depreciation: {
+ ...depreciation,
+ current_value: depreciation.book_value,
+ },
item_categories: undefined,
item_subcategories: undefined,
departments: undefined,
@@ -486,6 +493,11 @@ const exportAssets = async (query) => {
{ key: 'commencement_date', header: 'Commencement Date', type: 'date' },
{ key: 'purchase_date', header: 'Purchase Date', type: 'date' },
{ key: 'purchase_cost', header: 'Purchase Cost' },
+ { key: 'current_value', header: 'Current Value' },
+ { key: (row) => row.depreciation?.accumulated_depreciation ?? '', header: 'Accumulated Depreciation' },
+ { key: (row) => row.depreciation?.annual_depreciation ?? '', header: 'Annual Depreciation' },
+ { key: (row) => row.depreciation?.depreciation_method || '', header: 'Depreciation Method' },
+ { key: (row) => row.depreciation?.depreciation_rate ?? '', header: 'Depreciation Rate %' },
{ key: 'warranty_expiry_date', header: 'Warranty Expiry', type: 'date' },
{
key: (row) => row.maintenance_incharge_user?.full_name || '',