Last active
August 12, 2021 07:25
-
-
Save lptai/f188d080ce88e60852fb582ea3f2740a to your computer and use it in GitHub Desktop.
generate-txn.js
This file contains hidden or 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
const TRANSACTIONS_PER_ISSUER = 100000; | |
const INSERT_BATCH_SIZE = 5000; | |
const LOG_PROGRESS_EVERY_PASSED_PERCENTAGE = 5; | |
const startTime = Date.now(); | |
printjson(ISSUERS) | |
printWithDateTime("### START creating TXN data for all Issuers ###"); | |
for (var i = 0; i < ISSUERS.length; i++) { | |
var issuer = ISSUERS[i]; | |
printWithDateTime("### START creating TXN data for issuer " + issuer.code + " ### ") | |
var trackedProgress = 0; | |
var flowApiTxnEntities = []; | |
var flowIngestionTxnEntities = []; | |
var flowEngagementActivity = [], flowEngagementProgress = [], flowSubEngagementProgress = []; | |
// process for each issuer | |
for (var j = 1; j <= TRANSACTIONS_PER_ISSUER; j++) { | |
/** | |
* FLOW API's Transaction data | |
*/ | |
const rawTxn = createFlowApiRawTransaction(issuer); | |
flowApiTxnEntities.push(rawTxn) | |
/** | |
* FLOW INGESTION's Transaction data | |
*/ | |
const ingestedTxn = createFlowIngestionTransaction(issuer, rawTxn); | |
flowIngestionTxnEntities.push(ingestedTxn); | |
/** | |
* ENGAGEMENT | |
*/ | |
const { activities, engagementProgress, subEngagementProgress } = generateActivity({ | |
idx: j, | |
txnPerIssuer: TRANSACTIONS_PER_ISSUER, | |
flowTxn: ingestedTxn, | |
issuer, | |
}); | |
activities && flowEngagementActivity.push(...activities); | |
engagementProgress && flowEngagementProgress.push(engagementProgress); | |
subEngagementProgress && flowSubEngagementProgress.push(subEngagementProgress); | |
if (j % INSERT_BATCH_SIZE === 0 || j === TRANSACTIONS_PER_ISSUER) { | |
// batch insert flow-apiRawTransaction entities | |
db = db.getSiblingDB("flow-api"); | |
db.RawTransaction.insertMany(flowApiTxnEntities, { ordered : false } ); | |
// reset the bulk insert | |
flowApiTxnEntities = []; | |
// batch insert flow-ingestion.Transaction entities | |
db = db.getSiblingDB("flow-ingestion"); | |
db.Transaction.insertMany(flowIngestionTxnEntities, { ordered : false } ); | |
flowIngestionTxnEntities = []; | |
// TODO: batch insert flow-engagement.Activity entities | |
db = db.getSiblingDB("flow-engagement"); | |
db.Activity.insertMany(flowEngagementActivity, { ordered : false } ); | |
db.EngagementProgress.insertMany(flowEngagementProgress, { ordered : false } ); | |
db.SubEngagementProgress.insertMany(flowSubEngagementProgress, { ordered : false } ); | |
flowEngagementActivity = []; | |
flowEngagementProgress = []; | |
flowSubEngagementProgress = []; | |
// just to log the progress every at least 5% | |
var currentProgress = (j / TRANSACTIONS_PER_ISSUER * 100).toFixed(2); | |
if (currentProgress - trackedProgress >= LOG_PROGRESS_EVERY_PASSED_PERCENTAGE) { | |
printWithDateTime("Issuer '" + issuer.code + "' Insert TXN progress: " + currentProgress + "% - Total " + j + "/" + TRANSACTIONS_PER_ISSUER + "records"); | |
trackedProgress = Math.floor(currentProgress / LOG_PROGRESS_EVERY_PASSED_PERCENTAGE) * LOG_PROGRESS_EVERY_PASSED_PERCENTAGE; | |
} | |
} | |
} | |
} | |
printWithDateTime("### END creating TXN data for all Issuers took " + (Date.now() - startTime) + "ms ###"); | |
/** | |
* TODO add sponsorCode, issuerId, merchantId, playbookId | |
*/ | |
function printWithDateTime(str) { | |
print("[" + new Date() + "]: " + str); | |
} | |
function generateActivity({ idx, txnPerIssuer, flowTxn, issuer }) { | |
const ACTIVITY_OUTCOME_PERCENTAGE = 20; | |
const ACTIVITY_ONLY_PERCENTAGE = 80; | |
const percentage = (idx / txnPerIssuer) * 100; | |
const activity = getActivity(flowTxn); | |
const activities = [activity]; | |
if (percentage < ACTIVITY_ONLY_PERCENTAGE) { | |
return { activities }; | |
} | |
const scratchRatio = ACTIVITY_ONLY_PERCENTAGE + (ACTIVITY_OUTCOME_PERCENTAGE * 1) / 3; | |
const scratchWinRatio = ACTIVITY_ONLY_PERCENTAGE + (ACTIVITY_OUTCOME_PERCENTAGE * 1) / 6; | |
const punchRatio = ACTIVITY_ONLY_PERCENTAGE + (ACTIVITY_OUTCOME_PERCENTAGE * 2) / 3; | |
const punchCompletedRatio = | |
ACTIVITY_ONLY_PERCENTAGE + ACTIVITY_OUTCOME_PERCENTAGE * (1 / 3 + 1 / 6); | |
const flowTreeCompletedRatio = | |
ACTIVITY_ONLY_PERCENTAGE + ACTIVITY_OUTCOME_PERCENTAGE * (2 / 3 + 1 / 6); | |
const issuerId = issuer.id; | |
const sponsorCode = issuer.code; | |
const engagementId = ObjectId().str, | |
playbookId = ObjectId().str, | |
ruleId = ObjectId().str; | |
const activityOutcomeId = ObjectId().str; | |
const merchantId = flowTxn.paymentStore.flowStore.merchantId; | |
if (percentage < scratchRatio) { | |
// generate scratch cards which are not completed | |
const activityOutcome = getScratchOutcome({ | |
activityOutcomeId, | |
playbookId, | |
sponsorCode, | |
}); | |
if (percentage < scratchWinRatio) { | |
const reward = getVoucherReward(); | |
const completedOutcome = getCompletedActivity({ | |
activityOutcomeId, | |
flowTxn, | |
reward, | |
engagement: getChanceBasedEngagement({ playbookId, sponsorCode, reward }), | |
}); | |
activityOutcome.status = 'COMPLETED'; | |
activityOutcome.data.lockedRewards.push(completedOutcome.widgetContainer.wonReward); | |
activityOutcome.data.wonReward = completedOutcome.widgetContainer.wonReward; | |
activities.push(completedOutcome); | |
} | |
activity.outcomes.push(activityOutcome); | |
activity.widgetContainer.widgets.push( | |
getEngagementWidget({ | |
name: 'Scratch Card', | |
type: 'ChanceBased', | |
}), | |
); | |
return { | |
activities, | |
}; | |
} else if (percentage < punchRatio) { | |
// generate punch card | |
const engagementProgressId = ObjectId().str; | |
const progress = getProgress({ | |
...flowTxn, | |
playbookId, | |
engagementId, | |
engagementProgressId, | |
subLevelIncrements: [], | |
status: 'IN_PROGRESS', | |
goalLevel: 5, // todo, get from engagement or playbook? | |
currentStage: 0, | |
rolloverBehavior: 'TRANSFER_TO_NEXT_ENGAGEMENT', // todo, randomize with DO_NOTHING | |
}); | |
const activityOutcome = getPunchOutcome({ issuerId, playbookId, sponsorCode, progress }); | |
activity.outcomes.push(activityOutcome); | |
/** | |
* with completed scenario | |
*/ | |
if (percentage < punchCompletedRatio) { | |
const reward = getCashBackReward(); | |
// todo, should take care of previousLevel? currentLevel? | |
progress.status = 'COMPLETED'; | |
activityOutcome.data.wonReward = reward; | |
activity.outcomes.push(getPunchRewardOutcome({ reward, sponsorCode, playbookId })); | |
} | |
activity.widgetContainer.widgets.push( | |
getEngagementWidget({ | |
name: 'Punch card', | |
type: 'Progressive', | |
progress: progress, | |
}), | |
); | |
return { | |
activities, | |
engagementProgress: progress, | |
}; | |
} else { | |
// otherwise, just generate flow tree | |
const engagementProgressId = ObjectId().str; | |
const subEngagementProgress = getSubEngagementProgress({ | |
engagementProgressId, | |
merchantId, | |
activityOutcomeId, | |
}); | |
const progress = getProgress({ | |
...flowTxn, | |
playbookId, | |
engagementId, | |
engagementProgressId, | |
rolloverBehavior: 'DO_NOTHING', | |
subLevelIncrements: [subEngagementProgress], | |
status: 'IN_PROGRESS', | |
goalLevel: 1000, // todo, get from engagement or playbook? | |
currentStage: 0, // todo, randomize | |
}); | |
const activityOutcome = getFlowTreeOutcome({ | |
ruleId, | |
activityOutcomeId, | |
playbookId, | |
sponsorCode, | |
progress, | |
}); | |
/** | |
* todo, with completed scenario | |
*/ | |
if (percentage < flowTreeCompletedRatio) { | |
// change progress to completed | |
progress.status = 'COMPLETED'; | |
progress.currentLevel = progress.goalLevel; | |
const reward = getFlowTreeReward(); | |
const completedActivity = getCompletedActivity({ | |
activityOutcomeId, | |
flowTxn, | |
reward, | |
engagement: getFlowTreeEngagement({ playbookId, sponsorCode, reward, ruleId, progress }), | |
}); | |
activityOutcome.status = 'COMPLETED'; | |
activityOutcome.data.lockedRewards.push(completedActivity.widgetContainer.wonReward); | |
activityOutcome.data.wonReward = completedActivity.widgetContainer.wonReward; | |
activities.push(completedActivity); | |
} | |
activity.outcomes.push(activityOutcome); | |
activity.widgetContainer.widgets.push( | |
getEngagementWidget({ | |
name: 'Flow tree', | |
type: 'MerchantBasedProgressive', | |
progress, | |
engagement: activityOutcome, | |
}), | |
); | |
return { | |
activities, | |
engagementProgress: progress, | |
subEngagementProgress, | |
}; | |
} | |
} | |
function getFlowTreeReward() { | |
return { | |
_id: ObjectId().str, | |
name: "Tree Reward for Notebank's Flow-tree", | |
type: 'Tree', | |
data: { | |
rewardCollected: { | |
title: 'Reward collected title', | |
description: 'Not yet configured.', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
headerLogo: 'arbor-day-foundation.svg', | |
rewardReady: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and Notebank donating to the <strong>Arbor Day Foundation</strong> to plant a tree.<br /><br />Real trees clear our air, clean our water, and beautify our lands for generations to come.', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Flow tree reward display name.', | |
displayValue: 'Not yet configured.', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
aboutUrl: 'https://www.arborday.org/', | |
headerTitle: 'Arbor Day Foundation', | |
}, | |
status: 'Active', | |
}; | |
} | |
function getVoucherReward() { | |
return { | |
_id: ObjectId().str, | |
name: '$5 off', | |
type: 'Coupon', | |
data: { | |
rewardCollected: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
termAndCondition: | |
'Use the voucher code at checkout when you shop on the Appliance Bay website/app. <a href="https://www.appliancebay.com/customer-privacy-rights.html">Terms and Conditions</a> apply.', | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Appliance Bay Voucher', | |
displayValue: '$5 off', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
promoCode: 'MM1CX8', | |
discountType: 'FIXED_AMOUNT', | |
value: '5', | |
usageType: 'SINGLE', | |
}, | |
status: 'Active', | |
assets: { | |
rewardReady: { | |
name: 'Appliance Bay Reward Ready', | |
code: 'reward_ready.png', | |
type: 'Image', | |
owner: 'Client', | |
}, | |
rewardCollected: { | |
name: 'Appliance Bay Reward Collected', | |
code: 'reward_collected.png', | |
type: 'Image', | |
owner: 'Client', | |
}, | |
}, | |
expiredInDays: 30, | |
expiredAt: new ISODate(), | |
}; | |
} | |
function getCashBackReward() { | |
return { | |
_id: ObjectId().str, | |
name: '$10 Cashback', | |
type: 'Coupon', | |
data: { | |
rewardCollected: { | |
title: 'Reward Collected', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
termAndCondition: | |
'The cash back will be credited to your Note bank credit card in 5-7 business days. Notebank website/app. <a href="https://www.sc.com/sg/terms-and-conditions/unlimited-cashback-credit-card-terms-and-conditions/">Terms and Conditions</a> apply.', | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Notebank Reward', | |
displayValue: '$10 Cashback', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
discountType: 'FIXED_AMOUNT', | |
value: '10', | |
usageType: 'SINGLE', | |
}, | |
status: 'Active', | |
_class: 'io.flownetworks.engagement.domain.reward.RewardEntity', | |
}; | |
} | |
function getProgress({ | |
engagementProgressId, | |
clientCustomerId, | |
clientId, | |
playbookId, | |
engagementId, | |
status, | |
subLevelIncrements, | |
goalLevel, | |
currentStage, | |
rolloverBehavior, | |
}) { | |
return { | |
_id: engagementProgressId, | |
clientCustomerId, | |
clientId, | |
playbookId, | |
engagementId, | |
previousLevelIncrement: 1, // todo, randomize | |
leftoverIncrement: 0, | |
transferredIncrement: 0, | |
rolloverBehavior, | |
goalLevel, | |
status, | |
currentLevel: 1, // todo, randomize | |
currentStage, | |
subLevelIncrements, | |
engagementExpiredAt: new ISODate(), | |
createdBy: 'system', | |
createdDate: new ISODate(), | |
lastModifiedBy: 'system', | |
lastModifiedDate: new ISODate(), | |
_class: 'io.flownetworks.engagement.domain.activity.progress.EngagementProgress', | |
}; | |
} | |
function getSubEngagementProgress({ engagementProgressId, merchantId, activityOutcomeId }) { | |
return { | |
_id: ObjectId().str, | |
engagementProgressId, | |
subEngagementProgressKey: merchantId, | |
levelIncrement: 0, // todo, randomize | |
pendingLevelIncrements: { [activityOutcomeId]: 1940 }, // todo, randomize | |
createdBy: 'system', | |
createdDate: new ISODate(), | |
lastModifiedBy: 'system', | |
lastModifiedDate: new ISODate(), | |
_class: 'io.flownetworks.engagement.domain.activity.progress.SubEngagementProgress', | |
}; | |
} | |
function getFlowTreeOutcome({ ruleId, activityOutcomeId, playbookId, sponsorCode, progress }) { | |
return { | |
_id: activityOutcomeId, | |
kind: 'ENGAGEMENT', | |
status: 'NEW', | |
data: { | |
_id: ObjectId().str, | |
name: 'Flow tree', | |
code: 'flow_tree', | |
type: 'MerchantBasedProgressive', | |
data: { | |
goalLevel: '2000', | |
guidingScreen: { | |
title: '', | |
description: | |
'<div>For every <strong>$${input.customData.mcgConversionRateAmount} spent on ${input.customData.eligibleMcgDescriptions}</strong> with your Braindance card, your ${input.engagement.data.treeName} will grow by <strong>${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if>.</strong></div><br /><div>Grow your ${input.engagement.data.treeName} to <strong>${input.engagement.data.goalLevel} <#if input.engagement.data.goalLevel?number gt 1>leaves<#else>leaf</#if></strong> and ${input.engagement.data.qualifyingSponsorName} will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
subEngagementProgressKeyPath: 'data.paymentStore.flowMerchant.id', | |
progressInProgressUnclaimed: { | |
title: | |
"Don't leaf me hanging, claim ${input.engagement.progress.pendingLevelIncrement} <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if> now!", | |
description: | |
'Earn ${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if> for every $${input.customData.mcgConversionRateAmount} spent on ${input.transaction.paymentStore.mcgDescription}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
inProgress: { | |
title: 'Congratulations', | |
description: | |
'${input.engagement.progress.pendingLevelIncrement} <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if> have grown from your tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressInProgressClaimed: { | |
title: | |
'Earn ${input.engagement.currentProgress.goalLevel - input.engagement.currentProgress.currentLevel} more <#if (input.engagement.currentProgress.goalLevel - input.engagement.currentProgress.currentLevel) gt 1>leaves<#else>leaf</#if> to grow a real tree', | |
description: | |
'Earn ${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if> for every $${input.customData.mcgConversionRateAmount} spent on ${input.transaction.paymentStore.mcgDescription}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
loaded: { | |
title: 'Grow your digital tree and a real tree will be planted on your behalf', | |
description: | |
'Grow your tree by <strong>${input.engagement.progress.pendingLevelIncrement} <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if></strong> with ${input.transaction.paymentStore.mcgDescription}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressFinished: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and ${input.engagement.data.qualifyingSponsorName} is donating to the Arbor Day Foundation to plant a real tree.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
onboardingScreen2: { | |
title: '', | |
description: | |
'<div>For every <strong>$${input.customData.mcgConversionRateAmount} spent on ${input.customData.eligibleMcgDescriptions}</strong> with your Braindance card, your ${input.engagement.data.treeName} will grow by <strong>${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if>.</strong></div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
treeName: 'Braindance Tree', | |
onboardingScreen1: { | |
title: '', | |
description: | |
'<div>Grow your ${input.engagement.data.treeName} to <strong>${input.engagement.data.goalLevel} <#if input.engagement.data.goalLevel?number gt 1>leaves<#else>leaf</#if></strong> and ${input.engagement.data.qualifyingSponsorName} will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Braindance', | |
minQualifyingAmount: '1', | |
goalRewardName: 'Real tree', | |
rolloverBehavior: 'DO_NOTHING', | |
progressLoaded: { | |
title: | |
'You really autumn know by now, you have ${input.engagement.progress.pendingLevelIncrement} unclaimed <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if>...', | |
description: 'Claim your virtual leaves and contribute to growing a real tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
}, | |
resolvedData: { | |
goalLevel: '2000', | |
guidingScreen: { | |
title: '', | |
description: | |
'<div>For every <strong>$1 spent on Food & Drinks and Shopping</strong> with your Braindance card, your Braindance Tree will grow by <strong>2 leaves.</strong></div><br /><div>Grow your Braindance Tree to <strong>2000 leaves</strong> and Braindance will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
subEngagementProgressKeyPath: 'data.paymentStore.flowMerchant.id', | |
progressInProgressUnclaimed: { | |
title: "Don't leaf me hanging, claim 300 leaves now!", | |
description: 'Earn 2 leaves for every $1 spent on Food & Drinks', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
inProgress: { | |
title: 'Congratulations', | |
description: '300 leaves have grown from your tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressInProgressClaimed: { | |
title: 'Earn 2,000 more leaves to grow a real tree', | |
description: 'Earn 2 leaves for every $1 spent on Food & Drinks', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
loaded: { | |
title: 'Grow your digital tree and a real tree will be planted on your behalf', | |
description: 'Grow your tree by <strong>300 leaves</strong> with Food & Drinks', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressFinished: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and Braindance is donating to the Arbor Day Foundation to plant a real tree.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
onboardingScreen2: { | |
title: '', | |
description: | |
'<div>For every <strong>$1 spent on Food & Drinks and Shopping</strong> with your Braindance card, your Braindance Tree will grow by <strong>2 leaves.</strong></div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
treeName: 'Braindance Tree', | |
onboardingScreen1: { | |
title: '', | |
description: | |
'<div>Grow your Braindance Tree to <strong>2000 leaves</strong> and Braindance will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Braindance', | |
minQualifyingAmount: '1', | |
goalRewardName: 'Real tree', | |
rolloverBehavior: 'DO_NOTHING', | |
progressLoaded: { | |
title: 'You really autumn know by now, you have 300 unclaimed leaves...', | |
description: 'Claim your virtual leaves and contribute to growing a real tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
}, | |
progress, | |
expiredInSeconds: 31556926, | |
expiredAt: new ISODate(), | |
scoringConversions: [ | |
{ | |
name: "Flow-tree's scoring conversion", | |
minScore: 1, | |
maxScore: 1, | |
reward: { | |
_id: '4e0f98e0-015e-48c5-8f40-224afa66c234', | |
name: "Tree Reward for Braindance's Flow-tree", | |
type: 'Tree', | |
data: { | |
rewardCollected: { | |
title: "Braindance's Reward collected title", | |
description: 'Not yet configured.', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
headerLogo: 'arbor-day-foundation.svg', | |
rewardReady: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and Braindance is donating to the <strong>Arbor Day Foundation</strong> to plant a tree.<br /><br />Real trees clear our air, clean our water, and beautify our lands for generations to come.', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: "Braindance's Flow tree reward display name.", | |
displayValue: 'Not yet configured.', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
aboutUrl: 'https://www.arborday.org/', | |
headerTitle: 'Arbor Day Foundation', | |
}, | |
status: 'Active', | |
}, | |
}, | |
], | |
lockedRewards: [], | |
url: 'https://static-uat.flownetworks.io/14628874766771/engagement/master_page/?activityOutcomeId=9dfe471e-aeca-4f00-895c-a3761909f09e&sponsorCode=14628874766771&hiddenWidgets=SPEND_INSIGHT,PAYMENT_INFO,PAYMENT_METHOD,MERCHANT_INFO,REWARD,MERCHANT_LOCATION&engagementCode=flow_tree&merchantCode=2342454149177297&playbookId=fbd140ef-7995-455f-8dc6-7fcac0755f83', | |
briefUrl: | |
'https://static-uat.flownetworks.io/14628874766771/engagement/fbd140ef-7995-455f-8dc6-7fcac0755f83/engagement_brief/?activityOutcomeId=9dfe471e-aeca-4f00-895c-a3761909f09e&sponsorCode=14628874766771&hiddenWidgets=SPEND_INSIGHT,PAYMENT_INFO,PAYMENT_METHOD,MERCHANT_INFO,REWARD,MERCHANT_LOCATION&engagementCode=flow_tree&merchantCode=2342454149177297&playbookId=fbd140ef-7995-455f-8dc6-7fcac0755f83', | |
hiddenWidgets: [ | |
'SPEND_INSIGHT', | |
'PAYMENT_INFO', | |
'PAYMENT_METHOD', | |
'MERCHANT_INFO', | |
'REWARD', | |
'MERCHANT_LOCATION', | |
], | |
engagementStageConfiguration: { | |
calculationType: 'PERCENTAGE', | |
stages: [ | |
{ | |
min: { numVal: 0, inclusively: true }, | |
max: { numVal: 0, inclusively: true }, | |
name: 'No tree', | |
}, | |
{ | |
min: { numVal: 0, inclusively: false }, | |
max: { numVal: 33, inclusively: true }, | |
name: 'Baby tree', | |
}, | |
{ | |
min: { numVal: 33, inclusively: false }, | |
max: { numVal: 66, inclusively: true }, | |
name: 'Child tree', | |
}, | |
{ | |
min: { numVal: 66, inclusively: false }, | |
max: { numVal: 99, inclusively: true }, | |
name: 'Young adult tree', | |
}, | |
{ | |
min: { numVal: 99, inclusively: false }, | |
max: { numVal: 100, inclusively: true }, | |
name: 'Full grown tree', | |
}, | |
], | |
}, | |
conversionRates: { '01': { amount: 1, level: 2 }, '02': { amount: 1, level: 2 } }, | |
eligibleMcgs: [ | |
{ | |
_id: { $oid: '60c1693185dbff6f7d36291b' }, | |
issuerId: '60b42c4ccb6d0d1f3752294c', | |
code: '01', | |
description: 'Food & Drinks', | |
}, | |
{ | |
_id: { $oid: '60c1693185dbff6f7d36291c' }, | |
issuerId: '60b42c4ccb6d0d1f3752294c', | |
code: '02', | |
description: 'Shopping', | |
}, | |
], | |
_class: 'io.flownetworks.engagement.domain.engagement.EngagementEntity', | |
}, | |
ruleId, | |
playbookId, | |
sponsorCode, | |
}; | |
} | |
function getPunchRewardOutcome({ reward, sponsorCode, playbookId }) { | |
return { | |
_id: ObjectId().str, | |
kind: 'REWARD', | |
status: 'COMPLETED', | |
data: reward, | |
playbookId, | |
sponsorCode, | |
}; | |
} | |
function getPunchOutcome({ activityOutcomeId, issuerId, playbookId, sponsorCode, progress }) { | |
return { | |
_id: activityOutcomeId, | |
kind: 'ENGAGEMENT', | |
status: 'NEW', | |
data: { | |
_id: ObjectId().str, | |
name: 'Punch card', | |
code: 'punch_card', | |
type: 'Progressive', | |
data: { | |
goalLevel: '5', | |
loaded: { | |
title: 'My ${input.engagement.data.qualifyingSponsorName} Benefits', | |
description: | |
"Earn more when you spend on ${input.transaction.paymentStore.mcgDescription}. You've earned ${input.engagement.progress.currentLevel} <#if input.engagement.progress.currentLevel gt 1>stamps<#else>stamp</#if>. Make ${input.engagement.progress.goalLevel - input.engagement.progress.currentLevel} more <#if input.engagement.progress.goalLevel - input.engagement.progress.currentLevel gt 1>payments<#else>payment</#if> of ${input.engagement.data.currency}${input.engagement.data.minQualifyingAmount} or above with ${input.engagement.data.qualifyingSponsorName} on ${input.transaction.paymentStore.mcgDescription} to earn ${input.engagement.data.goalRewardName}.", | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
rewardCollected: { | |
title: 'Reward Collected', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
termAndCondition: | |
'<a href="https://www.citibank.com.sg/terms/cashback/index.htm">Learn More</a>', | |
inProgress: { | |
title: 'My ${input.engagement.data.qualifyingSponsorName} Benefits', | |
description: | |
"Earn more when you spend on ${input.transaction.paymentStore.mcgDescription}. You've earned ${input.engagement.progress.currentLevel} <#if input.engagement.progress.currentLevel gt 1>stamps<#else>stamp</#if>. Make ${input.engagement.progress.goalLevel - input.engagement.progress.currentLevel} more <#if input.engagement.progress.goalLevel - input.engagement.progress.currentLevel gt 1>payments<#else>payment</#if> of ${input.engagement.data.currency}${input.engagement.data.minQualifyingAmount} or above with ${input.engagement.data.qualifyingSponsorName} on ${input.transaction.paymentStore.mcgDescription} to earn ${input.engagement.data.goalRewardName}.", | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Braindance', | |
currency: '$', | |
minQualifyingAmount: '30', | |
goalRewardName: 'a $25 Braindance cashback', | |
rolloverBehavior: 'TRANSFER_TO_NEXT_ENGAGEMENT', | |
}, | |
resolvedData: { | |
goalLevel: '5', | |
loaded: { | |
title: 'My Braindance Benefits', | |
description: | |
"Earn more when you spend on Groceries. You've earned 1 stamp. Make 4 more payments of $30 or above with Braindance on Groceries to earn a $25 Braindance cashback.", | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
rewardCollected: { | |
title: 'Reward Collected', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
termAndCondition: | |
'<a href="https://www.citibank.com.sg/terms/cashback/index.htm">Learn More</a>', | |
inProgress: { | |
title: 'My Braindance Benefits', | |
description: | |
"Earn more when you spend on Groceries. You've earned 1 stamp. Make 4 more payments of $30 or above with Braindance on Groceries to earn a $25 Braindance cashback.", | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Braindance', | |
currency: '$', | |
minQualifyingAmount: '30', | |
goalRewardName: 'a $25 Braindance cashback', | |
rolloverBehavior: 'TRANSFER_TO_NEXT_ENGAGEMENT', | |
}, | |
progress, | |
expiredAt: new ISODate(), | |
scoringConversions: [ | |
{ | |
name: "Punch card's scoring conversion", | |
minScore: 1, | |
maxScore: 1, | |
reward: { | |
_id: '26a685a6-cd2a-4869-a1a4-0f693ddeca88', | |
name: '$25 Cashback', | |
type: 'Coupon', | |
data: { | |
rewardCollected: { | |
title: 'Reward Collected', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
termAndCondition: | |
'The cash back will be credited to your Braindance credit card in 5-7 business days. Braindance website/app. <a href="https://www.citibank.com.sg/terms/cashback/index.htm">Terms and Conditions</a> apply.', | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Braindance reward', | |
displayValue: '$25 Cashback', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
discountType: 'FIXED_AMOUNT', | |
value: '25', | |
usageType: 'SINGLE', | |
}, | |
status: 'Active', | |
}, | |
}, | |
], | |
lockedRewards: [], | |
url: 'https://static-uat.flownetworks.io/14628874766771/engagement/master_page/?activityOutcomeId=7b3d4972-aea2-4925-8797-4db6b4003cbf&sponsorCode=14628874766771&engagementCode=punch_card&merchantCode=29364980704299664340&playbookId=1a5bf2ac-4820-463d-adf4-65750f1504b4', | |
briefUrl: | |
'https://static-uat.flownetworks.io/14628874766771/engagement/1a5bf2ac-4820-463d-adf4-65750f1504b4/engagement_brief/?activityOutcomeId=7b3d4972-aea2-4925-8797-4db6b4003cbf&sponsorCode=14628874766771&engagementCode=punch_card&merchantCode=29364980704299664340&playbookId=1a5bf2ac-4820-463d-adf4-65750f1504b4', | |
hiddenWidgets: [], | |
eligibleMcgs: [ | |
{ | |
_id: ObjectId().str, | |
issuerId, | |
code: '03', | |
description: 'Groceries', | |
}, | |
], | |
_class: 'io.flownetworks.engagement.domain.engagement.EngagementEntity', | |
}, | |
playbookId, | |
sponsorCode, | |
}; | |
} | |
function getScratchOutcome({ activityOutcomeId, playbookId, sponsorCode }) { | |
return { | |
_id: activityOutcomeId, | |
kind: 'ENGAGEMENT', | |
status: 'NEW', | |
data: { | |
_id: ObjectId().str, | |
name: 'Scratch Card', | |
code: 'scratch_card', | |
type: 'ChanceBased', | |
data: { | |
loaded: { | |
title: 'Scratch to win', | |
description: 'Only ${remainingMinutes} left to play. Don’t miss out on your reward.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
termAndCondition: | |
'<a href="https://www.appliancebay.com/customer-privacy-rights.html">Terms & Conditions</a>', | |
expired: { | |
title: 'The one that got away', | |
description: 'You missed your chance to win a Appliance Bay voucher worth up to $1,000.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
inProgress: { | |
title: 'Scratch to win', | |
description: | |
'Earn more when you spend. Make ${remainingLevels} more payment(s) of ${minQualifyingAmount} or more at ${qualifyingSponsorName} to earn ${goalRewardName}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
lose: { | |
title: 'Aww', | |
description: | |
'Keep trying and better luck next time round! Stand a chance to win a Appliance Bay voucher worth up to $1,000.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Appliance Bay', | |
goalRewardName: 'a 5$ Appliance Bay voucher.', | |
}, | |
expiredInSeconds: 480, | |
expiredAt: new ISODate(), | |
scoringConversions: [ | |
{ | |
name: "Appliance Bay's $5 off", | |
minScore: 1, | |
maxScore: 1, | |
reward: { | |
_id: ObjectId().str, | |
name: '$5 off', | |
type: 'Coupon', | |
data: { | |
rewardCollected: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
termAndCondition: | |
'Use the voucher code at checkout when you shop on the Appliance Bay website/app. <a href="https://www.appliancebay.com/customer-privacy-rights.html">Terms and Conditions</a> apply.', | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Appliance Bay Voucher', | |
displayValue: '$5 off', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
promoCode: 'MM1CX8', | |
discountType: 'FIXED_AMOUNT', | |
value: '5', | |
usageType: 'SINGLE', | |
}, | |
status: 'Active', | |
assets: { | |
rewardReady: { | |
name: 'Appliance Bay Reward Ready', | |
code: 'reward_ready.png', | |
type: 'Image', | |
owner: 'Client', | |
}, | |
rewardCollected: { | |
name: 'Appliance Bay Reward Collected', | |
code: 'reward_collected.png', | |
type: 'Image', | |
owner: 'Client', | |
}, | |
}, | |
expiredInDays: 30, | |
}, | |
}, | |
], | |
lockedRewards: [], | |
url: 'https://static-uat.flownetworks.io/117319027707/engagement/master_page/?activityOutcomeId=933bfff2-6fba-4495-a925-d10cf54139fd&sponsorCode=6018468764087155&engagementCode=scratch_card&merchantCode=6018468764087155&playbookId=21ea7fac-c350-48f7-8cf8-8443e482db61', | |
briefUrl: | |
'https://static-uat.flownetworks.io/6018468764087155/engagement/21ea7fac-c350-48f7-8cf8-8443e482db61/engagement_brief/?activityOutcomeId=933bfff2-6fba-4495-a925-d10cf54139fd&sponsorCode=6018468764087155&engagementCode=scratch_card&merchantCode=6018468764087155&playbookId=21ea7fac-c350-48f7-8cf8-8443e482db61', | |
hiddenWidgets: [], | |
_class: 'io.flownetworks.engagement.domain.engagement.EngagementEntity', | |
}, | |
playbookId, | |
sponsorCode, | |
}; | |
} | |
function getEngagementWidget({ name, type, progress }) { | |
return { | |
kind: 'ENGAGEMENT', | |
data: { | |
briefUrl: | |
'https://static-uat.flownetworks.io/6018468764087155/engagement/21ea7fac-c350-48f7-8cf8-8443e482db61/engagement_brief/?activityOutcomeId=933bfff2-6fba-4495-a925-d10cf54139fd&sponsorCode=6018468764087155&engagementCode=scratch_card&merchantCode=6018468764087155&playbookId=21ea7fac-c350-48f7-8cf8-8443e482db61', | |
expiredAt: new ISODate(), | |
name, | |
progress, | |
id: ObjectId().str, | |
type, | |
url: 'https://static-uat.flownetworks.io/117319027707/engagement/master_page/?activityOutcomeId=933bfff2-6fba-4495-a925-d10cf54139fd&sponsorCode=6018468764087155&engagementCode=scratch_card&merchantCode=6018468764087155&playbookId=21ea7fac-c350-48f7-8cf8-8443e482db61', | |
}, | |
}; | |
} | |
function getChanceBasedEngagement({ playbookId, sponsorCode, reward }) { | |
return { | |
_id: ObjectId().str, | |
kind: 'ENGAGEMENT', | |
status: 'COMPLETED', | |
data: { | |
_id: ObjectId().str, | |
name: 'Scratch Card', | |
code: 'scratch_card', | |
type: 'ChanceBased', | |
data: { | |
loaded: { | |
title: 'Scratch to win', | |
description: 'Only ${remainingMinutes} left to play. Don’t miss out on your reward.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
termAndCondition: | |
'<a href="https://www.appliancebay.com/customer-privacy-rights.html">Terms & Conditions</a>', | |
expired: { | |
title: 'The one that got away', | |
description: 'You missed your chance to win a Appliance Bay voucher worth up to $1,000.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
inProgress: { | |
title: 'Scratch to win', | |
description: | |
'Earn more when you spend. Make ${remainingLevels} more payment(s) of ${minQualifyingAmount} or more at ${qualifyingSponsorName} to earn ${goalRewardName}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
lose: { | |
title: 'Aww', | |
description: | |
'Keep trying and better luck next time round! Stand a chance to win a Appliance Bay voucher worth up to $1,000.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Appliance Bay', | |
goalRewardName: 'a 5$ Appliance Bay voucher.', | |
}, | |
expiredInSeconds: 480, | |
expiredAt: new ISODate(), | |
scoringConversions: [ | |
{ | |
name: "Appliance Bay's $5 off", | |
minScore: 1, | |
maxScore: 1, | |
reward: { | |
_id: '62841695-7fc9-450e-a90f-7906cda55395', | |
name: '$5 off', | |
type: 'Coupon', | |
data: { | |
rewardCollected: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
termAndCondition: | |
'Use the voucher code at checkout when you shop on the Appliance Bay website/app. <a href="https://www.appliancebay.com/customer-privacy-rights.html">Terms and Conditions</a> apply.', | |
rewardReady: { | |
title: 'Congratulations', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Appliance Bay Voucher', | |
displayValue: '$5 off', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
promoCode: 'MM1CX8', | |
discountType: 'FIXED_AMOUNT', | |
value: '5', | |
usageType: 'SINGLE', | |
}, | |
status: 'Active', | |
assets: { | |
rewardReady: { | |
name: 'Appliance Bay Reward Ready', | |
code: 'reward_ready.png', | |
type: 'Image', | |
owner: 'Client', | |
}, | |
rewardCollected: { | |
name: 'Appliance Bay Reward Collected', | |
code: 'reward_collected.png', | |
type: 'Image', | |
owner: 'Client', | |
}, | |
}, | |
expiredInDays: { $numberLong: '30' }, | |
}, | |
}, | |
], | |
lockedRewards: [reward], | |
wonReward: reward, | |
score: 95, // todo, randomize score | |
url: 'https://static-uat.flownetworks.io/117319027707/engagement/master_page/?activityOutcomeId=11f48ec2-fb8d-435a-bd7b-680cd6e354b9&sponsorCode=6018468764087155&engagementCode=scratch_card&merchantCode=6018468764087155&playbookId=21ea7fac-c350-48f7-8cf8-8443e482db61', | |
briefUrl: | |
'https://static-uat.flownetworks.io/6018468764087155/engagement/21ea7fac-c350-48f7-8cf8-8443e482db61/engagement_brief/?activityOutcomeId=11f48ec2-fb8d-435a-bd7b-680cd6e354b9&sponsorCode=6018468764087155&engagementCode=scratch_card&merchantCode=6018468764087155&playbookId=21ea7fac-c350-48f7-8cf8-8443e482db61', | |
hiddenWidgets: [], | |
_class: 'io.flownetworks.engagement.domain.engagement.EngagementEntity', | |
}, | |
playbookId, | |
sponsorCode, | |
_class: 'io.flownetworks.engagement.domain.activity.ActivityOutcome', | |
}; | |
} | |
function getFlowTreeEngagement({ playbookId, sponsorCode, reward, ruleId, progress }) { | |
return { | |
_id: ObjectId().str, | |
kind: 'ENGAGEMENT', | |
status: 'COMPLETED', | |
data: { | |
_id: ObjectId().str, | |
name: 'Flow tree', | |
code: 'flow_tree', | |
type: 'MerchantBasedProgressive', | |
data: { | |
goalLevel: '1000', | |
guidingScreen: { | |
title: '', | |
description: | |
'<div>For every <strong>$${input.customData.mcgConversionRateAmount} spent on ${input.customData.eligibleMcgDescriptions}</strong> with your Noteworthy card, your ${input.engagement.data.treeName} will grow by <strong>${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if>.</strong></div><br /><div>Grow your ${input.engagement.data.treeName} to <strong>${input.engagement.data.goalLevel} <#if input.engagement.data.goalLevel?number gt 1>leaves<#else>leaf</#if></strong> and ${input.engagement.data.qualifyingSponsorName} will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
subEngagementProgressKeyPath: 'data.paymentStore.flowMerchant.id', | |
progressInProgressUnclaimed: { | |
title: | |
"Don't leaf me hanging, claim ${input.engagement.progress.pendingLevelIncrement} <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if> now!", | |
description: | |
'Earn ${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if> for every $${input.customData.mcgConversionRateAmount} spent on ${input.transaction.paymentStore.mcgDescription}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
inProgress: { | |
title: 'Congratulations', | |
description: | |
'${input.engagement.progress.pendingLevelIncrement} <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if> have grown from your tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressInProgressClaimed: { | |
title: | |
'Earn ${input.engagement.currentProgress.goalLevel - input.engagement.currentProgress.currentLevel} more <#if (input.engagement.currentProgress.goalLevel - input.engagement.currentProgress.currentLevel) gt 1>leaves<#else>leaf</#if> to grow a real tree', | |
description: | |
'Earn ${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if> for every $${input.customData.mcgConversionRateAmount} spent on ${input.transaction.paymentStore.mcgDescription}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
loaded: { | |
title: 'Grow your digital tree and a real tree will be planted on your behalf', | |
description: | |
'Grow your tree by <strong>${input.engagement.progress.pendingLevelIncrement} <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if></strong> with ${input.transaction.paymentStore.mcgDescription}', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressFinished: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and ${input.engagement.data.qualifyingSponsorName} donating to the Arbor Day Foundation to plant a real tree.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
onboardingScreen2: { | |
title: '', | |
description: | |
'<div>For every <strong>$${input.customData.mcgConversionRateAmount} spent on ${input.customData.eligibleMcgDescriptions}</strong> with your Noteworthy card, your ${input.engagement.data.treeName} will grow by <strong>${input.customData.mcgConversionRateLevel} <#if input.customData.mcgConversionRateLevel gt 1>leaves<#else>leaf</#if>.</strong></div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
treeName: 'Note Tree', | |
onboardingScreen1: { | |
title: '', | |
description: | |
'<div>Grow your ${input.engagement.data.treeName} to <strong>${input.engagement.data.goalLevel} <#if input.engagement.data.goalLevel?number gt 1>leaves<#else>leaf</#if></strong> and ${input.engagement.data.qualifyingSponsorName} will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Notebank', | |
minQualifyingAmount: '1', | |
goalRewardName: 'Real tree', | |
rolloverBehavior: 'DO_NOTHING', | |
progressLoaded: { | |
title: | |
'You really autumn know by now, you have ${input.engagement.progress.pendingLevelIncrement} unclaimed <#if input.engagement.progress.pendingLevelIncrement gt 1>leaves<#else>leaf</#if>...', | |
description: 'Claim your virtual leaves and contribute to growing a real tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
}, | |
resolvedData: { | |
goalLevel: '1000', | |
guidingScreen: { | |
title: '', | |
description: | |
'<div>For every <strong>$1 spent on Food & Drinks and Groceries</strong> with your Noteworthy card, your Note Tree will grow by <strong>3 leaves.</strong></div><br /><div>Grow your Note Tree to <strong>1000 leaves</strong> and Notebank will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
subEngagementProgressKeyPath: 'data.paymentStore.flowMerchant.id', | |
progressInProgressUnclaimed: { | |
title: "Don't leaf me hanging, claim 0 leaf now!", | |
description: 'Earn 3 leaves for every $1 spent on Groceries', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
inProgress: { | |
title: 'Congratulations', | |
description: '0 leaf have grown from your tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressInProgressClaimed: { | |
title: 'Earn 0 more leaf to grow a real tree', | |
description: 'Earn 3 leaves for every $1 spent on Groceries', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
loaded: { | |
title: 'Grow your digital tree and a real tree will be planted on your behalf', | |
description: 'Grow your tree by <strong>0 leaf</strong> with Groceries', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
progressFinished: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and Notebank donating to the Arbor Day Foundation to plant a real tree.', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
onboardingScreen2: { | |
title: '', | |
description: | |
'<div>For every <strong>$1 spent on Food & Drinks and Groceries</strong> with your Noteworthy card, your Note Tree will grow by <strong>3 leaves.</strong></div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
treeName: 'Note Tree', | |
onboardingScreen1: { | |
title: '', | |
description: | |
'<div>Grow your Note Tree to <strong>1000 leaves</strong> and Notebank will plant a real tree on your behalf.</div>', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
qualifyingSponsorName: 'Notebank', | |
minQualifyingAmount: '1', | |
goalRewardName: 'Real tree', | |
rolloverBehavior: 'DO_NOTHING', | |
progressLoaded: { | |
title: 'You really autumn know by now, you have 0 unclaimed leaf...', | |
description: 'Claim your virtual leaves and contribute to growing a real tree!', | |
_class: 'io.flownetworks.engagement.entity.EngagementInfo', | |
}, | |
}, | |
progress, | |
expiredInSeconds: 31556926, | |
expiredAt: new ISODate(), | |
scoringConversions: [ | |
{ | |
name: "Notebank flow-tree 's scoring conversion", | |
minScore: 1, | |
maxScore: 1, | |
reward: { | |
_id: '63af780c-a6e5-4261-8a16-fc76205e1cf3', | |
name: "Tree Reward for Notebank's Flow-tree", | |
type: 'Tree', | |
data: { | |
rewardCollected: { | |
title: 'Reward collected title', | |
description: 'Not yet configured.', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
headerLogo: 'arbor-day-foundation.svg', | |
rewardReady: { | |
title: 'Congratulations', | |
description: | |
'Your tree has grown, and Notebank donating to the <strong>Arbor Day Foundation</strong> to plant a tree.<br /><br />Real trees clear our air, clean our water, and beautify our lands for generations to come.', | |
_class: 'io.flownetworks.reward.entity.RewardInfo', | |
}, | |
display: { | |
displayName: 'Flow tree reward display name.', | |
displayValue: 'Not yet configured.', | |
_class: 'io.flownetworks.reward.entity.RewardDisplay', | |
}, | |
aboutUrl: 'https://www.arborday.org/', | |
headerTitle: 'Arbor Day Foundation', | |
}, | |
status: 'Active', | |
}, | |
}, | |
], | |
lockedRewards: [], | |
wonReward: reward, | |
score: 0, | |
url: 'https://static-uat.flownetworks.io/117319027707/engagement/master_page/?activityOutcomeId=394f479a-95cd-427d-a5fb-ffb0d97c4780&sponsorCode=117319027707&hiddenWidgets=SPEND_INSIGHT,PAYMENT_INFO,PAYMENT_METHOD,MERCHANT_INFO,REWARD,MERCHANT_LOCATION&engagementCode=flow_tree&merchantCode=29364980704299664340&playbookId=d156f175-5720-4076-8c2a-d4626b885ab7', | |
briefUrl: | |
'https://static-uat.flownetworks.io/117319027707/engagement/d156f175-5720-4076-8c2a-d4626b885ab7/engagement_brief/?activityOutcomeId=394f479a-95cd-427d-a5fb-ffb0d97c4780&sponsorCode=117319027707&hiddenWidgets=SPEND_INSIGHT,PAYMENT_INFO,PAYMENT_METHOD,MERCHANT_INFO,REWARD,MERCHANT_LOCATION&engagementCode=flow_tree&merchantCode=29364980704299664340&playbookId=d156f175-5720-4076-8c2a-d4626b885ab7', | |
hiddenWidgets: [ | |
'SPEND_INSIGHT', | |
'PAYMENT_INFO', | |
'PAYMENT_METHOD', | |
'MERCHANT_INFO', | |
'REWARD', | |
'MERCHANT_LOCATION', | |
], | |
engagementStageConfiguration: { | |
calculationType: 'PERCENTAGE', | |
stages: [ | |
{ | |
min: { numVal: 0, inclusively: true }, | |
max: { numVal: 0, inclusively: true }, | |
name: 'No tree', | |
}, | |
{ | |
min: { numVal: 0, inclusively: false }, | |
max: { numVal: 33, inclusively: true }, | |
name: 'Baby tree', | |
}, | |
{ | |
min: { numVal: 33, inclusively: false }, | |
max: { numVal: 66, inclusively: true }, | |
name: 'Child tree', | |
}, | |
{ | |
min: { numVal: 66, inclusively: false }, | |
max: { numVal: 99, inclusively: true }, | |
name: 'Young adult tree', | |
}, | |
{ | |
min: { numVal: 99, inclusively: false }, | |
max: { numVal: 100, inclusively: true }, | |
name: 'Full grown tree', | |
}, | |
], | |
}, | |
conversionRates: { '01': { amount: 1, level: 1 }, '03': { amount: 1, level: 3 } }, | |
eligibleMcgs: [ | |
{ | |
_id: { $oid: '60c1690f85dbff6f7d362904' }, | |
issuerId: '605567014d4e5b15a1daa772', | |
code: '01', | |
description: 'Food & Drinks', | |
}, | |
{ | |
_id: { $oid: '60c1690f85dbff6f7d362906' }, | |
issuerId: '605567014d4e5b15a1daa772', | |
code: '03', | |
description: 'Groceries', | |
}, | |
], | |
_class: 'io.flownetworks.engagement.domain.engagement.EngagementEntity', | |
}, | |
ruleId, | |
playbookId, | |
sponsorCode, | |
_class: 'io.flownetworks.engagement.domain.activity.ActivityOutcome', | |
}; | |
} | |
function getCompletedActivity({ activityOutcomeId, flowTxn, reward, engagement }) { | |
const { clientId, clientCustomerId, clientTransactionId } = flowTxn; | |
return { | |
_id: ObjectId().str, | |
clientId, | |
customerId: clientCustomerId, | |
kind: 'EngagementCompleted', | |
data: engagement, | |
clientTransactionId, | |
activityOutcomeId, | |
widgetContainer: { | |
activityOutcomeId, | |
clientTransactionId: clientTransactionId, | |
wonReward: reward, | |
widgets: [], | |
clientId, | |
customerId: clientCustomerId, | |
_class: 'io.flownetworks.engagement.domain.pipeline.EngagementCompletionContainer', | |
}, | |
outcomes: [], | |
savedInKafka: true, | |
createdBy: 'system', | |
createdDate: new ISODate(), | |
lastModifiedBy: 'system', | |
lastModifiedDate: new ISODate(), | |
_class: 'io.flownetworks.engagement.domain.activity.Activity', | |
}; | |
} | |
function getActivity(flowTxn) { | |
const { | |
clientId, | |
clientCode, | |
clientCustomerId, | |
clientTransactionId, | |
networkTransactionId, | |
state, | |
paymentStore, | |
paymentSource, | |
homeCurrency, | |
homeAmount, | |
merchantCurrency, | |
merchantAmount, | |
time, | |
} = flowTxn; | |
const kind = 'Transaction'; | |
const { address, location, name: storeName } = paymentStore.flowStore; | |
const { mcgDescription, categoryCode: mcc, mcgCode } = paymentStore; | |
return { | |
_id: ObjectId().str, | |
clientId, | |
clientCustomerId, | |
kind, | |
data: { | |
transaction: { | |
_id: ObjectId().str, | |
clientId, | |
clientCode, | |
clientTransactionId, | |
networkTransactionId, | |
time, | |
state, | |
homeCurrency, | |
homeAmount, | |
merchantCurrency, | |
merchantAmount, | |
}, | |
paymentStore, | |
paymentSource, | |
}, | |
clientTransactionId, | |
widgetContainer: { | |
clientTransactionId, | |
amount: homeAmount, | |
currency: merchantCurrency, | |
time: time, | |
widgets: [ | |
{ | |
kind: 'PAYMENT_INFO', | |
data: { | |
homeAmount, | |
merchantAmount, | |
time, | |
merchantCurrency, | |
homeCurrency, | |
}, | |
}, | |
{ | |
kind: 'MERCHANT_LOCATION', | |
data: { | |
...address, | |
...location, | |
storeName, | |
}, | |
}, | |
{ | |
kind: 'PAYMENT_METHOD', | |
data: { | |
...paymentSource, | |
}, | |
}, | |
{ | |
kind: 'MERCHANT_INFO', | |
data: { | |
mcgDescription, | |
logo: 'https://static-uat.flownetworks.io/29364980704299664340/assets%2FmerchantLogo.png', | |
mcc, | |
mcgCode, | |
merchantName: storeName, | |
mcgIcon: 'https://static-uat.flownetworks.io/117319027707/mcg/groceries.png', | |
}, | |
}, | |
], | |
clientId, | |
customerId: clientCustomerId, | |
_class: 'io.flownetworks.engagement.domain.pipeline.impl.TransactionWidgetContainer', | |
}, | |
outcomes: [], | |
savedInKafka: true, | |
createdBy: 'system', | |
createdDate: new ISODate(), | |
lastModifiedBy: 'system', | |
lastModifiedDate: new ISODate(), | |
_class: 'io.flownetworks.engagement.domain.activity.Activity', | |
}; | |
} | |
function createFlowApiRawTransaction(issuer) { | |
var clientTransactionId = ObjectId().str; | |
var clientCustomerId = ObjectId().str; | |
var clientPaymentSourceId = ObjectId().str; | |
var amount = (Math.random() * 1000).toFixed(2); | |
var last4Digits = ("0000" + Math.floor(Math.random() * 9999).toString()).substr(-4); | |
return { | |
"clientTransactionId": clientTransactionId, | |
"clientId": issuer.id, | |
"clientCustomerId": clientCustomerId, | |
"clientPaymentSourceId": clientPaymentSourceId, | |
"data": { | |
"clientCustomerId": clientCustomerId, | |
"clientTransactionId": clientTransactionId, | |
"networkTransactionId": ObjectId().str, | |
"transactionTime": new ISODate().getTime(), | |
"transactionState": "AUTHORIZED", | |
"merchantCurrency": "USD", | |
"merchantAmount": amount, | |
"homeCurrency": "USD", | |
"homeAmount": amount, | |
"paymentSource": { | |
"id": clientPaymentSourceId, | |
"par": ObjectId().str, | |
"last4Digits": last4Digits, | |
"paymentSourceProduct": "Noteworthy", | |
"paymentFundingSource": "Credit", | |
"paymentSourceNetwork": "Visa", | |
"paymentMethod": "ONLINE" | |
}, | |
"merchant": { | |
"id" : ObjectId().str, | |
"name": "Appliance Bay", | |
"categoryCode": "5732", | |
"acquirerBin": "372041000053360", | |
"cardAcceptorId": "186G2AJK", | |
"address1": "655 W Herndon Ave", | |
"address2": "USA", | |
"city": "Clovis", | |
"state": "CA", | |
"zipCode": "93612", | |
"countryCode": "US" | |
} | |
}, | |
"savedInKafka": true, | |
"createdBy": "system", | |
"createdDate": new ISODate(), | |
"lastModifiedBy": "system", | |
"lastModifiedDate": new ISODate(), | |
"_class": "io.flownetworks.transaction.entity.RawTransactionEntity" | |
} | |
} | |
function createFlowIngestionTransaction(issuer, rawTxn) { | |
var flowMerchantId = ObjectId(); | |
return { | |
"clientId" : issuer.id, | |
"clientCode" : issuer.code, | |
"clientTransactionId" : rawTxn.clientTransactionId, | |
"networkTransactionId" : rawTxn.data.networkTransactionId, | |
"time" : new Date(rawTxn.data.time), | |
"state" : rawTxn.data.state, | |
"clientCustomerId" : rawTxn.clientCustomerId, | |
"homeCurrency" : rawTxn.data.homeCurrency, | |
"homeAmount" : rawTxn.data.homeAmount, | |
"merchantCurrency" : rawTxn.data.merchantCurrency, | |
"merchantAmount" : rawTxn.data.merchantAmount, | |
"paymentSource" : { | |
"externalId" : rawTxn.data.paymentSource.id, | |
"par" : rawTxn.data.paymentSource.par, | |
"last4Digits" : rawTxn.data.paymentSource.last4Digits, | |
"paymentSourceProduct" : rawTxn.data.paymentSource.paymentSourceProduct, | |
"paymentFundingSource" : rawTxn.data.paymentSource.paymentFundingSource, | |
"paymentSourceNetwork" : rawTxn.data.paymentSource.paymentSourceNetwork, | |
"paymentMethod" : rawTxn.data.paymentSource.paymentMethod | |
}, | |
"paymentStore" : { | |
"storeId" : rawTxn.data.merchant.id, | |
"flowMerchant" : { | |
"_id" : flowMerchantId, | |
"name" : "APL Holding Group", | |
"displayName" : "Appliance Bay", | |
"code" : "APPLIANCE_BAY", | |
"status" : "Active", | |
"website" : "https://www.appliancebay.com", | |
"address" : { | |
"address1" : "2931 US Hwy 27 N", | |
"city" : "Sebring", | |
"state" : "FL", | |
"zipCode" : "33870", | |
"countryCode" : "US" | |
}, | |
"contactName" : "Andy Boyd", | |
"contactEmail" : "[email protected]", | |
"locale" : "en_US" | |
}, | |
"flowStore" : { | |
"_id" : ObjectId(), | |
"name" : "Appliance Bay Sebring", | |
"status" : "Active", | |
"address" : { | |
"address1" : "2931 US Hwy 27 N", | |
"city" : "Sebring", | |
"state" : "FL", | |
"zipCode" : "33870", | |
"countryCode" : "US" | |
}, | |
"location" : { | |
"longitude" : 27.509926569545954, | |
"latitude" : -81.49381600319408 | |
}, | |
"merchantId" : flowMerchantId.str | |
}, | |
"storeName" : rawTxn.data.merchant.name, | |
"categoryCode" : rawTxn.data.merchant.categoryCode, | |
"mcgCode" : "02", | |
"mcgDescription" : "Shopping", | |
"mcgIcon" : "shopping.png", | |
"acquirerBin" : rawTxn.data.merchant.acquirerBin, | |
"cardAcceptorId" : rawTxn.data.merchant.cardAcceptorId, | |
"address1" : rawTxn.data.merchant.address1, | |
"address2" : rawTxn.data.merchant.address2, | |
"city" : rawTxn.data.merchant.city, | |
"state" : rawTxn.data.merchant.state, | |
"zipCode" : rawTxn.data.merchant.zipCode, | |
"countryCode" : rawTxn.data.merchant.countryCode | |
}, | |
"savedInKafka" : true, | |
// TODO: randomly match receipt? 50%? | |
"receiptLinkingKey" : rawTxn.data.paymentSource.last4Digits + ":" + rawTxn.data.merchantAmount + ":" + rawTxn.data.merchantCurrency, | |
"createdBy" : "system", | |
"createdDate" : new ISODate(), | |
"lastModifiedBy" : "system", | |
"lastModifiedDate" : new ISODate(), | |
"_class" : "io.flownetworks.transaction.entity.TransactionEntity" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment