diff --git a/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php b/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php index 201f83f6..a330c75d 100644 --- a/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php @@ -257,7 +257,7 @@ class StoreReceivingAlipayBillMirrorRepository { if (($filters['store_name'] ?? '') !== '') { $shopIds = $this->mirror->connection()->table('ops_jst_shop_info') - ->where('shop_name', $filters['store_name']) + ->where('shop_name', 'like', '%' . $this->escapeLike((string) $filters['store_name']) . '%') ->pluck('shop_id') ->filter(static fn (mixed $value): bool => $value !== null && $value !== '') ->all(); @@ -271,7 +271,7 @@ class StoreReceivingAlipayBillMirrorRepository $query->where('b.channel', 'like', '%' . $this->escapeLike((string) $filters['alipay_account']) . '%'); } if (($filters['bill_item'] ?? '') !== '') { - $query->where('b.fee_name', $filters['bill_item']); + $query->where('b.fee_name', 'like', '%' . $this->escapeLike((string) $filters['bill_item']) . '%'); } if (($filters['business_type'] ?? '') !== '') { $query->where('b.inout_type', $this->directionCode((string) $filters['business_type'])); diff --git a/resources/assets/js/components/business/AccountBills.vue b/resources/assets/js/components/business/AccountBills.vue index 4a806bec..ffe967f8 100644 --- a/resources/assets/js/components/business/AccountBills.vue +++ b/resources/assets/js/components/business/AccountBills.vue @@ -68,4 +68,5 @@ export default { .table-workspace{padding:1rem;color:#171717;font:400 .8125rem/1.5 "JetBrains Mono","Microsoft YaHei","PingFang SC",monospace}.tw-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.75rem;margin-bottom:.75rem}.tw-stat{padding:.875rem 1rem;border:1px solid #d8d2c7;border-radius:.5rem;background:#fff}.tw-label,.tw-note,.tw-count{color:#595959;font-size:.75rem}.tw-value{margin-top:.375rem;font-size:1.375rem;font-weight:700;font-variant-numeric:tabular-nums}.tw-note{margin-top:.1875rem}.is-income{color:#53793e}.is-expense{color:#b80000}.tw-filter{display:flex;flex-wrap:wrap;gap:.75rem;margin-bottom:.75rem;padding:.875rem 1rem;border:1px solid #d8d2c7;border-radius:.5rem;background:#fff}.tw-filter>label{display:flex;flex-direction:column;gap:.25rem;color:#595959;font-size:.75rem;font-weight:500}.tw-filter input,.tw-tools select{height:2.125rem;min-width:10rem;padding:0 .625rem;border:1px solid #d8d2c7;border-radius:.5rem;background:#fff;color:#171717;font:400 .8125rem/1 inherit}.tw-filter input:focus,.tw-tools select:focus{border-color:#856632;box-shadow:0 0 0 3px rgba(133,102,50,.2);outline:none}.tw-filter .tw-keyword{flex:1;min-width:14rem}.tw-keyword input{width:100%}.tw-date span,.tw-actions,.tw-tools,.tw-page-actions{display:flex;align-items:center;gap:.5rem}.tw-date b{font-weight:400}.tw-date input{min-width:8.5rem}.tw-actions{align-self:flex-end;margin-left:auto}.tw-button,.tw-page-actions button{display:inline-flex;align-items:center;justify-content:center;gap:.375rem;height:2.125rem;padding:0 .875rem;border:1px solid #d8d2c7;border-radius:.5rem;background:#fff;color:#171717;font:500 .8125rem/1 inherit;cursor:pointer}.tw-button:hover{border-color:#856632;color:#856632}.tw-primary{border-color:#856632;background:#856632;color:#fff}.tw-primary:hover{background:#6a5129;color:#fff}.tw-button .material-icons-outlined{font-size:1.125rem}.tw-panel{overflow:visible;border:1px solid #d8d2c7;border-radius:.5rem;background:#fff}.tw-alert{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:.75rem;padding:.75rem;border:1px solid #b80000;border-radius:.5rem;background:#fff4f4;color:#b80000}.tw-alert button{border:0;background:transparent;color:#b80000;font:inherit;font-weight:600;cursor:pointer}.tw-toolbar{display:flex;align-items:center;justify-content:space-between;gap:.75rem;min-height:3.5rem;padding:.625rem .875rem;border-bottom:1px solid #d8d2c7}.tw-toolbar strong{margin-right:.625rem;font-size:.875rem}.tw-tools{flex-wrap:wrap;justify-content:flex-end}.tw-tools>select{min-width:13.75rem}.tw-scroll{position:relative;max-height:min(62vh,42rem);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.tw-table{width:max-content;min-width:100%;border-collapse:separate;border-spacing:0;font-size:.78125rem}.tw-table th,.tw-table td{min-width:7.5rem;padding:.5rem .625rem;border-right:1px solid #eeeae2;border-bottom:1px solid #eeeae2;white-space:nowrap}.tw-table thead th{position:sticky;z-index:4;background:#f7f0de;color:#171717;font-weight:600}.tw-groups th{top:0;height:2rem;text-align:center;color:#856632;font-size:.75rem}.tw-columns th{top:2rem;height:2.25rem;text-align:left;background:#fbfaf7;box-shadow:inset 0 -1px #d8d2c7}.tw-columns.is-single th{top:0}.tw-columns th.is-sortable{cursor:pointer}.tw-columns th.is-sortable:hover,.tw-sort{color:#856632}.tw-table tbody tr:hover{background:#f7f0de}.tw-table .is-number{text-align:right;font-variant-numeric:tabular-nums}.tw-table .is-id{color:#595959}.tw-tag{display:inline-block;padding:.0625rem .375rem;border-radius:.25rem;background:#f7f0de;color:#856632}.tw-empty{padding:3rem 1rem!important;text-align:center!important;color:#595959}.tw-pager{display:flex;align-items:center;justify-content:space-between;gap:.75rem;min-height:3.5rem;padding:.625rem .875rem;border-top:1px solid #d8d2c7;color:#595959}.tw-page-actions select{height:1.875rem;border:1px solid #d8d2c7;border-radius:.375rem}.tw-page-actions button{width:1.875rem;height:1.875rem;padding:0}.tw-page-actions button:disabled{cursor:not-allowed;opacity:.45}@media(max-width:900px){.table-workspace{padding:.75rem}.tw-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.tw-filter>label,.tw-filter .tw-keyword{width:100%}.tw-filter input{width:100%}.tw-date input{min-width:0}.tw-actions{margin-left:0}.tw-toolbar,.tw-pager{align-items:flex-start;flex-direction:column}.tw-tools{justify-content:flex-start}.tw-scroll{max-height:58vh;width:100%}}@media(max-width:520px){.tw-stats{grid-template-columns:1fr}.tw-date span{align-items:stretch;flex-direction:column}.tw-tools>select{min-width:0;max-width:100%}.tw-page-actions{flex-wrap:wrap}} .tw-toolbar { flex-wrap: wrap; } .tw-tools { flex: 1 1 24rem; min-width: 0; } +.tw-filter{display:grid;grid-template-columns:minmax(10rem,1fr) minmax(10rem,1fr) auto minmax(14rem,2fr) auto;align-items:end}.tw-filter>label{min-width:0}.tw-actions{align-self:auto;justify-self:end;margin-left:0}@media(max-width:900px){.tw-filter{grid-template-columns:1fr}.tw-actions{justify-self:start}} diff --git a/tests/Feature/Business/PagesTest.php b/tests/Feature/Business/PagesTest.php index 74e03258..ad029f50 100644 --- a/tests/Feature/Business/PagesTest.php +++ b/tests/Feature/Business/PagesTest.php @@ -157,6 +157,43 @@ class PagesTest extends FeatureTestCase ->assertJsonPath('summary.count', 1); } + public function testDouyinAccountBillsEndpointPassesAllFiltersToTheMirror(): void + { + $this->user->attachPermission( + Permission::where('name', 'read-admin-panel')->firstOrFail() + ); + + $filters = [ + 'store_name' => '放心购', + 'bill_item' => '交易佣', + 'start' => '2026-08-01', + 'end' => '2026-08-01', + 'keyword' => '', + ]; + + $repository = Mockery::mock(StoreReceivingDouyinBillMirrorRepository::class); + $repository->shouldReceive('paginate')->once()->with( + $filters, 'occurred_at', 'desc', 1, 10, + )->andReturn([ + 'current_page' => 1, + 'last_page' => 1, + 'per_page' => 10, + 'total' => 0, + 'data' => [], + 'summary' => ['income' => 0.0, 'expense' => 0.0, 'balance' => 0.0, 'count' => 0], + ]); + $this->app->instance(StoreReceivingDouyinBillMirrorRepository::class, $repository); + + $this->loginAs() + ->withHeader('X-Requested-With', 'XMLHttpRequest') + ->get(route('ecommerce-finance.account-bills.index', [ + 'bill_type' => 'douyin', + ...$filters, + ])) + ->assertOk() + ->assertJsonPath('total', 0); + } + public function testDouyinAccountBillsExportUsesSelectedColumnOrder(): void { $this->user->attachPermission( diff --git a/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php b/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php index 19368199..f9ac0fc7 100644 --- a/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php +++ b/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php @@ -273,21 +273,32 @@ class StoreReceivingAlipayBillMirrorRepositoryTest extends TestCase $db->table('ops_jst_original_bill_info')->insert([ $this->row(1, 7, '2026-08-01 09:00:00', '1', 100.25, 'TouTiaoFXGZJ'), $this->row(2, 7, '2026-08-02 09:00:00', '-1', 20.10, 'CommonBillTGCPay'), + $this->row(3, 7, '2026-08-02 10:00:00', '1', 55.40, 'TouTiaoFXGZJ'), ]); $douyin = new StoreReceivingDouyinBillMirrorRepository($this->repository); $result = $douyin->paginate([], 'occurred_at', 'desc', 1, 10); - $this->assertSame(1, $result['total']); - $this->assertSame('1', $result['data'][0]['record_code']); + $this->assertSame(2, $result['total']); + $this->assertSame('3', $result['data'][0]['record_code']); $this->assertSame('放心购旗舰店', $result['data'][0]['store_name']); $this->assertSame('TouTiaoFXGZJ', $result['data'][0]['payload']['settle_account']); $this->assertSame('头条放心购', $result['data'][0]['payload']['move_scene']); - $this->assertSame(100.25, $result['summary']['income']); + $this->assertSame(155.65, $result['summary']['income']); $this->assertSame(0.0, $result['summary']['expense']); + $filtered = $douyin->paginate([ + 'store_name' => '放心购', + 'bill_item' => '交易佣', + 'start' => '2026-08-01', + 'end' => '2026-08-01', + ], 'occurred_at', 'desc', 1, 10); + + $this->assertSame(1, $filtered['total']); + $this->assertSame('1', $filtered['data'][0]['record_code']); + $rows = iterator_to_array($douyin->exportRows([], 'occurred_at', 'asc')); - $this->assertCount(1, $rows); + $this->assertCount(2, $rows); $this->assertSame('1', $rows[0]['record_code']); }