-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into feat.hs-batching
- Loading branch information
Showing
60 changed files
with
45,435 additions
and
40,977 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
const { getMappingConfig } = require('../../../../v0/util'); | ||
|
||
const ConfigCategories = { | ||
TRACK: { | ||
type: 'track', | ||
name: 'propertiesMapping', | ||
}, | ||
}; | ||
const mappingConfig = getMappingConfig(ConfigCategories, __dirname); | ||
// Following contains the keys at item level mapping where key can be considered as destkey and value can be considered as sourcekey | ||
const productProperties = { | ||
skulist: 'sku', | ||
qlist: 'quantity', | ||
namelist: 'name', | ||
brandlist: 'brand', | ||
couponlist: 'coupon', | ||
catidlist: 'categoryId', | ||
catlist: 'category', | ||
disamtlist: 'discountAmount', | ||
distypelist: 'discountType', | ||
isclearancelist: 'isClearance', | ||
ismarketplacelist: 'isMarketPlace', | ||
issalelist: 'isSale', | ||
itmstatuslist: 'itmStatus', | ||
marginlist: 'margin', | ||
markdownlist: 'markdown', | ||
shipidlist: 'shipId', | ||
shipbylist: 'shipBy', | ||
taxexemptlist: 'taxExempt', | ||
sequencelist: 'sequence', | ||
}; | ||
// list of all properties that are required | ||
const requiredProductProperties = ['skulist', 'qlist', 'namelist']; | ||
module.exports = { ConfigCategories, mappingConfig, productProperties, requiredProductProperties }; |
101 changes: 101 additions & 0 deletions
101
src/cdk/v2/destinations/rakuten/data/propertiesMapping.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
[ | ||
{ | ||
"sourceKeys": "properties.orderId", | ||
"required": true, | ||
"destKey": "ord" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.tr", "properties.ranSiteID"], | ||
"required": true, | ||
"destKey": "tr" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.land", "properties.landTime"], | ||
"required": true, | ||
"destKey": "land" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.date", "properties.orderCompletedTime"], | ||
"destKey": "date" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.altord", "properties.alterOrderId"], | ||
"destKey": "altord" | ||
}, | ||
{ | ||
"sourceKeys": "properties.currency", | ||
"destKey": "cur" | ||
}, | ||
{ | ||
"sourceKeys": "properties.creditCardType", | ||
"destKey": "cc" | ||
}, | ||
{ | ||
"sourceKeys": "properties.commReason", | ||
"destKey": "commreason" | ||
}, | ||
{ | ||
"sourceKeys": "properties.isComm", | ||
"destKey": "iscomm" | ||
}, | ||
{ | ||
"sourceKeys": "properties.consumed", | ||
"destKey": "consumed" | ||
}, | ||
{ | ||
"sourceKeys": "properties.coupon", | ||
"destKey": "coupon" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.custId", "properties.customerId", "properties.userId"], | ||
"destKey": "custid" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.custScore", "properties.customerScore"], | ||
"destKey": "custscore" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.custStatus", "properties.customerStatus"], | ||
"destKey": "custstatus" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.dId", "properties.advertisingId"], | ||
"destKey": "did" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.disamt", "properties.discountAmout"], | ||
"destKey": "disamt" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.ordStatus", "properties.orderStatus"], | ||
"destKey": "ordstatus" | ||
}, | ||
{ | ||
"sourceKeys": "properties.segment", | ||
"destKey": "segment" | ||
}, | ||
{ | ||
"sourceKeys": "properties.shipcountry", | ||
"destKey": "shipcountry" | ||
}, | ||
{ | ||
"sourceKeys": "properties.shipped", | ||
"destKey": "shipped" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.sitename", "properties.url", "context.page.url"], | ||
"destKey": "sitename" | ||
}, | ||
{ | ||
"sourceKeys": "properties.storeId", | ||
"destKey": "storeid" | ||
}, | ||
{ | ||
"sourceKeys": ["properties.storecat", "properties.storeCategory"], | ||
"destKey": "storecat" | ||
}, | ||
{ | ||
"sourceKeys": "properties.currency", | ||
"destKey": "cur" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
bindings: | ||
- name: EventType | ||
path: ../../../../constants | ||
- path: ../../bindings/jsontemplate | ||
- name: defaultRequestConfig | ||
path: ../../../../v0/util | ||
- name: removeUndefinedAndNullValues | ||
path: ../../../../v0/util | ||
- path: ./utils | ||
|
||
steps: | ||
- name: messageType | ||
template: | | ||
.message.type.toLowerCase(); | ||
- name: validateInput | ||
template: | | ||
let messageType = $.outputs.messageType; | ||
$.assert(messageType, "message Type is not present. Aborting"); | ||
$.assert(messageType in {{$.EventType.([.TRACK])}}, "message type " + messageType + " is not supported"); | ||
$.assertConfig(.destination.Config.mid, "Merchant ID is not present. Aborting"); | ||
- name: prepareTrackPayload | ||
condition: $.outputs.messageType === {{$.EventType.TRACK}} | ||
template: | | ||
const properties = $.constructProperties(.message); | ||
const lineItems = $.constructLineItems(.message.properties) | ||
$.context.payload = {...properties,...lineItems,xml:1, mid:.destination.Config.mid} | ||
$.context.payload = $.removeUndefinedAndNullValues($.context.payload); | ||
- name: buildResponse | ||
template: | | ||
const response = $.defaultRequestConfig(); | ||
response.params = $.context.payload; | ||
response.method = "GET"; | ||
response.endpoint = "https://track.linksynergy.com/ep"; | ||
response.headers = { | ||
"accept": "application/json", | ||
"content-type": "application/json" | ||
}; | ||
response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
const { InstrumentationError } = require('@rudderstack/integrations-lib'); | ||
const { isDefinedAndNotNull } = require('rudder-transformer-cdk/build/utils'); | ||
const { | ||
mappingConfig, | ||
ConfigCategories, | ||
productProperties, | ||
requiredProductProperties, | ||
} = require('./config'); | ||
const { constructPayload } = require('../../../../v0/util'); | ||
|
||
/** | ||
* This fucntion constructs payloads based upon mappingConfig for Track call type | ||
* @param {*} message | ||
* @returns | ||
*/ | ||
const constructProperties = (message) => { | ||
const payload = constructPayload(message, mappingConfig[ConfigCategories.TRACK.name]); | ||
return payload; | ||
}; | ||
|
||
/** | ||
* This fucntion build the item level list | ||
* @param {*} properties | ||
* @returns | ||
*/ | ||
const constructLineItems = (properties) => { | ||
// Validate the existence and non-emptiness of the 'products' array in 'properties' | ||
if (!Array.isArray(properties?.products) || properties.products.length === 0) { | ||
throw new InstrumentationError('Either properties.product is not an array or is empty'); | ||
} | ||
|
||
const { products } = properties; | ||
const productList = {}; | ||
|
||
// Iterate over product properties to construct the payload | ||
Object.keys(productProperties).forEach((property) => { | ||
const propertyKey = productProperties[property]; | ||
|
||
// Extract values for the current property from the 'products' array | ||
const values = products.map((product) => | ||
isDefinedAndNotNull(product?.[propertyKey]) ? product[propertyKey] : '', | ||
); | ||
|
||
// Validate if a required property is missing | ||
if (requiredProductProperties.includes(property) && values.includes('')) { | ||
throw new InstrumentationError(`${propertyKey} is a required field. Aborting`); | ||
} | ||
|
||
// Include property in the payload if values are non-empty | ||
if (values.some((element) => element !== '')) { | ||
productList[property] = values.join('|'); | ||
} | ||
}); | ||
|
||
// Map 'amountList' by evaluating 'amount' or deriving it from 'price' and 'quantity' | ||
const amountList = products.map((product) => { | ||
if (!product?.amount && !product?.price) { | ||
throw new InstrumentationError('Either amount or price is required for every product'); | ||
} | ||
|
||
if (product.price) { | ||
return product.quantity * product.price * 100; | ||
} | ||
return product.amount * 100; | ||
}); | ||
productList.amtlist = amountList.join('|'); | ||
return productList; | ||
}; | ||
|
||
module.exports = { constructProperties, constructLineItems }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
const { constructLineItems } = require('./utils'); | ||
describe('constructLineItems', () => { | ||
it('should return a non-empty object when given a valid properties object with at least one product', () => { | ||
const properties = { | ||
products: [ | ||
{ | ||
name: 'Product 1', | ||
sku: 'sku_1', | ||
price: 10, | ||
quantity: 2, | ||
amount: 20, | ||
}, | ||
], | ||
}; | ||
const result = constructLineItems(properties); | ||
const expectedObj = { | ||
namelist: 'Product 1', | ||
skulist: 'sku_1', | ||
qlist: '2', | ||
amtlist: '2000', | ||
}; | ||
expect(result).toEqual(expectedObj); | ||
}); | ||
|
||
it('should include all mapped properties in the returned object when present in at least one product', () => { | ||
const properties = { | ||
products: [ | ||
{ | ||
name: 'Product 1', | ||
category: 'Category 1', | ||
sku: 'sku_1', | ||
brand: 'Brand 1', | ||
price: 10, | ||
quantity: 2, | ||
amount: 20, | ||
}, | ||
], | ||
}; | ||
|
||
const result = constructLineItems(properties); | ||
|
||
const expectedObj = { | ||
namelist: 'Product 1', | ||
catlist: 'Category 1', | ||
skulist: 'sku_1', | ||
brandlist: 'Brand 1', | ||
qlist: '2', | ||
amtlist: '2000', | ||
}; | ||
expect(result).toEqual(expectedObj); | ||
}); | ||
|
||
it('should include amtlist property in the returned object with calculated values', () => { | ||
const properties = { | ||
products: [ | ||
{ | ||
name: 'Product 1', | ||
sku: 'sku_1', | ||
price: 10, | ||
quantity: 2, | ||
}, | ||
{ | ||
name: 'Product 2', | ||
sku: 'sku_2', | ||
price: 5, | ||
quantity: 3, | ||
}, | ||
], | ||
}; | ||
|
||
const result = constructLineItems(properties); | ||
|
||
expect(result).toHaveProperty('amtlist'); | ||
expect(result.amtlist).toBe('2000|1500'); | ||
}); | ||
|
||
it('should throw an InstrumentationError when properties object is missing or has an empty products array', () => { | ||
const properties = {}; | ||
|
||
expect(() => constructLineItems(properties)).toThrow( | ||
'Either properties.product is not an array or is empty', | ||
); | ||
|
||
properties.products = []; | ||
|
||
expect(() => constructLineItems(properties)).toThrow( | ||
'Either properties.product is not an array or is empty', | ||
); | ||
}); | ||
it('should throw an InstrumentationError when a product is missing quantity property', () => { | ||
const properties = { | ||
products: [ | ||
{ | ||
name: 'Product 1', | ||
sku: 'sku_1', | ||
amount: '1234', | ||
}, | ||
], | ||
}; | ||
expect(() => constructLineItems(properties)).toThrow('quantity is a required field. Aborting'); | ||
}); | ||
it('should throw an InstrumentationError when a product is missing both amount and price properties', () => { | ||
const properties = { | ||
products: [ | ||
{ | ||
name: 'Product 1', | ||
sku: 'sku_1', | ||
quantity: 2, | ||
}, | ||
], | ||
}; | ||
|
||
expect(() => constructLineItems(properties)).toThrow( | ||
'Either amount or price is required for every product', | ||
); | ||
}); | ||
}); |
Oops, something went wrong.