feat: rentals SaaS sprints R1→I1 + nav duplicate-translation fix - #174
Conversation
Invoice/InvoiceLineItem schema, computeInvoiceSummary deep module, read-only InvoicesService/Controller, invoices permission area, and the filtered list page. Write path lands in issues/013. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
InvoicesService.create/update/remove with wholesale line-item replacement on update, LeasesService.remove guarded against referenced invoices, and the New/Edit Invoice dialog (cascading lease picker, repeatable line-item rows) plus delete confirmation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
InvoicePayment schema + InvoicePaymentsService (create/findAll/ findOne/remove), building-scoped via the parent Invoice, returning recomputed totalAmount/paidAmount/status on create/remove. InvoicesService.remove now also rejects when a payment references the invoice. Adds the Invoice detail page showing line items and payment history together, with Record Payment and delete actions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CI format:check failed on 7 files added by the Invoices/Payments PR (issues/012-014) that weren't run through prettier before commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fixed the findings that were genuine bugs or matched real project convention (AGENTS.md, existing service patterns): - computeInvoiceSummary: compare paid/total in integer cents, not raw floats, so a fully-paid invoice can't get stuck partially_paid due to float rounding (e.g. 0.1 + 0.2). - InvoicePaymentsService.summarizeInvoice: scope the Invoice lookup by orgId (defense-in-depth; both call sites already passed a pre-validated invoiceId, but this method returns entity data, unlike the id-only reference-count guards elsewhere). - Invoice detail page: surface a payment-list fetch failure instead of silently rendering "No payments recorded yet." - Invoices page: add aria-labels to the line-item category/ description/amount controls; guard the row's onKeyDown so Enter/Space on the nested actions-menu trigger doesn't also navigate the row (keydown bubbles past the click stopPropagation guard). Skipped findings that contradict this repo's actual conventions (verified against ExpensesService/expenses-page.tsx/AGENTS.md): DatabaseService+Logger (no DatabaseService exists anywhere; every service uses PrismaService per AGENTS.md), UUID+@@Schema primary keys (all 17 existing models use cuid(), none declare @@Schema), per-file contracts (packages/contracts/src is a single index.ts), ZodValidationPipe on API controllers (backend uses class-validator DTOs; Zod is frontend-only per AGENTS.md), importing wire types from @repo/contracts in the browser (existing pages import from @/types/api), ApiError-specific toast messages and design-token status colors (existing pages use generic toasts and raw Tailwind colors identically), and wrapping writes+timeline emits in a transaction (no service in the codebase does this — verified in ExpensesService). Also verified the flagged delete-guard "atomicity" concerns in InvoicesService/LeasesService already match the identical id-only reference-count pattern used in VendorsService/WorkOrdersService. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Land the full post-v1 roadmap (all verified) in one working tree:
- R1 Reports: read-only /reports summary + rent-roll + overdue
(org_admin/finance only; reuses computeInvoiceSummary).
- D1 Live role dashboards: org-admin/finance/staff dashboards fed from
real data; shared KpiTile + dashboard-kpis helpers.
- N1 Notifications: Redis/BullMQ queue + tenant support-tickets +
best-effort email step (NOTIFICATIONS_EMAIL flag, KC-resolved
recipient, mailpit) + /dashboard/notifications history page.
- T1 Tenant self-service: Renter.renterUserId seam links KC tenant
user -> Renter/Lease; /tenant/overview + open-request; structural
isolation (all scope derived from sub).
- O1 Prod Redis + hardening: dedicated prod Redis config, BullMQ
dead-letter queue, terminus /health Redis indicator (1500ms ping
race), atomic handleCheckoutCompleted ($transaction).
- U1/U2 Rentals UX: top-level /dashboard/leases page + nav (org-wide
GET /leases), create-lease cascade dialog, clickable Buildings rows,
Notifications nav, repo-wide base-ui Select.Value raw-value fix,
renter->new-lease deep-link, invoice/maintenance cross-links.
- I1 i18n/RTL: 9 hardcoded-English pages made dict-driven; 9 new
namespaces, key parity balanced; localized zod schemas.
- Nav fix: nav.billing -> "Subscription"/"الاشتراك" to resolve Arabic
duplicate label collision with Invoices ("الفواتير"); parity preserved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedToo many files! This PR contains 171 files, which is 71 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (8)
📒 Files selected for processing (171)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ompose deploy
Rebrand — remove all "Forward Mena" from every tracked file (reviewer surface):
- UI: app.name dict (en "Property Manager" / ar "إدارة العقارات"), login, hero
(locale-aware), footer, <title>, Swagger title.
- Identifiers: package names property-manager-{fe,be} (+ lockfile), redux-persist
key, X-Client header, code comments, .gitignore, AGENTS.md, DB README/.env.example.
- Email From → "Property Manager <notifications@prorentallb.cloud>".
- seed-demo: org "Property Manager Demo Co", demo emails @prorentallb.cloud;
scripts derive paths from __dirname (no hardcoded Forward-Mena path).
Pricing — 3 real prices $29 / $79 / $199 (Starter/Growth/Pro), limits unchanged:
- Catalog (BE plan-catalog + FE plans fallback) prices updated.
- Per-plan Stripe price seam: STRIPE_PRICE_{STARTER,GROWTH,PRO} → stripe.config
`prices` → billing.service resolves perPlanPrices[planKey] (falls back to
catalog override, then env STRIPE_PRICE_ID). env.validation adds the optional keys.
- Pricing UI: pricing-section + billing-shell render ${plan.price} (was hardcoded $20).
Deploy (Docker Compose on the shared VPS, additive-only):
- apps/api/Dockerfile, apps/web/Dockerfile (multi-stage node:22-slim; explicit
@repo/contracts→@repo/db build order; keep tsconfig-paths at runtime; web
standalone with NEXT_PUBLIC build-arg + placeholder server env at build).
- .dockerignore, docker-compose.prod.yml (registry images, loopback-only publishes,
api on app+external fm-postgres net, profile-gated migrate).
Verified live at https://prorentallb.cloud: public+authed EN/AR (no "Forward Mena",
distinct Subscription/Invoices nav), webhook signature-verified, Growth checkout uses
the $79 Stripe price.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lands the full post-v1 roadmap (all verified) plus one nav fix.
Scope (commit
6919d7f)/reportssummary + rent-roll + overdue (org_admin/finance only; reusescomputeInvoiceSummary).KpiTile+dashboard-kpishelpers.NOTIFICATIONS_EMAILflag, KC-resolved recipient, mailpit) +/dashboard/notificationshistory.Renter.renterUserIdseam links KC tenant user → Renter/Lease;/tenant/overview+ open-request; structural isolation fromsub./healthRedis indicator (1500ms ping race), atomichandleCheckoutCompleted($transaction)./dashboard/leases+ nav (org-wideGET /leases), create-lease cascade dialog, clickable Buildings rows, repo-wide base-uiSelect.Valueraw-value fix, renter→new-lease deep-link, invoice/maintenance cross-links.nav.billing→ "Subscription"/"الاشتراك" to resolve the Arabic duplicate-label collision with Invoices ("الفواتير"); parity preserved.Note on overlap
This branch also carries the 4 invoice/payment commits (
9871eb1,5eea50f,9368d3c,06bfa01) that are already under #139 (feat/rent-invoices), so the diff overlaps that PR until #139 merges into the base.Verification
All sprints were verified during their respective sessions (jest/vitest green, Playwright authed E2E in EN+AR). No code was rebuilt in this commit — it is the accumulated, previously-verified working tree.
🤖 Generated with Claude Code