169 lines
7.1 KiB
PHP
169 lines
7.1 KiB
PHP
<?php
|
||
|
||
namespace Modules\EcommerceFinance\Http\Controllers;
|
||
|
||
use Illuminate\Http\RedirectResponse;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Pagination\LengthAwarePaginator;
|
||
use Illuminate\Routing\Controller;
|
||
use Modules\EcommerceFinance\Repositories\DingProcessDetailMirrorRepository;
|
||
use Modules\EcommerceFinance\Services\DingProcessDetailMirrorImporter;
|
||
use Modules\EcommerceFinance\View\ProcessDetailsPageData;
|
||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||
use Throwable;
|
||
|
||
class ProcessDetails extends Controller
|
||
{
|
||
public function __construct(
|
||
private readonly DingProcessDetailMirrorRepository $repository,
|
||
) {}
|
||
|
||
public function show(Request $request)
|
||
{
|
||
$filters = $this->filters($request);
|
||
$page = max((int) $request->query('page', 1), 1);
|
||
$perPage = ProcessDetailsPageData::normalizePerPage($request->query('per_page'));
|
||
$paginationQuery = array_filter(
|
||
[...$filters, 'per_page' => $perPage],
|
||
static fn (mixed $value): bool => $value !== '' && $value !== null,
|
||
);
|
||
|
||
try {
|
||
$options = $this->repository->filterOptions($filters);
|
||
if ($filters['payment_state'] !== ''
|
||
&& ! in_array($filters['payment_state'], $options['payment_states'], true)) {
|
||
$filters['payment_state'] = '';
|
||
unset($paginationQuery['payment_state']);
|
||
}
|
||
$result = $this->repository->paginate($filters, $page, $perPage);
|
||
|
||
return view('business.pages.financial-operations.process-details', [
|
||
'section' => ['slug' => 'process-data', 'title' => '流程数据'],
|
||
'page' => ['slug' => 'oa-process', 'title' => 'OA流程'],
|
||
'processRows' => new LengthAwarePaginator(
|
||
$result['data'],
|
||
$result['total'],
|
||
$perPage,
|
||
$page,
|
||
['path' => $request->url(), 'query' => $paginationQuery],
|
||
),
|
||
'filters' => $filters,
|
||
'summary' => $result['summary'],
|
||
'documentTypes' => $options['document_types'],
|
||
'statuses' => $options['statuses'],
|
||
'paymentStates' => $options['payment_states'],
|
||
'mirrorStatus' => $result['status'],
|
||
'mirrorSyncedAt' => $result['last_synced_at'],
|
||
'mirrorStale' => $result['sync_stale'] ?? false,
|
||
'mirrorStaleAfterMinutes' => $result['sync_stale_after_minutes'] ?? 15,
|
||
'scope' => $result['scope'],
|
||
'error' => null,
|
||
]);
|
||
} catch (Throwable $exception) {
|
||
report($exception);
|
||
|
||
return view('business.pages.financial-operations.process-details', [
|
||
'section' => ['slug' => 'process-data', 'title' => '流程数据'],
|
||
'page' => ['slug' => 'oa-process', 'title' => 'OA流程'],
|
||
'processRows' => new LengthAwarePaginator([], 0, $perPage, $page, [
|
||
'path' => $request->url(),
|
||
'query' => $paginationQuery,
|
||
]),
|
||
'filters' => $filters,
|
||
'summary' => [
|
||
'rows' => 0,
|
||
'approvals' => 0,
|
||
'amount_total' => 0.0,
|
||
'bank_amount_total' => 0.0,
|
||
],
|
||
'documentTypes' => [],
|
||
'statuses' => [],
|
||
'paymentStates' => [],
|
||
'mirrorStatus' => 'unavailable',
|
||
'mirrorSyncedAt' => null,
|
||
'mirrorStale' => false,
|
||
'mirrorStaleAfterMinutes' => 15,
|
||
'scope' => $this->repository->scope(),
|
||
'error' => 'OA流程镜像尚未完成导入,请稍后重试。',
|
||
]);
|
||
}
|
||
}
|
||
|
||
public function export(Request $request): StreamedResponse|RedirectResponse
|
||
{
|
||
if (! $this->repository->ready()) {
|
||
return redirect()
|
||
->route('business.pages.show', [
|
||
'section' => 'process-data',
|
||
'page' => 'oa-process',
|
||
])
|
||
->withErrors(['export' => 'OA流程镜像尚未完成导入,暂时不能导出。']);
|
||
}
|
||
|
||
$filters = $this->filters($request);
|
||
|
||
return response()->streamDownload(function () use ($filters): void {
|
||
$stream = fopen('php://output', 'wb');
|
||
fwrite($stream, "\xEF\xBB\xBF");
|
||
fputcsv($stream, [...DingProcessDetailMirrorImporter::HEADERS, '付款状态', '付款差额']);
|
||
|
||
$number = 0;
|
||
foreach ($this->repository->exportRows($filters) as $row) {
|
||
$number++;
|
||
fputcsv($stream, [
|
||
$number,
|
||
(string) ($row['business_id'] ?? ''),
|
||
(string) ($row['originator_name'] ?? ''),
|
||
(string) ($row['status'] ?? ''),
|
||
(string) ($row['document_type'] ?? ''),
|
||
(string) ($row['purpose'] ?? ''),
|
||
(int) ($row['line_no'] ?? 0),
|
||
(string) ($row['account_code'] ?? ''),
|
||
(string) ($row['account_name'] ?? ''),
|
||
$row['amount'] ?? '',
|
||
(string) ($row['bank_account_code'] ?? ''),
|
||
(string) ($row['bank_account_name'] ?? ''),
|
||
$row['bank_amount'] ?? '',
|
||
(string) ($row['payment_method'] ?? ''),
|
||
(string) ($row['paid_at'] ?? ''),
|
||
(string) ($row['payment_state'] ?? ''),
|
||
isset($row['payment_difference'])
|
||
? number_format((float) $row['payment_difference'], 2, '.', '')
|
||
: '',
|
||
]);
|
||
}
|
||
|
||
fclose($stream);
|
||
}, 'OA流程_' . now()->format('Ymd_His') . '.csv', [
|
||
'Content-Type' => 'text/csv; charset=UTF-8',
|
||
]);
|
||
}
|
||
|
||
/** @return array<string,string> */
|
||
private function filters(Request $request): array
|
||
{
|
||
$status = DingProcessDetailMirrorRepository::normalizeStatusFilter(
|
||
$request->query('status', ''),
|
||
);
|
||
[$paidStart, $paidEnd] = ProcessDetailsPageData::normalizePaidDateRange(
|
||
$request->query('paid_start'),
|
||
$request->query('paid_end'),
|
||
$request->query('paid_date'),
|
||
);
|
||
$paymentState = DingProcessDetailMirrorRepository::normalizePaymentStateFilter(
|
||
$request->query('payment_state'),
|
||
);
|
||
|
||
return [
|
||
'paid_start' => $paidStart,
|
||
'paid_end' => $paidEnd,
|
||
'document_type' => mb_substr(trim((string) $request->query('document_type', '')), 0, 100),
|
||
'status' => mb_substr($status, 0, 20),
|
||
'payment_state' => $paymentState,
|
||
'business_id' => mb_substr(trim((string) $request->query('business_id', '')), 0, 32),
|
||
'originator_name' => mb_substr(trim((string) $request->query('originator_name', '')), 0, 100),
|
||
'keyword' => mb_substr(trim((string) $request->query('keyword', '')), 0, 100),
|
||
];
|
||
}
|
||
}
|