296 lines
10 KiB
PHP
296 lines
10 KiB
PHP
<?php
|
|
|
|
namespace Modules\Admin\app\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Traits\HasFilterRequest;
|
|
use App\Traits\HasOrderByRequest;
|
|
use App\Traits\HasSearchRequest;
|
|
use Illuminate\Http\Request;
|
|
use Modules\Admin\app\Models\ElectricityBill;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class ElectricityBillController extends Controller
|
|
{
|
|
use HasOrderByRequest;
|
|
use HasFilterRequest;
|
|
use HasSearchRequest;
|
|
|
|
/**
|
|
* Get all electricity bills with pagination
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
try {
|
|
$bills = new ElectricityBill;
|
|
|
|
// Order by
|
|
$this->orderByRequest($bills, $request);
|
|
|
|
// Filter
|
|
$this->filterRequest(
|
|
builder: $bills,
|
|
request: $request,
|
|
filterKeys: [
|
|
'billing_date' => self::F_TEXT,
|
|
]
|
|
);
|
|
|
|
// Search
|
|
$this->searchRequest(
|
|
builder: $bills,
|
|
value: $request->get('search'),
|
|
fields: ['billing_date', 'notes']
|
|
);
|
|
|
|
$responseData = $bills
|
|
->leftJoin('users as creator', 'electricity_bills.created_by', '=', 'creator.id')
|
|
->leftJoin('users as updater', 'electricity_bills.updated_by', '=', 'updater.id')
|
|
->orderBy('electricity_bills.billing_date', 'desc')
|
|
->select(
|
|
'electricity_bills.*',
|
|
'creator.name as creator_name',
|
|
'updater.name as updater_name'
|
|
)
|
|
->paginate($request->get('per_page', 15));
|
|
|
|
return AbstractController::ResultSuccess($responseData);
|
|
} catch (\Exception $e) {
|
|
Log::error('Error fetching electricity bills: ' . $e->getMessage());
|
|
return AbstractController::ResultError($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create new electricity bill
|
|
*/
|
|
public function create(Request $request)
|
|
{
|
|
try {
|
|
$validated = $request->validate([
|
|
'billing_date' => 'required|string',
|
|
'previous_reading' => 'required|numeric|min:0',
|
|
'current_reading' => 'required|numeric|min:0',
|
|
'unit_price' => 'required|numeric|min:0',
|
|
'notes' => 'nullable|string',
|
|
]);
|
|
|
|
// Check if billing_date already exists
|
|
$existingBill = ElectricityBill::where('billing_date', $validated['billing_date'])->first();
|
|
if ($existingBill) {
|
|
return AbstractController::ResultError('Bill for this month already exists', 422);
|
|
}
|
|
|
|
// Calculate total amount
|
|
$consumption = $validated['current_reading'] - $validated['previous_reading'];
|
|
$totalAmount = $consumption * $validated['unit_price'];
|
|
|
|
$bill = ElectricityBill::create([
|
|
'billing_date' => $validated['billing_date'],
|
|
'previous_reading' => $validated['previous_reading'],
|
|
'current_reading' => $validated['current_reading'],
|
|
'unit_price' => $validated['unit_price'],
|
|
'total_amount' => $totalAmount,
|
|
'notes' => $validated['notes'] ?? null,
|
|
'created_by' => auth('admins')->user()->id ?? null,
|
|
]);
|
|
|
|
return AbstractController::ResultSuccess($bill, 'Electricity bill created successfully');
|
|
} catch (\Exception $e) {
|
|
Log::error('Error creating electricity bill: ' . $e->getMessage());
|
|
return AbstractController::ResultError($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update electricity bill
|
|
*/
|
|
public function update(Request $request, $id)
|
|
{
|
|
try {
|
|
$validated = $request->validate([
|
|
'billing_date' => 'sometimes|string',
|
|
'previous_reading' => 'sometimes|numeric|min:0',
|
|
'current_reading' => 'sometimes|numeric|min:0',
|
|
'unit_price' => 'sometimes|numeric|min:0',
|
|
'notes' => 'nullable|string',
|
|
]);
|
|
|
|
$bill = ElectricityBill::findOrFail($id);
|
|
|
|
// Check if billing_date already exists (excluding current record)
|
|
if (isset($validated['billing_date'])) {
|
|
$existingBill = ElectricityBill::where('billing_date', $validated['billing_date'])
|
|
->where('id', '!=', $id)
|
|
->first();
|
|
if ($existingBill) {
|
|
return AbstractController::ResultError('Bill for this month already exists', 422);
|
|
}
|
|
}
|
|
|
|
// Recalculate total if any reading or price changed
|
|
$previousReading = $validated['previous_reading'] ?? $bill->previous_reading;
|
|
$currentReading = $validated['current_reading'] ?? $bill->current_reading;
|
|
$unitPrice = $validated['unit_price'] ?? $bill->unit_price;
|
|
$consumption = $currentReading - $previousReading;
|
|
$totalAmount = $consumption * $unitPrice;
|
|
|
|
$bill->update(array_merge($validated, [
|
|
'total_amount' => $totalAmount,
|
|
'updated_by' => auth('admins')->user()->id ?? null,
|
|
]));
|
|
|
|
return AbstractController::ResultSuccess($bill, 'Electricity bill updated successfully');
|
|
} catch (\Exception $e) {
|
|
Log::error('Error updating electricity bill: ' . $e->getMessage());
|
|
return AbstractController::ResultError($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete electricity bill
|
|
*/
|
|
public function delete(Request $request, $id)
|
|
{
|
|
try {
|
|
$bill = ElectricityBill::findOrFail($id);
|
|
$bill->delete();
|
|
|
|
return AbstractController::ResultSuccess(null, 'Electricity bill deleted successfully');
|
|
} catch (\Exception $e) {
|
|
Log::error('Error deleting electricity bill: ' . $e->getMessage());
|
|
return AbstractController::ResultError($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Export electricity bill to PDF
|
|
*/
|
|
public function exportPdf(Request $request, $id)
|
|
{
|
|
try {
|
|
$bill = ElectricityBill::findOrFail($id);
|
|
|
|
// Get month name from billing_date
|
|
$consumption = $bill->current_reading - $bill->previous_reading;
|
|
$totalText = $this->numberToVietnamese($bill->total_amount);
|
|
$date = Carbon::parse($bill->billing_date);
|
|
|
|
$dateNow = 'Ngày ' . $date->day .
|
|
' tháng ' . $date->month .
|
|
' năm ' . $date->year;
|
|
|
|
// Generate PDF
|
|
$pdf = Pdf::loadView('admin::admin.electricity_bills.pdf', [
|
|
'bill' => $bill,
|
|
'consumption' => $consumption,
|
|
'dateNow' => $dateNow,
|
|
'totalText' => $totalText
|
|
]);
|
|
|
|
$fileName = 'electricity_bill_' . $bill->billing_date . '.pdf';
|
|
$filePath = 'electricity_bills/' . $fileName;
|
|
|
|
// đảm bảo folder tồn tại
|
|
if (!Storage::disk('public')->exists('electricity_bills')) {
|
|
Storage::disk('public')->makeDirectory('electricity_bills');
|
|
}
|
|
|
|
// 👇 render 1 lần
|
|
$pdfContent = $pdf->output();
|
|
|
|
// 👇 lưu file
|
|
Storage::disk('public')->put($filePath, $pdfContent);
|
|
|
|
// update DB
|
|
$bill->update(['file_path' => $filePath]);
|
|
|
|
// 👇 trả về đúng file đã tạo
|
|
return response($pdfContent)
|
|
->header('Content-Type', 'application/pdf')
|
|
->header('Content-Disposition', 'attachment; filename="' . $fileName . '"');
|
|
} catch (\Exception $e) {
|
|
Log::error('Error exporting electricity bill to PDF: ' . $e->getMessage());
|
|
return AbstractController::ResultError($e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get electricity bill by ID
|
|
*/
|
|
public function show($id)
|
|
{
|
|
try {
|
|
$bill = ElectricityBill::with(['creator', 'updater'])->findOrFail($id);
|
|
return AbstractController::ResultSuccess($bill);
|
|
} catch (\Exception $e) {
|
|
Log::error('Error fetching electricity bill: ' . $e->getMessage());
|
|
return AbstractController::ResultError($e->getMessage());
|
|
}
|
|
}
|
|
|
|
function numberToVietnamese($number)
|
|
{
|
|
$units = ["", "một", "hai", "ba", "bốn", "năm", "sáu", "bảy", "tám", "chín"];
|
|
$levels = ["", "nghìn", "triệu", "tỷ"];
|
|
|
|
if ($number == 0) return "không đồng";
|
|
|
|
$number = (int)$number;
|
|
$result = "";
|
|
$level = 0;
|
|
|
|
while ($number > 0) {
|
|
$threeDigits = $number % 1000;
|
|
if ($threeDigits != 0) {
|
|
$result = $this->readThreeDigits($threeDigits, $units) . " " . $levels[$level] . " " . $result;
|
|
}
|
|
$number = floor($number / 1000);
|
|
$level++;
|
|
}
|
|
|
|
return ucfirst(trim(preg_replace('/\s+/', ' ', $result))) . " đồng";
|
|
}
|
|
|
|
function readThreeDigits($number, $units)
|
|
{
|
|
$hundreds = floor($number / 100);
|
|
$tens = floor(($number % 100) / 10);
|
|
$ones = $number % 10;
|
|
|
|
$result = "";
|
|
|
|
if ($hundreds > 0) {
|
|
$result .= $units[$hundreds] . " trăm";
|
|
if ($tens == 0 && $ones > 0) {
|
|
$result .= " lẻ";
|
|
}
|
|
}
|
|
|
|
if ($tens > 1) {
|
|
$result .= " " . $units[$tens] . " mươi";
|
|
if ($ones == 1) {
|
|
$result .= " mốt";
|
|
} elseif ($ones == 5) {
|
|
$result .= " lăm";
|
|
} elseif ($ones > 0) {
|
|
$result .= " " . $units[$ones];
|
|
}
|
|
} elseif ($tens == 1) {
|
|
$result .= " mười";
|
|
if ($ones == 5) {
|
|
$result .= " lăm";
|
|
} elseif ($ones > 0) {
|
|
$result .= " " . $units[$ones];
|
|
}
|
|
} elseif ($ones > 0) {
|
|
$result .= " " . $units[$ones];
|
|
}
|
|
|
|
return trim($result);
|
|
}
|
|
}
|