All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m0s
142 lines
5.4 KiB
PHP
142 lines
5.4 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. 獲取應付帳款資料 (已付款)
|
|
$accountPayables = \App\Modules\Finance\Models\AccountPayable::where('status', \App\Modules\Finance\Models\AccountPayable::STATUS_PAID)
|
|
->whereNotNull('paid_at')
|
|
->whereBetween('paid_at', [$start, $end])
|
|
->get();
|
|
|
|
// 取得供應商資料 (Manual Hydration)
|
|
$vendorIds = $accountPayables->pluck('vendor_id')->unique()->filter()->toArray();
|
|
$vendorsMap = $this->procurementService->getVendorsByIds($vendorIds)->keyBy('id');
|
|
|
|
// 付款方式對映
|
|
$paymentMethodMap = [
|
|
'cash' => '現金',
|
|
'bank_transfer' => '銀行轉帳',
|
|
'check' => '支票',
|
|
'credit_card' => '信用卡',
|
|
];
|
|
|
|
$payableRecords = $accountPayables->map(function ($ap) use ($vendorsMap, $paymentMethodMap) {
|
|
$vendorName = isset($vendorsMap[$ap->vendor_id]) ? $vendorsMap[$ap->vendor_id]->name : '未知廠商';
|
|
$mappedPaymentMethod = $paymentMethodMap[$ap->payment_method] ?? $ap->payment_method;
|
|
return [
|
|
'id' => 'AP-' . $ap->id,
|
|
'date' => Carbon::parse($ap->paid_at)->timezone(config('app.timezone'))->toDateString(),
|
|
'source' => '應付帳款',
|
|
'category' => '進貨支出',
|
|
'item' => $vendorName,
|
|
'reference' => $ap->document_number,
|
|
'invoice_date' => $ap->invoice_date ? $ap->invoice_date->format('Y-m-d') : null,
|
|
'invoice_number' => $ap->invoice_number,
|
|
'amount' => (float)$ap->total_amount,
|
|
'tax_amount' => (float)$ap->tax_amount,
|
|
'status' => $ap->status,
|
|
'payment_method' => $mappedPaymentMethod,
|
|
'payment_note' => $ap->payment_note,
|
|
'remarks' => $ap->remarks,
|
|
];
|
|
});
|
|
|
|
// 2. 獲取公共事業費 (已繳費)
|
|
$utilityFees = UtilityFee::where('payment_status', UtilityFee::STATUS_PAID)
|
|
->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_date' => null,
|
|
'invoice_number' => $fee->invoice_number,
|
|
'amount' => (float)$fee->amount,
|
|
'tax_amount' => 0.0,
|
|
'status' => $fee->payment_status,
|
|
'payment_method' => null,
|
|
'payment_note' => null,
|
|
'remarks' => $fee->description,
|
|
];
|
|
});
|
|
|
|
$allRecords = $payableRecords->concat($utilityFees)
|
|
->sortByDesc('date')
|
|
->values();
|
|
|
|
return [
|
|
'records' => $allRecords,
|
|
'summary' => [
|
|
'total_amount' => $allRecords->sum('amount'),
|
|
'payable_total' => $payableRecords->sum('amount'),
|
|
'utility_total' => $utilityFees->sum('amount'),
|
|
'record_count' => $allRecords->count(),
|
|
]
|
|
];
|
|
}
|
|
|
|
public function getUtilityFees(array $filters)
|
|
{
|
|
$query = UtilityFee::withCount('attachments');
|
|
|
|
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);
|
|
|
|
$defaultPerPage = \App\Modules\Core\Models\SystemSetting::getVal('display.per_page', 10);
|
|
$perPage = (int) ($filters['per_page'] ?? $defaultPerPage);
|
|
if (!in_array($perPage, [10, 20, 50, 100])) {
|
|
$perPage = $defaultPerPage;
|
|
}
|
|
|
|
return $query->paginate($perPage);
|
|
}
|
|
|
|
public function getUniqueCategories(): Collection
|
|
{
|
|
return UtilityFee::distinct()->pluck('category');
|
|
}
|
|
}
|