From 1ae5bf394b6cd36a3ca8176fda607b9ae2118edf Mon Sep 17 00:00:00 2001 From: WuYongJie <549727955@qq.com> Date: Mon, 7 Sep 2026 14:21:41 +0800 Subject: [PATCH] fix: query only the active promotion platform --- app/Http/Controllers/Business/Pages.php | 2 +- .../PlatformPromotionAccountRepository.php | 61 +++++++++++++------ .../View/PlatformPromotionAccountPageData.php | 2 +- .../MarketingPlatformPromotionBillsTest.php | 4 +- ...PlatformPromotionAccountRepositoryTest.php | 55 +++++++++++++++++ 5 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 tests/Unit/EcommerceFinance/PlatformPromotionAccountRepositoryTest.php diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index 2c3915fd..9dc7391a 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -1170,7 +1170,7 @@ class Pages extends Controller try { $repository = app(\Modules\EcommerceFinance\Repositories\PlatformPromotionAccountRepository::class); $filters['month'] = $month ?: ($repository->latestMonth() ?: now()->format('Y-m')); - $data = $repository->dashboard($filters, 5000); + $data = $repository->dashboard($filters, 5000, $platform); } catch (Throwable $exception) { report($exception); diff --git a/modules/EcommerceFinance/Repositories/PlatformPromotionAccountRepository.php b/modules/EcommerceFinance/Repositories/PlatformPromotionAccountRepository.php index 74fdc7c7..a54b0b28 100644 --- a/modules/EcommerceFinance/Repositories/PlatformPromotionAccountRepository.php +++ b/modules/EcommerceFinance/Repositories/PlatformPromotionAccountRepository.php @@ -2,6 +2,7 @@ namespace Modules\EcommerceFinance\Repositories; +use InvalidArgumentException; use Modules\EcommerceFinance\Services\UpstreamReadOnlyQuery; use Modules\EcommerceFinance\Services\UpstreamReadOnlyQueryFactory; @@ -14,34 +15,58 @@ class PlatformPromotionAccountRepository { } - public function dashboard(array $filters, int $limit = 200): array + public function dashboard(array $filters, int $limit = 200, ?string $platform = null): array { + if ($platform !== null && ! in_array($platform, ['jd', 'douyin', 'dewu', 'vip'], true)) { + throw new InvalidArgumentException('未知的推广账户平台。'); + } + $month = $filters['month']; $shop = $filters['shop_name'] ?? null; $account = $filters['account'] ?? null; $limit = min(max($limit, 1), 5000); $query = $this->queries->forSource(self::SOURCE); - $jd = $this->query($query, "SELECT TOP {$limit} data_month, shop_name, account, login_pin, in_out_type_name, trade_type_name, amount, balance_amount, settle_datetime, show_date, trade_no, remark FROM JSDataMiddlePlatform.dbo.jd_jzt_finance_records WHERE data_month = ?", [$month], $shop, $account, 'shop_name'); - $jdSummary = $this->query($query, "SELECT COALESCE(SUM(CASE WHEN in_out_type='IN' THEN amount ELSE 0 END),0) income, COALESCE(SUM(CASE WHEN in_out_type='OUT' THEN amount ELSE 0 END),0) expense, COUNT(*) record_count FROM JSDataMiddlePlatform.dbo.jd_jzt_finance_records WHERE data_month = ?", [$month], $shop, $account, 'shop_name', true)[0] ?? []; + $jd = []; + $jdSummary = []; + $douyin = []; + $douyinSummary = []; + $douyinStatus = []; + $dewu = []; + $dewuSummary = []; + $vipSales = []; + $vipTax = []; + $vipMarketing = []; + $vipSummary = []; - $douyin = $this->query($query, "SELECT TOP {$limit} shopName, account, qianchuanAavid, qianchuanAccountName, statDate, cost, income, transferOut, transferIn, balance, status, remark FROM JSDataMiddlePlatform.dbo.dy_qianchuan_finance_transactions WHERE dataMonth = ? AND rowType = N'daily' AND status = N'success'", [$month . '-01'], $shop, $account, 'shopName'); - $douyinSummary = $this->query($query, "SELECT COALESCE(SUM(cost),0) cost, COALESCE(SUM(income),0) income, COALESCE(SUM(transferOut),0) transfer_out, COALESCE(SUM(transferIn),0) transfer_in, COUNT(DISTINCT qianchuanAavid) account_count FROM JSDataMiddlePlatform.dbo.dy_qianchuan_finance_transactions WHERE dataMonth = ? AND rowType = N'daily' AND status = N'success'", [$month . '-01'], $shop, $account, 'shopName', true)[0] ?? []; - $douyinStatus = $this->query($query, "SELECT COUNT(*) status_count FROM JSDataMiddlePlatform.dbo.dy_qianchuan_finance_transactions WHERE dataMonth = ? AND rowType = N'status' AND status = N'no_permission'", [$month . '-01'], $shop, $account, 'shopName', true)[0] ?? []; + if ($platform === null || $platform === 'jd') { + $jd = $this->query($query, "SELECT TOP {$limit} data_month, shop_name, account, login_pin, in_out_type_name, trade_type_name, amount, balance_amount, settle_datetime, show_date, trade_no, remark FROM JSDataMiddlePlatform.dbo.jd_jzt_finance_records WHERE data_month = ?", [$month], $shop, $account, 'shop_name'); + $jdSummary = $this->query($query, "SELECT COALESCE(SUM(CASE WHEN in_out_type='IN' THEN amount ELSE 0 END),0) income, COALESCE(SUM(CASE WHEN in_out_type='OUT' THEN amount ELSE 0 END),0) expense, COUNT(*) record_count FROM JSDataMiddlePlatform.dbo.jd_jzt_finance_records WHERE data_month = ?", [$month], $shop, $account, 'shop_name', true)[0] ?? []; + } - $dewu = $this->query($query, "SELECT TOP {$limit} data_month, shop_name, account, amount_type, flow_type, trade_amount_yuan, balance_yuan, trade_date, date_time, remark FROM JSDataMiddlePlatform.dbo.dw_ad_finance_records WHERE data_month = ?", [$month], $shop, $account, 'shop_name'); - $dewuSummary = $this->query($query, 'SELECT COALESCE(SUM(total_income_amount),0) income, COALESCE(SUM(total_expense_amount),0) expense, COALESCE(SUM(net_amount),0) net, COALESCE(SUM(record_count),0) record_count FROM JSDataMiddlePlatform.dbo.dw_ad_finance_month_summaries WHERE data_month = ?', [$month], $shop, $account, 'shop_name', true)[0] ?? []; + if ($platform === null || $platform === 'douyin') { + $douyin = $this->query($query, "SELECT TOP {$limit} shopName, account, qianchuanAavid, qianchuanAccountName, statDate, cost, income, transferOut, transferIn, balance, status, remark FROM JSDataMiddlePlatform.dbo.dy_qianchuan_finance_transactions WHERE dataMonth = ? AND rowType = N'daily' AND status = N'success'", [$month . '-01'], $shop, $account, 'shopName'); + $douyinSummary = $this->query($query, "SELECT COALESCE(SUM(cost),0) cost, COALESCE(SUM(income),0) income, COALESCE(SUM(transferOut),0) transfer_out, COALESCE(SUM(transferIn),0) transfer_in, COUNT(DISTINCT qianchuanAavid) account_count FROM JSDataMiddlePlatform.dbo.dy_qianchuan_finance_transactions WHERE dataMonth = ? AND rowType = N'daily' AND status = N'success'", [$month . '-01'], $shop, $account, 'shopName', true)[0] ?? []; + $douyinStatus = $this->query($query, "SELECT COUNT(*) status_count FROM JSDataMiddlePlatform.dbo.dy_qianchuan_finance_transactions WHERE dataMonth = ? AND rowType = N'status' AND status = N'no_permission'", [$month . '-01'], $shop, $account, 'shopName', true)[0] ?? []; + } - $vipSales = $this->query($query, "SELECT TOP {$limit} shopName, dataMonth, monthName, previousYearSalesAmount, salesTarget, actualSalesAmount, updatedAt FROM JSDataMiddlePlatform.dbo.vip_monthlySaleProgress WHERE dataMonth = ?", [$month], $shop, null, 'shopName'); - $vipTax = $this->query($query, "SELECT TOP {$limit} shopName, storeName, reportAmount, returnOrderCount, returnServiceAmount, returnSkuAmount, saleOrderCount, salesServiceAmount, salesSkuAmount, transactionNum, transactionTime FROM JSDataMiddlePlatform.dbo.vip_taxDeclarationDetail WHERE dataMonth = ?", [$month], $shop, null, 'shopName'); - $vipMarketing = $this->query($query, "SELECT TOP {$limit} account, accountName, advertiserId, dataMonth, totalCostYuan, totalImpressionCount, recordCount, updatedAt FROM JSDataMiddlePlatform.dbo.vip_marketingMonthlySummary WHERE dataMonth = ?", [$month], null, $account, 'account'); - $vipSummary = [ - 'sales' => $this->sum($vipSales, 'actualSalesAmount'), - 'target' => $this->sum($vipSales, 'salesTarget'), - 'tax' => $this->sum($vipTax, 'reportAmount'), - 'marketing_cost' => $this->sum($vipMarketing, 'totalCostYuan'), - 'impressions' => $this->sum($vipMarketing, 'totalImpressionCount'), - ]; + if ($platform === null || $platform === 'dewu') { + $dewu = $this->query($query, "SELECT TOP {$limit} data_month, shop_name, account, amount_type, flow_type, trade_amount_yuan, balance_yuan, trade_date, date_time, remark FROM JSDataMiddlePlatform.dbo.dw_ad_finance_records WHERE data_month = ?", [$month], $shop, $account, 'shop_name'); + $dewuSummary = $this->query($query, 'SELECT COALESCE(SUM(total_income_amount),0) income, COALESCE(SUM(total_expense_amount),0) expense, COALESCE(SUM(net_amount),0) net, COALESCE(SUM(record_count),0) record_count FROM JSDataMiddlePlatform.dbo.dw_ad_finance_month_summaries WHERE data_month = ?', [$month], $shop, $account, 'shop_name', true)[0] ?? []; + } + + if ($platform === null || $platform === 'vip') { + $vipSales = $this->query($query, "SELECT TOP {$limit} shopName, dataMonth, monthName, previousYearSalesAmount, salesTarget, actualSalesAmount, updatedAt FROM JSDataMiddlePlatform.dbo.vip_monthlySaleProgress WHERE dataMonth = ?", [$month], $shop, null, 'shopName'); + $vipTax = $this->query($query, "SELECT TOP {$limit} shopName, storeName, reportAmount, returnOrderCount, returnServiceAmount, returnSkuAmount, saleOrderCount, salesServiceAmount, salesSkuAmount, transactionNum, transactionTime FROM JSDataMiddlePlatform.dbo.vip_taxDeclarationDetail WHERE dataMonth = ?", [$month], $shop, null, 'shopName'); + $vipMarketing = $this->query($query, "SELECT TOP {$limit} account, accountName, advertiserId, dataMonth, totalCostYuan, totalImpressionCount, recordCount, updatedAt FROM JSDataMiddlePlatform.dbo.vip_marketingMonthlySummary WHERE dataMonth = ?", [$month], null, $account, 'account'); + $vipSummary = [ + 'sales' => $this->sum($vipSales, 'actualSalesAmount'), + 'target' => $this->sum($vipSales, 'salesTarget'), + 'tax' => $this->sum($vipTax, 'reportAmount'), + 'marketing_cost' => $this->sum($vipMarketing, 'totalCostYuan'), + 'impressions' => $this->sum($vipMarketing, 'totalImpressionCount'), + ]; + } return [ 'jd' => $jd, diff --git a/modules/EcommerceFinance/View/PlatformPromotionAccountPageData.php b/modules/EcommerceFinance/View/PlatformPromotionAccountPageData.php index 7d1b80a9..1d502252 100644 --- a/modules/EcommerceFinance/View/PlatformPromotionAccountPageData.php +++ b/modules/EcommerceFinance/View/PlatformPromotionAccountPageData.php @@ -38,7 +38,7 @@ class PlatformPromotionAccountPageData $month = $this->repository->latestMonth() ?: $month; $filters['month'] = $month; } - $data = $this->repository->dashboard($filters, 5000); + $data = $this->repository->dashboard($filters, 5000, $platform); return [ 'view' => 'banking.marketing_platform_promotion_bills.partials.embedded-table', diff --git a/tests/Feature/Business/MarketingPlatformPromotionBillsTest.php b/tests/Feature/Business/MarketingPlatformPromotionBillsTest.php index 91373883..9eaf313c 100644 --- a/tests/Feature/Business/MarketingPlatformPromotionBillsTest.php +++ b/tests/Feature/Business/MarketingPlatformPromotionBillsTest.php @@ -19,7 +19,7 @@ class MarketingPlatformPromotionBillsTest extends FeatureTestCase 'month' => '2026-08', 'shop_name' => '', 'account' => '', - ], 5000)->andReturn($this->dashboardData()); + ], 5000, 'jd')->andReturn($this->dashboardData()); $this->app->instance(PlatformPromotionAccountRepository::class, $repository); $this->loginAs() @@ -52,7 +52,7 @@ class MarketingPlatformPromotionBillsTest extends FeatureTestCase 'month' => '2026-08', 'shop_name' => '测试', 'account' => 'account-01', - ], 5000)->andReturn($this->dashboardData()); + ], 5000, 'jd')->andReturn($this->dashboardData()); $this->app->instance(PlatformPromotionAccountRepository::class, $repository); $response = $this->loginAs()->get(route('business.pages.export', [ diff --git a/tests/Unit/EcommerceFinance/PlatformPromotionAccountRepositoryTest.php b/tests/Unit/EcommerceFinance/PlatformPromotionAccountRepositoryTest.php new file mode 100644 index 00000000..c63435bc --- /dev/null +++ b/tests/Unit/EcommerceFinance/PlatformPromotionAccountRepositoryTest.php @@ -0,0 +1,55 @@ +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')), + ['2026-08'], + )->andReturn([['shop_name' => '测试店铺', 'amount' => 100]]); + $query->shouldReceive('select')->once()->ordered()->with( + Mockery::on(static fn (string $sql): bool => str_contains($sql, 'SUM(CASE WHEN in_out_type') + && str_contains($sql, 'jd_jzt_finance_records')), + ['2026-08'], + )->andReturn([['income' => 100, 'expense' => 0, 'record_count' => 1]]); + + $result = (new PlatformPromotionAccountRepository($factory))->dashboard([ + 'month' => '2026-08', + 'shop_name' => '', + 'account' => '', + ], 5000, 'jd'); + + $this->assertCount(1, $result['jd']); + $this->assertSame(1, $result['jdSummary']['record_count']); + $this->assertSame([], $result['dy']); + $this->assertSame([], $result['dw']); + $this->assertSame([], $result['vipSales']); + } + + public function test_dashboard_rejects_an_unknown_platform_before_connecting(): void + { + $factory = Mockery::mock(UpstreamReadOnlyQueryFactory::class); + + $this->expectException(InvalidArgumentException::class); + (new PlatformPromotionAccountRepository($factory))->dashboard([ + 'month' => '2026-08', + ], 200, 'unknown'); + } +} -- 2.47.2