feat: Implement client payment history endpoint and add type filtering to product category API.

This commit is contained in:
pbao9
2026-03-13 10:38:56 +07:00
parent a388eabe17
commit 5160ac967a
4 changed files with 199 additions and 115 deletions
+110 -114
View File
@@ -1,5 +1,6 @@
<?php
use App\Http\Controllers\admin\VCenterManagerController;
use App\Http\Controllers\Api\Admin\Auth\AuthController;
use App\Http\Controllers\Api\QueueMonitorController;
use App\Http\Controllers\Api\Admin\Staff\StaffOnlineController;
@@ -40,12 +41,12 @@ Route::prefix('v1')
/* Api for Admin */
->group(function () {
Route::prefix('administrator')->group(function () {
Route::post('login', [AuthController::class, 'login']);
Route::post('login', [AuthController::class, 'login']);
Route::middleware('api.auth:admin')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::post('logout', [AuthController::class, 'logout']);
Route::post('refresh', [AuthController::class, 'refresh']);
Route::get('me', [AuthController::class, 'me']);
Route::get('me', [AuthController::class, 'me']);
// Role Permissions
Route::prefix('role-permissions')->group(function () {
@@ -71,44 +72,45 @@ Route::prefix('v1')
});
// Customers (module: customer)
Route::prefix('customers')->group(function () {
Route::get('trash', [CustomerController::class, 'trash'])->middleware('perm:customer.view');
Route::get('/', [CustomerController::class, 'index'])->middleware('perm:customer.view');
Route::post('/', [CustomerController::class, 'store'])->middleware('perm:customer.create');
Route::get('{uuid}', [CustomerController::class, 'show'])->middleware('perm:customer.view');
Route::put('{uuid}', [CustomerController::class, 'update'])->middleware('perm:customer.edit');
Route::delete('{uuid}', [CustomerController::class, 'destroy'])->middleware('perm:customer.destroy');
Route::delete('{uuid}/destroy', [CustomerController::class, 'destroy'])->middleware('perm:customer.destroy');
Route::post('{uuid}/reset-password', [CustomerController::class, 'resetPassword'])->middleware('perm:customer.edit');
Route::post('{uuid}/add-credit', [CustomerController::class, 'addCredit'])->middleware('perm:customer.edit');
Route::get('{uuid}/services', [CustomerController::class, 'getServices'])->middleware('perm:customer.view');
Route::get('{uuid}/orders', [CustomerController::class, 'getOrders'])->middleware('perm:customer.view');
Route::get('{uuid}/invoices', [CustomerController::class, 'getInvoices'])->middleware('perm:customer.view');
Route::get('{uuid}/transactions', [CustomerController::class, 'getTransactions'])->middleware('perm:customer.view');
Route::get('{uuid}/domains', [CustomerController::class, 'getDomains'])->middleware('perm:customer.view');
Route::post('{uuid}/restore', [CustomerController::class, 'restore'])->middleware('perm:customer.edit');
Route::delete('{uuid}/force', [CustomerController::class, 'forceDelete'])->middleware('perm:customer.destroy');
Route::prefix('customers')->controller(CustomerController::class)->group(function () {
Route::get('trash', 'trash')->middleware('perm:customer.view');
Route::get('/', 'index')->middleware('perm:customer.view');
Route::post('/', 'store')->middleware('perm:customer.create');
Route::get('{uuid}', 'show')->middleware('perm:customer.view');
Route::put('{uuid}', 'update')->middleware('perm:customer.edit');
Route::delete('{uuid}', 'destroy')->middleware('perm:customer.destroy');
Route::delete('{uuid}/destroy', 'destroy')->middleware('perm:customer.destroy');
Route::post('{uuid}/reset-password', 'resetPassword')->middleware('perm:customer.edit');
Route::post('{uuid}/add-credit', 'addCredit')->middleware('perm:customer.edit');
Route::get('{uuid}/services', 'getServices')->middleware('perm:customer.view');
Route::get('{uuid}/orders', 'getOrders')->middleware('perm:customer.view');
Route::get('{uuid}/invoices', 'getInvoices')->middleware('perm:customer.view');
Route::get('{uuid}/transactions', 'getTransactions')->middleware('perm:customer.view');
Route::get('{uuid}/domains', 'getDomains')->middleware('perm:customer.view');
Route::post('{uuid}/restore', 'restore')->middleware('perm:customer.edit');
Route::delete('{uuid}/force', 'forceDelete')->middleware('perm:customer.destroy');
});
// Products (module: product-service)
Route::prefix('products')->group(function () {
Route::get('export', [ProductController::class, 'export'])->middleware('perm:product-service.manager');
Route::get('/', [ProductController::class, 'index'])->middleware('perm:product-service.view');
Route::post('/', [ProductController::class, 'store'])->middleware('perm:product-service.create');
Route::post('import', [ProductController::class, 'import'])->middleware('perm:product-service.create');
Route::prefix('products')->controller(ProductController::class)->group(function () {
Route::get('export', 'export')->middleware('perm:product-service.manager');
Route::get('/', 'index')->middleware('perm:product-service.view');
Route::post('/', 'store')->middleware('perm:product-service.create');
Route::post('import', 'import')->middleware('perm:product-service.create');
// OS list for product configuration - must be before {id} routes
Route::get('os', [ProductController::class, 'getOsList'])->middleware('perm:product-service.view');
Route::controller(ProductController::class)->group(function () {
Route::get('os', 'getOsList')->middleware('perm:product-service.view');
Route::get('{id}', [ProductController::class, 'show'])->middleware('perm:product-service.view');
Route::get('{id}/os', [ProductController::class, 'getOs'])->middleware('perm:product-service.view');
Route::get('{id}/operating-systems', [ProductController::class, 'getOperatingSystems'])->middleware('perm:product-service.view');
Route::put('{id}', [ProductController::class, 'update'])->middleware('perm:product-service.edit');
Route::delete('{id}', [ProductController::class, 'destroy'])->middleware('perm:product-service.destroy');
Route::post('{id}/duplicate', [ProductController::class, 'duplicate'])->middleware('perm:product-service.create');
Route::get('{id}', 'show')->middleware('perm:product-service.view');
Route::get('{id}/os', 'getOs')->middleware('perm:product-service.view');
Route::get('{id}/operating-systems', 'getOperatingSystems')->middleware('perm:product-service.view');
Route::put('{id}', 'update')->middleware('perm:product-service.edit');
Route::delete('{id}', 'destroy')->middleware('perm:product-service.destroy');
Route::post('{id}/duplicate', 'duplicate')->middleware('perm:product-service.create');
});
});
// Product Categories / Groups (module: product-service)
Route::prefix('product-categories')
->controller(ProductCategoryController::class)
->as('product-categories.')
@@ -120,44 +122,44 @@ Route::prefix('v1')
Route::delete('{id}', 'destroy')->middleware('perm:product-service.destroy')->name('destroy');
});
// Orders (module: order)
Route::prefix('orders')->controller(OrderController::class)->group(function () {
Route::get('/', 'index')->middleware('perm:order.view');
Route::post('/upload-proof', 'uploadProof')->middleware('perm:order.create');
Route::post('/', 'store')->middleware('perm:order.create');
Route::get('{id}', 'show')->middleware('perm:order.view');
Route::put('{id}', 'update')->middleware('perm:order.edit');
Route::delete('{id}', 'destroy')->middleware('perm:order.destroy');
Route::post('{id}/accept', 'accept')->middleware('perm:order.edit');
Route::post('{id}/cancel', 'cancel')->middleware('perm:order.edit');
// Orders (module: order)
Route::prefix('orders')->controller(OrderController::class)->group(function () {
Route::get('/', 'index')->middleware('perm:order.view');
Route::post('/upload-proof', 'uploadProof')->middleware('perm:order.create');
Route::post('/', 'store')->middleware('perm:order.create');
Route::get('{id}', 'show')->middleware('perm:order.view');
Route::put('{id}', 'update')->middleware('perm:order.edit');
Route::delete('{id}', 'destroy')->middleware('perm:order.destroy');
Route::post('{id}/accept', 'accept')->middleware('perm:order.edit');
Route::post('{id}/cancel', 'cancel')->middleware('perm:order.edit');
});
// Invoices (module: invoice)
Route::prefix('invoices')->group(function () {
Route::get('/', [InvoiceController::class, 'index'])->middleware('perm:invoice.view');
Route::get('/datatable', [InvoiceController::class, 'datatable'])->middleware('perm:invoice.view');
Route::post('/', [InvoiceController::class, 'store'])->middleware('perm:invoice.create');
Route::get('{id}', [InvoiceController::class, 'show'])->middleware('perm:invoice.view');
Route::put('{id}', [InvoiceController::class, 'update'])->middleware('perm:invoice.edit');
Route::delete('{id}', [InvoiceController::class, 'destroy'])->middleware('perm:invoice.destroy');
Route::post('{id}/paid', [InvoiceController::class, 'markAsPaid'])->middleware('perm:invoice.edit');
Route::post('{id}/cancel', [InvoiceController::class, 'cancel'])->middleware('perm:invoice.edit');
Route::prefix('invoices')->controller(InvoiceController::class)->group(function () {
Route::get('/', 'index')->middleware('perm:invoice.view');
Route::get('/datatable', 'datatable')->middleware('perm:invoice.view');
Route::post('/', 'store')->middleware('perm:invoice.create');
Route::get('{id}', 'show')->middleware('perm:invoice.view');
Route::put('{id}', 'update')->middleware('perm:invoice.edit');
Route::delete('{id}', 'destroy')->middleware('perm:invoice.destroy');
Route::post('{id}/paid', 'markAsPaid')->middleware('perm:invoice.edit');
Route::post('{id}/cancel', 'cancel')->middleware('perm:invoice.edit');
// Attachments
Route::get('{id}/attachments', [InvoiceController::class, 'listAttachments'])->middleware('perm:invoice.view');
Route::post('{id}/attachments', [InvoiceController::class, 'uploadAttachment'])->middleware('perm:invoice.edit');
Route::delete('{id}/attachments/{attachmentId}', [InvoiceController::class, 'deleteAttachment'])->middleware('perm:invoice.edit');
Route::get('{id}/attachments', 'listAttachments')->middleware('perm:invoice.view');
Route::post('{id}/attachments', 'uploadAttachment')->middleware('perm:invoice.edit');
Route::delete('{id}/attachments/{attachmentId}', 'deleteAttachment')->middleware('perm:invoice.edit');
// Send mail notification
Route::post('{id}/send-mail', [InvoiceController::class, 'sendMail'])->middleware('perm:invoice.edit');
Route::post('{id}/send-mail', 'sendMail')->middleware('perm:invoice.edit');
});
// Payments (module: payment)
Route::prefix('payments')->group(function () {
Route::get('for-select', [PaymentController::class, 'forSelect']);
Route::get('/', [PaymentController::class, 'index'])->middleware('perm:payment.view');
Route::post('/', [PaymentController::class, 'store'])->middleware('perm:payment.create');
Route::get('{id}', [PaymentController::class, 'show'])->middleware('perm:payment.view');
Route::put('{id}', [PaymentController::class, 'update'])->middleware('perm:payment.edit');
Route::delete('{id}', [PaymentController::class, 'destroy'])->middleware('perm:payment.destroy');
Route::prefix('payments')->controller(PaymentController::class)->group(function () {
Route::get('for-select', 'forSelect');
Route::get('/', 'index')->middleware('perm:payment.view');
Route::post('/', 'store')->middleware('perm:payment.create');
Route::get('{id}', 'show')->middleware('perm:payment.view');
Route::put('{id}', 'update')->middleware('perm:payment.edit');
Route::delete('{id}', 'destroy')->middleware('perm:payment.destroy');
});
// OS Groups & OS Entries (module: module-vcenter)
@@ -182,68 +184,68 @@ Route::prefix('v1')
});
// VPS (module: module-vcenter)
Route::prefix('vps')->group(function () {
Route::get('/', [VPSController::class, 'index'])->middleware('perm:module-vcenter.view');
Route::get('{id}', [VPSController::class, 'show'])->middleware('perm:module-vcenter.view');
Route::put('{id}', [VPSController::class, 'update'])->middleware('perm:module-vcenter.edit');
Route::post('{id}/power-on', [VPSController::class, 'powerOn'])->middleware('perm:module-vcenter.edit');
Route::post('{id}/power-off', [VPSController::class, 'powerOff'])->middleware('perm:module-vcenter.edit');
Route::post('{id}/restart', [VPSController::class, 'restart'])->middleware('perm:module-vcenter.edit');
Route::get('{id}/console-ticket', [VPSController::class, 'getConsoleTicket'])->middleware('perm:module-vcenter.view');
Route::prefix('vps')->controller(VPSController::class)->group(function () {
Route::get('/', 'index')->middleware('perm:module-vcenter.view');
Route::get('{id}', 'show')->middleware('perm:module-vcenter.view');
Route::put('{id}', 'update')->middleware('perm:module-vcenter.edit');
Route::post('{id}/power-on', 'powerOn')->middleware('perm:module-vcenter.edit');
Route::post('{id}/power-off', 'powerOff')->middleware('perm:module-vcenter.edit');
Route::post('{id}/restart', 'restart')->middleware('perm:module-vcenter.edit');
Route::get('{id}/console-ticket', 'getConsoleTicket')->middleware('perm:module-vcenter.view');
});
// vCenter (module: module-vcenter)
Route::prefix('vcenter')->group(function () {
Route::get('tree', [VCenterController::class, 'tree'])->middleware('perm:module-vcenter.view');
Route::get('console-ticket', [VCenterController::class, 'consoleTicket'])->middleware('perm:module-vcenter.view');
Route::post('/', [VCenterController::class, 'store'])->middleware('perm:module-vcenter.create');
Route::post('sync', [VCenterController::class, 'sync'])->middleware('perm:module-vcenter.edit');
Route::put('node/{type}/{id}', [VCenterController::class, 'updateNode'])->middleware('perm:module-vcenter.edit');
Route::delete('node/{type}/{id}', [VCenterController::class, 'destroyNode'])->middleware('perm:module-vcenter.destroy');
Route::prefix('vcenter')->controller(VCenterController::class)->group(function () {
Route::get('tree', 'tree')->middleware('perm:module-vcenter.view');
Route::get('console-ticket', 'consoleTicket')->middleware('perm:module-vcenter.view');
Route::post('/', 'store')->middleware('perm:module-vcenter.create');
Route::post('sync', 'sync')->middleware('perm:module-vcenter.edit');
Route::put('node/{type}/{id}', 'updateNode')->middleware('perm:module-vcenter.edit');
Route::delete('node/{type}/{id}', 'destroyNode')->middleware('perm:module-vcenter.destroy');
});
// DNS Manager — Domains (module: domain.manager)
Route::prefix('domains')->group(function () {
Route::get('/', [DnsDomainController::class, 'index'])->middleware('perm:domain.manager');
Route::post('/', [DnsDomainController::class, 'store'])->middleware('perm:domain.manager');
Route::get('{id}', [DnsDomainController::class, 'show'])->middleware('perm:domain.manager');
Route::put('{id}', [DnsDomainController::class, 'update'])->middleware('perm:domain.manager');
Route::delete('{id}', [DnsDomainController::class, 'destroy'])->middleware('perm:domain.manager');
// DNS Records
Route::get('{id}/dns', [DnsDomainController::class, 'dnsIndex'])->middleware('perm:domain.manager');
Route::post('{id}/dns', [DnsDomainController::class, 'dnsStore'])->middleware('perm:domain.manager');
Route::put('{id}/dns/{recordId}', [DnsDomainController::class, 'dnsUpdate'])->middleware('perm:domain.manager');
Route::delete('{id}/dns/{recordId}', [DnsDomainController::class, 'dnsDestroy'])->middleware('perm:domain.manager');
Route::prefix('domains')->controller(DnsDomainController::class)->group(function () {
Route::get('/', 'index')->middleware('perm:domain.manager');
Route::post('/', 'store')->middleware('perm:domain.manager');
Route::get('{id}', 'show')->middleware('perm:domain.manager');
Route::put('{id}', 'update')->middleware('perm:domain.manager');
Route::delete('{id}', 'destroy')->middleware('perm:domain.manager');
// DNS Records
Route::get('{id}/dns', 'dnsIndex')->middleware('perm:domain.manager');
Route::post('{id}/dns', 'dnsStore')->middleware('perm:domain.manager');
Route::put('{id}/dns/{recordId}', 'dnsUpdate')->middleware('perm:domain.manager');
Route::delete('{id}/dns/{recordId}', 'dnsDestroy')->middleware('perm:domain.manager');
});
// DNS Manager — Servers (module: domain.manager)
Route::prefix('dns-servers')->group(function () {
Route::get('/', [DnsServerController::class, 'index'])->middleware('perm:domain.manager');
Route::post('/', [DnsServerController::class, 'store'])->middleware('perm:domain.manager');
Route::get('{id}', [DnsServerController::class, 'show'])->middleware('perm:domain.manager');
Route::put('{id}', [DnsServerController::class, 'update'])->middleware('perm:domain.manager');
Route::delete('{id}', [DnsServerController::class, 'destroy'])->middleware('perm:domain.manager');
Route::prefix('dns-servers')->controller(DnsServerController::class)->group(function () {
Route::get('/', 'index')->middleware('perm:domain.manager');
Route::post('/', 'store')->middleware('perm:domain.manager');
Route::get('{id}', 'show')->middleware('perm:domain.manager');
Route::put('{id}', 'update')->middleware('perm:domain.manager');
Route::delete('{id}', 'destroy')->middleware('perm:domain.manager');
});
// Staff Online
Route::prefix('staff-online')->group(function () {
Route::get('/', [StaffOnlineController::class, 'index']);
Route::post('ping', [StaffOnlineController::class, 'ping']);
Route::prefix('staff-online')->controller(StaffOnlineController::class)->group(function () {
Route::get('/', 'index');
Route::post('ping', 'ping');
});
// Queue Monitor (Horizon)
Route::prefix('queue')->group(function () {
Route::get('jobs/recent', [QueueMonitorController::class, 'recent']);
Route::get('jobs/pending', [QueueMonitorController::class, 'pending']);
Route::get('jobs/failed', [QueueMonitorController::class, 'failed']);
Route::get('jobs/metrics', [QueueMonitorController::class, 'metrics']);
Route::prefix('queue')->controller(QueueMonitorController::class)->group(function () {
Route::get('jobs/recent', 'recent');
Route::get('jobs/pending', 'pending');
Route::get('jobs/failed', 'failed');
Route::get('jobs/metrics', 'metrics');
});
// vCenter Manager Power Operations (module: module-vcenter)
Route::prefix('vcenter-manager')->group(function () {
Route::post('vm/power-on', [App\Http\Controllers\admin\VCenterManagerController::class, 'powerOn'])->middleware('perm:module-vcenter.edit');
Route::post('vm/power-off', [App\Http\Controllers\admin\VCenterManagerController::class, 'powerOff'])->middleware('perm:module-vcenter.edit');
Route::get('vms/powered-off', [App\Http\Controllers\admin\VCenterManagerController::class, 'getPoweredOffVms'])->middleware('perm:module-vcenter.view');
Route::prefix('vcenter-manager')->controller(VCenterManagerController::class)->group(function () {
Route::post('vm/power-on', 'powerOn')->middleware('perm:module-vcenter.edit');
Route::post('vm/power-off', 'powerOff')->middleware('perm:module-vcenter.edit');
Route::get('vms/powered-off', 'getPoweredOffVms')->middleware('perm:module-vcenter.view');
});
});
});
@@ -322,12 +324,6 @@ Route::prefix('v1')
});
});
// Compression Testing Routes (Development/Testing only)
Route::prefix('v1/system/compression')->middleware(['api'])->group(function () {
Route::get('test', [CompressionTestController::class, 'test'])->name('api.compression.test');
Route::get('stats', [CompressionTestController::class, 'stats'])->name('api.compression.stats');
});
Route::any('{any}', function () {
return response()->json([
'error' => true,