feat: OA流程付款状态直接筛选已付款
移除包含已付款审批开关,付款状态直接筛选待付款和已付款。
This commit is contained in:
parent
f71fa8f669
commit
efa4193fbd
@ -510,78 +510,6 @@ class DingProcessDetailMirrorRepository
|
||||
{
|
||||
$query->where('ding_process_detail_mirror.source_scope', $this->scope());
|
||||
|
||||
if (array_key_exists('include_paid', $filters) && $filters['include_paid'] !== '1') {
|
||||
$query->whereNotExists(function (Builder $paidApproval): void {
|
||||
$paidApproval
|
||||
->selectRaw('1')
|
||||
->from('ding_process_detail_mirror as paid_approval')
|
||||
->whereColumn(
|
||||
'paid_approval.business_id',
|
||||
'ding_process_detail_mirror.business_id',
|
||||
)
|
||||
->whereColumn(
|
||||
'paid_approval.source_scope',
|
||||
'ding_process_detail_mirror.source_scope',
|
||||
)
|
||||
->where('paid_approval.cashier_status', 'completed');
|
||||
});
|
||||
if ($this->structuredPaymentsEnabled()) {
|
||||
$query->whereNotExists(function (Builder $fullyPaidApproval): void {
|
||||
$fullyPaidApproval
|
||||
->select('payment_fully_paid.business_id')
|
||||
->from('ding_process_payment_mirror as payment_fully_paid')
|
||||
->whereColumn(
|
||||
'payment_fully_paid.business_id',
|
||||
'ding_process_detail_mirror.business_id',
|
||||
)
|
||||
->whereColumn(
|
||||
'payment_fully_paid.source_scope',
|
||||
'ding_process_detail_mirror.source_scope',
|
||||
)
|
||||
->groupBy(
|
||||
'payment_fully_paid.business_id',
|
||||
'payment_fully_paid.source_scope',
|
||||
)
|
||||
->havingRaw(
|
||||
'SUM(COALESCE(payment_fully_paid.amount, 0)) > 0',
|
||||
)
|
||||
->havingRaw(
|
||||
'SUM(COALESCE(payment_fully_paid.amount, 0)) + 0.01 >= ('
|
||||
. 'SELECT SUM(COALESCE(detail_fully_paid.amount, 0)) '
|
||||
. 'FROM ding_process_detail_mirror AS detail_fully_paid '
|
||||
. 'WHERE detail_fully_paid.business_id = ding_process_detail_mirror.business_id '
|
||||
. 'AND detail_fully_paid.source_scope = ding_process_detail_mirror.source_scope'
|
||||
. ')',
|
||||
);
|
||||
});
|
||||
} else {
|
||||
$query->whereNotExists(function (Builder $fullyPaidApproval): void {
|
||||
$fullyPaidApproval
|
||||
->select('fully_paid_approval.business_id')
|
||||
->from('ding_process_detail_mirror as fully_paid_approval')
|
||||
->whereColumn(
|
||||
'fully_paid_approval.business_id',
|
||||
'ding_process_detail_mirror.business_id',
|
||||
)
|
||||
->whereColumn(
|
||||
'fully_paid_approval.source_scope',
|
||||
'ding_process_detail_mirror.source_scope',
|
||||
)
|
||||
->groupBy(
|
||||
'fully_paid_approval.business_id',
|
||||
'fully_paid_approval.source_scope',
|
||||
)
|
||||
->havingRaw(
|
||||
'SUM(COALESCE(fully_paid_approval.bank_amount, 0)) > 0',
|
||||
)
|
||||
->havingRaw(
|
||||
'SUM(COALESCE(fully_paid_approval.bank_amount, 0)) + 0.01 '
|
||||
. '>= SUM(COALESCE(fully_paid_approval.amount, 0))',
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$paidStart = $this->filterDate($filters['paid_start'] ?? '');
|
||||
$paidEnd = $this->filterDate($filters['paid_end'] ?? '');
|
||||
if ($paidStart === '' && $paidEnd === '') {
|
||||
|
||||
@ -232,7 +232,6 @@ class ProcessDetailsPageData
|
||||
'current_approver_name' => mb_substr(trim((string) $request->query('current_approver_name', '')), 0, 100),
|
||||
'waiting_bucket' => $waitingBucket,
|
||||
'keyword' => mb_substr(trim((string) $request->query('keyword', '')), 0, 100),
|
||||
'include_paid' => $request->boolean('include_paid') ? '1' : '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -267,10 +267,6 @@
|
||||
grid-column: span 5;
|
||||
}
|
||||
|
||||
.process-details-field.is-paid-toggle {
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.process-details-field.is-business {
|
||||
grid-column: span 3;
|
||||
}
|
||||
@ -314,61 +310,6 @@
|
||||
box-shadow: 0 0 0 3px rgba(133, 102, 50, .2);
|
||||
}
|
||||
|
||||
.process-details-paid-scope {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
height: 2.125rem;
|
||||
padding: 0 .65rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .5rem;
|
||||
background: #fff;
|
||||
color: var(--vip-content-ink, #171717) !important;
|
||||
font-size: .8125rem !important;
|
||||
font-weight: 500 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.process-details-paid-scope input {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
}
|
||||
|
||||
.process-details-paid-scope__box {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border: 1px solid var(--vip-border, #D8D2C7);
|
||||
border-radius: .25rem;
|
||||
background: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.process-details-paid-scope__box .material-icons-outlined {
|
||||
font-size: .8rem;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.process-details-paid-scope input:checked + .process-details-paid-scope__box {
|
||||
border-color: var(--vip-content-accent-dark, #856632);
|
||||
background: var(--vip-content-accent-dark, #856632);
|
||||
}
|
||||
|
||||
.process-details-paid-scope input:checked + .process-details-paid-scope__box .material-icons-outlined {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.process-details-paid-scope input:focus-visible + .process-details-paid-scope__box {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(133, 102, 50, .2);
|
||||
}
|
||||
|
||||
.process-details-combobox {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@ -1000,7 +941,6 @@
|
||||
.process-details-field.is-date-range,
|
||||
.process-details-field.is-waiting,
|
||||
.process-details-field.is-keyword,
|
||||
.process-details-field.is-paid-toggle,
|
||||
.process-details-actions {
|
||||
grid-column: span 6;
|
||||
}
|
||||
@ -1056,7 +996,6 @@
|
||||
.process-details-field.is-approver,
|
||||
.process-details-field.is-date-range,
|
||||
.process-details-field.is-waiting,
|
||||
.process-details-field.is-paid-toggle,
|
||||
.process-details-field.is-keyword,
|
||||
.process-details-actions {
|
||||
grid-column: 1;
|
||||
@ -1317,22 +1256,6 @@
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="process-details-field is-paid-toggle">
|
||||
<span class="process-details-field__label">展示范围</span>
|
||||
<label class="process-details-paid-scope" for="process-details-include-paid">
|
||||
<input
|
||||
id="process-details-include-paid"
|
||||
type="checkbox"
|
||||
name="include_paid"
|
||||
value="1"
|
||||
@checked(($filters['include_paid'] ?? '') === '1')
|
||||
>
|
||||
<span class="process-details-paid-scope__box" aria-hidden="true">
|
||||
<span class="material-icons-outlined">check</span>
|
||||
</span>
|
||||
<span>包含已付款审批</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="process-details-field">
|
||||
<label for="process-details-originator">发起人</label>
|
||||
<input id="process-details-originator" type="search" name="originator_name" value="{{ $filters['originator_name'] ?? '' }}" placeholder="支持包含查询">
|
||||
@ -1390,7 +1313,7 @@
|
||||
</summary>
|
||||
<div class="process-details-note-content">
|
||||
<p>
|
||||
页面默认仅展示现金付款节点尚未完成的审批;需核对历史全量时,可勾选“包含已付款审批”。
|
||||
付款状态可直接选择“待付款”或“已付款”:待付款只展示尚未完成付款的审批,已付款只展示已有付款事实的审批。
|
||||
应付金额按审批费用明细汇总;实际付款按审批表单中的结构化付款明细汇总。
|
||||
未产生付款记录的审批,其实际付款按 0 元展示,因此应付金额与实际付款金额不要求相等。
|
||||
打款日期以审批单为准:审批单在所选期间有打款记录时,整张审批单的明细和付款金额都计入汇总;
|
||||
|
||||
@ -104,9 +104,9 @@ class ProcessDetailsPageTest extends FeatureTestCase
|
||||
->assertSee('name="waiting_bucket"', false)
|
||||
->assertSee('value="1_2d" selected', false)
|
||||
->assertSee('2天以上', false)
|
||||
->assertSee('name="include_paid"', false)
|
||||
->assertSee('包含已付款审批')
|
||||
->assertSee('页面默认仅展示现金付款节点尚未完成的审批')
|
||||
->assertDontSee('name="include_paid"', false)
|
||||
->assertDontSee('包含已付款审批')
|
||||
->assertSee('付款状态可直接选择“待付款”或“已付款”')
|
||||
->assertDontSee('name="entry_start"', false)
|
||||
->assertDontSee('name="entry_end"', false)
|
||||
->assertSee('placeholder="开始日期"', false)
|
||||
@ -119,6 +119,7 @@ class ProcessDetailsPageTest extends FeatureTestCase
|
||||
->assertSee('name="payment_state"', false)
|
||||
->assertSee('审批状态')
|
||||
->assertSee('付款状态')
|
||||
->assertSee('<option value="已付款"', false)
|
||||
->assertSee('当前审批人')
|
||||
->assertSee('进入时间')
|
||||
->assertSee('已等待')
|
||||
|
||||
@ -126,15 +126,21 @@ class DingProcessDetailMirrorRepositoryTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function test_paid_approvals_are_excluded_unless_explicitly_included(): void
|
||||
public function test_payment_status_filter_splits_paid_and_pending_approvals(): void
|
||||
{
|
||||
DB::connection('business_mirror')
|
||||
->table('ding_process_detail_mirror')
|
||||
->where('business_id', '202601011200000000001')
|
||||
->update(['cashier_status' => 'pending']);
|
||||
|
||||
$all = $this->repository->paginate([], 1, 50);
|
||||
$this->assertSame(4, $all['total']);
|
||||
$this->assertSame(2, $all['summary']['approvals']);
|
||||
$this->assertEqualsWithDelta(650.5, $all['summary']['amount_total'], 0.001);
|
||||
$this->assertEqualsWithDelta(350.5, $all['summary']['bank_amount_total'], 0.001);
|
||||
|
||||
$pending = $this->repository->paginate([
|
||||
'include_paid' => '',
|
||||
'payment_state' => '待付款',
|
||||
], 1, 50);
|
||||
$this->assertSame(2, $pending['total']);
|
||||
$this->assertSame(2, $pending['summary']['rows']);
|
||||
@ -142,14 +148,16 @@ class DingProcessDetailMirrorRepositoryTest extends TestCase
|
||||
$this->assertEqualsWithDelta(500, $pending['summary']['amount_total'], 0.001);
|
||||
$this->assertEqualsWithDelta(200, $pending['summary']['bank_amount_total'], 0.001);
|
||||
|
||||
$all = $this->repository->paginate([
|
||||
'include_paid' => '1',
|
||||
$paid = $this->repository->paginate([
|
||||
'payment_state' => '已付款',
|
||||
], 1, 50);
|
||||
$this->assertSame(4, $all['total']);
|
||||
$this->assertSame(2, $all['summary']['approvals']);
|
||||
$this->assertSame(2, $paid['total']);
|
||||
$this->assertSame(1, $paid['summary']['approvals']);
|
||||
$this->assertEqualsWithDelta(150.5, $paid['summary']['amount_total'], 0.001);
|
||||
$this->assertEqualsWithDelta(150.5, $paid['summary']['bank_amount_total'], 0.001);
|
||||
|
||||
$approvalSummary = $this->repository->paginateApprovals([
|
||||
'include_paid' => '',
|
||||
'payment_state' => '待付款',
|
||||
], 1, 50);
|
||||
$this->assertSame(1, $approvalSummary['total']);
|
||||
$this->assertSame(2, $approvalSummary['summary']['rows']);
|
||||
|
||||
@ -53,9 +53,9 @@ class ProcessDetailsPageDataTest extends TestCase
|
||||
$this->assertStringContainsString('<th class="num">应付金额</th>', $content);
|
||||
$this->assertStringContainsString('<th class="num">实际付款</th>', $content);
|
||||
$this->assertStringContainsString('<th>进入时间</th>', $content);
|
||||
$this->assertStringContainsString('name="include_paid"', $content);
|
||||
$this->assertStringContainsString('包含已付款审批', $content);
|
||||
$this->assertStringContainsString('页面默认仅展示现金付款节点尚未完成的审批', $content);
|
||||
$this->assertStringNotContainsString('name="include_paid"', $content);
|
||||
$this->assertStringNotContainsString('包含已付款审批', $content);
|
||||
$this->assertStringContainsString('付款状态可直接选择“待付款”或“已付款”', $content);
|
||||
$this->assertStringNotContainsString('process-details-approval-link', $content);
|
||||
$this->assertStringNotContainsString(
|
||||
"route('business.process-details.detail'",
|
||||
@ -141,7 +141,7 @@ class ProcessDetailsPageDataTest extends TestCase
|
||||
$this->assertSame('已付款', $data['filters']['payment_state']);
|
||||
$this->assertSame('王五', $data['filters']['current_approver_name']);
|
||||
$this->assertSame('12_24h', $data['filters']['waiting_bucket']);
|
||||
$this->assertSame('', $data['filters']['include_paid']);
|
||||
$this->assertArrayNotHasKey('include_paid', $data['filters']);
|
||||
$this->assertSame(
|
||||
[
|
||||
'待付款',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user