法人名称按账户数量排序 #967
@ -8,6 +8,7 @@ use App\Utilities\FinanceLedgerAccountType;
|
||||
use App\Utilities\FinanceLedgerAccess;
|
||||
use App\Utilities\FinanceLedgerIndependentAccounts;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Carbon;
|
||||
@ -609,6 +610,9 @@ class FinanceLedger extends Controller
|
||||
->reorder()
|
||||
->select('accounts.company_name')
|
||||
->pluck('accounts.company_name');
|
||||
$legalRepresentativeCounts = $legalRepresentativeCountSource->countBy(
|
||||
static fn ($companyName): string => trim((string) ($legalRepresentatives[trim((string) $companyName)] ?? '')),
|
||||
);
|
||||
$summaryQuery = clone $query;
|
||||
$summary = [
|
||||
'count' => (clone $query)->count(),
|
||||
@ -624,19 +628,8 @@ class FinanceLedger extends Controller
|
||||
$sortField = in_array($sortField, $headerFilterColumns, true) ? $sortField : '';
|
||||
$sortDirection = strtolower((string) $request->query('keep_direction', 'asc'));
|
||||
$sortDirection = $sortDirection === 'desc' ? 'desc' : 'asc';
|
||||
if ($sortField !== '') {
|
||||
if ($sortField === 'legal_representative') {
|
||||
if ($connection->getSchemaBuilder()->hasTable('ops_fys_company_info')) {
|
||||
$legalRepresentativeOrder = $connection->table('ops_fys_company_info')
|
||||
->select('legalRepresentative')
|
||||
->whereColumn('businessLicenseName', 'accounts.company_name')
|
||||
->orderByDesc('Id')
|
||||
->limit(1);
|
||||
$query->orderBy($legalRepresentativeOrder, $sortDirection);
|
||||
} else {
|
||||
$query->orderBy('accounts.company_name', $sortDirection);
|
||||
}
|
||||
} elseif ($sortField === 'account_type') {
|
||||
if ($sortField !== '' && $sortField !== 'legal_representative') {
|
||||
if ($sortField === 'account_type') {
|
||||
$query->orderByRaw(
|
||||
'CASE WHEN type_override_id IS NOT NULL THEN effective_account_type'
|
||||
. ' ELSE sort_account_type END ' . $sortDirection,
|
||||
@ -674,27 +667,75 @@ class FinanceLedger extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$rows = $query
|
||||
$hydrateRows = static function ($rows) use ($legalRepresentatives, $legalRepresentativeCounts): void {
|
||||
$rows->transform(static function ($row) use ($legalRepresentatives, $legalRepresentativeCounts) {
|
||||
$row->account_status = FinanceLedgerAccountStatus::normalize($row->effective_account_status ?? null);
|
||||
if ($row->type_override_id !== null) {
|
||||
$row->account_type = (string) ($row->effective_account_type ?? '');
|
||||
}
|
||||
$row->todo_current_progress = $row->todo_current_progress ?: 'not_started';
|
||||
$row->legal_representative = $legalRepresentatives[trim((string) $row->company_name)] ?? null;
|
||||
$row->legal_representative_count = (int) ($legalRepresentativeCounts[
|
||||
trim((string) $row->legal_representative)
|
||||
] ?? 0);
|
||||
|
||||
return $row;
|
||||
});
|
||||
};
|
||||
|
||||
$orderedQuery = $query
|
||||
->orderBy('accounts.company_name')
|
||||
->orderBy('accounts.account_short')
|
||||
->paginate(50)
|
||||
->appends($filters)
|
||||
->appends(array_filter([
|
||||
->orderBy('accounts.account_short');
|
||||
if ($sortField === 'legal_representative') {
|
||||
$allRows = $orderedQuery->get();
|
||||
$hydrateRows($allRows);
|
||||
$allRows = $allRows->sort(static function ($left, $right) use ($sortDirection): int {
|
||||
$countOrder = (int) $left->legal_representative_count <=> (int) $right->legal_representative_count;
|
||||
if ($sortDirection === 'desc') {
|
||||
$countOrder *= -1;
|
||||
}
|
||||
if ($countOrder !== 0) {
|
||||
return $countOrder;
|
||||
}
|
||||
|
||||
$nameOrder = strnatcasecmp(
|
||||
trim((string) $left->legal_representative),
|
||||
trim((string) $right->legal_representative),
|
||||
);
|
||||
if ($nameOrder !== 0) {
|
||||
return $nameOrder;
|
||||
}
|
||||
|
||||
$companyOrder = strnatcasecmp((string) $left->company_name, (string) $right->company_name);
|
||||
|
||||
return $companyOrder !== 0
|
||||
? $companyOrder
|
||||
: strnatcasecmp((string) $left->account_short, (string) $right->account_short);
|
||||
})->values();
|
||||
$lastPage = max(1, (int) ceil($allRows->count() / 50));
|
||||
$page = min($lastPage, max(1, (int) $request->query('page', 1)));
|
||||
$rows = new LengthAwarePaginator(
|
||||
$allRows->forPage($page, 50)->values(),
|
||||
$allRows->count(),
|
||||
50,
|
||||
$page,
|
||||
['path' => $request->url(), 'query' => $request->query()],
|
||||
);
|
||||
$rows->appends($filters)->appends([
|
||||
'keep_sort' => $sortField,
|
||||
'keep_direction' => $sortField !== '' ? $sortDirection : '',
|
||||
]))
|
||||
->withQueryString();
|
||||
|
||||
$rows->getCollection()->transform(static function ($row) use ($legalRepresentatives) {
|
||||
$row->account_status = FinanceLedgerAccountStatus::normalize($row->effective_account_status ?? null);
|
||||
if ($row->type_override_id !== null) {
|
||||
$row->account_type = (string) ($row->effective_account_type ?? '');
|
||||
}
|
||||
$row->todo_current_progress = $row->todo_current_progress ?: 'not_started';
|
||||
$row->legal_representative = $legalRepresentatives[trim((string) $row->company_name)] ?? null;
|
||||
|
||||
return $row;
|
||||
});
|
||||
])->withQueryString();
|
||||
} else {
|
||||
$rows = $orderedQuery
|
||||
->paginate(50)
|
||||
->appends($filters)
|
||||
->appends(array_filter([
|
||||
'keep_sort' => $sortField,
|
||||
'keep_direction' => $sortField !== '' ? $sortDirection : '',
|
||||
]))
|
||||
->withQueryString();
|
||||
$hydrateRows($rows->getCollection());
|
||||
}
|
||||
|
||||
$ownerOptions = self::UNRETAINED_OWNER_OPTIONS;
|
||||
$headerOptionValues = static function (iterable $values, bool $includeEmpty = false): array {
|
||||
@ -714,9 +755,6 @@ class FinanceLedger extends Controller
|
||||
};
|
||||
$hasEmpty = static fn (string $column): bool => $headerOptionRows
|
||||
->contains(static fn ($row): bool => trim((string) ($row->{$column} ?? '')) === '');
|
||||
$legalRepresentativeCounts = $legalRepresentativeCountSource->countBy(
|
||||
static fn ($companyName): string => trim((string) ($legalRepresentatives[trim((string) $companyName)] ?? '')),
|
||||
);
|
||||
$legalRepresentativeOptions = [];
|
||||
if (($legalRepresentativeCounts[''] ?? 0) > 0) {
|
||||
$legalRepresentativeOptions[] = '未填写(' . $legalRepresentativeCounts[''] . ')';
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
$keepHeaderColumns = [
|
||||
['column' => 'company_name', 'label' => '公司名称', 'filterType' => 'searchable-enum'],
|
||||
['column' => 'account_short', 'label' => '账户简称', 'filterType' => 'searchable-enum'],
|
||||
['column' => 'legal_representative', 'label' => '法人名称', 'filterType' => 'searchable-enum'],
|
||||
['column' => 'legal_representative', 'label' => '法人名称 / 数量', 'filterType' => 'searchable-enum'],
|
||||
['column' => 'account_type', 'label' => '账户类型', 'filterType' => 'searchable-enum'],
|
||||
['column' => 'account_status', 'label' => '账户状态', 'filterType' => 'searchable-enum'],
|
||||
['column' => 'account_no', 'label' => '账号', 'filterType' => 'searchable-enum'],
|
||||
@ -333,7 +333,7 @@
|
||||
{{ $row->company_name ?: '未填写' }}
|
||||
</td>
|
||||
<td>{{ $row->account_short ?: '未填写' }}</td>
|
||||
<td>{{ $row->legal_representative ?: '未填写' }}</td>
|
||||
<td data-keep-legal-representative="{{ $row->legal_representative }}" data-keep-legal-representative-count="{{ $row->legal_representative_count }}">{{ $row->legal_representative ?: '未填写' }}({{ $row->legal_representative_count }})</td>
|
||||
<td>{{ $row->account_type ?: '未填写' }}</td>
|
||||
<td><span class="keep-task-status is-{{ $row->account_status }}">{{ $accountStatusOptions[$row->account_status] ?? '正常' }}</span></td>
|
||||
<td>{{ $row->account_no ?: '未填写' }}</td>
|
||||
|
||||
@ -391,6 +391,53 @@ class FinanceLedgerAccountKeepTodoTest extends FeatureTestCase
|
||||
->assertDontSee('data-keep-account="法人计数甲二"', false);
|
||||
}
|
||||
|
||||
public function test_legal_representative_sort_uses_account_group_counts(): void
|
||||
{
|
||||
$connection = DB::connection('business_mirror');
|
||||
$connection->table('fin_accounts')->insert([
|
||||
['company_name' => '法人排序公司甲', 'account_short' => '法人排序甲一', 'account_should_keep' => '否'],
|
||||
['company_name' => '法人排序公司乙', 'account_short' => '法人排序甲二', 'account_should_keep' => '否'],
|
||||
['company_name' => '法人排序公司丙', 'account_short' => '法人排序甲三', 'account_should_keep' => '否'],
|
||||
['company_name' => '法人排序公司丁', 'account_short' => '法人排序乙一', 'account_should_keep' => '否'],
|
||||
['company_name' => '法人排序公司戊', 'account_short' => '法人排序丙一', 'account_should_keep' => '否'],
|
||||
]);
|
||||
$connection->table('ops_fys_company_info')->insert([
|
||||
['Id' => 41, 'businessLicenseName' => '法人排序公司甲', 'legalRepresentative' => '赵法人'],
|
||||
['Id' => 42, 'businessLicenseName' => '法人排序公司乙', 'legalRepresentative' => '赵法人'],
|
||||
['Id' => 43, 'businessLicenseName' => '法人排序公司丙', 'legalRepresentative' => '赵法人'],
|
||||
['Id' => 44, 'businessLicenseName' => '法人排序公司丁', 'legalRepresentative' => '李法人'],
|
||||
['Id' => 45, 'businessLicenseName' => '法人排序公司戊', 'legalRepresentative' => '王法人'],
|
||||
]);
|
||||
|
||||
$rows = function (string $direction): array {
|
||||
$content = $this->loginAs()->get($this->keepTasksUrl([
|
||||
'keep_sort' => 'legal_representative',
|
||||
'keep_direction' => $direction,
|
||||
]))->assertOk()->getContent();
|
||||
preg_match_all('/<tr data-keep-account="([^"]+)">(.*?)<\/tr>/su', $content, $matches, PREG_SET_ORDER);
|
||||
|
||||
return array_map(static function (array $match): array {
|
||||
preg_match('/data-keep-legal-representative-count="(\d+)"/u', $match[2], $count);
|
||||
|
||||
return [(string) $match[1], (int) ($count[1] ?? 0)];
|
||||
}, $matches);
|
||||
};
|
||||
|
||||
$descending = $rows('desc');
|
||||
$this->assertSame([3, 3, 3], array_column(array_slice($descending, 0, 3), 1));
|
||||
$this->assertSame([1, 1], array_column(array_slice($descending, 3, 2), 1));
|
||||
|
||||
$ascending = $rows('asc');
|
||||
$this->assertSame([1, 1], array_column(array_slice($ascending, 0, 2), 1));
|
||||
$this->assertSame([3, 3, 3], array_column(array_slice($ascending, 2, 3), 1));
|
||||
$this->loginAs()->get($this->keepTasksUrl([
|
||||
'keep_sort' => 'legal_representative',
|
||||
'keep_direction' => 'desc',
|
||||
]))->assertOk()
|
||||
->assertSee('data-keep-legal-representative-count="3"', false)
|
||||
->assertSee('赵法人(3)');
|
||||
}
|
||||
|
||||
public function test_keep_tasks_header_filters_apply_with_typeahead_options(): void
|
||||
{
|
||||
$connection = DB::connection('business_mirror');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user