diff --git a/app/Http/Controllers/CustomerSupportController.php b/app/Http/Controllers/CustomerSupportController.php
index b1b2a6c..c2813a9 100644
--- a/app/Http/Controllers/CustomerSupportController.php
+++ b/app/Http/Controllers/CustomerSupportController.php
@@ -201,7 +201,7 @@ public function support_details(Request $request)
public function support_create(Request $request): RedirectResponse
{
Validator::make($request->toArray(), [
- 'category_id' => ['required', 'integer'],
+ 'category_id' => ['nullable', 'integer'],
'subject' => ['required', 'string'],
'priority' => ['required', 'string'],
'message' => ['required', 'string'],
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index bc70acd..d64d643 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -7,7 +7,9 @@
use App\Http\Middleware\Authenticate;
use App\Http\Middleware\EncryptCookies;
use App\Http\Middleware\IdentifyAdminProductLists;
+use App\Http\Middleware\IdentifyAdminStatus;
use App\Http\Middleware\IdentifyCustomerProductLists;
+use App\Http\Middleware\IdentifyCustomerStatus;
use App\Http\Middleware\IdentifyTenant;
use App\Http\Middleware\InjectNavigateables;
use App\Http\Middleware\InjectShopCategoryOrProduct;
@@ -112,5 +114,7 @@ class Kernel extends HttpKernel
'shop.categoryOrProduct' => InjectShopCategoryOrProduct::class,
'products.admin' => IdentifyAdminProductLists::class,
'products.customer' => IdentifyCustomerProductLists::class,
+ 'status.admin' => IdentifyAdminStatus::class,
+ 'status.customer' => IdentifyCustomerStatus::class,
];
}
diff --git a/app/Http/Middleware/IdentifyAdminProductLists.php b/app/Http/Middleware/IdentifyAdminProductLists.php
index 7a6cbec..a39aacd 100644
--- a/app/Http/Middleware/IdentifyAdminProductLists.php
+++ b/app/Http/Middleware/IdentifyAdminProductLists.php
@@ -29,7 +29,7 @@ public function handle(Request $request, Closure $next)
{
$results = [];
- $products = Products::list()->reject(function ($handler) {
+ Products::list()->reject(function ($handler) {
return !$handler->ui()->admin;
})->each(function ($handler) use (&$results) {
$results[] = (object) [
diff --git a/app/Http/Middleware/IdentifyAdminStatus.php b/app/Http/Middleware/IdentifyAdminStatus.php
new file mode 100644
index 0000000..7fbcefd
--- /dev/null
+++ b/app/Http/Middleware/IdentifyAdminStatus.php
@@ -0,0 +1,70 @@
+
+ */
+class IdentifyAdminStatus
+{
+ /**
+ * Handle an incoming request.
+ *
+ * @param Request $request
+ * @param Closure $next
+ *
+ * @return mixed
+ */
+ public function handle(Request $request, Closure $next)
+ {
+ $request->attributes->add([
+ 'badges' => (object) [
+ 'orders' => ShopOrderQueue::where('invalid', '=', false)
+ ->where('approved', '=', true)
+ ->where('disapproved', '=', false)
+ ->where('setup', '=', false)
+ ->where('deleted', '=', false)
+ ->where('fails', '<', 3)
+ ->count(),
+ 'tickets' => SupportTicket::where('status', '=', 'open')
+ ->where(function (Builder $builder) {
+ return $builder->where('category_id', '=', 0)
+ ->orWhereNull('category_id')
+ ->orWhereHas('category', function (Builder $builder) {
+ return $builder->whereHas('assignments', function (Builder $builder) {
+ return $builder->where('user_id', '=', Auth::id());
+ });
+ });
+ })
+ ->get()
+ ->filter(function (SupportTicket $ticket) {
+ $lastMessage = $ticket->messages->filter(function (SupportTicketMessage $message) {
+ return !$message->note;
+ })->last();
+
+ return !in_array($lastMessage->user?->role, [
+ 'admin',
+ 'employee',
+ ]);
+ })
+ ->count(),
+ ],
+ ]);
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/IdentifyCustomerProductLists.php b/app/Http/Middleware/IdentifyCustomerProductLists.php
index 4186f06..e7da4fa 100644
--- a/app/Http/Middleware/IdentifyCustomerProductLists.php
+++ b/app/Http/Middleware/IdentifyCustomerProductLists.php
@@ -29,7 +29,7 @@ public function handle(Request $request, Closure $next)
{
$results = [];
- $products = Products::list()->reject(function ($handler) {
+ Products::list()->reject(function ($handler) {
return !$handler->ui()->customer;
})->each(function ($handler) use (&$results) {
$results[] = (object) [
diff --git a/app/Http/Middleware/IdentifyCustomerStatus.php b/app/Http/Middleware/IdentifyCustomerStatus.php
new file mode 100644
index 0000000..ea2d6e0
--- /dev/null
+++ b/app/Http/Middleware/IdentifyCustomerStatus.php
@@ -0,0 +1,70 @@
+
+ */
+class IdentifyCustomerStatus
+{
+ /**
+ * Handle an incoming request.
+ *
+ * @param Request $request
+ * @param Closure $next
+ *
+ * @return mixed
+ */
+ public function handle(Request $request, Closure $next)
+ {
+ $invoices = Invoice::where('user_id', '=', Auth::id())
+ ->where('status', '=', 'unpaid')
+ ->whereDoesntHave('type', function (Builder $builder) {
+ return $builder->where('type', '=', 'prepaid');
+ })
+ ->get();
+
+ $request->attributes->add([
+ 'badges' => (object) [
+ 'invoices' => (object) [
+ 'total' => (clone $invoices)->count(),
+ 'overdue' => (clone $invoices)->filter(function (Invoice $invoice) {
+ return $invoice->overdue;
+ })->count(),
+ ],
+ 'tickets' => SupportTicket::whereHas('assignments', function (Builder $builder) {
+ return $builder->where('user_id', '=', Auth::id());
+ })
+ ->where('status', '=', 'open')
+ ->get()
+ ->filter(function (SupportTicket $ticket) {
+ $lastMessage = $ticket->messages->filter(function (SupportTicketMessage $message) {
+ return !$message->note;
+ })->last();
+
+ return in_array($lastMessage->user?->role, [
+ 'admin',
+ 'employee',
+ ]);
+ })
+ ->count(),
+ ],
+ ]);
+
+ return $next($request);
+ }
+}
diff --git a/composer.lock b/composer.lock
index 3d200ca..4bcfc0d 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "11227b59f860e2dd590368b44e4652b8",
+ "content-hash": "defde7552a959aa4b07010a9b742ee3b",
"packages": [
{
"name": "awobaz/compoships",
@@ -2055,16 +2055,16 @@
},
{
"name": "forepath/obms-theme-aurora",
- "version": "v1.2.1",
+ "version": "v1.3.3",
"source": {
"type": "git",
"url": "https://github.com/forepath/obms-theme-aurora.git",
- "reference": "f1ff227a81818b7d71c495ce70838e8b03791aa0"
+ "reference": "df5bd322fcc432c159e3761b228a156fe0eda1e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/forepath/obms-theme-aurora/zipball/f1ff227a81818b7d71c495ce70838e8b03791aa0",
- "reference": "f1ff227a81818b7d71c495ce70838e8b03791aa0",
+ "url": "https://api.github.com/repos/forepath/obms-theme-aurora/zipball/df5bd322fcc432c159e3761b228a156fe0eda1e0",
+ "reference": "df5bd322fcc432c159e3761b228a156fe0eda1e0",
"shasum": ""
},
"require": {
@@ -2094,7 +2094,7 @@
"issues": "https://github.com/forepath/obms-theme-aurora/issues",
"source": "https://github.com/forepath/obms-theme-aurora"
},
- "time": "2025-08-09T08:16:15+00:00"
+ "time": "2025-08-09T20:15:56+00:00"
},
{
"name": "fruitcake/php-cors",
diff --git a/database/migrations/2025_08_09_000001_update_support_tables.php b/database/migrations/2025_08_09_000001_update_support_tables.php
new file mode 100644
index 0000000..0977958
--- /dev/null
+++ b/database/migrations/2025_08_09_000001_update_support_tables.php
@@ -0,0 +1,75 @@
+foreignId('category_id')->nullable()->change();
+ });
+
+ Schema::table('support_ticket_history', function (Blueprint $table) {
+ $table->enum('type', [
+ 'message',
+ 'priority',
+ 'assignment',
+ 'category',
+ 'escalation',
+ 'deescalation',
+ 'lock',
+ 'unlock',
+ 'hold',
+ 'unhold',
+ 'close',
+ 'reopen',
+ 'file',
+ 'status',
+ 'run',
+ ])->change();
+ });
+
+ Schema::table('support_runs', function (Blueprint $table) {
+ $table->foreignId('category_id')->nullable()->change();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down()
+ {
+ Schema::table('support_runs', function (Blueprint $table) {
+ $table->foreignId('category_id')->nullable(false)->change();
+ });
+
+ Schema::table('support_ticket_history', function (Blueprint $table) {
+ $table->enum('type', [
+ 'message',
+ 'priority',
+ 'assignment',
+ 'category',
+ 'escalation',
+ 'deescalation',
+ 'lock',
+ 'unlock',
+ 'hold',
+ 'unhold',
+ 'close',
+ 'reopen',
+ 'file',
+ ])->change();
+ });
+
+ Schema::table('tenants', function (Blueprint $table) {
+ $table->foreignId('category_id')->nullable(false)->change();
+ });
+ }
+};
diff --git a/routes/web.php b/routes/web.php
index 7cbcac1..ecf73cf 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -67,6 +67,7 @@
'middleware' => [
'role.customer',
'products.customer',
+ 'status.customer',
],
], function () {
Route::get('/accept', [App\Http\Controllers\CustomerDashboardController::class, 'accept'])->name('customer.accept');
@@ -179,6 +180,7 @@
'middleware' => [
'role.employee',
'products.admin',
+ 'status.admin',
],
], function () {
Route::get('/home', [App\Http\Controllers\AdminDashboardController::class, 'index'])->name('admin.home');
@@ -526,6 +528,7 @@
Route::group([
'middleware' => [
'products.customer',
+ 'status.customer',
],
], function () {
Page::query()->each(function (Page $page) {
@@ -540,6 +543,7 @@
'middleware' => [
'shop.categoryOrProduct',
'products.customer',
+ 'status.customer',
],
], function () {
Route::get('/shop', [App\Http\Controllers\CustomerShopController::class, 'render_category'])->name('public.shop');