CaiWuXiTong/app/Http/Controllers/Business/SupplierSummaryConfirmationShare.php
苏木 770ddea8a9 feat(供应商对账): 增加免登录送货确认链接 (#1180)
Co-authored-by: 苏木 <594326199@qq.com>
Co-committed-by: 苏木 <594326199@qq.com>
2026-11-15 11:36:27 +08:00

151 lines
5.3 KiB
PHP

<?php
namespace App\Http\Controllers\Business;
use Carbon\CarbonImmutable;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\EcommerceFinance\Services\SupplierDingTalkNotifier;
use Modules\EcommerceFinance\Services\SupplierSummaryConfirmation;
use Modules\EcommerceFinance\Services\SupplierSummaryShareLink;
use Symfony\Component\HttpFoundation\Response;
use Throwable;
/**
* 钉钉群推送的厂家货款确认页,无需厂家登录。
*/
class SupplierSummaryConfirmationShare extends Controller
{
public function __construct(
private readonly SupplierSummaryConfirmation $confirmations,
private readonly SupplierSummaryShareLink $shareLinks,
private readonly SupplierDingTalkNotifier $notifier,
) {
}
public function show(Request $request, string $token): Response
{
$target = $this->resolveRecord($request, $token);
$expiresAt = $this->expiresAt($request);
return response()
->view('business.pages.supplier-reconciliation.summary-confirmation-share', [
'supplier' => $target['supplier'],
'month' => $target['month'],
'monthLabel' => $this->displayMonth($target['month']),
'qty' => (float) ($target['record']['qty'] ?? 0),
'amount' => (float) ($target['record']['amount'] ?? 0),
'status' => (string) ($target['record']['status'] ?? ''),
'confirmedAt' => (string) ($target['record']['confirmed_at'] ?? ''),
'expiresAt' => $expiresAt,
'confirmUrl' => $this->shareLinks->signedRoute(
'signed.supplier-summary-confirmations.confirm',
$token,
$target['companyId'],
$expiresAt,
),
])
->withHeaders([
'Cache-Control' => 'private, no-store, max-age=0',
'X-Robots-Tag' => 'noindex, nofollow, noarchive',
'Referrer-Policy' => 'no-referrer',
]);
}
public function confirm(Request $request, string $token): RedirectResponse
{
$target = $this->resolveRecord($request, $token);
if (($target['record']['status'] ?? '') === SupplierSummaryConfirmation::STATUS_CONFIRMED) {
return $this->redirectToPage($request, $token, $target)
->with('success', '本期货款已经确认,无需重复操作。');
}
$result = $this->confirmations->confirm(
$target['request_id'],
$target['companyId'],
null,
'',
'manufacturer_link',
);
if ($result['newly_confirmed']) {
try {
$this->notifier->sendSummaryConfirmationReceipt($result['record']);
} catch (Throwable $exception) {
report($exception);
}
}
return $this->redirectToPage($request, $token, $target)
->with(
'success',
$result['newly_confirmed']
? '已确认本期货款,财务系统已实时更新。'
: '本期货款已经确认,无需重复操作。',
);
}
/**
* @return array{
* supplier:string,
* month:string,
* push_basis:string,
* request_id:string,
* companyId:int,
* record:array<string,mixed>
* }
*/
private function resolveRecord(Request $request, string $token): array
{
$companyId = (int) ($request->route('company_id') ?: company_id() ?: 1);
$payload = $this->shareLinks->resolveToken($token, $companyId);
abort_if($payload === null, 404, '该货款确认链接无效或已过期。');
$record = $this->confirmations->find($payload['request_id'], $companyId);
abort_if($record === null, 404, '该货款确认记录不存在,请联系财务重新发送。');
abort_unless(
trim((string) ($record['supplier'] ?? '')) === $payload['supplier']
&& trim((string) ($record['month'] ?? '')) === $payload['month']
&& trim((string) ($record['push_basis'] ?? '')) === $payload['push_basis'],
404,
'该货款确认记录与链接不一致。',
);
return [
...$payload,
'companyId' => $companyId,
'record' => $record,
];
}
/** @param array<string,mixed> $target */
private function redirectToPage(Request $request, string $token, array $target): RedirectResponse
{
$pageUrl = $this->shareLinks->signedRoute(
'signed.supplier-summary-confirmations.show',
$token,
$target['companyId'],
$this->expiresAt($request),
);
return redirect()->to($pageUrl);
}
private function expiresAt(Request $request): CarbonImmutable
{
$expires = (int) $request->query('expires', 0);
return $expires > 0
? CarbonImmutable::createFromTimestamp($expires)
: now()->addDays(SupplierSummaryShareLink::TTL_DAYS);
}
private function displayMonth(string $month): string
{
[$year, $monthNumber] = explode('-', $month, 2);
return (int) $year . '年' . (int) $monthNumber . '月';
}
}