feat: 合作合同乙方签约地支持编辑 (#343)
This commit is contained in:
parent
5c20defc79
commit
d1b14fc10d
@ -523,6 +523,7 @@ class CourierAgreementSignatures extends Controller
|
||||
'cooperation_party_a_phone' => ['required_if:document_type,cooperation-contract', 'string', 'max:64'],
|
||||
'cooperation_party_b_name' => ['required_if:document_type,cooperation-contract', 'string', 'max:255'],
|
||||
'cooperation_party_b_phone' => ['required_if:document_type,cooperation-contract', 'string', 'max:64'],
|
||||
'cooperation_party_b_signing_place' => ['nullable', 'string', 'max:100'],
|
||||
'cooperation_contract_number' => ['nullable', 'string', 'max:100'],
|
||||
'cooperation_party_b_legal_representative' => ['nullable', 'string', 'max:100'],
|
||||
'cooperation_start_date' => ['required_if:document_type,cooperation-contract', 'date'],
|
||||
@ -548,6 +549,7 @@ class CourierAgreementSignatures extends Controller
|
||||
unset($payload['esign_account'], $payload['idempotency_key'], $payload['operator_name'], $payload['credential_images']);
|
||||
$payload['authorization_items'] = array_values(array_map('strval', $data['authorization_items'] ?? []));
|
||||
if (($data['document_type'] ?? '') === 'cooperation-contract' && ($data['partner_type'] ?? 'courier') === 'courier') {
|
||||
$payload['cooperation_party_b_signing_place'] = trim((string) ($data['cooperation_party_b_signing_place'] ?? '')) ?: '常州市';
|
||||
$payload['cooperation_contract_number'] = trim((string) ($data['cooperation_contract_number'] ?? ''));
|
||||
$payload['cooperation_party_b_legal_representative'] = ($data['counterparty_signer_type'] ?? 'organization') === 'person'
|
||||
? null : trim((string) ($data['cooperation_party_b_legal_representative'] ?? ''));
|
||||
|
||||
@ -1866,6 +1866,11 @@
|
||||
<label for="agreement-cooperation-end-date">协议结束日期 <span class="agreement-required" aria-hidden="true">*</span></label>
|
||||
<input class="agreement-control" id="agreement-cooperation-end-date" name="cooperation_end_date" type="date" value="{{ now()->addYear()->toDateString() }}" required>
|
||||
</div>
|
||||
<div class="agreement-field" data-courier-contract-metadata>
|
||||
<label for="agreement-cooperation-party-b-signing-place">乙方签约地</label>
|
||||
<input class="agreement-control" id="agreement-cooperation-party-b-signing-place" name="cooperation_party_b_signing_place" type="text" maxlength="100" value="{{ old('cooperation_party_b_signing_place', '常州市') }}" placeholder="填写乙方实际签约地点">
|
||||
<p class="agreement-help">默认常州市,可按实际签约地点修改;留空时仍使用常州市。</p>
|
||||
</div>
|
||||
<div class="agreement-field" data-courier-contract-metadata>
|
||||
<label for="agreement-cooperation-contract-number">合同编号(选填)</label>
|
||||
<input class="agreement-control" id="agreement-cooperation-contract-number" name="cooperation_contract_number" type="text" maxlength="100" placeholder="填写正式合同编号,不填写则合同管理显示未填写">
|
||||
@ -3627,6 +3632,7 @@
|
||||
setPreviewValue('cooperationPartyAPhone', fieldValue('[name="cooperation_party_a_phone"]', '待填写'));
|
||||
setPreviewValue('cooperationPartyBName', fieldValue('[name="cooperation_party_b_name"]', courier === '快递公司' ? '待填写' : courier));
|
||||
setPreviewValue('cooperationPartyBPhone', fieldValue('[name="cooperation_party_b_phone"]', '待填写'));
|
||||
setPreviewValue('cooperationPartyBSigningPlace', fieldValue('[name="cooperation_party_b_signing_place"]', '常州市'));
|
||||
setPreviewValue('cooperationStartDate', formatDateField('[name="cooperation_start_date"]', '待填写'));
|
||||
setPreviewValue('cooperationEndDate', formatDateField('[name="cooperation_end_date"]', '待填写'));
|
||||
if (supplierContract) {
|
||||
|
||||
@ -144,7 +144,7 @@
|
||||
<p>代表人:</p>
|
||||
<div class="agreement-preview-handwriting-blank"></div>
|
||||
<p>日 期:<span data-preview-bind="signatureDate">待填写</span></p>
|
||||
<p>签约地:常州市</p>
|
||||
<p>签约地:<span class="agreement-preview-value" data-preview-bind="cooperationPartyBSigningPlace">常州市</span></p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
@ -166,7 +166,7 @@
|
||||
<p class="contract-signatures__line">代表人:</p>
|
||||
<div class="contract-signatures__handwriting"></div>
|
||||
<p class="contract-signatures__line">日 期:{!! $mixedText($signatureDate) !!}</p>
|
||||
<p class="contract-signatures__line">签约地:常州市</p>
|
||||
<p class="contract-signatures__line">签约地:{!! $mixedText(trim((string) ($payload['cooperation_party_b_signing_place'] ?? '')) ?: '常州市') !!}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -507,6 +507,18 @@ class AgreementSigningPageTest extends FeatureTestCase
|
||||
->assertSeeText('委托有效期:从');
|
||||
}
|
||||
|
||||
public function test_cooperation_contract_has_an_editable_party_b_signing_place_and_preview(): void
|
||||
{
|
||||
$this->loginAs()->get(route('business.pages.show', [
|
||||
'section' => 'courier-payables', 'page' => 'agreement-signing', 'agreement_view' => 'create',
|
||||
]))
|
||||
->assertOk()
|
||||
->assertSeeText('乙方签约地')
|
||||
->assertSee('name="cooperation_party_b_signing_place"', false)
|
||||
->assertSee('data-preview-bind="cooperationPartyBSigningPlace"', false)
|
||||
->assertSeeText('默认常州市,可按实际签约地点修改;留空时仍使用常州市。');
|
||||
}
|
||||
|
||||
public function testAgreementSigningPageRejectsUsersWithoutItsSidebarPermission(): void
|
||||
{
|
||||
$subject = 'user_' . $this->user->id;
|
||||
|
||||
@ -545,6 +545,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
|
||||
$payload = $this->cooperationContractPayload('cooperation-001');
|
||||
$payload['cooperation_contract_number'] = ' KD-2026-009 ';
|
||||
$payload['cooperation_party_b_legal_representative'] = ' 王法人 ';
|
||||
$payload['cooperation_party_b_signing_place'] = ' 南京市鼓楼区 ';
|
||||
|
||||
$this->loginAs()
|
||||
->post(route('business.courier-agreement-signatures.store'), $payload)
|
||||
@ -559,6 +560,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
|
||||
$this->assertSame('2026-12-31', $signature->payload['cooperation_end_date']);
|
||||
$this->assertSame('KD-2026-009', $signature->payload['cooperation_contract_number']);
|
||||
$this->assertSame('王法人', $signature->payload['cooperation_party_b_legal_representative']);
|
||||
$this->assertSame('南京市鼓楼区', $signature->payload['cooperation_party_b_signing_place']);
|
||||
|
||||
Http::assertSent(function (ClientRequest $request): bool {
|
||||
if ($request->url() !== 'https://smlopenapi.esign.test/v3/sign-flow/create-by-file') {
|
||||
@ -585,8 +587,9 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
|
||||
$payload = $this->cooperationContractPayload('contract-metadata-too-long');
|
||||
$payload['cooperation_contract_number'] = str_repeat('X', 101);
|
||||
$payload['cooperation_party_b_legal_representative'] = str_repeat('法', 101);
|
||||
$payload['cooperation_party_b_signing_place'] = str_repeat('地', 101);
|
||||
$this->loginAs()->post(route('business.courier-agreement-signatures.store'), $payload)
|
||||
->assertSessionHasErrors(['cooperation_contract_number', 'cooperation_party_b_legal_representative']);
|
||||
->assertSessionHasErrors(['cooperation_contract_number', 'cooperation_party_b_legal_representative', 'cooperation_party_b_signing_place']);
|
||||
$this->assertSame(0, CourierAgreementSignature::query()->count());
|
||||
Http::assertNothingSent();
|
||||
}
|
||||
@ -595,6 +598,7 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
|
||||
{
|
||||
$payload = $this->cooperationContractPayload('cooperation-font');
|
||||
$payload['signature_date'] = '2026-10-10';
|
||||
$payload['cooperation_party_b_signing_place'] = '南京市 <script>签约点</script>';
|
||||
$signature = new CourierAgreementSignature([
|
||||
'business_no' => 'AGR-FONT-REGRESSION',
|
||||
'template_code' => 'TPL-COOPERATION-CONTRACT-V1',
|
||||
@ -635,11 +639,39 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase
|
||||
$this->assertStringContainsString('95%', $text);
|
||||
$this->assertStringContainsString('5000元/次', $text);
|
||||
$xpath = new DOMXPath($document);
|
||||
$parties = $xpath->query('//table[@class="contract-signatures__table"]//td');
|
||||
$this->assertStringContainsString('签约地:常州市', $parties->item(0)->textContent);
|
||||
$this->assertStringContainsString('签约地:南京市 <script>签约点</script>', $parties->item(1)->textContent);
|
||||
$this->assertSame(0, $xpath->query('//body//script')->length);
|
||||
foreach ($xpath->query('//body//text()[not(ancestor::*[contains(concat(" ", normalize-space(@class), " "), " latin ")])]') as $node) {
|
||||
$this->assertDoesNotMatchRegularExpression('/[\x21-\x7E\x{2018}-\x{201F}]/u', $node->nodeValue);
|
||||
}
|
||||
}
|
||||
|
||||
/** @dataProvider missingOrBlankSigningPlaces */
|
||||
public function test_cooperation_contract_defaults_missing_or_blank_party_b_signing_place(?string $place): void
|
||||
{
|
||||
$this->fakeEsign();
|
||||
$payload = $this->cooperationContractPayload('signing-place-default');
|
||||
if ($place !== null) {
|
||||
$payload['cooperation_party_b_signing_place'] = $place;
|
||||
}
|
||||
$this->loginAs()->post(route('business.courier-agreement-signatures.store'), $payload)->assertRedirect();
|
||||
$signature = CourierAgreementSignature::query()->firstOrFail();
|
||||
$this->assertSame('常州市', $signature->payload['cooperation_party_b_signing_place']);
|
||||
|
||||
// Old saved payloads also retain the previous location when rendered.
|
||||
$html = view('business.partials.cooperation-contract', [
|
||||
'mode' => 'pdf', 'payload' => [], 'signatureDate' => '待填写', 'mixedText' => fn ($value) => e($value),
|
||||
])->render();
|
||||
$this->assertSame(2, substr_count($html, '签约地:常州市'));
|
||||
}
|
||||
|
||||
public static function missingOrBlankSigningPlaces(): array
|
||||
{
|
||||
return ['missing' => [null], 'empty' => [''], 'whitespace' => [' ']];
|
||||
}
|
||||
|
||||
public function test_cooperation_contract_uses_the_persons_real_name_instead_of_the_courier_name(): void
|
||||
{
|
||||
$this->fakeEsign();
|
||||
|
||||
@ -69,6 +69,7 @@ class CourierAgreementSignatureLayoutTest extends TestCase
|
||||
'contract_partner_name' => '示例合作公司', 'shared_courier_names' => ['示例快递'],
|
||||
'cooperation_party_a_name' => '示例甲方公司', 'cooperation_party_a_phone' => '00000000000',
|
||||
'cooperation_party_b_name' => '示例乙方公司', 'cooperation_party_b_phone' => '00000000000',
|
||||
'cooperation_party_b_signing_place' => '江苏省南京市鼓楼区',
|
||||
'cooperation_start_date' => '2026-10-11', 'cooperation_end_date' => '2027-10-10',
|
||||
'principal_name' => '示例委托方', 'principal_id_number' => 'EXAMPLE-ID',
|
||||
'trustee_name' => '示例受托方', 'trustee_id_number' => 'EXAMPLE-ID',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user