CaiWuXiTong/app/Http/Controllers/Business/CourierQuoteSignatures.php
limeng a46d4dc678 修复签署文件日期未生成 (#225)
统一使用 signature_date 变量,并在推送 E 签宝前写入协议与报价确认单。
2026-09-21 10:02:37 +08:00

110 lines
5.0 KiB
PHP

<?php
namespace App\Http\Controllers\Business;
use App\Models\Business\CourierQuoteSignature;
use App\Models\Business\CourierQuoteVersion;
use App\Services\Esign\EsignClient;
use App\Support\CourierQuoteSignatureService;
use App\Utilities\SystemAccess;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\StreamedResponse;
class CourierQuoteSignatures extends Controller
{
public function __construct(private readonly CourierQuoteSignatureService $service)
{
}
public function prepare(Request $request, CourierQuoteVersion $quoteVersion): RedirectResponse
{
$this->ensureCanManage();
abort_unless($quoteVersion->status === 'approved', 422, '只有已审核报价版本可以生成签署文件。');
$data = $request->validate([
'signature_date' => ['required', 'date'],
]);
$signature = $this->service->prepareVersion($quoteVersion, user_id(), $data['signature_date']);
return redirect()->route('business.courier-quote-changes.show', $quoteVersion->source_change_id)
->with('success', "{$quoteVersion->version_code} 的签署 PDF 已生成,文件校验值已固定。")
->with('signature_id', $signature->id);
}
public function send(Request $request, CourierQuoteSignature $quoteSignature): RedirectResponse
{
$this->ensureCanManage();
abort_unless($quoteSignature->version?->status === 'approved', 422, '只有已审核报价版本可以发起签署。');
abort_unless(EsignClient::configured(), 422, 'E 签宝沙箱尚未配置 App ID 或 AppSecret。');
$data = $request->validate([
'organization_name' => ['required', 'string', 'min:2', 'max:255'],
'operator_name' => ['required', 'string', 'min:2', 'max:100'],
'operator_account' => ['required', 'string', 'max:255'],
'notice_type' => ['required', 'in:1,2'],
'signature_date' => ['required', 'date'],
'expires_at' => ['required', 'date', 'after:now', 'before_or_equal:' . now()->addDays(90)->toDateTimeString()],
]);
$this->validateAccountForNotice($data['operator_account'], $data['notice_type']);
$quoteSignature = $this->service->prepareVersion(
$quoteSignature->version,
user_id(),
$data['signature_date'],
);
$signature = $this->service->send($quoteSignature, $data, user_id());
$environment = $signature->environment === 'sandbox' ? '沙箱' : '正式环境';
return redirect()->route('business.courier-quote-changes.show', $signature->version->source_change_id)
->with('success', "{$signature->version->version_code} 已推送到 E 签宝{$environment},等待快递公司签署。");
}
public function synchronize(CourierQuoteSignature $quoteSignature): RedirectResponse
{
$this->ensureCanManage();
$signature = $this->service->synchronize($quoteSignature, user_id());
$message = $signature->status === CourierQuoteSignature::STATUS_ARCHIVED
? '签署完成,签署 PDF 和完成证书已私有归档。'
: "已同步 E 签宝状态:{$signature->statusLabel()}。";
return redirect()->route('business.courier-quote-changes.show', $signature->version->source_change_id)
->with('success', $message);
}
public function download(CourierQuoteSignature $quoteSignature, string $kind): StreamedResponse
{
[$path, $suffix] = match ($kind) {
'source' => [$quoteSignature->source_pdf_path, '报价签署原文'],
'signed' => [$quoteSignature->signed_pdf_path, '已签署报价'],
'certificate' => [$quoteSignature->certificate_path, '签署完成证书'],
default => abort(404),
};
abort_if(blank($path) || ! \Storage::disk('uploads')->exists($path), 404, '归档文件不存在。');
$fileName = $quoteSignature->version->version_code . '-' . $suffix . '.pdf';
return \Storage::disk('uploads')->download($path, $fileName, ['Content-Type' => 'application/pdf']);
}
private function validateAccountForNotice(string $account, string $noticeType): void
{
$valid = $noticeType === '1'
? preg_match('/^1\d{10}$/', $account) === 1
: filter_var($account, FILTER_VALIDATE_EMAIL) !== false;
if (! $valid) {
$message = $noticeType === '1' ? '短信通知必须填写 11 位手机号。' : '邮件通知必须填写有效邮箱。';
throw ValidationException::withMessages(['operator_account' => $message]);
}
}
private function ensureCanManage(): void
{
abort_unless(
in_array(SystemAccess::roleName(user()), [SystemAccess::SUPER_ADMIN, SystemAccess::ADMIN], true),
403,
'当前账号没有报价签署管理权限。',
);
}
}