diff --git a/app/Http/Controllers/admin/CustomerController.php b/app/Http/Controllers/admin/CustomerController.php
index 33d7876..39d49c3 100644
--- a/app/Http/Controllers/admin/CustomerController.php
+++ b/app/Http/Controllers/admin/CustomerController.php
@@ -7,6 +7,9 @@ use App\Http\Facade\SignRSA;
use App\Http\Requests\AddPayRequest;
use App\Http\Requests\CreateCustomerRequest;
use App\Jobs\Mail\PasswordRecoverJob;
+use App\Models\Invoice;
+use App\Models\Order;
+use App\Models\Transaction;
use App\Repositories\Customer\CustomerRepositoryInterface;
use App\Repositories\Hosting\HostingRepositoryInterface;
use App\Repositories\Invoice\InvoiceRepositoryInterface;
@@ -32,7 +35,7 @@ use Yajra\DataTables\Facades\DataTables;
class CustomerController extends Controller
{
-
+
public function __construct(
public CustomerRepositoryInterface $customerRepository,
public InvoiceItemRepositoryInterface $invoiceItemRepository,
@@ -46,7 +49,8 @@ class CustomerController extends Controller
public InvoiceRepositoryInterface $invoiceRepository,
public TransactionRepositoryInterface $transactionRepository,
public MailRepositoryInterface $mailRepository
- ) {}
+ ) {
+ }
public function index(Request $request)
{
@@ -222,7 +226,7 @@ class CustomerController extends Controller
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$customer = $this->customerRepository->find($userid);
- if (! $customer) {
+ if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalidated Request');
}
@@ -231,15 +235,15 @@ class CustomerController extends Controller
['customer_id' => $userid],
['server']
);
-
+
$vpsServices = $this->vmwareRepository->filter(
['customer_id' => $userid],
['ipaddress.host.datacenter.vCenter', 'os.osGroup']
);
-
+
// Kết hợp và format dữ liệu
$allService = collect();
-
+
foreach ($hostingServices as $hosting) {
$allService->push((object) [
'product_id' => $hosting->id,
@@ -248,7 +252,7 @@ class CustomerController extends Controller
'description' => $hosting->name . ' (Hosting)'
]);
}
-
+
foreach ($vpsServices as $vps) {
$allService->push((object) [
'product_id' => $vps->id,
@@ -257,7 +261,7 @@ class CustomerController extends Controller
'description' => $vps->name . ' (VPS)'
]);
}
-
+
// Lấy invoice_item cụ thể cho sản phẩm
$invoice_item = $this->invoiceItemRepository->findBy(
$userid,
@@ -267,11 +271,11 @@ class CustomerController extends Controller
'value' => $userid
]
);
-
+
$type = null;
$product = null;
$productName = '';
-
+
if ($invoice_item) {
$product_id = $invoice_item->product_id ?? null;
$product_module_id = $request->get('product') ?? $invoice_item->product_id ?? null;
@@ -326,7 +330,7 @@ class CustomerController extends Controller
public function storeCustomerProduct(Request $request)
{
- if (! $request->product_type) {
+ if (!$request->product_type) {
return back()->with($request->except(['_token', '_method']))->withErrors('Invalid Request');
}
@@ -335,7 +339,7 @@ class CustomerController extends Controller
$rules = [];
switch ($request->product_type) {
case 3:
- $rules = [
+ $rules = [
'product_id' => 'required',
'next_due_date' => 'required',
'next_payment' => 'required',
@@ -360,7 +364,7 @@ class CustomerController extends Controller
if ($validator->fails()) {
return back()->withErrors($validator->errors()->first());
}
- if (! $product) {
+ if (!$product) {
return back()->withErrors('Product not found');
}
try {
@@ -418,7 +422,7 @@ class CustomerController extends Controller
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$customer = $this->customerRepository->find($userid);
- if (! $customer) {
+ if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalid Request');
}
$domains = $this->moduleDomainRepository->filter(
@@ -542,7 +546,7 @@ class CustomerController extends Controller
$customer = $this->customerRepository->find($userid);
- if (! $customer) {
+ if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalid Request');
}
@@ -713,7 +717,7 @@ class CustomerController extends Controller
}
$customer = $this->customerRepository->find($request->get('userid'));
- if (! $customer) {
+ if (!$customer) {
return back()->withErrors('Invalid request');
}
Auth::guard('users')->login($customer);
@@ -739,12 +743,163 @@ class CustomerController extends Controller
);
return DataTables::eloquent($query)
+ ->addColumn('status', function ($d) {
+ return view('administrator.pages.customer.datatable.status', ['row' => $d])->render();
+ })
->addColumn(
'action',
function ($d) {
return view('administrator.pages.customer.datatable.action', ['row' => $d])->render();
}
)
+ ->rawColumns(['status', 'action'])
->make(true);
}
+
+ public function edit(int $id = 0)
+ {
+ $customer = $this->customerRepository->find($id);
+
+ if (!$customer) {
+ return back()->withErrors('Invalid request.');
+ }
+
+ $title = 'Edit Customer';
+ return view('administrator.pages.customer.edit', compact('title', 'customer'));
+ }
+
+ public function update(int $id = 0, CreateCustomerRequest $request)
+ {
+ $customer = $this->customerRepository->find($id);
+
+ if (!$customer) {
+ return back()->withErrors('Invalid request.');
+ }
+
+ $request->validated();
+
+ try {
+ DB::beginTransaction();
+
+ $data = $request->except(['_token', 'password']);
+
+ if (!empty($request->password)) {
+ $data['password'] = password_hash($request->password, PASSWORD_BCRYPT);
+ }
+
+ $this->customerRepository->update($id, $data);
+
+ DB::commit();
+ } catch (Exception $error) {
+ DB::rollBack();
+ return back()->withErrors($error->getMessage());
+ }
+
+ return redirect()->route('customer.index')->with('success', 'Update customer successfully!');
+ }
+
+ public function destroy(int $id = 0)
+ {
+ $customer = $this->customerRepository->find($id);
+
+ if (!$customer) {
+ return back()->withErrors('Invalid request.');
+ }
+
+ DB::beginTransaction();
+ try {
+ Invoice::where('customer_id', $id)->delete();
+ Order::where('customer_id', $id)->delete();
+ Transaction::where('customer_id', $id)->delete();
+
+ $customer->delete();
+
+ DB::commit();
+ } catch (Exception $error) {
+ DB::rollBack();
+ return back()->withErrors($error->getMessage());
+ }
+
+ return redirect()->route('customer.index')->with('success', 'Deleted customer successfully!');
+ }
+
+ public function trash()
+ {
+ $title = 'Trash Customers';
+ return view('administrator.pages.customer.trash', compact('title'));
+ }
+
+ public function datatableTrash(Request $request)
+ {
+ $query = $this->customerRepository->onlyTrashed(
+ [],
+ ['hosting', 'vps', 'domain']
+ );
+
+ return DataTables::eloquent($query)
+ ->addColumn('status', function ($d) {
+ return view('administrator.pages.customer.datatable.status', ['row' => $d])->render();
+ })
+ ->addColumn(
+ 'action',
+ function ($d) {
+ return view('administrator.pages.customer.datatable.action-trash', ['row' => $d])->render();
+ }
+ )
+ ->rawColumns(['status', 'action'])
+ ->make(true);
+ }
+
+ public function restore(int $id = 0)
+ {
+ $customer = $this->customerRepository->find($id);
+
+ if (!$customer) {
+ $customer = $this->customerRepository->onlyTrashed()->find($id);
+ }
+
+ if (!$customer) {
+ return back()->withErrors('Invalid request.');
+ }
+
+ DB::beginTransaction();
+ try {
+ $customer->restore();
+ Invoice::withTrashed()->where('customer_id', $id)->restore();
+ Order::withTrashed()->where('customer_id', $id)->restore();
+ Transaction::withTrashed()->where('customer_id', $id)->restore();
+
+ DB::commit();
+ } catch (Exception $error) {
+ DB::rollBack();
+ return back()->withErrors($error->getMessage());
+ }
+
+ return back()->with('success', 'Restored customer successfully!');
+ }
+
+ public function forceDelete(int $id = 0)
+ {
+ $customer = $this->customerRepository->onlyTrashed()->find($id);
+
+ if (!$customer) {
+ return back()->withErrors('Invalid request.');
+ }
+
+ DB::beginTransaction();
+ try {
+ Invoice::withTrashed()->where('customer_id', $id)->forceDelete();
+ Order::withTrashed()->where('customer_id', $id)->forceDelete();
+ Transaction::withTrashed()->where('customer_id', $id)->forceDelete();
+
+ $customer->forceDelete();
+
+ DB::commit();
+ } catch (Exception $error) {
+ DB::rollBack();
+ return back()->withErrors($error->getMessage());
+ }
+
+ return back()->with('success', 'Permanently deleted customer!');
+ }
}
diff --git a/app/Models/Customer.php b/app/Models/Customer.php
index b18b149..d7fe73d 100644
--- a/app/Models/Customer.php
+++ b/app/Models/Customer.php
@@ -4,12 +4,13 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Sanctum\HasApiTokens;
class Customer extends Authenticatable
{
- use HasFactory, HasApiTokens, HasUuids;
+ use HasFactory, HasApiTokens, HasUuids, SoftDeletes;
protected $table = 'customers';
diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php
index ab79a67..7f9e7e2 100644
--- a/app/Models/Invoice.php
+++ b/app/Models/Invoice.php
@@ -5,10 +5,11 @@ namespace App\Models;
use App\Enums\Invoice\InvoiceStatus;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
class Invoice extends Model
{
- use HasFactory;
+ use HasFactory, SoftDeletes;
protected $table = 'invoice';
public $timestamps = true;
diff --git a/app/Models/Order.php b/app/Models/Order.php
index f5b91a3..1c10913 100644
--- a/app/Models/Order.php
+++ b/app/Models/Order.php
@@ -4,10 +4,11 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
class Order extends Model
{
- use HasFactory;
+ use HasFactory, SoftDeletes;
protected $table = 'order';
diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php
index 9b5c980..a4c7aed 100644
--- a/app/Models/Transaction.php
+++ b/app/Models/Transaction.php
@@ -4,10 +4,11 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
class Transaction extends Model
{
- use HasFactory;
+ use HasFactory, SoftDeletes;
protected $table = 'transaction';
protected $fillable = [
diff --git a/app/Repositories/Customer/CustomerCachedRepository.php b/app/Repositories/Customer/CustomerCachedRepository.php
index 53c90e1..936301e 100644
--- a/app/Repositories/Customer/CustomerCachedRepository.php
+++ b/app/Repositories/Customer/CustomerCachedRepository.php
@@ -67,4 +67,9 @@ class CustomerCachedRepository extends BaseCachedRepository implements CustomerR
return $this->customerRepository->findBy($key, $value);
});
}
+
+ public function onlyTrashed(array $relationships = [], array $withCount = [])
+ {
+ return $this->customerRepository->onlyTrashed($relationships, $withCount);
+ }
}
diff --git a/app/Repositories/Customer/CustomerRepository.php b/app/Repositories/Customer/CustomerRepository.php
index 3d0e8e7..e140a5d 100644
--- a/app/Repositories/Customer/CustomerRepository.php
+++ b/app/Repositories/Customer/CustomerRepository.php
@@ -125,4 +125,15 @@ class CustomerRepository extends BaseRepository implements CustomerRepositoryInt
}
return $this->model->where($key, $value)->first();
}
+
+ public function onlyTrashed(array $relationships = [], array $withCount = [])
+ {
+ $query = $this->model->with($relationships);
+
+ if (count($withCount) > 0) {
+ $query = $query->withCount($withCount);
+ }
+
+ return $query->onlyTrashed();
+ }
}
diff --git a/app/Repositories/Customer/CustomerRepositoryInterface.php b/app/Repositories/Customer/CustomerRepositoryInterface.php
index 83631d2..4c83e67 100644
--- a/app/Repositories/Customer/CustomerRepositoryInterface.php
+++ b/app/Repositories/Customer/CustomerRepositoryInterface.php
@@ -15,4 +15,5 @@ interface CustomerRepositoryInterface extends BaseRepositoryInterface
);
public function findWithRelationships(int $id = 0, array $relationships = [],array $withCount = [], array $withSum = []);
public function findBy(string $key = '',string $value = '');
+ public function onlyTrashed(array $relationships = [], array $withCount = []);
}
\ No newline at end of file
diff --git a/database/migrations/2024_01_31_145201_customer.php b/database/migrations/2024_01_31_145201_customer.php
index 79e45f5..5f44f7a 100644
--- a/database/migrations/2024_01_31_145201_customer.php
+++ b/database/migrations/2024_01_31_145201_customer.php
@@ -42,6 +42,7 @@ return new class extends Migration {
$table->string('remember_token', 100)->nullable();
$table->tinyInteger('status')->default(1);
$table->timestamps();
+ $table->softDeletes();
$table->foreign('province_code')
->references('code')
@@ -66,6 +67,6 @@ return new class extends Migration {
public function down()
{
//
- Schema::dropIfExists('customer');
+ Schema::dropIfExists('customers');
}
};
diff --git a/database/migrations/2024_01_31_155621_order.php b/database/migrations/2024_01_31_155621_order.php
index 403e33d..e39224a 100644
--- a/database/migrations/2024_01_31_155621_order.php
+++ b/database/migrations/2024_01_31_155621_order.php
@@ -27,6 +27,7 @@ return new class extends Migration {
$table->string('client_ip', 100)->nullable();
$table->tinyInteger('status')->default(0);
$table->timestamps();
+ $table->softDeletes();
});
}
diff --git a/database/migrations/2024_01_31_155824_invoice.php b/database/migrations/2024_01_31_155824_invoice.php
index 0d2990b..811fc7a 100644
--- a/database/migrations/2024_01_31_155824_invoice.php
+++ b/database/migrations/2024_01_31_155824_invoice.php
@@ -31,6 +31,7 @@ return new class extends Migration {
$table->tinyInteger('status')->default(0);
$table->timestamps();
+ $table->softDeletes();
});
}
diff --git a/database/migrations/2026_02_16_000000_add_softdeletes_to_customer_invoice_order_tables.php b/database/migrations/2026_02_16_000000_add_softdeletes_to_customer_invoice_order_tables.php
new file mode 100644
index 0000000..d03acee
--- /dev/null
+++ b/database/migrations/2026_02_16_000000_add_softdeletes_to_customer_invoice_order_tables.php
@@ -0,0 +1,45 @@
+softDeletes();
+ });
+
+ Schema::table('invoice', function (Blueprint $table) {
+ $table->softDeletes();
+ });
+
+ Schema::table('order', function (Blueprint $table) {
+ $table->softDeletes();
+ });
+
+ Schema::table('transaction', function (Blueprint $table) {
+ $table->softDeletes();
+ });
+ }
+
+ public function down()
+ {
+ Schema::table('customers', function (Blueprint $table) {
+ $table->dropSoftDeletes();
+ });
+
+ Schema::table('invoice', function (Blueprint $table) {
+ $table->dropSoftDeletes();
+ });
+
+ Schema::table('order', function (Blueprint $table) {
+ $table->dropSoftDeletes();
+ });
+
+ Schema::table('transaction', function (Blueprint $table) {
+ $table->dropSoftDeletes();
+ });
+ }
+};
diff --git a/database/migrations/2026_02_16_120000_add_softdeletes_to_transaction_table.php b/database/migrations/2026_02_16_120000_add_softdeletes_to_transaction_table.php
new file mode 100644
index 0000000..4c141d3
--- /dev/null
+++ b/database/migrations/2026_02_16_120000_add_softdeletes_to_transaction_table.php
@@ -0,0 +1,21 @@
+softDeletes();
+ });
+ }
+
+ public function down()
+ {
+ Schema::table('transaction', function (Blueprint $table) {
+ $table->dropSoftDeletes();
+ });
+ }
+};
diff --git a/resources/views/administrator/pages/block/customer/btn.blade.php b/resources/views/administrator/pages/block/customer/btn.blade.php
new file mode 100644
index 0000000..765c52e
--- /dev/null
+++ b/resources/views/administrator/pages/block/customer/btn.blade.php
@@ -0,0 +1,2 @@
+