供应商对账:内部可搜索厂家并隔离厂家名称
This commit is contained in:
parent
4511f6c71a
commit
c7bb212fb9
@ -170,8 +170,10 @@ class SupplierReconciliationPageData
|
||||
$supplierNames = array_keys($suppliers);
|
||||
sort($supplierNames);
|
||||
|
||||
$selected = trim((string) request()->query('supplier', ''));
|
||||
if ($selected === '' || ! in_array($selected, $supplierNames, true)) {
|
||||
$supplierQuery = trim((string) request()->query('supplier', ''));
|
||||
$selected = in_array($supplierQuery, $supplierNames, true) ? $supplierQuery : '';
|
||||
$supplierNotFound = $supplierQuery !== '' && $selected === '';
|
||||
if ($supplierQuery === '') {
|
||||
$selected = $supplierNames[0] ?? '';
|
||||
}
|
||||
|
||||
@ -184,6 +186,8 @@ class SupplierReconciliationPageData
|
||||
return [
|
||||
'view' => 'business.pages.supplier-reconciliation.supplier-data',
|
||||
'supplierNames' => $supplierNames,
|
||||
'supplierQuery' => $supplierQuery,
|
||||
'supplierNotFound' => $supplierNotFound,
|
||||
'selectedSupplier' => $selected,
|
||||
'uploads' => $selected !== '' ? $this->statements->uploads($selected, $companyId) : [],
|
||||
'statementRows' => array_slice($statementRows, ($page - 1) * self::PER_PAGE, self::PER_PAGE),
|
||||
|
||||
@ -63,16 +63,29 @@
|
||||
|
||||
<div class="sr-card">
|
||||
<h2>厂家对账单 · 上传与实时数据</h2>
|
||||
<form method="GET" class="sr-toolbar" aria-label="选择厂家">
|
||||
<label class="sr-field"><span>厂家</span>
|
||||
<select name="supplier" onchange="this.form.submit()">
|
||||
<form method="GET" class="sr-toolbar" aria-label="查询厂家">
|
||||
<label class="sr-field"><span>厂家名称</span>
|
||||
<input type="search"
|
||||
name="supplier"
|
||||
value="{{ $supplierQuery !== '' ? $supplierQuery : $selectedSupplier }}"
|
||||
list="supplier-name-options"
|
||||
placeholder="输入厂家名称搜索"
|
||||
autocomplete="off"
|
||||
required>
|
||||
<datalist id="supplier-name-options">
|
||||
@foreach ($supplierNames as $supplier)
|
||||
<option value="{{ $supplier }}" @selected($selectedSupplier === $supplier)>{{ $supplier }}</option>
|
||||
<option value="{{ $supplier }}"></option>
|
||||
@endforeach
|
||||
</select>
|
||||
</datalist>
|
||||
</label>
|
||||
<button type="submit" class="sr-button is-primary">查询厂家</button>
|
||||
<a href="{{ $statementTemplateUrl }}" class="sr-button">下载对账单模板</a>
|
||||
</form>
|
||||
@if ($supplierNotFound)
|
||||
<div class="biz-alert biz-alert-error" role="alert">
|
||||
未找到名为「{{ $supplierQuery }}」的厂家,请输入完整名称并从搜索建议中选择。
|
||||
</div>
|
||||
@endif
|
||||
<p class="sr-hint">
|
||||
厂家只能按模板上传(表头列名与顺序必须与模板完全一致):快递名称、快递单号、单据编号(采购单号)可以留空;
|
||||
单价或金额留空时按数量自动补齐(都留空按 0,未定价行可直接导出上传);其余列必填;
|
||||
|
||||
@ -155,10 +155,48 @@ class SupplierReconciliationTest extends FeatureTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function test_supplier_page_uses_a_searchable_exact_supplier_picker(): void
|
||||
{
|
||||
$this->seedStatement('晨丰', [
|
||||
$this->statementRow('ZSJ-1', '128.00', '2', '256.00'),
|
||||
]);
|
||||
$this->seedStatement('鸣飞家具', [
|
||||
array_merge($this->statementRow('SJ-1', '96.00', '1', '96.00'), ['supplier' => '鸣飞家具']),
|
||||
]);
|
||||
|
||||
$pageUrl = route('business.pages.show', [
|
||||
'company_id' => $this->company->id,
|
||||
'section' => 'supplier-reconciliation',
|
||||
'page' => 'supplier-data',
|
||||
]);
|
||||
|
||||
$this->loginAs()->get($pageUrl)
|
||||
->assertOk()
|
||||
->assertSee('name="supplier"', false)
|
||||
->assertSee('list="supplier-name-options"', false)
|
||||
->assertSeeText('查询厂家')
|
||||
->assertSee('value="晨丰"', false)
|
||||
->assertSee('value="鸣飞家具"', false);
|
||||
|
||||
$this->loginAs()->get($pageUrl . '?supplier=' . urlencode('鸣飞家具'))
|
||||
->assertOk()
|
||||
->assertSeeText('鸣飞家具 · 上传记录')
|
||||
->assertDontSeeText('晨丰 · 上传记录');
|
||||
|
||||
$this->loginAs()->get($pageUrl . '?supplier=' . urlencode('不存在的厂家'))
|
||||
->assertOk()
|
||||
->assertSeeText('未找到名为「不存在的厂家」的厂家')
|
||||
->assertDontSeeText('晨丰 · 上传记录')
|
||||
->assertDontSeeText('鸣飞家具 · 上传记录');
|
||||
}
|
||||
|
||||
public function test_vendor_portal_shows_only_all_returns_for_the_logged_in_supplier(): void
|
||||
{
|
||||
$store = app(SupplierPayableOverrideStore::class);
|
||||
$companyId = (int) $this->company->id;
|
||||
$this->seedStatement('鸣飞家具', [
|
||||
array_merge($this->statementRow('OTHER-SUPPLIER', '100.00', '1', '100.00'), ['supplier' => '鸣飞家具']),
|
||||
]);
|
||||
for ($i = 1; $i <= 20; $i++) {
|
||||
$store->save('final:supplier:return-reconciliation', sprintf('portal:%02d', $i), [
|
||||
'summary_month' => '2026-09',
|
||||
@ -198,6 +236,8 @@ class SupplierReconciliationTest extends FeatureTestCase
|
||||
->assertSeeText('PORTAL-01')
|
||||
->assertDontSeeText('PORTAL-20')
|
||||
->assertDontSeeText('OTHER-SUPPLIER-RETURN')
|
||||
->assertDontSeeText('鸣飞家具')
|
||||
->assertDontSee('supplier-name-options', false)
|
||||
->assertDontSeeText('预估单价');
|
||||
|
||||
$this->loginAs($vendor)->get($portalUrl . '?return_page=2')
|
||||
@ -283,6 +323,28 @@ class SupplierReconciliationTest extends FeatureTestCase
|
||||
$this->assertCount(0, app(SupplierStatementStore::class)->rows('鸣飞家具', (int) $this->company->id));
|
||||
}
|
||||
|
||||
public function test_vendor_portal_rejects_a_statement_for_another_supplier(): void
|
||||
{
|
||||
$this->withExceptionHandling();
|
||||
$vendor = $this->createVendorPortalUser('晨丰');
|
||||
$file = UploadedFile::fake()->createWithContent(
|
||||
'statement.csv',
|
||||
"\xEF\xBB\xBF" . self::HEADER . "\n"
|
||||
. ",,PORTAL-WRONG-SUPPLIER,2026-09-30,鸣飞家具,ZSJ-1,规格甲,2,128.00,256.00\n",
|
||||
);
|
||||
|
||||
$this->loginAs($vendor)
|
||||
->post(route('portal.supplier-reconciliation.statement.upload', ['company_id' => $this->company->id]), [
|
||||
'import' => $file,
|
||||
])
|
||||
->assertSessionHasErrors([
|
||||
'import' => '第 2 行:供应商必须填写「晨丰」,不能提交其他厂家的数据。',
|
||||
]);
|
||||
|
||||
$this->assertCount(0, app(SupplierStatementStore::class)->rows('晨丰', (int) $this->company->id));
|
||||
$this->assertCount(0, app(SupplierStatementStore::class)->rows('鸣飞家具', (int) $this->company->id));
|
||||
}
|
||||
|
||||
public function test_return_bookkeeping_note_is_identical_on_finance_and_supplier_views(): void
|
||||
{
|
||||
$companyId = (int) $this->company->id;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user