This commit is contained in:
pbao9
2025-07-29 17:31:45 +07:00
parent d80580d1e4
commit b048edee11
15 changed files with 382 additions and 16 deletions
@@ -0,0 +1,65 @@
<?php
namespace App\Http\Controllers\admin;
use App\Http\Controllers\Controller;
use App\Repositories\Module\IPPool\IPPoolRepositoryInterface;
use Illuminate\Http\Request;
class ModuleIPPoolController extends Controller
{
public function __construct(
public IPPoolRepositoryInterface $ipPoolRepository
) {
}
public function index(Request $request)
{
$modules = $this->ipPoolRepository->filter(
[
'page' => $request->get('page') ?? 1
]
);
$title = 'List all server ip pool';
return view('admin.module.ippool.index', compact('modules', 'title'));
}
public function create()
{
$title = 'Add new server ip pool';
return view('admin.module.ippool.add', compact('title'));
}
public function store(Request $request)
{
$data = $request->all();
$ipAddresses = explode(',', $data['ip_address']);
$moduleNetworkId = $data['module_network_id'];
foreach ($ipAddresses as $ip) {
$this->ipPoolRepository->create([
'ip_address' => trim($ip),
'module_network_id' => $moduleNetworkId,
]);
}
return redirect()->route('module.ippool.index')->with('success', 'Add new server ip pool success');
}
public function edit(int $id = 0)
{
$module = $this->ipPoolRepository->find($id);
$title = 'Edit server ip pool';
return view('admin.module.ippool.edit', compact('module', 'title'));
}
public function update(Request $request, int $id = 0)
{
$this->ipPoolRepository->update($id, $request->all());
}
public function destroy(int $id = 0)
{
$this->ipPoolRepository->delete($id);
return redirect()->route('module.ippool.index')->with('success', 'Delete server ip pool success');
}
}
@@ -756,7 +756,7 @@ class ServiceController extends Controller
], 422);
}
$productId = htmlspecialchars(strip_tags(trim($request->product_id)), ENT_QUOTES, 'UTF-8');
$productId = $request->product_id;
$userId = $user->id;
$product = ModuleVmware::where('vmware_id', $productId)
@@ -117,14 +117,6 @@ class ProcessOrderPaymentJob implements ShouldQueue
$successfulVMs = array_filter($vmCreationResults, fn($vm) => $vm['success']);
$failedVMs = array_filter($vmCreationResults, fn($vm) => !$vm['success']);
Log::info("Kết quả tạo VM cho đơn hàng #{$this->order->order_num}", [
'order_id' => $this->order->id,
'total_vms' => count($vmCreationResults),
'successful_vms' => count($successfulVMs),
'failed_vms' => count($failedVMs),
'vm_results' => $vmCreationResults
]);
// Nếu tất cả VM được tạo thành công, tiến hành thanh toán
if ($allVMsCreated && count($successfulVMs) > 0) {
DB::beginTransaction();
@@ -142,13 +134,6 @@ class ProcessOrderPaymentJob implements ShouldQueue
DB::commit();
Log::info("Thanh toán thành công cho đơn hàng #{$this->order->order_num}", [
'order_id' => $this->order->id,
'vm_results' => $vmCreationResults,
'total_vms' => count($vmCreationResults),
'successful_vms' => count($successfulVMs)
]);
// Gửi thông báo thành công cho khách hàng
$this->sendSuccessNotification($vmCreationResults);
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class IpPool extends Model
{
use HasFactory;
protected $fillable = [
'ip_address',
'module_network_id',
];
public function network()
{
return $this->belongsTo(ModuleNetwork::class, 'module_network_id', 'id');
}
}
+8
View File
@@ -38,6 +38,8 @@ use App\Repositories\Module\Datastore\DatastoreCachedRepository;
use App\Repositories\Module\Datastore\DatastoreRepositoryInterface;
use App\Repositories\Module\DnsServer\DnsServerCachedRepository;
use App\Repositories\Module\DnsServer\DnsServerRepositoryInterface;
use App\Repositories\Module\IPPool\IPPoolCachedRepository;
use App\Repositories\Module\IPPool\IPPoolRepositoryInterface;
use App\Repositories\Note\NoteCachedRepository;
use App\Repositories\Note\NoteRepositoryInterface;
use App\Repositories\Order\OrderCachedRepository;
@@ -327,6 +329,12 @@ class RepositoryProvider extends ServiceProvider
VPSRepositoryInterface::class,
VPSCachedRepository::class
);
//Module IP Pool
$this->app->bind(
IPPoolRepositoryInterface::class,
IPPoolCachedRepository::class
);
}
/**
@@ -0,0 +1,44 @@
<?php
namespace App\Repositories\Module\IPPool;
use App\Repositories\BaseCachedRepository;
use Illuminate\Support\Facades\Cache;
class IPPoolCachedRepository extends BaseCachedRepository implements IPPoolRepositoryInterface
{
public function __construct(
public IPPoolRepository $ipPoolRepository
) {
parent::__construct();
}
public function getModel()
{
return $this->ipPoolRepository->getModel();
}
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'])
{
$cacheKey = $this->getCacheKey(md5(json_encode([
'filterItem' => [
'data' => $data,
'relationships' => $relationships,
'select' => $select,
'withCount' => $withCount
]
])));
return Cache::remember($cacheKey, $this->cacheTime, function () use ($data, $relationships, $select, $withCount) {
return $this->ipPoolRepository->filter($data, $relationships, $withCount, $select);
});
}
public function findByName(string $name = '')
{
$cacheKey = $this->getCacheKey(md5(json_encode([
'findByName' => [
'name' => $name
]
])));
return Cache::remember($cacheKey, $this->cacheTime, function () use ($name){
return $this->ipPoolRepository->findByName($name);
});
}
}
@@ -0,0 +1,54 @@
<?php
namespace App\Repositories\Module\IPPool;
use App\Models\IPPool;
use App\Repositories\BaseRepository;
class IPPoolRepository extends BaseRepository implements IPPoolRepositoryInterface
{
public function getModel()
{
return IPPool::class;
}
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'])
{
$model = $this->model->with($relationships)->select($select);
if (isset($data['relations'])) {
foreach ($data['relations'] as $key => $value) {
$model = $model->whereHas($key, function ($query) use ($value) {
if (isset($value['condition'])) {
switch (strtoupper($value['condition'])) {
case "IN":
$query->whereIn($value['key'], $value['value']);
break;
case "NotIn":
$query->whereNotIn($value['key'], $value['value']);
break;
default:
$query->where($value['key'], $value['condition'], $value['value']);
break;
}
} else {
$query->where($value['key'], $value['value']);
}
});
}
}
if (count($withCount) > 0) {
$model = $model->withCount($withCount);
}
if (isset($data['page'])) {
return $model->paginate(15);
}
return $model->get();
}
public function findByName(string $name = '')
{
if (empty($name)) {
return false;
}
return $this->model->where('name','LIKE',"%$name%")->first();
}
}
@@ -0,0 +1,10 @@
<?php
namespace App\Repositories\Module\IPPool;
use App\Repositories\BaseRepositoryInterface;
interface IPPoolRepositoryInterface extends BaseRepositoryInterface{
public function filter(array $data = [],array $relationships = [],array $withCount = [],array $select = ['*']);
public function findByName(string $name = '');
}
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('ip_pools', function (Blueprint $table) {
$table->id();
$table->string('ip_address');
$table->unsignedBigInteger('module_network_id');
$table->foreign('module_network_id')->references('id')->on('module_network');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('ip_pools');
}
};
+6
View File
@@ -92,6 +92,12 @@ class RolesAndPermissions extends Seeder
Permission::create(['name' => 'edit module vcenter']);
Permission::create(['name' => 'delete module vcenter']);
// create module ippool permissions
Permission::create(['name' => 'manager module ippool']);
Permission::create(['name' => 'add module ippool']);
Permission::create(['name' => 'edit module ippool']);
Permission::create(['name' => 'delete module ippool']);
// create package permissions
Permission::create(['name' => 'manager package module']);
Permission::create(['name' => 'add package module']);
@@ -0,0 +1,9 @@
<a href="{{ route('module.ippool.create') }}" class="btn btn-outline-secondary"><i class="fas fa-plus-circle"></i> Add New IP Pool</a>
<form action="{{ route('module.ippool.import') }}" class="d-lg-inline" enctype="multipart/form-data" method="post">
@csrf
<input type="file" name="file" class="d-none file-selector" accept=".csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" onchange="form.submit()" />
<button type="button" class="btn btn-outline-secondary btn-import__from">
<i class="fas fa-plus-circle"></i> Import From Excel
</button>
</form>
<a href="{{ url('file/IPPool.xlsx') }}" class="btn btn-outline-secondary"><i class="fas fa-download"></i> File Import Demo</a>
@@ -0,0 +1,41 @@
@extends('admin.main')
@section('content')
@if (auth()->guard('admins')->user()->can('add module ippool'))
<div class="card card-outline card-primary">
<form action="{{ route('module.ippool.store') }}" method="post">
@csrf
<div class="card-body">
<div class="row">
<div class="col">
{{-- Server Host --}}
<div class="form-group row">
<label class="col-md-3" for="ip_address">IP Address</label>
<div class="col-md-9">
<textarea type="text" id="ip_address" name="ip_address" placeholder="103.42.58.1, 103.42.58.2..." rows="4"
value="{{ old('ip_address') }}" class="form-control"></textarea>
</div>
</div>
{{-- Module Network --}}
<div class="form-group row">
<label class="col-md-3" for="module_network_id">Module Network</label>
<div class="col-md-9">
<input type="text" id="module_network_id" name="module_network_id" placeholder="1"
value="{{ old('module_network_id') }}" class="form-control">
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<a href="{{ route('module.ippool.index') }}" class="btn btn-outline-secondary">Back</a>
<button type="submit" class="btn btn-outline-primary">Save</button>
</div>
</form>
</div>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i class="icon fas fa-ban"></i> Access Denied - You are not assigned to any Module IP Pool
management department</h5>
</div>
@endif
@endsection
@@ -0,0 +1,77 @@
@php use App\Http\Helpers\Helper; @endphp
@extends('admin.main')
@section('content')
@if (auth()->guard('admins')->user()->can('manager module ippool'))
<div class="card card-primary card-outline">
<div class="card-header">
@include('admin.block.ModuleIPPool')
</div>
<div class="card-body">
<table class="table table-invoice table-bordered">
<thead>
<tr>
<th>
<label>
<input type="checkbox" name="check" class="check-all">
</label>
</th>
<th>IP Address</th>
<th>Module Network</th>
<th>vCenter</th>
<th style="width:40px"></th>
<th style="width: 40px"></th>
</tr>
</thead>
<tbody>
@if (count($modules) > 0)
@foreach ($modules as $item)
<tr>
<td class="text-center">
<label for=""></label><input type="checkbox" name="id[]"
value="{{ $item->id }}" id="">
</td>
<td class="text-center">
{{ $item->ip_address }}
</td>
<td class="text-center">
{{ $item->network->name . ' - ' . $item->network->network }}
</td>
<td class="text-center">
{{ $item->network->host->datacenter->vCenter->host }}
</td>
<td>
<a class="btn btn-warning btn-sm"
href="{{ route('module.ippool.edit', ['id' => $item->id]) }}">
<i class="fas fa-user-edit"></i>
</a>
</td>
<td>
@if (auth()->guard('admins')->user()->can('delete module ippool'))
<form method="post" class="d-inline"
action="{{ route('module.ippool.destroy', ['id' => $item->id]) }}">
@method('delete')
@csrf
<button type="submit" data-toggle="tooltip" data-placement="top"
title="" class="btn btn-sm btn-danger" data-original-title="Xoá">
<i class="fas fa-trash"></i>
</button>
</form>
@endif
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
<div class="card-footer">
{{ $modules->withQueryString()->links() }}
</div>
</div>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i class="icon fas fa-ban"></i> Access Denied - You are not assigned to any Module IP Pool
management department</h5>
</div>
@endif
@endsection
+6
View File
@@ -119,6 +119,12 @@
<p>Module vCenter</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('module.ippool.index') }}" class="nav-link">
<i class="fas fa-network-wired nav-icon"></i>
<p>Module IP Pool</p>
</a>
</li>
</ul>
</li>
+11
View File
@@ -13,6 +13,7 @@ use App\Http\Controllers\admin\MediaController;
use App\Http\Controllers\admin\MenuController;
use App\Http\Controllers\admin\ModuleDNSController;
use App\Http\Controllers\admin\ModuleHostingController;
use App\Http\Controllers\admin\ModuleIPPoolController;
use App\Http\Controllers\admin\ModulevCenterController;
use App\Http\Controllers\admin\OrderController;
use App\Http\Controllers\admin\package\Datacenter;
@@ -203,6 +204,16 @@ Route::prefix('administrator')->group(function () {
Route::delete('remove-server-dns/{id}', 'destroy')->name('module.dns.destroy');
});
Route::controller(ModuleIPPoolController::class)->group(function () {
Route::get('list-all-server-ip-pool', 'index')->name('module.ippool.index');
Route::post('import-ip-pool-from-csv', 'import')->name('module.ippool.import');
Route::get('add-new-server-ip-pool', 'create')->name('module.ippool.create');
Route::post('add-new-server-ip-pool', 'store')->name('module.ippool.store');
Route::get('view-server-ip-pool/{id}', 'edit')->name('module.ippool.edit');
Route::put('view-server-ip-pool/{id}', 'update')->name('module.ippool.update');
Route::delete('remove-server-ip-pool/{id}', 'destroy')->name('module.ippool.destroy');
});
//Module vCenter Server
Route::controller(ModulevCenterController::class)->group(function () {
Route::get('list-all-vcenter', 'index')->name('module.vcenter.index');