fix: preserve reviewer risk notice after standard adjustment
This commit is contained in:
@@ -93,7 +93,7 @@ import {
|
||||
import {
|
||||
buildCurrentStandardAdjustmentMap,
|
||||
buildStandardAdjustmentPayload as buildStandardAdjustmentPayloadModel,
|
||||
filterSubmitterStandardAdjustedRiskCards as filterSubmitterStandardAdjustedRiskCardsModel,
|
||||
filterSubmitterResolvedRiskCards as filterSubmitterResolvedRiskCardsModel,
|
||||
isRiskCardMissingExpenseNote as isRiskCardMissingExpenseNoteModel,
|
||||
resolveExpenseItemForRiskCard as resolveExpenseItemForRiskCardModel
|
||||
} from './travelRequestDetailStandardAdjustment.js'
|
||||
@@ -1179,8 +1179,8 @@ export default {
|
||||
return resolveExpenseItemForRiskCardModel(card, expenseItems.value)
|
||||
}
|
||||
|
||||
function filterSubmitterStandardAdjustedRiskCards(cards, businessStage) {
|
||||
return filterSubmitterStandardAdjustedRiskCardsModel({
|
||||
function filterSubmitterResolvedRiskCards(cards, businessStage) {
|
||||
return filterSubmitterResolvedRiskCardsModel({
|
||||
cards,
|
||||
businessStage,
|
||||
isCurrentApplicant: isCurrentApplicant.value,
|
||||
@@ -1597,7 +1597,7 @@ export default {
|
||||
: []
|
||||
const scopedRiskCards = [
|
||||
...(hasActionableRiskCards ? [] : summaryRiskCards),
|
||||
...filterSubmitterStandardAdjustedRiskCards(directRiskCards, currentBusinessStage)
|
||||
...filterSubmitterResolvedRiskCards(directRiskCards, currentBusinessStage)
|
||||
]
|
||||
const riskCards = filterRiskCardsForVisibility(scopedRiskCards, riskViewerContext.value)
|
||||
|
||||
|
||||
@@ -31,14 +31,6 @@ export function resolveExpenseItemForRiskCard(card, expenseItems = []) {
|
||||
|| null
|
||||
}
|
||||
|
||||
export function hasStandardAdjustmentForItem(item, standardAdjustmentMap = new Map()) {
|
||||
const itemId = normalizeText(item?.id)
|
||||
if (!itemId) {
|
||||
return false
|
||||
}
|
||||
return Boolean(item?.standardAdjustmentAccepted || standardAdjustmentMap.has(itemId))
|
||||
}
|
||||
|
||||
export function isRiskCardMissingExpenseNote(card, expenseItems = []) {
|
||||
const item = resolveExpenseItemForRiskCard(card, expenseItems)
|
||||
if (!item) {
|
||||
@@ -47,7 +39,15 @@ export function isRiskCardMissingExpenseNote(card, expenseItems = []) {
|
||||
return !normalizeText(item.itemNote)
|
||||
}
|
||||
|
||||
function isRiskCardCoveredByStandardAdjustment(card, expenseItems, standardAdjustmentMap) {
|
||||
export function hasStandardAdjustmentForItem(item, standardAdjustmentMap = new Map()) {
|
||||
const itemId = normalizeText(item?.id)
|
||||
if (!itemId) {
|
||||
return false
|
||||
}
|
||||
return Boolean(item?.standardAdjustmentAccepted || standardAdjustmentMap.has(itemId))
|
||||
}
|
||||
|
||||
function isRiskCardResolvedForSubmitter(card, expenseItems, standardAdjustmentMap) {
|
||||
if (normalizeText(card?.source) === STANDARD_ADJUSTMENT_RISK_SOURCE) {
|
||||
return true
|
||||
}
|
||||
@@ -57,7 +57,7 @@ function isRiskCardCoveredByStandardAdjustment(card, expenseItems, standardAdjus
|
||||
)
|
||||
}
|
||||
|
||||
export function filterSubmitterStandardAdjustedRiskCards({
|
||||
export function filterSubmitterResolvedRiskCards({
|
||||
cards = [],
|
||||
businessStage = 'reimbursement',
|
||||
isCurrentApplicant = false,
|
||||
@@ -67,7 +67,7 @@ export function filterSubmitterStandardAdjustedRiskCards({
|
||||
if (businessStage !== 'reimbursement' || !isCurrentApplicant) {
|
||||
return cards
|
||||
}
|
||||
return cards.filter((card) => !isRiskCardCoveredByStandardAdjustment(card, expenseItems, standardAdjustmentMap))
|
||||
return cards.filter((card) => !isRiskCardResolvedForSubmitter(card, expenseItems, standardAdjustmentMap))
|
||||
}
|
||||
|
||||
function extractRiskCardMoneyValues(card) {
|
||||
|
||||
@@ -24,6 +24,9 @@ import {
|
||||
buildEmployeeProfileAdviceItems,
|
||||
buildTravelReceiptMaterialPrompts
|
||||
} from '../src/views/scripts/travelRequestDetailAdviceModel.js'
|
||||
import {
|
||||
filterSubmitterResolvedRiskCards
|
||||
} from '../src/views/scripts/travelRequestDetailStandardAdjustment.js'
|
||||
|
||||
const detailViewTemplate = readFileSync(
|
||||
fileURLToPath(new URL('../src/views/TravelRequestDetailView.vue', import.meta.url)),
|
||||
@@ -708,7 +711,8 @@ test('expense detail shows standard-adjusted reimbursable amount separately from
|
||||
assert.match(detailViewTemplate, /submitConfirmAmountDisplay/)
|
||||
assert.match(detailViewStyle, /\.expense-original-amount[\s\S]*text-decoration-line: line-through/)
|
||||
assert.match(detailViewScript, /const expenseTotal = computed\(\(\) => \{[\s\S]*item\.reimbursableAmount/)
|
||||
assert.match(detailViewScript, /filterSubmitterStandardAdjustedRiskCards/)
|
||||
assert.match(detailViewScript, /filterSubmitterResolvedRiskCards/)
|
||||
assert.doesNotMatch(detailViewScript, /filterSubmitterStandardAdjustedRiskCards/)
|
||||
assert.match(detailViewScript, /acceptExpenseClaimStandardAdjustment/)
|
||||
assert.match(detailExpenseModelScript, /STANDARD_ADJUSTMENT_RISK_SOURCE = 'reimbursement_standard_adjustment'/)
|
||||
assert.match(requestsComposableScript, /STANDARD_ADJUSTMENT_RISK_SOURCE = 'reimbursement_standard_adjustment'/)
|
||||
@@ -744,6 +748,66 @@ test('expense detail shows standard-adjusted reimbursable amount separately from
|
||||
assert.equal(item.hasStandardAdjustment, true)
|
||||
})
|
||||
|
||||
test('standard adjustment resolves submitter risk prompt only after accepted while reviewer still sees notice', () => {
|
||||
const originalRiskCard = {
|
||||
id: 'risk-hotel-1',
|
||||
source: 'attachment_analysis',
|
||||
itemId: 'expense-item-1',
|
||||
tone: 'high',
|
||||
risk: '住宿票据金额超过职级标准。'
|
||||
}
|
||||
const reviewerNoticeCard = {
|
||||
id: 'standard-adjustment-1',
|
||||
source: 'reimbursement_standard_adjustment',
|
||||
itemId: 'expense-item-1',
|
||||
tone: 'medium',
|
||||
risk: '提交人已选择按职级标准报销,超出部分由员工自担。'
|
||||
}
|
||||
const expenseItems = [{ id: 'expense-item-1' }]
|
||||
const standardAdjustmentMap = buildStandardAdjustmentMap({
|
||||
riskFlags: [
|
||||
{
|
||||
source: 'reimbursement_standard_adjustment',
|
||||
item_id: 'expense-item-1',
|
||||
original_amount: '880.00',
|
||||
reimbursable_amount: '600.00',
|
||||
employee_absorbed_amount: '280.00'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert.deepEqual(
|
||||
filterSubmitterResolvedRiskCards({
|
||||
cards: [originalRiskCard],
|
||||
businessStage: 'reimbursement',
|
||||
isCurrentApplicant: true,
|
||||
expenseItems,
|
||||
standardAdjustmentMap: new Map()
|
||||
}),
|
||||
[originalRiskCard]
|
||||
)
|
||||
assert.deepEqual(
|
||||
filterSubmitterResolvedRiskCards({
|
||||
cards: [originalRiskCard],
|
||||
businessStage: 'reimbursement',
|
||||
isCurrentApplicant: true,
|
||||
expenseItems,
|
||||
standardAdjustmentMap
|
||||
}),
|
||||
[]
|
||||
)
|
||||
assert.deepEqual(
|
||||
filterSubmitterResolvedRiskCards({
|
||||
cards: [originalRiskCard, reviewerNoticeCard],
|
||||
businessStage: 'reimbursement',
|
||||
isCurrentApplicant: false,
|
||||
expenseItems,
|
||||
standardAdjustmentMap
|
||||
}),
|
||||
[originalRiskCard, reviewerNoticeCard]
|
||||
)
|
||||
})
|
||||
|
||||
test('expense item upload remains limited to one receipt per detail row', () => {
|
||||
assert.match(detailViewTemplate, /ref="expenseUploadInput"[\s\S]*type="file"/)
|
||||
assert.doesNotMatch(
|
||||
|
||||
Reference in New Issue
Block a user