Download Latest Version v0.4.0 -- Security fix + behavioral change_ manager hierarchy visibility source code.zip (1.3 MB)
Email in envelope

Get an email when there's a new version of openestate

Home / v0.2.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-08-06 6.0 kB
v0.2.0 -- PLC _ unit-charge pricing_ GST and collection correctness fixes source code.tar.gz 2026-08-06 859.7 kB
v0.2.0 -- PLC _ unit-charge pricing_ GST and collection correctness fixes source code.zip 2026-08-06 1.2 MB
Totals: 3 Items   2.1 MB 0

Upgrade note: upgrade-native.sh now syncs new PERMISSIONS rows to existing installs automatically (see the permission-delivery fix below), but it does not — and should not — grant them to any role for you. After upgrading, an admin must open Admin → Roles, edit each role that should get the new PLC/charge-management capability, check inventory.unit.plc-manage / inventory.unit.charge-manage, and save. This is a deliberate, permissions-only sync — see the entry below for why auto-granting them would be its own bug, not a fix.

Fixed

  • Correctness fix affecting GST charged on bookings and extra charges — check your invoices if your company's GST State Code was ever unset. isIntraStateSupply() used to silently default to intra-state (CGST+SGST) whenever the company's GST state code or a booking's place-of-supply state code was missing, instead of raising an error. Any company whose Company Config GST fields were never filled in — every install created before those columns existed, or any install where nobody had visited Company Config yet — has been charging CGST+SGST on every booking and extra charge regardless of where the property actually is, which is the WRONG tax treatment (IGST) whenever the real place of supply is in a different state from the company's own. This produced no error and no warning; the only way to notice was to already know the correct treatment and check by hand. If this applies to you, review bookings/extra charges made while your GST config was incomplete and correct any wrongly-taxed invoices — this release does not retroactively fix already-issued invoices. Going forward, isIntraStateSupply() now throws instead of guessing — a booking or extra charge with incomplete GST config is rejected with a clear error naming what to set in Company Config, rather than silently taxed wrong. The app also now logs a warning at boot listing any company with incomplete GST config, and the staff admin UI shows a persistent banner linking to Company Config until it's completed.

  • Correctness fix affecting reported collection figures — upgrade and let the migration run before trusting any collection report. A prior bug (see the REPORTS-phase entry in CLAUDE.md) left bounced-cheque receipts still marked as collected (is_reversed = false) in every collection report, rollup, and the customer portal's own payment history — the code fix stops this going forward, but does nothing for receipts that already bounced before you upgrade. Migration 20260804120000_backfill_bounced_receipt_is_reversed corrects those existing rows on your next prisma migrate deploy (part of the normal upgrade path — no manual step needed). It only touches the is_reversed/reversal_reason flag on affected receipts; it does not alter any ledger entry, allocation, or installment. If your reported collection totals looked too high before upgrading, they'll drop by the sum of any previously-bounced cheques once this runs.

  • A release that adds a PERMISSIONS constant never reached an existing install — only a fresh one. seed.ts's permission-upsert loop ran unconditionally, but the early-return gate right after it (if (existingCompany) return) meant no other seeded content, and critically no later permission addition, was ever re-applied to a company created in an earlier release. upgrade-native.sh now runs a dedicated sync-permissions.ts step (idempotent, permissions-table only) on every upgrade, so new permission rows reach existing installs the same way they reach fresh ones. Deliberately does NOT extend to masters or roles — see the upgrade note above and CLAUDE.md for why that's a different (and mostly correct-as-is) problem.

  • A system role (super_admin, company_admin, etc.) could never be granted a newly-added permission through the UI, at all. RolesService.update() rejected any change to a system role, not just a rename — so even with the fix above delivering the permission row, there was no way to actually grant it to a role. Scoped the guard to an actual name change only; a system role's permission set is now freely editable (its name and existence stay protected, as before).

Added

  • PLC and unit-charge management. Unit-level PLCs (park-facing, corner, etc.) and extra charges (IFMS, legal, etc.) can now be assigned per unit from the Inventory → Project → Pricing panel, and flow into a booking's cost breakup and the confirm step's total automatically. PLC amounts are snapshotted in paise at assignment time (from a percentage of the unit's rate, or a flat amount) and never retroactively change if the base rate is revised later.
  • Per-charge-type GST rates. Charge Types now carry their own optional GST rate and HSN/SAC code (Masters → Charge Types). A cost line's GST resolves in order: its own rate, then its charge type's rate, then the booking's base-line rate — never silently zero-rated. A PLC line has no charge type, so it always inherits the base line's rate; this is stated explicitly rather than left implicit.

Changed

  • Replaced the argon2 password-hashing dependency with @node-rs/argon2 (pure Rust via napi-rs). argon2 had caused two separate deployment failures on two different platforms (an Alpine/musl prebuild issue, and a still-unexplained SIGSEGV crash-loop on GitHub's ubuntu-latest CI runners — see CLAUDE.md for the full, ultimately-inconclusive investigation); the replacement ships prebuilt binaries for every platform this project targets and never falls back to compiling from source. Existing stored password hashes remain verifiable — both libraries use the same standard PHC string format, confirmed by directly cross-verifying a real hash between the two before switching. No action needed on upgrade, no password resets.
Source: README.md, updated 2026-08-06