diff --git a/app/Console/Commands/ApplyRealEstateRevaluationCommand.php b/app/Console/Commands/ApplyRealEstateRevaluationCommand.php
new file mode 100644
index 00000000..ddd002e7
--- /dev/null
+++ b/app/Console/Commands/ApplyRealEstateRevaluationCommand.php
@@ -0,0 +1,72 @@
+whereNotNull('revaluation_percentage')
+ ->where('revaluation_percentage', '!=', 0)
+ ->with('account')
+ ->get();
+
+ $applied = 0;
+ $skipped = 0;
+
+ foreach ($details as $detail) {
+ $account = $detail->account;
+
+ if (! $account) {
+ $skipped++;
+
+ continue;
+ }
+
+ $latestBalance = $account->balances()
+ ->orderByDesc('balance_date')
+ ->first();
+
+ if (! $latestBalance) {
+ $skipped++;
+
+ continue;
+ }
+
+ $monthlyRate = (float) $detail->revaluation_percentage / 12 / 100;
+ $newBalance = (int) round($latestBalance->balance * (1 + $monthlyRate));
+
+ $account->balances()->updateOrCreate(
+ ['balance_date' => now()->toDateString()],
+ ['balance' => $newBalance],
+ );
+
+ $applied++;
+ }
+
+ $this->info("Revaluation applied to {$applied} account(s), skipped {$skipped}.");
+
+ return self::SUCCESS;
+ }
+}
diff --git a/app/Http/Controllers/Settings/AccountController.php b/app/Http/Controllers/Settings/AccountController.php
index 1b8762c6..f0ec307e 100644
--- a/app/Http/Controllers/Settings/AccountController.php
+++ b/app/Http/Controllers/Settings/AccountController.php
@@ -64,6 +64,7 @@ class AccountController extends Controller
$realEstateData = collect($validated)->only([
'property_type', 'address', 'purchase_price', 'purchase_date',
'area_value', 'area_unit', 'linked_loan_account_id', 'notes',
+ 'revaluation_percentage',
])->filter(fn ($value) => $value !== null)->toArray();
if (! empty($realEstateData)) {
diff --git a/app/Http/Requests/Settings/StoreAccountRequest.php b/app/Http/Requests/Settings/StoreAccountRequest.php
index a9d4ef46..d977ed16 100644
--- a/app/Http/Requests/Settings/StoreAccountRequest.php
+++ b/app/Http/Requests/Settings/StoreAccountRequest.php
@@ -71,6 +71,7 @@ class StoreAccountRequest extends FormRequest
}),
],
'notes' => ['nullable', 'string', 'max:2000'],
+ 'revaluation_percentage' => ['nullable', 'numeric', 'min:-100', 'max:100'],
]);
}
diff --git a/app/Http/Requests/UpdateRealEstateDetailRequest.php b/app/Http/Requests/UpdateRealEstateDetailRequest.php
index 49afbeb5..fc7ba89f 100644
--- a/app/Http/Requests/UpdateRealEstateDetailRequest.php
+++ b/app/Http/Requests/UpdateRealEstateDetailRequest.php
@@ -46,6 +46,7 @@ class UpdateRealEstateDetailRequest extends FormRequest
}),
],
'notes' => ['nullable', 'string', 'max:2000'],
+ 'revaluation_percentage' => ['nullable', 'numeric', 'min:-100', 'max:100'],
];
}
}
diff --git a/app/Models/RealEstateDetail.php b/app/Models/RealEstateDetail.php
index 3e727100..e87fb6ed 100644
--- a/app/Models/RealEstateDetail.php
+++ b/app/Models/RealEstateDetail.php
@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property PropertyType $property_type
* @property int|null $purchase_price
+ * @property string|null $revaluation_percentage
*/
class RealEstateDetail extends Model
{
@@ -28,6 +29,7 @@ class RealEstateDetail extends Model
'area_value',
'area_unit',
'notes',
+ 'revaluation_percentage',
];
protected function casts(): array
@@ -37,6 +39,7 @@ class RealEstateDetail extends Model
'purchase_price' => 'integer',
'purchase_date' => 'date',
'area_value' => 'decimal:2',
+ 'revaluation_percentage' => 'decimal:2',
];
}
diff --git a/database/factories/RealEstateDetailFactory.php b/database/factories/RealEstateDetailFactory.php
index e9ebb894..e936ae30 100644
--- a/database/factories/RealEstateDetailFactory.php
+++ b/database/factories/RealEstateDetailFactory.php
@@ -29,6 +29,7 @@ class RealEstateDetailFactory extends Factory
'area_value' => fake()->randomFloat(2, 50, 500),
'area_unit' => fake()->randomElement(['sqm', 'sqft']),
'notes' => fake()->optional()->sentence(),
+ 'revaluation_percentage' => fake()->optional()->randomFloat(2, -5, 10),
];
}
diff --git a/database/migrations/2026_03_25_125717_add_revaluation_percentage_to_real_estate_details_table.php b/database/migrations/2026_03_25_125717_add_revaluation_percentage_to_real_estate_details_table.php
new file mode 100644
index 00000000..28479066
--- /dev/null
+++ b/database/migrations/2026_03_25_125717_add_revaluation_percentage_to_real_estate_details_table.php
@@ -0,0 +1,28 @@
+decimal('revaluation_percentage', 5, 2)->nullable()->after('notes');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('real_estate_details', function (Blueprint $table) {
+ $table->dropColumn('revaluation_percentage');
+ });
+ }
+};
diff --git a/lang/es.json b/lang/es.json
index 086bd2d4..99250148 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -27,6 +27,7 @@
"...and 40+ more": "...y m\u00e1s de 40",
"/12 min": "/12 min",
"/month": "/mes",
+ "/year": "/año",
"1,200+ users": "1.200+ usuarios",
"1. Data Controller": "1. Controlador de Datos",
"10. Children's Privacy": "10. Privacidad de los Ni\u00f1os",
@@ -152,6 +153,9 @@
"Amount is required": "Se requiere un valor",
"An unexpected error occurred during sync.": "Se produjo un error inesperado durante la sincronizaci\u00f3n.",
"Annual": "Anual",
+ "Annual Revaluation": "Revalorización anual",
+ "Annual Revaluation (%)": "Revalorización anual (%)",
+ "Annual percentage applied monthly. Use negative values for depreciation.": "Porcentaje anual aplicado mensualmente. Usa valores negativos para depreciación.",
"Any bugs, viruses, or similar harmful components transmitted through the service": "Cualquier error, virus o componente da\u00f1ino similar transmitido a trav\u00e9s del servicio",
"Any bugs, viruses, or similar harmful\\n components transmitted through the service": "Cualquier error, virus u otros componentes da\u00f1inos transmitidos a trav\u00e9s del servicio",
"Any errors or omissions in content or any loss or damage incurred from using content": "Cualquier error u omisi\u00f3n en el contenido o cualquier p\u00e9rdida o da\u00f1o incurrido por usar el contenido",
diff --git a/resources/js/components/accounts/account-form.tsx b/resources/js/components/accounts/account-form.tsx
index 6e50bb10..d15ec2a7 100644
--- a/resources/js/components/accounts/account-form.tsx
+++ b/resources/js/components/accounts/account-form.tsx
@@ -33,6 +33,7 @@ import { CustomBankData, CustomBankForm } from './custom-bank-form';
const BALANCE_ACCOUNT_TYPES: AccountType[] = [
'investment',
'loan',
+ 'real_estate',
'retirement',
'savings',
];
@@ -46,6 +47,7 @@ export interface RealEstateFormData {
areaUnit: AreaUnit | null;
linkedLoanAccountId: string | null;
notes: string;
+ revaluationPercentage: string;
}
export interface AccountFormData {
@@ -86,6 +88,7 @@ const initialRealEstateData: RealEstateFormData = {
areaUnit: null,
linkedLoanAccountId: null,
notes: '',
+ revaluationPercentage: '',
};
export function AccountForm({
@@ -522,6 +525,33 @@ export function AccountForm({
rows={3}
/>
+
+
+
+
+ setRealEstateData((prev) => ({
+ ...prev,
+ revaluationPercentage: e.target.value,
+ }))
+ }
+ placeholder="0.00"
+ min="-100"
+ max="100"
+ step="0.01"
+ />
+
+ {__(
+ 'Annual percentage applied monthly. Use negative values for depreciation.',
+ )}
+
+
>
)}
>
diff --git a/resources/js/components/accounts/create-account-dialog.tsx b/resources/js/components/accounts/create-account-dialog.tsx
index 030d68c1..bd7f6ad3 100644
--- a/resources/js/components/accounts/create-account-dialog.tsx
+++ b/resources/js/components/accounts/create-account-dialog.tsx
@@ -185,6 +185,9 @@ export function CreateAccountDialog({
.linkedLoanAccountId,
notes:
formDataRef.current.realEstate.notes || null,
+ revaluation_percentage:
+ formDataRef.current.realEstate
+ .revaluationPercentage || null,
}
: {}),
},
diff --git a/resources/js/pages/Accounts/Show.tsx b/resources/js/pages/Accounts/Show.tsx
index 1b3407fa..4fa68979 100644
--- a/resources/js/pages/Accounts/Show.tsx
+++ b/resources/js/pages/Accounts/Show.tsx
@@ -553,6 +553,10 @@ function PropertyDetailsCard({
linked_loan_account_id:
detail.linked_loan_account_id ?? (null as string | null),
notes: detail.notes ?? '',
+ revaluation_percentage:
+ detail.revaluation_percentage != null
+ ? String(detail.revaluation_percentage)
+ : '',
});
function handleSubmit(e: React.FormEvent) {
@@ -570,6 +574,7 @@ function PropertyDetailsCard({
area_unit: formData.area_unit,
linked_loan_account_id: formData.linked_loan_account_id,
notes: formData.notes || null,
+ revaluation_percentage: formData.revaluation_percentage || null,
},
{
preserveScroll: true,
@@ -589,6 +594,10 @@ function PropertyDetailsCard({
area_unit: detail.area_unit ?? null,
linked_loan_account_id: detail.linked_loan_account_id ?? null,
notes: detail.notes ?? '',
+ revaluation_percentage:
+ detail.revaluation_percentage != null
+ ? String(detail.revaluation_percentage)
+ : '',
});
onEditToggle(false);
}
@@ -795,6 +804,32 @@ function PropertyDetailsCard({
/>
+
+
+
+ setFormData((prev) => ({
+ ...prev,
+ revaluation_percentage: e.target.value,
+ }))
+ }
+ placeholder="0.00"
+ min="-100"
+ max="100"
+ step="0.01"
+ />
+
+ {__(
+ 'Annual percentage applied monthly. Use negative values for depreciation.',
+ )}
+
+
+
)}
+
+ {detail.revaluation_percentage != null && (
+
+
+ {__('Annual Revaluation')}
+
+
+ {Number(detail.revaluation_percentage) > 0
+ ? '+'
+ : ''}
+ {detail.revaluation_percentage}%{__('/year')}
+
+
+ )}
{detail.notes && (
diff --git a/resources/js/types/account.ts b/resources/js/types/account.ts
index 21a1d687..878ab229 100644
--- a/resources/js/types/account.ts
+++ b/resources/js/types/account.ts
@@ -94,6 +94,7 @@ export interface RealEstateDetail {
area_value: string | null;
area_unit: AreaUnit | null;
notes: string | null;
+ revaluation_percentage: number | null;
linked_loan_account_id: UUID | null;
linked_loan_account: Account | null;
current_market_value: number | null;
diff --git a/routes/console.php b/routes/console.php
index d860e9bc..a3e3fc37 100644
--- a/routes/console.php
+++ b/routes/console.php
@@ -7,3 +7,4 @@ Schedule::command('horizon:snapshot')->everyFiveMinutes();
Schedule::command('budgets:generate-periods')->daily();
Schedule::command('banking:sync')->everySixHours();
Schedule::command('banks:check-logos')->weekly();
+Schedule::command('real-estate:apply-revaluation')->monthlyOn(1, '00:00');
diff --git a/tests/Feature/ApplyRealEstateRevaluationTest.php b/tests/Feature/ApplyRealEstateRevaluationTest.php
new file mode 100644
index 00000000..5e63fbbe
--- /dev/null
+++ b/tests/Feature/ApplyRealEstateRevaluationTest.php
@@ -0,0 +1,285 @@
+user = User::factory()->onboarded()->create();
+});
+
+// -------------------------------------------------------------------
+// Applying revaluation to accounts with positive percentage
+// -------------------------------------------------------------------
+
+it('applies positive annual revaluation monthly', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => 6.00, // 6% annual = 0.5% monthly
+ ]);
+
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 10000000, // 100,000.00
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ $newBalance = AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->first();
+
+ expect($newBalance)->not->toBeNull();
+ // 10,000,000 * (1 + 6/12/100) = 10,000,000 * 1.005 = 10,050,000
+ expect($newBalance->balance)->toBe(10050000);
+});
+
+// -------------------------------------------------------------------
+// Applying revaluation with negative percentage (depreciation)
+// -------------------------------------------------------------------
+
+it('applies negative annual revaluation monthly', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => -12.00, // -12% annual = -1% monthly
+ ]);
+
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 20000000, // 200,000.00
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ $newBalance = AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->first();
+
+ expect($newBalance)->not->toBeNull();
+ // 20,000,000 * (1 + (-12)/12/100) = 20,000,000 * 0.99 = 19,800,000
+ expect($newBalance->balance)->toBe(19800000);
+});
+
+// -------------------------------------------------------------------
+// Skipping accounts without balance
+// -------------------------------------------------------------------
+
+it('skips accounts that have no existing balance', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => 5.00,
+ ]);
+
+ // No balance created
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ expect(AccountBalance::where('account_id', $account->id)->count())->toBe(0);
+});
+
+// -------------------------------------------------------------------
+// Skipping accounts with null revaluation percentage
+// -------------------------------------------------------------------
+
+it('skips accounts with null revaluation percentage', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => null,
+ ]);
+
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 10000000,
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ // Should not create a new balance for today
+ expect(
+ AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->exists()
+ )->toBeFalse();
+});
+
+// -------------------------------------------------------------------
+// Skipping accounts with zero revaluation percentage
+// -------------------------------------------------------------------
+
+it('skips accounts with zero revaluation percentage', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => 0,
+ ]);
+
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 10000000,
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ expect(
+ AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->exists()
+ )->toBeFalse();
+});
+
+// -------------------------------------------------------------------
+// Uses the latest balance as the basis for revaluation
+// -------------------------------------------------------------------
+
+it('uses the latest balance for revaluation calculation', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => 12.00, // 1% monthly
+ ]);
+
+ // Older balance
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->subMonths(3)->toDateString(),
+ 'balance' => 5000000,
+ ]);
+
+ // More recent balance — this should be used
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 10000000,
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ $newBalance = AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->first();
+
+ // Should use 10,000,000 not 5,000,000
+ // 10,000,000 * 1.01 = 10,100,000
+ expect($newBalance->balance)->toBe(10100000);
+});
+
+// -------------------------------------------------------------------
+// Processes multiple accounts
+// -------------------------------------------------------------------
+
+it('processes multiple real estate accounts', function () {
+ $account1 = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account1->id,
+ 'revaluation_percentage' => 12.00,
+ ]);
+ AccountBalance::factory()->create([
+ 'account_id' => $account1->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 10000000,
+ ]);
+
+ $user2 = User::factory()->onboarded()->create();
+ $account2 = Account::factory()->realEstate()->create([
+ 'user_id' => $user2->id,
+ ]);
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account2->id,
+ 'revaluation_percentage' => 6.00,
+ ]);
+ AccountBalance::factory()->create([
+ 'account_id' => $account2->id,
+ 'balance_date' => now()->subMonth()->toDateString(),
+ 'balance' => 20000000,
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ $balance1 = AccountBalance::query()
+ ->where('account_id', $account1->id)
+ ->where('balance_date', now()->toDateString())
+ ->first();
+
+ $balance2 = AccountBalance::query()
+ ->where('account_id', $account2->id)
+ ->where('balance_date', now()->toDateString())
+ ->first();
+
+ expect($balance1->balance)->toBe(10100000); // 10M * 1.01
+ expect($balance2->balance)->toBe(20100000); // 20M * 1.005
+});
+
+// -------------------------------------------------------------------
+// Upserts balance for today if one already exists
+// -------------------------------------------------------------------
+
+it('updates existing balance for today instead of creating duplicate', function () {
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => 12.00,
+ ]);
+
+ AccountBalance::factory()->create([
+ 'account_id' => $account->id,
+ 'balance_date' => now()->toDateString(),
+ 'balance' => 10000000,
+ ]);
+
+ artisan('real-estate:apply-revaluation')->assertSuccessful();
+
+ // Should have exactly one balance for today (upserted, not duplicated)
+ expect(
+ AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->count()
+ )->toBe(1);
+
+ $balance = AccountBalance::query()
+ ->where('account_id', $account->id)
+ ->where('balance_date', now()->toDateString())
+ ->first();
+
+ // 10,000,000 * 1.01 = 10,100,000
+ expect($balance->balance)->toBe(10100000);
+});
diff --git a/tests/Feature/RealEstateTest.php b/tests/Feature/RealEstateTest.php
index 0ec859bd..7d7c4f90 100644
--- a/tests/Feature/RealEstateTest.php
+++ b/tests/Feature/RealEstateTest.php
@@ -592,3 +592,156 @@ it('preserves real estate detail when account is soft deleted', function () {
// Real estate detail still exists (FK cascade only applies to hard deletes)
assertDatabaseHas('real_estate_details', ['id' => $detail->id]);
});
+
+// -------------------------------------------------------------------
+// Creating real estate accounts with balance and revaluation percentage
+// -------------------------------------------------------------------
+
+it('can create a real estate account with initial market value', function () {
+ actingAs($this->user);
+
+ $data = [
+ 'name' => 'My House',
+ 'currency_code' => 'EUR',
+ 'type' => AccountType::RealEstate->value,
+ 'property_type' => PropertyType::Residential->value,
+ 'balance' => 30000000, // 300,000.00 in cents
+ ];
+
+ $response = $this->post(route('accounts.store'), $data);
+
+ $response->assertRedirect();
+
+ $account = Account::query()
+ ->where('user_id', $this->user->id)
+ ->where('type', AccountType::RealEstate->value)
+ ->first();
+
+ assertDatabaseHas('account_balances', [
+ 'account_id' => $account->id,
+ 'balance' => 30000000,
+ 'balance_date' => now()->toDateString(),
+ ]);
+});
+
+it('can create a real estate account with revaluation percentage', function () {
+ actingAs($this->user);
+
+ $data = [
+ 'name' => 'Appreciating Property',
+ 'currency_code' => 'USD',
+ 'type' => AccountType::RealEstate->value,
+ 'property_type' => PropertyType::Residential->value,
+ 'balance' => 50000000,
+ 'revaluation_percentage' => 3.50,
+ ];
+
+ $response = $this->post(route('accounts.store'), $data);
+
+ $response->assertRedirect();
+
+ $account = Account::query()
+ ->where('user_id', $this->user->id)
+ ->where('type', AccountType::RealEstate->value)
+ ->first();
+
+ assertDatabaseHas('real_estate_details', [
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => '3.50',
+ ]);
+
+ assertDatabaseHas('account_balances', [
+ 'account_id' => $account->id,
+ 'balance' => 50000000,
+ ]);
+});
+
+it('can create a real estate account with negative revaluation percentage', function () {
+ actingAs($this->user);
+
+ $data = [
+ 'name' => 'Depreciating Property',
+ 'currency_code' => 'USD',
+ 'type' => AccountType::RealEstate->value,
+ 'property_type' => PropertyType::Commercial->value,
+ 'revaluation_percentage' => -2.00,
+ ];
+
+ $response = $this->post(route('accounts.store'), $data);
+
+ $response->assertRedirect();
+
+ $account = Account::query()
+ ->where('user_id', $this->user->id)
+ ->where('type', AccountType::RealEstate->value)
+ ->first();
+
+ assertDatabaseHas('real_estate_details', [
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => '-2.00',
+ ]);
+});
+
+it('validates revaluation percentage is between -100 and 100', function () {
+ actingAs($this->user);
+
+ $data = [
+ 'name' => 'My House',
+ 'currency_code' => 'USD',
+ 'type' => AccountType::RealEstate->value,
+ 'property_type' => PropertyType::Residential->value,
+ 'revaluation_percentage' => 150,
+ ];
+
+ $response = $this->post(route('accounts.store'), $data);
+
+ $response->assertSessionHasErrors(['revaluation_percentage']);
+});
+
+it('can update revaluation percentage via real estate detail endpoint', function () {
+ actingAs($this->user);
+
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ $detail = RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => null,
+ ]);
+
+ $response = $this->patch(route('accounts.real-estate-detail.update', $account), [
+ 'revaluation_percentage' => 5.25,
+ ]);
+
+ $response->assertRedirect(route('accounts.show', $account));
+
+ assertDatabaseHas('real_estate_details', [
+ 'id' => $detail->id,
+ 'revaluation_percentage' => '5.25',
+ ]);
+});
+
+it('can clear revaluation percentage by setting null', function () {
+ actingAs($this->user);
+
+ $account = Account::factory()->realEstate()->create([
+ 'user_id' => $this->user->id,
+ ]);
+
+ RealEstateDetail::factory()->create([
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => 3.50,
+ ]);
+
+ $response = $this->patch(route('accounts.real-estate-detail.update', $account), [
+ 'revaluation_percentage' => null,
+ ]);
+
+ $response->assertRedirect(route('accounts.show', $account));
+
+ assertDatabaseHas('real_estate_details', [
+ 'account_id' => $account->id,
+ 'revaluation_percentage' => null,
+ ]);
+});