interim fix for drop downs, BROKEN FIX, interinm fix

This commit is contained in:
Mark Gregory
2026-07-07 12:38:13 +01:00
parent a12372963a
commit 12c1470319
10 changed files with 251 additions and 83 deletions
@@ -4,6 +4,7 @@ namespace Modules\Company\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Modules\Company\Models\Company;
@@ -16,12 +17,24 @@ class CompanyController extends Controller
*/
public function index()
{
$counts = ['users', 'warehouses', 'licenseKeys'];
if (Schema::hasTable('company_divisions')) {
$counts[] = 'divisions';
}
$companies = Company::query()
->with(['country'])
->withCount($counts)
->orderBy('name')
->paginate(20);
$companies->getCollection()->each(function (Company $company): void {
$company->setAttribute('divisions_count', $company->getAttribute('divisions_count') ?? 0);
});
return view('company::index', [
'companies' => Company::query()
->with(['address.country', 'country'])
->withCount(['users', 'warehouses', 'licenseKeys', 'divisions'])
->orderBy('name')
->paginate(20),
'companies' => $companies,
'countries' => $this->countries(),
]);
}
@@ -57,16 +70,20 @@ class CompanyController extends Controller
*/
public function show(Company $company)
{
$company->load([
'address.country',
'divisions.address.country',
'divisions.warehouses',
'divisions.users',
'warehouses.address.country',
'warehouses.division',
'directorAssignments.user',
'directorAssignments.division',
])->loadCount(['users', 'warehouses', 'licenseKeys', 'payments', 'divisions']);
$loads = ['country'];
$counts = ['users', 'warehouses', 'licenseKeys', 'payments'];
if (Schema::hasTable('company_divisions')) {
$loads[] = 'divisions';
$counts[] = 'divisions';
}
if (Schema::hasTable('company_director_assignments')) {
$loads[] = 'directorAssignments.user';
}
$company->load($loads)->loadCount($counts);
$company->setAttribute('divisions_count', $company->getAttribute('divisions_count') ?? 0);
return view('company::show', [
'company' => $company,
@@ -74,8 +91,6 @@ class CompanyController extends Controller
'recentWarehouses' => $company->warehouses()->latest('id')->limit(5)->get(),
'recentLicenseKeys' => $company->licenseKeys()->latest('id')->limit(5)->get(),
'countries' => $this->countries(),
'companyUsers' => $company->users()->orderBy('name')->get(['id', 'name', 'email', 'company_id']),
'unassignedWarehouses' => $company->warehouses()->whereNull('division_id')->orderBy('name')->get(),
]);
}
@@ -85,7 +100,7 @@ class CompanyController extends Controller
public function edit(Company $company)
{
return view('company::edit', [
'company' => $company->loadMissing(['address.country', 'country']),
'company' => $company->loadMissing('country'),
'countries' => $this->countries(),
]);
}
@@ -125,10 +140,14 @@ class CompanyController extends Controller
'country_id' => ['nullable', Rule::exists('countries', 'id')->where('is_active', true)],
]);
$data['slug'] = Str::slug($data['name']);
$data['timezone'] = $company?->timezone ?: 'Europe/London';
return $data;
return [
'name' => $data['name'],
'billing_email' => $data['billing_email'] ?? null,
'status' => $data['status'],
'country_id' => $data['country_id'] ?? null,
'slug' => Str::slug($data['name']),
'timezone' => $company?->timezone ?: 'Europe/London',
];
}
private function countries()
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Modules\Company\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Modules\Countries\Models\Country;
class CompanyAddress extends Model
{
protected $guarded = [];
protected $casts = [
'is_primary' => 'boolean',
];
public function addressable(): MorphTo
{
return $this->morphTo();
}
public function country(): BelongsTo
{
return $this->belongsTo(Country::class);
}
}
@@ -0,0 +1,27 @@
<?php
namespace Modules\Company\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class CompanyDirectorAssignment extends Model
{
protected $guarded = [];
public function company(): BelongsTo
{
return $this->belongsTo(Company::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function division(): BelongsTo
{
return $this->belongsTo(CompanyDivision::class, 'company_division_id');
}
}
@@ -0,0 +1,35 @@
<?php
namespace Modules\Company\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Modules\Warehouse\app\Models\Warehouse;
class CompanyDivision extends Model
{
protected $guarded = [];
public function company(): BelongsTo
{
return $this->belongsTo(Company::class);
}
public function address(): MorphOne
{
return $this->morphOne(CompanyAddress::class, 'addressable');
}
public function warehouses(): HasMany
{
return $this->hasMany(Warehouse::class, 'division_id');
}
public function users(): HasMany
{
return $this->hasMany(User::class, 'division_id');
}
}
@@ -7,7 +7,7 @@
id="name"
name="name"
value="{{ old('name', $company->name) }}"
class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
class="mt-2 h-12 w-full rounded-xl border-zinc-300 bg-white px-4 text-sm text-zinc-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
required
>
@error('name')
@@ -23,7 +23,7 @@
name="billing_email"
value="{{ old('billing_email', $company->billing_email) }}"
placeholder="billing@example.com"
class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
class="mt-2 h-12 w-full rounded-xl border-zinc-300 bg-white px-4 text-sm text-zinc-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
>
@error('billing_email')
<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
@@ -35,7 +35,7 @@
<select
id="status"
name="status"
class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
class="mt-2 h-12 w-full rounded-xl border-zinc-300 bg-white px-4 text-sm text-zinc-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
required
>
<option value="active" @selected(old('status', $company->status) === 'active')>Active</option>
@@ -54,12 +54,12 @@
name="country_id"
data-wms-select2
data-placeholder="Search and select a country"
class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
class="w-full"
>
<option value="">Search and select a country</option>
<option value=""></option>
@foreach ($countries as $country)
<option value="{{ $country->id }}" @selected((int) old('country_id', $company->country_id ?? $company->address?->country_id) === $country->id)>
{{ $country->effective_name ?? $country->name }}
<option value="{{ $country->id }}" @selected((int) old('country_id', $company->country_id) === $country->id)>
{{ $country->display_name ?: $country->common_name ?: $country->name }}
</option>
@endforeach
</select>
@@ -70,7 +70,7 @@
</div>
<div class="mt-6 flex flex-wrap items-center gap-3">
<button class="rounded-xl bg-zinc-900 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-zinc-700 dark:bg-white dark:text-zinc-900">
<button class="rounded-xl bg-green-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-green-500/40">
Save company
</button>
@@ -0,0 +1,16 @@
<x-layouts::app :title="__('Create company')">
<div class="space-y-6">
<x-wms.page-hero
eyebrow="Platform Administration"
title="Create company"
description="Add a new tenant company and assign its country."
icon="fa-solid fa-building-circle-plus"
/>
<div class="rounded-3xl bg-white p-6 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<form method="POST" action="{{ route('platform.companies.store') }}">
@include('company::_form')
</form>
</div>
</div>
</x-layouts::app>
@@ -0,0 +1,17 @@
<x-layouts::app :title="__('Edit company')">
<div class="space-y-6">
<x-wms.page-hero
eyebrow="Platform Administration"
title="Edit company"
description="Update company details and country assignment."
icon="fa-solid fa-building"
/>
<div class="rounded-3xl bg-white p-6 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<form method="POST" action="{{ route('platform.companies.update', $company) }}">
@method('PUT')
@include('company::_form')
</form>
</div>
</div>
</x-layouts::app>
+13 -50
View File
@@ -86,11 +86,11 @@
name="country_id"
data-wms-select2
data-placeholder="Search and select country"
class="mt-2 w-full"
class="w-full"
>
<option value="">Search and select country</option>
@foreach ($countries as $country)
<option value="{{ $country->id }}" @selected((int) old('country_id') === $country->id)>
<option value=""></option>
@foreach($countries as $country)
<option value="{{ $country->id }}" @selected(old('country_id') == $country->id)>
{{ $country->display_name ?: $country->common_name ?: $country->name }}
</option>
@endforeach
@@ -127,23 +127,10 @@
<td class="p-4 font-semibold text-zinc-900 dark:text-white">
{{ $company->name }}
</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">
{{ $company->users_count }}
</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">
{{ $company->divisions_count }}
</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">
{{ $company->warehouses_count }}
</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">
{{ $company->license_keys_count }}
</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">{{ $company->users_count }}</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">{{ $company->divisions_count ?? 0 }}</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">{{ $company->warehouses_count }}</td>
<td class="p-4 text-zinc-700 dark:text-zinc-300">{{ $company->license_keys_count }}</td>
<td class="p-4">
<span class="inline-flex rounded-full px-2.5 py-1 text-xs font-semibold
@if ($company->is_system_company)
@@ -157,38 +144,16 @@
{{ $company->is_system_company ? 'System' : ucfirst($company->status) }}
</span>
</td>
<td class="p-4">
<div class="flex justify-end gap-2">
<a
href="{{ route('platform.companies.show', $company) }}"
class="rounded-lg border border-zinc-300 px-3 py-1.5 text-xs font-semibold text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-800"
>
View
</a>
<a
href="{{ route('platform.companies.edit', $company) }}"
class="rounded-lg bg-blue-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-blue-700"
>
Edit
</a>
<a href="{{ route('platform.companies.show', $company) }}" class="rounded-lg border border-zinc-300 px-3 py-1.5 text-xs font-semibold text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-800">View</a>
<a href="{{ route('platform.companies.edit', $company) }}" class="rounded-lg bg-blue-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-blue-700">Edit</a>
@unless ($company->is_system_company)
<form
method="POST"
action="{{ route('platform.companies.destroy', $company) }}"
onsubmit="return confirm('Delete this company? This cannot be undone.');"
>
<form method="POST" action="{{ route('platform.companies.destroy', $company) }}" onsubmit="return confirm('Delete this company? This cannot be undone.');">
@csrf
@method('DELETE')
<button
type="submit"
class="rounded-lg bg-red-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-red-700"
>
Delete
</button>
<button type="submit" class="rounded-lg bg-red-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-red-700">Delete</button>
</form>
@endunless
</div>
@@ -196,9 +161,7 @@
</tr>
@empty
<tr>
<td colspan="7" class="p-8 text-center text-zinc-500 dark:text-zinc-400">
No companies found.
</td>
<td colspan="7" class="p-8 text-center text-zinc-500 dark:text-zinc-400">No companies found.</td>
</tr>
@endforelse
</tbody>
@@ -0,0 +1,66 @@
<x-layouts::app :title="$company->name">
<div class="space-y-6">
<x-wms.page-hero
eyebrow="Platform Administration"
:title="$company->name"
description="Company tenant overview."
icon="fa-solid fa-building"
/>
@if (session('status'))
<div class="rounded-2xl bg-green-50 p-4 text-sm font-semibold text-green-700 ring-1 ring-green-200 dark:bg-green-950 dark:text-green-300 dark:ring-green-900">
{{ session('status') }}
</div>
@endif
<div class="grid gap-4 md:grid-cols-4">
<div class="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<p class="text-xs font-bold uppercase tracking-wide text-zinc-500">Users</p>
<p class="mt-2 text-2xl font-bold text-zinc-900 dark:text-white">{{ $company->users_count ?? 0 }}</p>
</div>
<div class="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<p class="text-xs font-bold uppercase tracking-wide text-zinc-500">Divisions</p>
<p class="mt-2 text-2xl font-bold text-zinc-900 dark:text-white">{{ $company->divisions_count ?? 0 }}</p>
</div>
<div class="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<p class="text-xs font-bold uppercase tracking-wide text-zinc-500">Warehouses</p>
<p class="mt-2 text-2xl font-bold text-zinc-900 dark:text-white">{{ $company->warehouses_count ?? 0 }}</p>
</div>
<div class="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<p class="text-xs font-bold uppercase tracking-wide text-zinc-500">Licences</p>
<p class="mt-2 text-2xl font-bold text-zinc-900 dark:text-white">{{ $company->license_keys_count ?? 0 }}</p>
</div>
</div>
<div class="rounded-3xl bg-white p-6 shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<h2 class="text-lg font-bold text-zinc-900 dark:text-white">Company details</h2>
<dl class="mt-4 grid gap-4 text-sm md:grid-cols-2">
<div>
<dt class="font-semibold text-zinc-500">Billing email</dt>
<dd class="mt-1 text-zinc-900 dark:text-white">{{ $company->billing_email ?: 'Not set' }}</dd>
</div>
<div>
<dt class="font-semibold text-zinc-500">Country</dt>
<dd class="mt-1 text-zinc-900 dark:text-white">{{ $company->country?->display_name ?: $company->country?->common_name ?: $company->country?->name ?: 'Not set' }}</dd>
</div>
<div>
<dt class="font-semibold text-zinc-500">Status</dt>
<dd class="mt-1 text-zinc-900 dark:text-white">{{ ucfirst($company->status) }}</dd>
</div>
<div>
<dt class="font-semibold text-zinc-500">Timezone</dt>
<dd class="mt-1 text-zinc-900 dark:text-white">{{ $company->timezone }}</dd>
</div>
</dl>
</div>
<div class="flex gap-2">
<a href="{{ route('platform.companies.edit', $company) }}" class="rounded-xl bg-blue-600 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-700">Edit</a>
<a href="{{ route('platform.companies.index') }}" class="rounded-xl border border-zinc-300 px-4 py-2 text-sm font-semibold text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-800">Back</a>
</div>
</div>
</div>
</div>
</x-layouts::app>
+1 -3
View File
@@ -24,10 +24,8 @@ Route::middleware(['auth', 'verified', 'tenant.assigned', 'platform.admin'])
Route::post('/licenses', [LicenseKeyController::class, 'store'])->name('licenses.store');
Route::get('/payments', [PaymentController::class, 'index'])->name('payments.index');
Route::post('/payments', [PaymentController::class, 'store'])->name('payments.store');
if (! Route::has('platform.companies.index')) {
Route::resource('/companies', CompanyController::class);
}
Route::resource('/prices', PlatformPriceController::class)->except(['show']);
Route::resource('/companies', CompanyController::class);
});
Route::post('/stripe/webhook', StripeWebhookController::class)->name('stripe.webhook');