Skip to content

Implement ViolationUtils lib #31083

@cead22

Description

@cead22
  • Design Doc
  • Implement a new ViolationUtils lib (src/libs/ViolationUtils.js or src/libs/ViolationUtils.ts)
    1. Add a method getViolationForField(object transactionViolation, string field) : string
      • getViolationForField will check transactionViolation and return an an array of strings with the translated copies of the violations for that field, eg
      • When field is ‘category’, the method will pull the violations that apply to the category field, and then call translate on the violation names, like missingCategory and return that
      • See code example below
    2. Add a method getViolationsOnyxData(Transaction transaction, object transactionViolations, bool policyRequiresTags, object[] policyTags, bool policyRequiresCategories, object[] policyCategories) that calculates the new transaction violations (by adding/removing those that have been addressed with the current user changes), and returns an object that we can save into onyx. The updatedTransactionViolations variable shown in the code snippet below will be set like so:
      • If policyRequiresCategories === true, the transactionViolations array doesn't have one with name: categoryOutOfPolicy and the passed transaction contains a category, and the policyCategories collection doesn’t have that category with its enabled value set to true, then it’ll add the object {‘name’:’categoryOutOfPolicy’, ‘type’: ‘violation’} to updatedTransactionViolations
      • If policyRequiresCategories === true, the passed transaction contains a category that is enabled in the policy, and the onyx data had a missingCategory violation, we’ll clear it from updatedTransactionViolations using _.reject(transactionViolations, e => e.name === 'missingCategory')
      • If policyRequiresTag === true, the transactionViolations array doesn't have one with name: tagOutOfPolicy and the passed transaction contains a tag, and the policyTags collection doesn’t have that tag with its enabled value set to true, then it’ll add the object {‘name’:’categoryOutOfPolicy’, ‘type’: ‘violation’} to updatedTransactionViolations
      • If policyRequiresTag === true, the passed transaction contains a tag that is enabled in the policy, and the onyx data had a missingTag violation, we’ll clear it from updatedTransactionViolations using `_.reject(transactionViolations, e => e.name === 'missingTag')
    3. Add const formFields = {merchant: 'merchant', amount: 'amount', category: 'category', ...}
    4. Add a const violationField = {missingCategory: 'category', categoryOutOfPolicy: 'category', ...} with a mapping of violation names to the name of the field where the violation is shown (more in code snippet below
    5. Feel free to add dummy translations to the EN and ES files for now for the violations
function getViolationForField(transactionViolations, field) {
    const {translate} = useLocalize();
    const fieldViolations = _.filter(transactionViolations, (violation) => violations[violation.name] === field);
    return fieldViolations.map(violation => translate(violation.name));
}
// Example object returned by getViolationsOnyxData
{
    onyxMethod: Onyx.METHOD.SET, 
    key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`
    value: updatedTransactionViolations
}
const formFields = {
    merchant: 'merchant',
    amount: 'amount',
    category: 'category', 
    date: 'date',
    tag: 'tag',
    comment: 'comment',
    billable: 'billable',
    receipt: 'receipt',
    tax: 'tax',
};
const violationFields = {
    perDayLimit: formFields.amount,
    maxAge: formFields.date,
    overLimit: formFields.amount,
    overLimitAttendee: formFields.amount,
    overCategoryLimit: formFields.amount,
    receiptRequired: formFields.receipt,
    missingCategory: formFields.category,
    categoryOutOfPolicy: formFields.category,
    missingTag: formFields.tag,
    tagOutOfPolicy: formFields.tag,
    missingComment: formFields.comment,
    taxRequired: formFields.tax,
    taxOutOfPolicy: formFields.tax,
    billableExpense: formFields.billable,
};

Example

getViolationForField([{name: 'overLimit', type: 'violation'}], 'amount') 
// should return => translate('overLimit')

getViolationForField([{name: 'maxAge', type: 'violation'}], 'amount') 
// should return => ''

getViolationForField([{name: 'maxAge', type: 'violation'}], 'date') 
// should return => translate('maxAge')
getViolationsOnyxData(
    transaction = {category: '', ...}, 
    transactionViolations = [], 
    policyRequiresTags = false,
    policyTags = [],
    policyRequiresCategories = true, 
    policyCategories = [{Entertainment: {name: 'Entertainment', enabled: true}}]
)
// should return 
{
    onyxMethod: Onyx.METHOD.SET, 
    key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`,
    value: [{name: 'missingCategory', type: 'violation'}],
}


getViolationsOnyxData(
    transaction = {tag: '', ...}, 
    transactionViolations = [], 
    policyRequiresTags = true,
    policyTags = [{Entertainment: {name: 'Engineering', enabled: true}}],
    policyRequiresCategories = true, 
    policyCategories = []
)
// should return
{
    onyxMethod: Onyx.METHOD.SET, 
    key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`,
    value: [{name: 'missingTag', type: 'violation'}],
}

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions