Files
TheTree_mock/tests/s2/test_facility_upkeep_settlement.gd
Takeshi 5dde0c5ec2 Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
2026-09-30 23:52:24 +09:00

129 lines
7.8 KiB
GDScript

extends SceneTree
const Accrual = preload("res://scripts/economy/facility_upkeep_accrual.gd")
const Settlement = preload("res://scripts/economy/facility_upkeep_settlement.gd")
var checks := 0
var failures := 0
class RejectingEconomy:
extends EconomyService
func post(_entries: Array, _key: StringName = &"", _transaction: StringName = &"", _notify := true) -> CommandResult:
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, 0, "injected refusal")
func _initialize() -> void:
call_deferred("_run")
func expect(value: bool, label: String) -> void:
checks += 1
if not value:
failures += 1
push_error(label)
func _economy(cash: int) -> EconomyService:
var economy := EconomyService.new({&"PLAYER_CASH": false})
if cash > 0:
economy.initialize_account(&"PLAYER_CASH", cash)
expect(Settlement.prepare_accounts(economy), "prepare designated expense/payable accounts")
return economy
func _period(start: int, units: Dictionary) -> Dictionary:
return {&"period_start": start, &"period_end": (start / 1440 + 1) * 1440, &"facility_units": units}
func _run() -> void:
var economy := _economy(5)
var service := Settlement.new()
var period := _period(0, {"a": 10 * 1440, "b": 2 * 1440 + 10})
var first := service.settle(period, economy)
expect(first.ok and not first.replayed, "first midnight settles")
expect(economy.get_balance(Settlement.CASH) == 0, "cash cannot become negative")
expect(economy.get_balance(Settlement.EXPENSE) == 12, "expense includes unpaid amount")
expect(economy.get_balance(Settlement.PAYABLE) == -7, "seven gold remains payable")
expect(service.get_report().arrears_by_facility == {"a": 5, "b": 2}, "insufficient funds allocate deterministically by facility ID")
expect(service.get_report().fraction_units == {"b": 10}, "sub-gold expense is retained")
expect(economy.has_pending_transaction_notification(first.transaction_id), "notification is deferred to outer transaction commit")
expect(economy.commit_transaction_notification(first.transaction_id), "notification can be published after state commit")
var guard := economy.create_snapshot()
var snapshot := service.create_snapshot()
var replay := service.settle(period, economy)
expect(replay.ok and replay.replayed and replay.transaction_id == &"", "same settlement is idempotent and emits no notification")
expect(economy.create_snapshot() == guard and service.create_snapshot() == snapshot, "replay changes neither balances nor receipts")
var wrong := period.duplicate(true)
wrong.facility_units.a += 1
expect(not service.settle(wrong, economy).ok and economy.create_snapshot() == guard, "changed request cannot reuse a closed period")
expect(not service.settle(_period(2880, {}), economy).ok, "missing financial day rejected")
# Facility a has been demolished; its debt must still be paid next midnight.
economy.initialize_account(Settlement.CASH, 20, 1500, &"cash.for.next.day")
var second := service.settle(_period(1440, {"b": 1430}), economy)
expect(second.ok, "following day settles including prior arrears")
expect(service.get_arrears_through(1439) == 0, "no historical debt before first settlement")
expect(service.get_arrears_through(1440) == 7, "historical close retains its original debt after repayment")
expect(service.get_arrears_through(2879) == 7, "interim query uses the last completed settlement")
expect(service.get_arrears_through(2880) == 0, "repayment boundary clears current debt")
expect(service.get_arrears_through(9999) == 0, "future query does not invent debt")
expect(economy.get_balance(Settlement.EXPENSE) == 13, "prior debt repayment is not a new expense")
expect(economy.get_balance(Settlement.CASH) == 12 and economy.get_balance(Settlement.PAYABLE) == 0, "eight gold pays debt and new fractional carry")
expect(service.get_report().arrears_total == 0 and service.get_report().fraction_units.is_empty(), "debt and fractions cleared after payment")
expect(service.validate_ledger(economy) and economy.validate_ledger().ok, "service and double-entry ledger reconcile")
var expense_entries := 0
var payment_entries := 0
for entry: LedgerEntry in economy.get_entries():
if entry.category == &"MAINTENANCE_ACCRUAL":
expense_entries += 1
expect(entry.absolute_minute in [1439, 2879], "expense belongs to the day being closed")
if entry.category == &"MAINTENANCE_PAYMENT":
payment_entries += 1
expect(entry.absolute_minute in [1440, 2880], "cash payment records actual midnight")
expect(expense_entries == 3 and payment_entries == 3, "only positive recognized expenses and payments produce entries")
var loaded_economy := EconomyService.new()
expect(loaded_economy.restore_snapshot(economy.create_snapshot()), "ledger restores")
var loaded := Settlement.new()
expect(loaded.restore_snapshot(service.create_snapshot(), loaded_economy), "receipts restore with ledger crosschecks")
expect(loaded.get_report() == service.get_report(), "derived debt/fractions rebuild exactly")
var future := _period(2880, {"new": 3 * 1440})
expect(service.settle(future, economy).ok and loaded.settle(future, loaded_economy).ok, "both timelines advance")
expect(service.create_snapshot() == loaded.create_snapshot() and economy.create_snapshot() == loaded_economy.create_snapshot(), "same future after reload")
var valid := loaded.create_snapshot()
var invalid := valid.duplicate(true)
invalid.receipts[0].rows[0].new_expense += 1
expect(not loaded.restore_snapshot(invalid, loaded_economy) and loaded.create_snapshot() == valid, "forged expense rejected atomically")
invalid = valid.duplicate(true)
invalid.receipts[0].rows[0].paid = true
expect(not loaded.restore_snapshot(invalid, loaded_economy), "boolean amount rejected")
invalid = valid.duplicate(true)
invalid.receipts[0].transaction_id = "missing"
expect(not loaded.restore_snapshot(invalid, loaded_economy), "missing ledger transaction rejected")
invalid = valid.duplicate(true)
invalid.receipts[0].period.facility_units.a += 1
expect(not loaded.restore_snapshot(invalid, loaded_economy), "forged numerator and unchanged receipt rejected")
invalid = valid.duplicate(true)
invalid.receipts.pop_front()
expect(not loaded.restore_snapshot(invalid, loaded_economy), "omitting settled debt history rejected by ledger ownership")
invalid = valid.duplicate(true)
invalid.version = 2
expect(not loaded.restore_snapshot(invalid, loaded_economy), "unknown save version rejected")
var unrelated := _economy(100)
expect(not loaded.restore_snapshot(valid, unrelated), "receipts cannot be restored onto unrelated money")
var rejecting := RejectingEconomy.new({Settlement.CASH: false})
expect(Settlement.prepare_accounts(rejecting), "prepare rejecting ledger")
var failed_service := Settlement.new()
var before_service := failed_service.create_snapshot()
var before_ledger := rejecting.create_snapshot()
expect(not failed_service.settle(_period(0, {"room": 1440}), rejecting).ok, "ledger failure propagates")
expect(failed_service.create_snapshot() == before_service and rejecting.create_snapshot() == before_ledger, "failed ledger post leaves all authoritative state unchanged")
var empty := Settlement.new()
var no_cash := _economy(0)
expect(empty.settle(_period(0, {}), no_cash).ok, "empty day requires no zero-value ledger entry")
var empty_loaded := Settlement.new()
expect(empty_loaded.restore_snapshot(empty.create_snapshot(), no_cash), "empty settled day persists")
# End-to-end cost math at completion/demolition boundaries with real ledger.
var accrual := Accrual.new()
accrual.start_at(360)
accrual.advance_to(720, {})
accrual.advance_to(1080, {"built_at_noon": 24})
var closed: Dictionary = accrual.advance_to(1440, {}).closed_periods[0]
var life := Settlement.new()
var life_cash := _economy(100)
expect(life.settle(closed, life_cash).ok and life_cash.get_balance(Settlement.EXPENSE) == 6, "six-hour completed ownership charges six gold after demolition")
print("%s: %d checks" % ["PASS" if failures == 0 else "FAIL", checks])
quit(failures)