Overview
In Genpact Deductions Recovery, a case is considered valid or invalid or partially valid for deductions based on some pre-defined rule. The document-validation-type.yaml file defines the respective fields from the header, line-level and the POD data, which are considered for validation.
The document-validation.yaml file configures the rules for validation of the extracted header, line-item and POD data. Based on fulfillment of these pre-defined rules the deduction case is marked as Valid, Invalid or Partially valid and processed accordingly.
The caseform-validation-statuses.yaml file defines the available validation status for a case in the portal and the system.
The caseform-invalid-reasons.yaml file configures the deduction invalid reasons that can be chosen and will appear in the case details in the portal.
Sample YAML settings
caseform-validation-statuses.yaml
kind: document
metadata:
name: deduction/v1/documents/caseform-validation-statuses
spec:
values:
- "valid"
- "invalid"
- "partial"
- "empty"
| Parameter | Description |
|---|---|
| values | The values for the validation status.
|
caseform-invalid-reasons.yaml
kind: document
metadata:
name: deduction/v1/documents/caseform-invalid-reasons
spec:
values:
- "asaf test"
- "test"
- "POD does not support shortages"
- "POD support partial shortages"
- "Deducted SKU is not invoiced"
- "Customer deducted at higher price"
- "UOM issue"
| Parameter | Description |
|---|---|
| values | The reasons for an invalid status. |
document-validation-types.yaml
kind: document
metadata:
name: deduction/v1/documents/document-validation-types
spec:
# --------------------------
# HEADER
# --------------------------
- name: "Header"
fields:
- fieldName: InvoiceNumber
type: "System.String"
defaultNull:
- fieldName: ReasonCode
type: "System.String"
defaultNull:
- fieldName: DeductionStatus
type: "System.String"
defaultNull:
- fieldName: CustomerID
type: "System.String"
defaultNull:
- fieldName: Amount
type: "System.Decimal"
defaultNull: 0
- fieldName: InvoiceBillQuantity
type: "System.Decimal"
defaultNull: 0
- fieldName: PO_OrderNumber
type: "System.String"
defaultNull:
- fieldName: Bol
type: "System.String"
defaultNull:
- fieldName: Carrier
type: "System.String"
defaultNull:
- fieldName: CarrierReferenceNumber
type: "System.String"
defaultNull:
- fieldName: PODNumberOfPackages
type: "System.Decimal"
defaultNull: 0
- fieldName: Document_provider
type: "System.String"
defaultNull:
- fieldName: Carrier_sign
type: "System.Boolean"
defaultNull: false
- fieldName: Customer_sign
type: "System.Boolean"
defaultNull: false
- fieldName: CustomerName
type: "System.String"
defaultNull:
- fieldName: SubjectToCount
type: "System.Boolean"
defaultNull: false
# --------------------------
# POD
# --------------------------
- name: "POD"
fields:
- fieldName: document_provider
type: "System.String"
defaultNull:
- fieldName: customer_sign
type: "System.Boolean"
defaultNull: false
- fieldName: customer_sign_text
type: "System.String"
defaultNull:
- fieldName: carrier_sign
type: "System.Boolean"
defaultNull: false
- fieldName: carrier_sign_text
type: "System.String"
defaultNull:
- fieldName: subject_to_count
type: "System.Boolean"
defaultNull: false
- fieldName: freight_charge_terms
type: "System.String"
defaultNull:
- fieldName: total_packages_quantity
type: "System.Decimal"
defaultNull: 0
- fieldName: total_lbs_quantity
type: "System.Decimal"
defaultNull: 0
- fieldName: Bol
type: "System.String"
defaultNull:
- fieldName: TotalShortage
type: "System.Decimal"
defaultNull: 0
- fieldName: TotalDamage
type: "System.Decimal"
defaultNull: 0
- fieldName: TotalOverage
type: "System.Decimal"
defaultNull: 0
# --------------------------
# PURCHASE ORDER
# --------------------------
- name: "PurchaseOrder"
fields:
- fieldName: order_number
type: "System.String"
defaultNull:
- fieldName: TotalLbsQty
type: "System.Decimal"
defaultNull: 0
- fieldName: TotalPackageQty
type: "System.Decimal"
defaultNull: 0
# --------------------------
# LINES
# --------------------------
- name: "Lines"
fields:
- fieldName: InvoiceId
type: "System.String"
defaultNull:
- fieldName: InvoiceNumber
type: "System.String"
defaultNull:
- fieldName: SKU
type: "System.String"
defaultNull:
- fieldName: ProductItemId
type: "System.String"
defaultNull:
- fieldName: ItemName
type: "System.String"
defaultNull:
- fieldName: CustomerSKU
type: "System.String"
defaultNull:
- fieldName: BackupPricePerQty
type: "System.Decimal"
defaultNull: 0
- fieldName: BilledQtyBackup
type: "System.Decimal"
defaultNull: 0
- fieldName: DeductAmt
type: "System.Decimal"
defaultNull: 0
- fieldName: DeductedQty
type: "System.Decimal"
defaultNull: 0
- fieldName: BilledQtyInvoice
type: "System.Decimal"
defaultNull: 0
- fieldName: GrossPrice
type: "System.Decimal"
defaultNull: 0
- fieldName: InvoiceGrossPricePerQty
type: "System.Decimal"
defaultNull: 0
- fieldName: InvoiceNetPricePerQty
type: "System.Decimal"
defaultNull: 0
- fieldName: NetPrice
type: "System.Decimal"
defaultNull: 0
- fieldName: InvoiceItemDescription
type: "System.String"
defaultNull:
- fieldName: InvoiceQtyEach
type: "System.Decimal"
defaultNull: 0
- fieldName: Shortage
type: "System.Decimal"
defaultNull: 0
- fieldName: Damaged
type: "System.Decimal"
defaultNull: 0
- fieldName: Overage
type: "System.Decimal"
defaultNull: 0
- fieldName: PackListQuantity
type: "System.Decimal"
defaultNull: 0
| Parameter | Description |
|---|---|
| name | The name of the type of data, header, line-item or POD. |
| fields | The fields to be considered for validation. |
document-validation.yaml
kind: ruleSet
metadata:
name: deduction/v1/ruleset/document-validation
spec:
######################################################################################################
# !!!!!!! RULE EXECUTION PRIORITY !!!!!!
# Validation rules are evaluated in sequence, from top to bottom.
# All matching rules will run (not just the first one).
# However, rules defined earlier take precedence when setting or overriding values.
# Therefore, place higher-priority or more specific rules at the TOP of each node section.
# Additionally Any then section must include the line --productitemId: ':it.Line["ProductItemId"]'--
######################################################################################################
nodes:
##################################################################### Clorox #############################################
- if: '1 == 1' #'it.Header["CustomerName"] == "Clorox"'
nodes:
##################################################################### HEADER #############################################
- if: 'it.Header["InvoiceBillQuantity"]!=0 and it.Header["InvoiceBillQuantity"] == it.POD["total_packages_quantity"]'
then:
validationStatus: "Invalid"
invalidReason: "POD # packages match in invoice"
productitemId: ':it.Line["ProductItemId"]'
invalidQuantity: ':it.Line["DeductedQty"]'
invalidAmount: ':it.Line["DeductAmt"]'
##################################################################### INVALID #############################################
# 1. Invalid: SKU is not invoiced
- if: 'it.Line["BilledQtyInvoice"] == 0'
then:
validationStatus: "Invalid"
invalidReason: "SKU is not invoiced"
productitemId: ':it.Line["ProductItemId"]'
invalidQuantity: ':it.Line["DeductedQty"]'
invalidAmount: ':it.Line["DeductAmt"]'
# 2. Invalid: Customer deducted at higher price
- if: 'it.Line["InvoiceNetPricePerQty"] != 0 and ToDecimal(it.Line["BackupPricePerQty"]) > ToDecimal(it.Line["InvoiceNetPricePerQty"])'
then:
validationStatus: "Invalid"
invalidReason: "Customer deducted at higher price"
productitemId: ':it.Line["ProductItemId"]'
invalidQuantity: ':it.Line["DeductedQty"]'
invalidAmount: ':it.Line["DeductAmt"]'
# 3. Invalid: POD does not support shortages
- if: 'it.Line["Shortage"] == 0'
then:
validationStatus: "Invalid"
invalidReason: "POD does not support shortages"
productitemId: ':it.Line["ProductItemId"]'
invalidQuantity: ':it.Line["DeductedQty"]'
invalidAmount: ':it.Line["DeductAmt"]'
##################################################################### PARTIAL #############################################
- if: 'it.Line["BilledQtyInvoice"] != 0 and
it.Line["BackupPricePerQty"] == it.Line["InvoiceNetPricePerQty"] and
it.Line["Shortage"] > 0 and
ToDecimal(it.Line["Shortage"]) < ToDecimal(it.Line["DeductedQty"])'
then:
validationStatus: "Partial Valid"
validQuantity: ':Math.Min(ToDecimal(it.Line["Shortage"]), ToDecimal(it.Line["DeductedQty"]))'
validAmount: ':Math.Min(ToDecimal(it.Line["Shortage"]), ToDecimal(it.Line["DeductedQty"])) * ToDecimal(it.Line["BackupPricePerQty"])'
invalidQuantity: ':ToDecimal(it.Line["DeductedQty"]) - Math.Min(ToDecimal(it.Line["Shortage"]), ToDecimal(it.Line["DeductedQty"]))'
invalidAmount: ':(ToDecimal(it.Line["DeductedQty"]) - Math.Min(ToDecimal(it.Line["Shortage"]), ToDecimal(it.Line["DeductedQty"]))) * ToDecimal(it.Line["BackupPricePerQty"])'
invalidReason: "Partial Valid"
productitemId: ':it.Line["ProductItemId"]'
##################################################################### VALID #############################################
- if: 'it.Line["BilledQtyInvoice"] != 0 and
it.Line["BackupPricePerQty"] == it.Line["InvoiceNetPricePerQty"] and
it.Line["Shortage"] == it.Line["DeductedQty"]'
then:
validationStatus: "Valid"
validQuantity: ':it.Line["DeductedQty"]'
validAmount: ':it.Line["DeductAmt"]'
invalidQuantity: 0
invalidAmount: 0
invalidReason: ""
productitemId: ':it.Line["ProductItemId"]'
##################################################################### DEFAULT NO HIT #############################################
- if: 'true'
then:
validationStatus: "DEFAULT NO HIT"
validQuantity: 0
validAmount: 0
invalidQuantity: 0
invalidAmount: 0
invalidReason: "DEFAULT NO HIT"
productitemId: ':it.Line["ProductItemId"]'
##################################################################### Amazon #############################################
- if: 'it.Header["CustomerName"] == "Amazon"'
nodes:
- if: '1 == 1'
then:
validationStatus: "Amazon"
productitemId: ':it.Line["ProductItemId"]'
| Parameter | Description |
|---|---|
| if then | The condition based on which the rules will be applied. |
| ValidationStatus | The validation status of the case based on rules. |
| ValidQuantity | The deduction quantity in case of valid deduction. |
| ValidAmount | The deduction amount in case of valid deduction. |
| InvalidQuantity | The deduction quantity in case of invalid deduction. |
| InvalidAmount | The deduction amount in case of invalid deduction. |
| InvalidReason | The deduction reason in case of invalid deduction. |
| ProductItemId | The unique Id of the product for which deduction is processed. |
For example, in the above template:
- if: 'it.Line["BilledQtyInvoice"] != 0 and
it.Line["BackupPricePerQty"] == it.Line["InvoiceNetPricePerQty"] and
it.Line["Shortage"] == it.Line["DeductedQty"]'
then:
validationStatus: "Valid"
validQuantity: ':it.Line["DeductedQty"]'
validAmount: ':it.Line["DeductAmt"]'
invalidQuantity: 0
invalidAmount: 0
invalidReason: ""
productitemId: ':it.Line["ProductItemId"]'
If the Billed quantity in invoice is not 0 and the price per quantity in the backup file is equal to the net price per quantity in the invoice and the shortage is equal to the deducted quantity then the deduction is considered valid and the case validation status is set to Valid in the portal.