Skip to content

Instantly share code, notes, and snippets.

@lptai
Last active August 12, 2021 07:25
Show Gist options
  • Save lptai/f188d080ce88e60852fb582ea3f2740a to your computer and use it in GitHub Desktop.
Save lptai/f188d080ce88e60852fb582ea3f2740a to your computer and use it in GitHub Desktop.
generate-txn.js
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