Skip to content

Cost tracking + Profit/Loss reporting (#82)#163

Merged
v0l merged 3 commits into
masterfrom
cost-tracking
Jul 15, 2026
Merged

Cost tracking + Profit/Loss reporting (#82)#163
v0l merged 3 commits into
masterfrom
cost-tracking

Conversation

@v0l

@v0l v0l commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Closes #82.

Summary

Adds optional, admin-only cost tracking used to compute profit/loss, plus a P/L report endpoint.

Rather than adding cost columns to vm_host/ip_range, costs live in one generic resource_cost table weakly linked to any resource via (resource_type, resource_id). This is extensible (new cost-bearing resource kinds need no schema change) and lets a single resource carry multiple cost rows (e.g. a host's recurring rent and a one-time hardware investment).

DB changes

  • New resource_cost table: resource_type (TINYINT enum: vm_host/ip_range), resource_id, cost_type (recurring/one_time), amount (smallest units; per-IP for ip_range recurring), currency, interval_amount/interval_type (reuses existing IntervalType), billing_start, billing_end (null = ongoing), timestamps.
  • AdminResource::ResourceCost (24) + migration granting super_admin the full permission set.
  • ResourceCost, CostResourceType, CostType models; AdminDb CRUD + admin_list_resource_costs_active_between; mysql + mock impls.

Admin API

Dedicated cost endpoints (resource_cost permission):

  • GET/POST /api/admin/v1/resource_costs
  • GET/PATCH/DELETE /api/admin/v1/resource_costs/{id} (PATCH-clear semantics for interval/billing fields)

Profit/Loss report

GET /api/admin/v1/reports/profit-loss (modelled on the sales time-series report, analytics::view):

  • Per-period (month/year) rows, reported in a single target currency (currency param or the company's base currency).
  • Revenue uses each payment's stored historical rate to value it in its company base currency (never live rates); a base→report-currency step only applies when aggregating companies with differing base currencies.
  • Costs (no stored rate) are converted with current exchange rates; recurring costs normalized per active calendar month, ip_range per-IP costs scaled by the range's current assigned-IP count, one-time costs booked in their billing_start period.
  • Optional company_id and region_id filters.

Deferred (follow-up)

  • Historical (per-month) IP assignment counts — currently uses the range's current assigned-IP count.
  • Costs are global, not company-scoped (so company_id filters revenue only).

Testing

  • cargo build --workspace clean; cargo test -p lnvps_db model roundtrip tests pass (incl. new ResourceCost/CostType enum roundtrips).

Docs

  • ADMIN_API_ENDPOINTS.md and API_CHANGELOG.md updated.

v0l added 3 commits July 15, 2026 15:05
Add optional, admin-only cost tracking via a generic resource_cost table
weakly linked to any resource by (resource_type, resource_id), plus a
profit/loss report.

- DB: resource_cost table (recurring/one-time, interval + billing_start/
  billing_end), AdminResource::ResourceCost (24) RBAC + migration
- Model: ResourceCost, CostResourceType, CostType enums
- AdminDb CRUD + active-between query; mysql + mock impls
- Admin API: dedicated /api/admin/v1/resource_costs endpoints
- Report: GET /api/admin/v1/reports/profit-loss (month/year), converted to
  a single target currency. Revenue uses each payment's stored historical
  rate; costs use current exchange rates. company_id + region_id filters.
- Docs: ADMIN_API_ENDPOINTS.md, API_CHANGELOG.md
Add CostResourceType::Generic (2) for costs not tied to an internal DB
entity, identified by a user-supplied free-form label (e.g. colo/transit
subscriptions). Adds a nullable label column; resource_id is ignored for
generic costs and they are excluded from region-filtered reports.
@v0l
v0l force-pushed the cost-tracking branch from e0332a1 to 7aa622e Compare July 15, 2026 14:07
@v0l
v0l merged commit 470f8b7 into master Jul 15, 2026
8 checks passed
@v0l
v0l deleted the cost-tracking branch July 15, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cost Tracking

1 participant