Files
star-erp/app/Modules/Finance/Services/FinanceService.php
2026-03-06 14:40:14 +08:00

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');
}
}