Merge remote-tracking branch 'origin/main' into feature/limeng-third-party-warehouse-data
This commit is contained in:
commit
7ca35fc796
@ -1732,6 +1732,29 @@ class Pages extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
if ($platform === 'jd') {
|
||||
fputcsv($csv, [
|
||||
'平台', '店铺', '账户', '日期', '收支类型', '交易类型',
|
||||
'金额(元)', '余额(元)', '备注',
|
||||
]);
|
||||
foreach ($data['jd'] ?? [] as $row) {
|
||||
fputcsv($csv, [
|
||||
'京东京准通',
|
||||
$row['shop_name'] ?? '',
|
||||
$row['account'] ?? '',
|
||||
$row['show_date'] ?? $row['settle_datetime'] ?? '',
|
||||
$row['in_out_type_name'] ?? '',
|
||||
$row['trade_type_name'] ?? '',
|
||||
$row['amount'] ?? '',
|
||||
$row['balance_amount'] ?? '',
|
||||
$row['remark'] ?? '',
|
||||
]);
|
||||
}
|
||||
fclose($csv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fputcsv($csv, ['平台', '店铺/账户', '日期', '类型', '金额(元)', '余额(元)', '备注']);
|
||||
$emit = static function (string $platform, array $rows, array $map) use ($csv): void {
|
||||
foreach ($rows as $row) {
|
||||
@ -1746,9 +1769,7 @@ class Pages extends Controller
|
||||
]);
|
||||
}
|
||||
};
|
||||
if ($platform === 'jd') {
|
||||
$emit('京东京准通', $data['jd'] ?? [], ['name' => fn ($row) => $row['shop_name'] . ' / ' . $row['account'], 'date' => fn ($row) => $row['show_date'] ?? $row['settle_datetime'], 'type' => fn ($row) => $row['trade_type_name'] ?? $row['in_out_type_name'], 'amount' => fn ($row) => $row['amount'] ?? '', 'balance' => fn ($row) => $row['balance_amount'] ?? '', 'remark' => fn ($row) => $row['remark'] ?? '']);
|
||||
} elseif ($platform === 'douyin') {
|
||||
if ($platform === 'douyin') {
|
||||
$emit('抖音千川', $data['dy'] ?? [], ['name' => fn ($row) => $row['shopName'] . ' / ' . $row['account'] . ' / ' . $row['qianchuanAavid'], 'date' => fn ($row) => $row['statDate'] ?? '', 'type' => fn () => '花费', 'amount' => fn ($row) => $row['cost'] ?? '', 'balance' => fn ($row) => $row['balance'] ?? '', 'remark' => fn ($row) => $row['remark'] ?? '']);
|
||||
} elseif ($platform === 'dewu') {
|
||||
$emit('得物推广', $data['dw'] ?? [], ['name' => fn ($row) => $row['shop_name'] . ' / ' . $row['account'], 'date' => fn ($row) => $row['trade_date'] ?? $row['date_time'], 'type' => fn ($row) => $row['flow_type'] ?? '', 'amount' => fn ($row) => $row['trade_amount_yuan'] ?? '', 'balance' => fn ($row) => $row['balance_yuan'] ?? '', 'remark' => fn ($row) => $row['remark'] ?? '']);
|
||||
|
||||
@ -20,7 +20,34 @@ class ShowInAdmin
|
||||
*/
|
||||
public function handle(Event $event): void
|
||||
{
|
||||
$this->renderSections($event->menu, self::groupPayables(SidebarPermissions::navigationFor(user())));
|
||||
$this->renderSections($event->menu, self::groupBasicData(self::groupPayables(SidebarPermissions::navigationFor(user()))));
|
||||
}
|
||||
|
||||
public static function groupBasicData(array $navigation): array
|
||||
{
|
||||
$keys = ['order-data', 'refunds'];
|
||||
$children = array_values(array_filter($navigation, static fn (array $section): bool => in_array($section['slug'], $keys, true)));
|
||||
if ($children === []) {
|
||||
return $navigation;
|
||||
}
|
||||
|
||||
$group = ['slug' => 'basic-data', 'title' => '基础数据', 'icon' => 'folder', 'sections' => $children];
|
||||
$hasDirectory = in_array('basic-data', array_column($navigation, 'slug'), true);
|
||||
$result = [];
|
||||
foreach ($navigation as $section) {
|
||||
if ($section['slug'] === 'basic-data') {
|
||||
$result[] = array_replace($section, ['sections' => $children]);
|
||||
} elseif (in_array($section['slug'], $keys, true)) {
|
||||
if (! $hasDirectory) {
|
||||
$result[] = $group;
|
||||
$hasDirectory = true;
|
||||
}
|
||||
} else {
|
||||
$result[] = $section;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function groupPayables(array $navigation): array
|
||||
|
||||
@ -289,9 +289,15 @@ $navigation = [
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'slug' => 'basic-data',
|
||||
'title' => '基础数据',
|
||||
'icon' => 'folder',
|
||||
'pages' => [],
|
||||
],
|
||||
[
|
||||
'slug' => 'product-inventory',
|
||||
'title' => '商品及库存管理',
|
||||
'title' => '商品价格管理',
|
||||
'icon' => 'inventory_2',
|
||||
'pages' => [
|
||||
['slug' => 'normal-products', 'title' => '普通商品资料'],
|
||||
@ -654,6 +660,7 @@ $navigation = [
|
||||
|
||||
// Keep the requested finance-data sections together while preserving every other section's order.
|
||||
$requestedSectionOrder = [
|
||||
'basic-data',
|
||||
'invoice-management',
|
||||
'fund-management',
|
||||
'order-data',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -11,7 +11,7 @@
|
||||
$titles = ['jd' => '京东京准通', 'douyin' => '抖音千川', 'dewu' => '得物推广账户', 'vip' => '唯品会推广流水'];
|
||||
$filterLabel = $platform === 'vip' ? $titles[$platform] . '筛选' : $titles[$platform] . '推广账户筛选';
|
||||
$columns = match ($platform) {
|
||||
'jd' => [['shop_name', '店铺'], ['account', '账户'], ['show_date', '日期'], ['trade_type_name', '交易类型'], ['amount', '金额'], ['balance_amount', '余额'], ['remark', '备注']],
|
||||
'jd' => [['shop_name', '店铺'], ['account', '账户'], ['show_date', '日期'], ['in_out_type_name', '收支类型'], ['trade_type_name', '交易类型'], ['amount', '金额'], ['balance_amount', '余额'], ['remark', '备注']],
|
||||
'douyin' => [['shopName', '店铺'], ['account', '账户'], ['qianchuanAavid', '广告账户'], ['statDate', '日期'], ['cost', '花费'], ['income', '收入'], ['transferIn', '转入'], ['transferOut', '转出'], ['balance', '余额'], ['status', '状态'], ['remark', '备注']],
|
||||
'dewu' => [['shop_name', '店铺'], ['account', '账户'], ['trade_date', '日期'], ['amount_type', '金额类型'], ['flow_type', '收支类型'], ['trade_amount_yuan', '金额'], ['balance_yuan', '余额'], ['remark', '备注']],
|
||||
default => [
|
||||
|
||||
@ -32,6 +32,8 @@ class MarketingPlatformPromotionBillsTest extends FeatureTestCase
|
||||
->assertSeeText('京东京准通')
|
||||
->assertSee('aria-label="京东京准通推广账户筛选"', false)
|
||||
->assertSeeText('测试店铺')
|
||||
->assertSeeText('收支类型')
|
||||
->assertSeeText('出账')
|
||||
->assertSeeText('导出 CSV')
|
||||
->assertSee('class="my-6 business-page--marketing-account-bills"', false)
|
||||
->assertSee(route('business.pages.show', [
|
||||
@ -72,7 +74,12 @@ class MarketingPlatformPromotionBillsTest extends FeatureTestCase
|
||||
"filename*=utf-8''" . rawurlencode($filename),
|
||||
(string) $response->headers->get('Content-Disposition'),
|
||||
);
|
||||
$this->assertStringContainsString('测试店铺', $response->streamedContent());
|
||||
$csv = $response->streamedContent();
|
||||
$this->assertStringContainsString('测试店铺', $csv);
|
||||
$this->assertStringContainsString('收支类型', $csv);
|
||||
$this->assertStringContainsString('交易类型', $csv);
|
||||
$this->assertStringContainsString('出账', $csv);
|
||||
$this->assertStringContainsString('推广费', $csv);
|
||||
}
|
||||
|
||||
public function test_vip_tab_uses_marketing_daily_data(): void
|
||||
@ -195,7 +202,8 @@ class MarketingPlatformPromotionBillsTest extends FeatureTestCase
|
||||
'shop_name' => '测试店铺',
|
||||
'account' => 'account-01',
|
||||
'show_date' => '2026-08-01',
|
||||
'trade_type_name' => '充值',
|
||||
'in_out_type_name' => '出账',
|
||||
'trade_type_name' => '推广费',
|
||||
'amount' => 100,
|
||||
'balance_amount' => 100,
|
||||
'remark' => '测试记录',
|
||||
|
||||
@ -217,14 +217,17 @@ class PagesTest extends FeatureTestCase
|
||||
]);
|
||||
}
|
||||
|
||||
public function testDouyinAccountBillsExportUsesSelectedColumnOrder(): void
|
||||
public function testDouyinAccountBillsExportUsesDateFiltersAndSelectedColumnOrder(): void
|
||||
{
|
||||
$this->user->attachPermission(
|
||||
Permission::where('name', 'read-admin-panel')->firstOrFail()
|
||||
);
|
||||
|
||||
$repository = Mockery::mock(StoreReceivingDouyinBillMirrorRepository::class);
|
||||
$repository->shouldReceive('exportRows')->once()->with([], 'occurred_at', 'desc')->andReturn([[
|
||||
$repository->shouldReceive('exportRows')->once()->with([
|
||||
'start' => '2026-09-09',
|
||||
'end' => '2026-09-09',
|
||||
], 'occurred_at', 'desc')->andReturn([[
|
||||
'record_code' => '9001',
|
||||
'payload' => [
|
||||
'move_scene' => '头条放心购',
|
||||
@ -235,6 +238,8 @@ class PagesTest extends FeatureTestCase
|
||||
|
||||
$response = $this->loginAs()->get(route('ecommerce-finance.account-bills.export', [
|
||||
'bill_type' => 'douyin',
|
||||
'start' => '2026-09-09',
|
||||
'end' => '2026-09-09',
|
||||
'columns' => 'payload.move_scene,record_code,payload.settle_account',
|
||||
]));
|
||||
|
||||
|
||||
@ -9,6 +9,40 @@ use Tests\Feature\FeatureTestCase;
|
||||
|
||||
class NavigationTest extends FeatureTestCase
|
||||
{
|
||||
public function testGroupedNavigationRendersExistingPageLinks(): void
|
||||
{
|
||||
$this->loginAs()
|
||||
->get(route('business.pages.show', ['section' => 'basic-data']))
|
||||
->assertOk()
|
||||
->assertSeeText('基础数据')
|
||||
->assertSeeText('商品价格管理')
|
||||
->assertSee('/workspace/order-data/raw-data', false)
|
||||
->assertSee('/workspace/refunds/non-jingxi-refund-data', false)
|
||||
->assertSee('/workspace/product-inventory/normal-products', false);
|
||||
}
|
||||
|
||||
public function testGroupedNavigationKeepsRestrictedPagePermissions(): void
|
||||
{
|
||||
$this->user->roles()->sync([Role::where('name', 'manager')->firstOrFail()->id]);
|
||||
$subject = 'user_' . $this->user->id;
|
||||
setting()->set('system.sidebar_permissions', [
|
||||
'configured' => [$subject],
|
||||
'subjects' => [$subject => ['basic-data', 'refunds/non-jingxi-refund-data']],
|
||||
]);
|
||||
setting()->save();
|
||||
|
||||
$this->loginAs()
|
||||
->get(route('business.pages.show', ['section' => 'basic-data']))
|
||||
->assertOk()
|
||||
->assertSee('/workspace/refunds/non-jingxi-refund-data', false)
|
||||
->assertDontSee('/workspace/order-data/raw-data', false)
|
||||
->assertDontSee('/workspace/product-inventory/normal-products', false);
|
||||
|
||||
$this->withExceptionHandling()
|
||||
->get(route('business.pages.show', ['section' => 'order-data']))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testAdminCanUpdateSidebarLabels()
|
||||
{
|
||||
$this->user->roles()->sync([
|
||||
@ -87,7 +121,7 @@ class NavigationTest extends FeatureTestCase
|
||||
'退款数据',
|
||||
'账单流水数据',
|
||||
'账单余额数据',
|
||||
'商品及库存管理',
|
||||
'商品价格管理',
|
||||
],
|
||||
array_column(array_slice($navigation, $invoiceIndex, 7), 'title')
|
||||
);
|
||||
|
||||
@ -21,7 +21,8 @@ class PlatformPromotionAccountRepositoryTest extends TestCase
|
||||
$factory->shouldReceive('forSource')->once()->with('js_data_middle_platform')->andReturn($query);
|
||||
$query->shouldReceive('select')->once()->ordered()->with(
|
||||
Mockery::on(static fn (string $sql): bool => str_contains($sql, 'SELECT TOP 5000')
|
||||
&& str_contains($sql, 'jd_jzt_finance_records')),
|
||||
&& str_contains($sql, 'jd_jzt_finance_records')
|
||||
&& str_contains($sql, 'in_out_type_name')),
|
||||
['2026-08'],
|
||||
)->andReturn([['shop_name' => '测试店铺', 'amount' => 100]]);
|
||||
$query->shouldReceive('select')->once()->ordered()->with(
|
||||
|
||||
46
tests/Unit/View/BasicDataNavigationTest.php
Normal file
46
tests/Unit/View/BasicDataNavigationTest.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\View;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use App\Listeners\Menu\ShowInAdmin;
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/app/Listeners/Menu/ShowInAdmin.php';
|
||||
|
||||
class BasicDataNavigationTest extends TestCase
|
||||
{
|
||||
public function test_group_moves_only_order_data_and_refunds_without_changing_pages(): void
|
||||
{
|
||||
$navigation = require dirname(__DIR__, 3) . '/config/business_navigation.php';
|
||||
$grouped = ShowInAdmin::groupBasicData($navigation);
|
||||
$slugs = array_column($grouped, 'slug');
|
||||
$group = $grouped[array_search('basic-data', $slugs, true)];
|
||||
$this->assertSame(['order-data', 'refunds'], array_column($group['sections'], 'slug'));
|
||||
$this->assertNotContains('order-data', $slugs);
|
||||
$this->assertNotContains('refunds', $slugs);
|
||||
foreach ($group['sections'] as $section) {
|
||||
$this->assertSame($navigation[array_search($section['slug'], array_column($navigation, 'slug'), true)], $section);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_group_contains_only_authorized_sections_even_without_directory_permission(): void
|
||||
{
|
||||
$allowed = [['slug' => 'refunds', 'title' => '退款', 'pages' => [['slug' => 'non-jingxi-refund-data']]]];
|
||||
$grouped = ShowInAdmin::groupBasicData($allowed);
|
||||
$this->assertSame($allowed, $grouped[0]['sections']);
|
||||
$this->assertSame([], ShowInAdmin::groupBasicData([]));
|
||||
}
|
||||
|
||||
public function test_basic_data_is_an_empty_top_level_directory_before_invoice_management(): void
|
||||
{
|
||||
$navigation = require dirname(__DIR__, 3) . '/config/business_navigation.php';
|
||||
$slugs = array_column($navigation, 'slug');
|
||||
$index = array_search('basic-data', $slugs, true);
|
||||
|
||||
$this->assertNotFalse($index);
|
||||
$this->assertSame('基础数据', $navigation[$index]['title']);
|
||||
$this->assertSame([], $navigation[$index]['pages']);
|
||||
$this->assertSame('invoice-management', $slugs[$index + 1]);
|
||||
$this->assertCount(1, array_keys($slugs, 'basic-data', true));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user