105 lines
3.7 KiB
PHP
105 lines
3.7 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Modules\Finance\Services;
|
||
|
|
|
||
|
|
use App\Modules\Finance\Contracts\FinanceServiceInterface;
|
||
|
|
use App\Modules\Finance\Models\UtilityFee;
|
||
|
|
use App\Modules\Procurement\Contracts\ProcurementServiceInterface;
|
||
|
|
use Illuminate\Support\Collection;
|
||
|
|
use Illuminate\Support\Carbon;
|
||
|
|
|
||
|
|
class FinanceService implements FinanceServiceInterface
|
||
|
|
{
|
||
|
|
protected $procurementService;
|
||
|
|
|
||
|
|
public function __construct(ProcurementServiceInterface $procurementService)
|
||
|
|
{
|
||
|
|
$this->procurementService = $procurementService;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getAccountingReportData(string $start, string $end): array
|
||
|
|
{
|
||
|
|
// 1. 獲取採購單資料
|
||
|
|
$purchaseOrders = $this->procurementService->getPurchaseOrdersByDate($start, $end)
|
||
|
|
->map(function ($po) {
|
||
|
|
return [
|
||
|
|
'id' => 'PO-' . $po->id,
|
||
|
|
'date' => Carbon::parse($po->created_at)->timezone(config('app.timezone'))->toDateString(),
|
||
|
|
'source' => '採購單',
|
||
|
|
'category' => '進貨支出',
|
||
|
|
'item' => $po->vendor->name ?? '未知廠商',
|
||
|
|
'reference' => $po->code,
|
||
|
|
'invoice_number' => $po->invoice_number,
|
||
|
|
'amount' => (float)$po->grand_total,
|
||
|
|
];
|
||
|
|
});
|
||
|
|
|
||
|
|
// 2. 獲取公共事業費 (注意:目前資料表欄位為 transaction_date)
|
||
|
|
$utilityFees = UtilityFee::whereBetween('transaction_date', [$start, $end])
|
||
|
|
->get()
|
||
|
|
->map(function ($fee) {
|
||
|
|
return [
|
||
|
|
'id' => 'UF-' . $fee->id,
|
||
|
|
'date' => $fee->transaction_date->format('Y-m-d'),
|
||
|
|
'source' => '公共事業費',
|
||
|
|
'category' => $fee->category,
|
||
|
|
'item' => $fee->description ?: $fee->category,
|
||
|
|
'reference' => '-',
|
||
|
|
'invoice_number' => $fee->invoice_number,
|
||
|
|
'amount' => (float)$fee->amount,
|
||
|
|
];
|
||
|
|
});
|
||
|
|
|
||
|
|
$allRecords = $purchaseOrders->concat($utilityFees)
|
||
|
|
->sortByDesc('date')
|
||
|
|
->values();
|
||
|
|
|
||
|
|
return [
|
||
|
|
'records' => $allRecords,
|
||
|
|
'summary' => [
|
||
|
|
'total_amount' => $allRecords->sum('amount'),
|
||
|
|
'purchase_total' => $purchaseOrders->sum('amount'),
|
||
|
|
'utility_total' => $utilityFees->sum('amount'),
|
||
|
|
'record_count' => $allRecords->count(),
|
||
|
|
]
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getUtilityFees(array $filters)
|
||
|
|
{
|
||
|
|
$query = UtilityFee::query();
|
||
|
|
|
||
|
|
if (!empty($filters['search'])) {
|
||
|
|
$search = $filters['search'];
|
||
|
|
$query->where(function($q) use ($search) {
|
||
|
|
$q->where('category', 'like', "%{$search}%")
|
||
|
|
->orWhere('invoice_number', 'like', "%{$search}%")
|
||
|
|
->orWhere('description', 'like', "%{$search}%");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!empty($filters['category']) && $filters['category'] !== 'all') {
|
||
|
|
$query->where('category', $filters['category']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!empty($filters['date_start'])) {
|
||
|
|
$query->where('transaction_date', '>=', $filters['date_start']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!empty($filters['date_end'])) {
|
||
|
|
$query->where('transaction_date', '<=', $filters['date_end']);
|
||
|
|
}
|
||
|
|
|
||
|
|
$sortField = $filters['sort_field'] ?? 'created_at';
|
||
|
|
$sortDirection = $filters['sort_direction'] ?? 'desc';
|
||
|
|
$query->orderBy($sortField, $sortDirection);
|
||
|
|
|
||
|
|
return $query->paginate($filters['per_page'] ?? 10);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getUniqueCategories(): Collection
|
||
|
|
{
|
||
|
|
return UtilityFee::distinct()->pluck('category');
|
||
|
|
}
|
||
|
|
}
|