feat: add VAT settings page and controller

This commit is contained in:
Ghassan Yusuf 2026-06-01 12:10:01 +03:00
parent b19396c996
commit 04ced4d2da
3 changed files with 91 additions and 0 deletions

View File

@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers\Settings;
use App\Http\Controllers\Controller;
use App\Models\Setting;
use Illuminate\Http\Request;
class VatSettingController extends Controller
{
public function index()
{
$vatRate = Setting::get('vat_rate', '0');
return view('settings.vat', compact('vatRate'));
}
public function update(Request $request)
{
$validated = $request->validate([
'vat_rate' => ['required', 'numeric', 'min:0', 'max:100'],
]);
Setting::set('vat_rate', (string) $validated['vat_rate']);
return response()->json(['message' => 'VAT rate saved.', 'vat_rate' => $validated['vat_rate']]);
}
}

View File

@ -0,0 +1,59 @@
@extends('layouts.app')
@section('title', 'Settings — VAT')
@section('content')
<div class="mb-5">
<h1 class="page-title">VAT Settings</h1>
<p class="page-subtitle">Set the global VAT rate applied to vatable items on supplier quotes.</p>
</div>
<div style="max-width:480px;">
<div style="background:white;border:1px solid #e2e8f0;border-radius:0.875rem;overflow:hidden;">
<div style="padding:1.25rem 1.5rem;border-bottom:1px solid #e2e8f0;background:#f8fafc;">
<div style="font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:.05em;">VAT Configuration</div>
</div>
<div style="padding:1.5rem;">
<label style="display:block;font-size:12px;font-weight:600;color:#374151;margin-bottom:6px;">
VAT Rate (%)
</label>
<div style="display:flex;align-items:center;gap:10px;">
<input type="number" id="vat-rate-input" value="{{ $vatRate }}"
min="0" max="100" step="0.01" placeholder="e.g. 10"
style="width:160px;padding:9px 12px;border:1.5px solid #e2e8f0;border-radius:8px;font-size:14px;font-weight:600;outline:none;"
onfocus="this.style.borderColor='#2563eb'" onblur="this.style.borderColor='#e2e8f0'">
<span style="font-size:14px;color:#64748b;font-weight:500;">%</span>
</div>
<p style="font-size:12px;color:#94a3b8;margin-top:8px;">
Enter 0 to disable VAT. Suppliers will see a VAT checkbox on each item when this is greater than 0.
</p>
<button onclick="saveVat()"
style="margin-top:20px;padding:10px 24px;background:#2563eb;color:#fff;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;">
Save VAT Rate
</button>
</div>
</div>
</div>
<script>
var CSRF = document.querySelector('meta[name="csrf-token"]').content;
function saveVat() {
var rate = document.getElementById('vat-rate-input').value;
fetch('{{ route('settings.vat.update') }}', {
method: 'POST',
headers: { 'X-CSRF-TOKEN': CSRF, 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({ vat_rate: rate })
}).then(function(r) {
return r.json().then(function(body) {
if (!r.ok) return Promise.reject(body);
return body;
});
}).then(function() {
showToast('VAT rate saved.', 'success');
}).catch(function(err) {
var msg = (err.errors && err.errors.vat_rate) ? err.errors.vat_rate[0] : (err.message || 'Failed to save.');
showToast(msg, 'error');
});
}
</script>
@endsection

View File

@ -29,6 +29,7 @@ use App\Http\Controllers\Sales\SalesOrderController;
use App\Http\Controllers\MailAccountController; use App\Http\Controllers\MailAccountController;
use App\Http\Controllers\SettingsController; use App\Http\Controllers\SettingsController;
use App\Http\Controllers\Settings\ProjectSettingController; use App\Http\Controllers\Settings\ProjectSettingController;
use App\Http\Controllers\Settings\VatSettingController;
use App\Models\Settings\Location; use App\Models\Settings\Location;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -163,6 +164,10 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::post('settings/projects/companies/{company}/departments', [ProjectSettingController::class, 'storeDepartment'])->name('settings.projects.companies.departments.store'); Route::post('settings/projects/companies/{company}/departments', [ProjectSettingController::class, 'storeDepartment'])->name('settings.projects.companies.departments.store');
Route::patch('settings/projects/companies/{company}/departments/{department}', [ProjectSettingController::class, 'updateDepartment'])->name('settings.projects.companies.departments.update'); Route::patch('settings/projects/companies/{company}/departments/{department}', [ProjectSettingController::class, 'updateDepartment'])->name('settings.projects.companies.departments.update');
Route::delete('settings/projects/companies/{company}/departments/{department}', [ProjectSettingController::class, 'destroyDepartment'])->name('settings.projects.companies.departments.destroy'); Route::delete('settings/projects/companies/{company}/departments/{department}', [ProjectSettingController::class, 'destroyDepartment'])->name('settings.projects.companies.departments.destroy');
// VAT settings
Route::get('settings/vat', [VatSettingController::class, 'index'])->name('settings.vat');
Route::post('settings/vat', [VatSettingController::class, 'update'])->name('settings.vat.update');
}); });
}); });