diff --git a/api/script/index.js b/api/script/index.js index 1e003ef1..28f2e7e5 100644 --- a/api/script/index.js +++ b/api/script/index.js @@ -83,12 +83,14 @@ function conditionSend({ .concat(source?.region?.map(itemNameId => ({itemNameId, factor: 'ss', type: 'region'}))) .concat(source?.city?.map(itemNameId => ({itemNameId, factor: 'ss', type: 'city'}))) .concat(source?.cardProduct?.map(itemNameId => ({itemNameId, factor: 'sc', type: 'cardProduct'}))) + .concat(source?.cardType?.map(itemNameId => ({itemNameId, factor: 'sc', type: 'cardType'}))) .concat(source?.accountProduct?.map(itemNameId => ({itemNameId, factor: 'sc', type: 'accountProduct'}))) .concat(source?.accountFeePolicy?.map(itemNameId => ({itemNameId, factor: 'sp', type: 'feePolicy'}))) .concat(destination?.country?.map(itemNameId => ({itemNameId, factor: 'ds', type: 'country'}))) .concat(destination?.region?.map(itemNameId => ({itemNameId, factor: 'ds', type: 'region'}))) .concat(destination?.city?.map(itemNameId => ({itemNameId, factor: 'ds', type: 'city'}))) .concat(destination?.cardProduct?.map(itemNameId => ({itemNameId, factor: 'dc', type: 'cardProduct'}))) + .concat(destination?.cardType?.map(itemNameId => ({itemNameId, factor: 'dc', type: 'cardType'}))) .concat(destination?.accountProduct?.map(itemNameId => ({itemNameId, factor: 'dc', type: 'accountProduct'}))) .concat(destination?.accountFeePolicy?.map(itemNameId => ({itemNameId, factor: 'dp', type: 'feePolicy'}))) .filter(Boolean) @@ -151,6 +153,7 @@ function conditionReceive({ kyc: getProp(conditionProperty, 'sk', 'source.kyc'), customerType: getProp(conditionProperty, 'st', 'source.customerType'), cardProduct: get(conditionItem, 'sc', 'cardProduct', 'itemNameId'), + cardType: get(conditionItem, 'sc', 'cardType', 'itemNameId'), accountProduct: get(conditionItem, 'sc', 'accountProduct', 'itemNameId'), country: get(conditionItem, 'ss', 'country', 'itemNameId'), region: get(conditionItem, 'ss', 'region', 'itemNameId'), @@ -163,6 +166,7 @@ function conditionReceive({ kyc: getProp(conditionProperty, 'dk', 'destination.kyc'), customerType: getProp(conditionProperty, 'dt', 'destination.customerType'), cardProduct: get(conditionItem, 'dc', 'cardProduct', 'itemNameId'), + cardType: get(conditionItem, 'dc', 'cardType', 'itemNameId'), accountProduct: get(conditionItem, 'dc', 'accountProduct', 'itemNameId'), country: get(conditionItem, 'ds', 'country', 'itemNameId'), region: get(conditionItem, 'ds', 'region', 'itemNameId'), diff --git a/api/sql/schema/750-rule.dropdown.list.sql b/api/sql/schema/750-rule.dropdown.list.sql index ff153946..a7675ba6 100644 --- a/api/sql/schema/750-rule.dropdown.list.sql +++ b/api/sql/schema/750-rule.dropdown.list.sql @@ -45,6 +45,11 @@ SELECT [value], [label], [parent] FROM core.item(@languageId, 'cardProduct') ORDER BY ISNULL(itemOrder, 99999), 2 +SELECT 'rule.cardType' AS resultSetName +SELECT [value], [label], [parent] +FROM core.item(@languageId, 'cardType') +ORDER BY ISNULL(itemOrder, 99999), 2 + SELECT 'rule.channel' AS resultSetName SELECT [value], [label], [parent] FROM core.item(@languageId, 'channel') diff --git a/history/config/rule.js b/history/config/rule.js index 16797ed5..fd373966 100644 --- a/history/config/rule.js +++ b/history/config/rule.js @@ -51,6 +51,7 @@ module.exports = { {key: 'source,cities', title: 'City', transform: conditionItemTransform}, {key: 'source,organization', title: 'Organization'}, {key: 'source,cardProducts', title: 'Product', transform: conditionItemTransform}, + {key: 'source,cardTypes', title: 'Type', transform: conditionItemTransform}, {key: 'source,accountProduct', title: 'Account Product'}, {key: 'source,properties', title: 'Properties', transform: propertyTransform} ], diff --git a/model/condition.js b/model/condition.js index d8b2ffe5..127c0abd 100644 --- a/model/condition.js +++ b/model/condition.js @@ -393,6 +393,9 @@ module.exports = ({joi}) => ({ cardProduct: { widget: {type: 'multiSelect', dropdown: 'rule.cardProduct'} }, + cardType: { + widget: {type: 'multiSelect', dropdown: 'rule.cardType'} + }, country: { widget: {type: 'multiSelect', dropdown: 'rule.country'} }, @@ -430,6 +433,9 @@ module.exports = ({joi}) => ({ cardProduct: { widget: {type: 'multiSelect', dropdown: 'rule.cardProduct'} }, + cardType: { + widget: {type: 'multiSelect', dropdown: 'rule.cardType'} + }, country: { widget: {type: 'multiSelect', dropdown: 'rule.country'} }, @@ -536,6 +542,7 @@ module.exports = ({joi}) => ({ 'source.customerType', 'source.kyc', 'source.cardProduct', + 'source.cardType', 'source.accountProduct', 'condition.sourceAccountId' ] @@ -552,6 +559,7 @@ module.exports = ({joi}) => ({ 'destination.customerType', 'destination.kyc', 'destination.cardProduct', + 'destination.cardType', 'destination.accountProduct', 'condition.destinationAccountId' ] diff --git a/ui/common.js b/ui/common.js index 5e99ae63..f2a76529 100644 --- a/ui/common.js +++ b/ui/common.js @@ -20,6 +20,7 @@ const propMap = { city: 'cities', operation: 'operations', cardProduct: 'cardProducts', + cardType: 'cardTypes', feePolicy: 'accountFeePolicies', so: 'source', do: 'destination', @@ -60,6 +61,8 @@ function prepareRuleModel(dbresult) { countries: [], cities: [], regions: [], + cardProducts: [], + cardTypes: [], accountFeePolicies: [] }, source: { @@ -68,6 +71,7 @@ function prepareRuleModel(dbresult) { cities: [], regions: [], cardProducts: [], + cardTypes: [], accountFeePolicies: [] }, split: { @@ -94,7 +98,7 @@ function prepareRuleModel(dbresult) { }); // condition item (dbresult.conditionItem || []).forEach((item) => { - if (['operation', 'country', 'city', 'region', 'cardProduct', 'feePolicy'].indexOf(item.type) > -1) { + if (['operation', 'country', 'city', 'region', 'cardProduct', 'cardType', 'feePolicy'].indexOf(item.type) > -1) { const obj = rule[propMap[item.factor]] && rule[propMap[item.factor]][propMap[item.type]]; obj && obj.push({ key: item.itemNameId, diff --git a/ui/react/configuration/reducers.js b/ui/react/configuration/reducers.js index 3796f837..673d639c 100644 --- a/ui/react/configuration/reducers.js +++ b/ui/react/configuration/reducers.js @@ -13,6 +13,7 @@ const defaultUiState = { 'operation', 'supervisor', 'cardProduct', + 'cardType', 'accountProduct', 'feePolicy', 'account' @@ -133,6 +134,10 @@ const defaultUiState = { visible: true, title: 'Product' }, + cardType: { + visible: true, + title: 'Type' + }, accountProduct: { visible: true, title: 'Account Product' @@ -163,6 +168,14 @@ const defaultUiState = { visible: true, title: 'Organization' }, + cardProduct: { + visible: true, + title: 'Product' + }, + cardType: { + visible: true, + title: 'Type' + }, accountProduct: { visible: true, title: 'Account Product' diff --git a/ui/react/pages/RuleProfile/Tabs/Destination/index.js b/ui/react/pages/RuleProfile/Tabs/Destination/index.js index 71553210..aba03a0a 100644 --- a/ui/react/pages/RuleProfile/Tabs/Destination/index.js +++ b/ui/react/pages/RuleProfile/Tabs/Destination/index.js @@ -24,7 +24,9 @@ const propTypes = { accountProducts: PropTypes.array, fieldValues: PropTypes.object, errors: PropTypes.object, // immutable - destinationConfig: PropTypes.object.isRequired + destinationConfig: PropTypes.object.isRequired, + cardProducts: PropTypes.object, + cardTypes: PropTypes.object }; const defaultProps = { @@ -52,6 +54,8 @@ class DestinationTab extends Component { accountProducts, fieldValues, feePolicies, + cardTypes, + cardProducts, destinationConfig: { fields } } = this.props; const changeInput = (field, value) => { @@ -109,6 +113,32 @@ class DestinationTab extends Component { label={fields.organization.title || 'Organization'} /> } + {fields.cardProduct.visible &&
+ { changeInput(field); }} + label={fields.cardProduct.title || 'Product'} + /> +
} + {fields.cardType.visible &&
+ { changeInput(field); }} + label={fields.cardType.title || 'Type'} + /> +
} {fields.accountProduct.visible &&
{ cities: state.ruleProfileReducer.getIn(['nomenclatures', 'city']).toJS(), feePolicies: state.ruleProfileReducer.getIn(['nomenclatures', 'feePolicy']).toJS(), organizations: state.ruleProfileReducer.getIn(['nomenclatures', 'organization']).toJS(), + cardProducts: state.ruleProfileReducer.getIn(['nomenclatures', 'cardProduct']).toJS(), + cardTypes: state.ruleProfileReducer.getIn(['nomenclatures', 'cardType']).toJS(), fieldValues: state.ruleProfileReducer.getIn([mode, id, destinationProp], fromJS({})).toJS(), accountProducts: state.ruleProfileReducer.getIn(['nomenclatures', 'accountProduct']).toJS(), errors: state.ruleProfileReducer.getIn([mode, id, 'errors', destinationProp]) || fromJS({}), diff --git a/ui/react/pages/RuleProfile/Tabs/Source/index.js b/ui/react/pages/RuleProfile/Tabs/Source/index.js index a88a1a9b..09f77d6d 100644 --- a/ui/react/pages/RuleProfile/Tabs/Source/index.js +++ b/ui/react/pages/RuleProfile/Tabs/Source/index.js @@ -22,6 +22,7 @@ const propTypes = { feePolicies: PropTypes.array, organizations: PropTypes.array, cardProducts: PropTypes.array, + cardTypes: PropTypes.array, accountProducts: PropTypes.array, fieldValues: PropTypes.object, errors: PropTypes.object, // immutable @@ -51,6 +52,7 @@ class SourceTab extends Component { cities, organizations, cardProducts, + cardTypes, accountProducts, fieldValues, feePolicies, @@ -124,6 +126,19 @@ class SourceTab extends Component { label={fields.cardProduct.title || 'Product'} />
} + {fields.cardType.visible &&
+ { changeInput(field); }} + label={fields.cardType.title || 'Type'} + /> +
} {fields.accountProduct.visible &&
{ feePolicies: state.ruleProfileReducer.getIn(['nomenclatures', 'feePolicy']).toJS(), organizations: state.ruleProfileReducer.getIn(['nomenclatures', 'organization']).toJS(), cardProducts: state.ruleProfileReducer.getIn(['nomenclatures', 'cardProduct']).toJS(), + cardTypes: state.ruleProfileReducer.getIn(['nomenclatures', 'cardType']).toJS(), accountProducts: state.ruleProfileReducer.getIn(['nomenclatures', 'accountProduct']).toJS(), fieldValues: state.ruleProfileReducer.getIn([mode, id, destinationProp], fromJS({})).toJS(), errors: state.ruleProfileReducer.getIn([mode, id, 'errors', destinationProp]) || fromJS({}), diff --git a/ui/react/pages/RuleProfile/Tabs/defaultState.js b/ui/react/pages/RuleProfile/Tabs/defaultState.js index c7417e4c..d50f7271 100644 --- a/ui/react/pages/RuleProfile/Tabs/defaultState.js +++ b/ui/react/pages/RuleProfile/Tabs/defaultState.js @@ -77,6 +77,8 @@ export const defaultTabState = { cities: [], organization: '', role: null, + cardProducts: [], + cardTypes: [], properties: [], accountFeePolicies: [], accountProduct: null @@ -95,6 +97,7 @@ export const defaultTabState = { organization: '', role: null, cardProducts: [], + cardTypes: [], accountFeePolicies: [], accountProduct: null, properties: [] diff --git a/ui/react/pages/RuleProfile/Tabs/style.css b/ui/react/pages/RuleProfile/Tabs/style.css index 9ea7781e..4a666a38 100644 --- a/ui/react/pages/RuleProfile/Tabs/style.css +++ b/ui/react/pages/RuleProfile/Tabs/style.css @@ -115,7 +115,7 @@ width: 30%; } .outerWrap .labelWrap { - width: 25%; + width: 30%; display: table-cell; font-weight: bold; vertical-align: middle; diff --git a/ui/react/pages/RuleProfile/helpers.js b/ui/react/pages/RuleProfile/helpers.js index b4365cd4..246eb26e 100644 --- a/ui/react/pages/RuleProfile/helpers.js +++ b/ui/react/pages/RuleProfile/helpers.js @@ -55,7 +55,7 @@ const conditionPropertyFactor = { export const formatNomenclatures = (items) => { const formattedPayload = {}; // default object properties - ['accountProduct', 'cardProduct', 'channel', 'city', 'country', 'operation', 'region', 'currency', 'organization'] + ['accountProduct', 'cardProduct', 'cardType', 'channel', 'city', 'country', 'operation', 'region', 'currency', 'organization'] .forEach((objName) => (formattedPayload[objName] = [])); items.map(item => { if (!formattedPayload[item.type]) { @@ -137,16 +137,20 @@ export const prepareRuleToSave = (rule) => { }); }); - const cardProducts = rule && rule.source && rule.source.cardProducts; - if (cardProducts && cardProducts.length) { - cardProducts.forEach(cp => { + const pushItems = (items, factor) => { + items.forEach(cp => { formattedRule.conditionItem.push({ itemNameId: cp.key, conditionId, - factor: factors.sourceCategory + factor: factors[factor] }); }); - } + }; + + rule?.source?.cardProducts?.length && pushItems(rule?.source?.cardProducts, 'sourceCategory'); + rule?.source?.cardTypes?.length && pushItems(rule?.source?.cardTypes, 'sourceCategory'); + rule?.destination?.cardProducts?.length && pushItems(rule?.destination?.cardProducts, 'destinationCategory'); + rule?.destination?.cardTypes?.length && pushItems(rule?.destination?.cardTypes, 'destinationCategory'); formattedRule.conditionProperty = []; @@ -182,7 +186,7 @@ export const prepareRuleToSave = (rule) => { }); }); - formattedRule.split = {data: {rows: []}}; + formattedRule.split = { data: { rows: [] } }; split.splits.forEach(split => { if (!split.name) return; const formattedSplit = {}; @@ -295,7 +299,7 @@ export const prepareRuleErrors = (rule, existErrors) => { // cumulative split.cumulatives.forEach(function(cumulative, cidx) { cumulative && !cumulative.currency && !isEmptyValuesOnly(cumulative) && - (errors = errors.setIn(['split', 'splits', idx, 'cumulatives', cidx, 'currency'], errorMessage.currencyRequired)); + (errors = errors.setIn(['split', 'splits', idx, 'cumulatives', cidx, 'currency'], errorMessage.currencyRequired)); // ranges cumulative && cumulative.ranges && cumulative.ranges.forEach(function(range, ridx) { diff --git a/ui/react/pages/RuleProfile/reducer.js b/ui/react/pages/RuleProfile/reducer.js index b2120b6f..9485b663 100644 --- a/ui/react/pages/RuleProfile/reducer.js +++ b/ui/react/pages/RuleProfile/reducer.js @@ -7,6 +7,7 @@ const defaultState = { nomenclatures: { accountProduct: [], cardProduct: [], + cardType: [], channel: [], city: [], country: [], diff --git a/validations/rule/rule.dropdown.list.js b/validations/rule/rule.dropdown.list.js index 90cc131b..e2852fb2 100644 --- a/validations/rule/rule.dropdown.list.js +++ b/validations/rule/rule.dropdown.list.js @@ -18,6 +18,7 @@ module.exports = ({ 'rule.city': dropdownItems, 'rule.accountProduct': dropdownItems, 'rule.cardProduct': dropdownItems, + 'rule.cardType': dropdownItems, 'rule.channel': dropdownItems, 'rule.role': dropdownItems, 'rule.kyc': dropdownItems,