feat(assets): atomic asset disposal workflow (avyttring, utrangering, verksamhetsoverlatelse) (#1391)
* feat(assets): atomic asset disposal workflow (avyttring, utrangering, verksamhetsoverlatelse) Disposal books depreciation to the disposal date, clears cost and accumulated depreciation, books gain (3973) or loss (7973), applies output VAT on third-party sales, honors the ML 5 kap. 38 § verksamhetsoverlatelse exemption, and recalculates ML 15 kap. jamkning server-side from tax years and original input VAT. The voucher, the disposal-date depreciation schedule and the immutable register state commit in one dedicated commit_asset_disposal RPC transaction that delegates voucher numbering to commit_journal_entry. Fixes #325 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(assets): harden disposal per review and pg-real findings - commit_asset_disposal now uses the NULL-safe caller_is_company_member() guard (tenant-guard ratchet) and passes the allowed 'user_accept' commit_method instead of the unlisted 'asset_disposal' value - disposal metadata invariants validated in the RPC (non-negative proceeds/VAT, VAT requires a treatment, VAT <= gross, scrap carries no proceeds) since the RPC is independently callable - new FK and CHECK constraints added NOT VALID + VALIDATE CONSTRAINT so the migration never blocks writes on the hot journal_entries table - disposeAsset paginates fiscal periods and depreciation schedules with fetchAllRows; jamkning_remaining_years keeps a valid 0 (?? not ||) - engine imports shared AssetDisposalType/AssetJamkningDirection/ VatTreatment unions; post-commit reload retries once and logs before surfacing, so a transient read cannot masquerade as a failed disposal - dispose page parses Swedish-formatted amounts (125 000,50) and blocks submission on unparseable proceeds - assets pg tests write disposal attributes in the disposal transition itself and gain a regression test that the register is frozen after Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
1c9d378df8
commit
cb3ef45f14
+56
-1
@@ -836,7 +836,62 @@
|
||||
"category_vehicle": "Vehicle",
|
||||
"category_computer": "Computer",
|
||||
"category_other_tangible": "Other tangible",
|
||||
"count_footer": "{count, plural, one {1 asset} other {# assets}}"
|
||||
"count_footer": "{count, plural, one {1 asset} other {# assets}}",
|
||||
"disposal": {
|
||||
"title": "Dispose of asset",
|
||||
"load_failed_title": "Could not load the disposal",
|
||||
"try_again": "Please try again.",
|
||||
"submit_failed_title": "Disposal failed",
|
||||
"success_title": "Asset disposed",
|
||||
"success_description": "Depreciation, disposal, and the asset register were posted together.",
|
||||
"not_found": "The asset could not be found.",
|
||||
"already_disposed": "The asset was already disposed ({date}).",
|
||||
"back": "Back",
|
||||
"acquisition_cost": "Acquisition cost",
|
||||
"acquired": "Acquired",
|
||||
"bas_accounts": "Accounts (BAS)",
|
||||
"details_title": "Disposal details",
|
||||
"type_label": "Event",
|
||||
"type_sale": "Sale",
|
||||
"type_scrap": "Scrapping",
|
||||
"type_business_transfer": "Transfer of a business",
|
||||
"date_label": "Disposal date",
|
||||
"period_label": "Fiscal period",
|
||||
"period_placeholder": "Select period",
|
||||
"locked": "locked",
|
||||
"period_locked": "The selected period is locked or closed. Select an open period.",
|
||||
"proceeds_label": "Amount received including VAT",
|
||||
"consideration_label": "Consideration for the asset",
|
||||
"proceeds_account_label": "Receiving account",
|
||||
"vat_title": "VAT on the sale",
|
||||
"vat_treatment_label": "VAT treatment",
|
||||
"vat_standard_25": "Swedish VAT 25%",
|
||||
"vat_reverse_charge": "Reverse charge",
|
||||
"vat_export": "Export outside the EU",
|
||||
"vat_exempt": "VAT-exempt sale",
|
||||
"gross": "Gross",
|
||||
"vat": "Output VAT",
|
||||
"net": "Net",
|
||||
"adjustment_title": "Input VAT adjustment (ML chapter 15)",
|
||||
"within_adjustment_period": "Within the adjustment period: {years} years remain of {total}",
|
||||
"outside_adjustment_period": "Outside the adjustment period",
|
||||
"original_vat_label": "Total original input VAT",
|
||||
"original_vat_hint": "Enter the full VAT amount, not only the deducted part. Threshold: SEK {threshold}.",
|
||||
"original_percent_label": "Original deduction right (%)",
|
||||
"adjustment_direction": "Direction",
|
||||
"adjustment_amount": "Calculated adjustment",
|
||||
"direction_increase": "Increased deduction",
|
||||
"direction_decrease": "Decreased deduction",
|
||||
"direction_none": "No adjustment",
|
||||
"direction_transferred": "Transferred to the acquirer",
|
||||
"adjustment_capped": "The amount was capped at 25% of the sale price excluding VAT.",
|
||||
"business_transfer_confirm": "I confirm that the transfer covers an entire business or independent branch and meets the conditions in ML chapter 5, section 38.",
|
||||
"adjustment_document_confirm": "I confirm that an adjustment document is prepared for the acquirer.",
|
||||
"adjustment_data_required": "VAT basis data is required because the asset may be an investment good.",
|
||||
"cancel": "Cancel",
|
||||
"submit": "Post disposal",
|
||||
"write_required": "Only users with write access can dispose of assets."
|
||||
}
|
||||
},
|
||||
"employees": {
|
||||
"title": "Employees",
|
||||
|
||||
Reference in New Issue
Block a user