feat: add GeneratesUniqueSlug class for unique slug generation

feat: create PostCategoryFactory for generating post category data

feat: create PostFactory for generating post data

feat: add retry_requested_at column to services table

feat: add vcenter provisioning fields to products table

feat: add module_host_id to os table

feat: create email_notification_templates table for email templates

feat: add scenario and format fields to template table

feat: add admin fields to transactions table

fix: update ticket table columns and types

feat: add uuid to ticket table and backfill existing records

fix: make ticket_reply user_id nullable

feat: create notifications table for user notifications

fix: make ticket uuid nullable

feat: create post_categories table for blog categories

feat: create posts table for blog posts

feat: add invoice email template for PDF generation
This commit is contained in:
baodev0
2026-05-25 15:39:42 +07:00
parent a31d238135
commit 520f21cb11
73 changed files with 4682 additions and 440 deletions
+97 -5
View File
@@ -12,6 +12,7 @@ use App\Http\Controllers\Api\Admin\Invoice\InvoiceController;
use App\Http\Controllers\Api\Admin\Invoice\InvoiceTestController;
use App\Http\Controllers\Api\Admin\Order\OrderController;
use App\Http\Controllers\Api\Admin\Payment\PaymentController;
use App\Http\Controllers\Api\Admin\Addon\AddonController;
use App\Http\Controllers\Api\Admin\Product\ProductCategoryController;
use App\Http\Controllers\Api\Admin\Product\ProductController;
use App\Http\Controllers\Api\Admin\VPS\VPSController;
@@ -23,8 +24,13 @@ use App\Http\Controllers\Api\Admin\OsManager\OsController;
use App\Http\Controllers\Api\Admin\IpPool\IpPoolController;
use App\Http\Controllers\Api\Admin\Bank\BankController;
use App\Http\Controllers\Api\Admin\EmailTemplate\EmailTemplateController;
use App\Http\Controllers\Api\Admin\EmailNotificationTemplateController;
use App\Http\Controllers\Api\Admin\ActivityLog\ActivityLogController;
use App\Http\Controllers\Api\Admin\Transaction\AdminTransactionController;
use App\Http\Controllers\Api\Admin\Ticket\TicketController as AdminTicketController;
use App\Http\Controllers\Api\Admin\Docs\PostCategoryController as AdminPostCategoryController;
use App\Http\Controllers\Api\Admin\Docs\PostController as AdminPostController;
use App\Http\Controllers\Api\NotificationController;
use App\Http\Controllers\Api\Admin\InfraManagement\InfraManagementController;
use App\Http\Services\Media;
use App\Http\Services\vCenter as ServiceVCenter;
@@ -44,6 +50,14 @@ use Illuminate\Support\Facades\Route;
|
*/
Route::prefix('admin')->middleware('api.auth:admin')->group(function () {
Route::post('posts/sync-wordpress', [AdminPostController::class, 'syncWordpress']);
Route::apiResource('post-categories', AdminPostCategoryController::class)
->only(['index', 'store', 'show', 'update', 'destroy']);
Route::apiResource('posts', AdminPostController::class)
->only(['index', 'store', 'show', 'update', 'destroy']);
});
Route::prefix('v1')
->group(function () {
// Invoice Test — Send invoice email with PDF attachment
@@ -53,6 +67,13 @@ Route::prefix('v1')
Route::post('{invoiceNumber}/send-email', 'sendInvoiceEmail');
Route::get('{invoiceNumber}/preview-pdf', 'previewInvoicePdf');
});
Route::prefix('admin')->middleware('api.auth:admin')->group(function () {
Route::apiResource('post-categories', AdminPostCategoryController::class)
->only(['index', 'store', 'show', 'update', 'destroy']);
Route::apiResource('posts', AdminPostController::class)
->only(['index', 'store', 'show', 'update', 'destroy']);
});
})
/* Api for Admin */
->group(function () {
@@ -105,6 +126,7 @@ Route::prefix('v1')
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::post('{uuid}/add-total', 'addTotal')->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');
@@ -169,6 +191,42 @@ Route::prefix('v1')
->name('force-delete');
});
// Addons (module: product-service)
Route::prefix('addons')
->controller(AddonController::class)
->group(function () {
Route::get('/', 'index')->middleware('perm:product-service.view');
Route::post('/', 'store')->middleware('perm:product-service.create');
Route::post('bulk-update-status', 'bulkUpdateStatus')->middleware('perm:product-service.edit');
Route::post('bulk-destroy', 'bulkDestroy')->middleware('perm:product-service.destroy');
Route::get('{id}', 'show')->middleware('perm:product-service.view');
Route::put('{id}', 'update')->middleware('perm:product-service.edit');
Route::delete('{id}', 'destroy')->middleware('perm:product-service.destroy');
});
Route::prefix('post-categories')
->controller(AdminPostCategoryController::class)
->as('post-categories.')
->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'store')->name('store');
Route::get('{id}', 'show')->name('show');
Route::put('{id}', 'update')->name('update');
Route::delete('{id}', 'destroy')->name('destroy');
});
Route::prefix('posts')
->controller(AdminPostController::class)
->as('posts.')
->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'store')->name('store');
Route::post('sync-wordpress', 'syncWordpress')->name('sync-wordpress');
Route::get('{id}', 'show')->name('show');
Route::put('{id}', 'update')->name('update');
Route::delete('{id}', 'destroy')->name('destroy');
});
// Orders (module: order)
Route::prefix('orders')
->controller(OrderController::class)
@@ -351,11 +409,27 @@ Route::prefix('v1')
Route::prefix('email-templates')
->controller(EmailTemplateController::class)
->group(function () {
Route::get('/', 'index');
Route::post('/', 'store');
Route::get('{id}', 'show');
Route::put('{id}', 'update');
Route::delete('{id}', 'destroy');
Route::get('/', 'index');
Route::post('/', 'store');
Route::get('email-settings', 'getEmailSettings');
Route::put('email-settings', 'updateEmailSettings');
Route::get('{id}', 'show');
Route::put('{id}', 'update');
Route::delete('{id}', 'destroy');
Route::get('{id}/preview-invoice','previewInvoiceJson');
});
// Notification Email Templates — block-based editor
Route::prefix('notification-templates')
->controller(EmailNotificationTemplateController::class)
->group(function () {
Route::get('/', 'index');
Route::post('/', 'store');
Route::get('field-definitions','fieldDefinitions');
Route::get('{id}', 'show');
Route::put('{id}', 'update');
Route::delete('{id}', 'destroy');
Route::get('{id}/preview', 'preview');
});
// Transactions — manual deposit review (module: transaction)
@@ -393,6 +467,24 @@ Route::prefix('v1')
Route::get('vms/powered-off', 'getPoweredOffVms')->middleware('perm:module-vcenter.view');
});
// Tickets (support tickets)
Route::prefix('tickets')
->controller(AdminTicketController::class)
->group(function () {
Route::get('/', 'index');
Route::get('{ticket_num}', 'show');
Route::patch('{ticket_num}/status', 'updateStatus');
Route::post('{ticket_num}/reply', 'reply');
});
Route::prefix('notifications')
->controller(NotificationController::class)
->group(function () {
Route::get('/', fn () => app(NotificationController::class)->index(request(), 'admin'));
Route::patch('{id}/read', fn ($id) => app(NotificationController::class)->markRead(request(), 'admin', (int) $id));
Route::patch('read-all', fn () => app(NotificationController::class)->markAllRead(request(), 'admin'));
});
// Activity Logs
Route::prefix('activity-logs')
->controller(ActivityLogController::class)