Created
November 8, 2022 14:10
-
-
Save endihunter/ecba910bc984bf1671bbcabd730101b3 to your computer and use it in GitHub Desktop.
Loyalty Orchestration Merchant Inclusion Flow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function main() { | |
// IMPORT loyalty accounts from merchant SQ1 | |
importLoyaltyAccounts('SQ1'); | |
// IMPORT loyalty accounts from merchant SQ2 | |
importLoyaltyAccounts('SQ2'); | |
// throttler that limits the # of requests up to 20rps to LoyaltyAPI and up to 100rps for FS application | |
// throttler will pause requests either if # or requests to LoyaltyAPI exis | |
// throttler is a chain of limiters: | |
// 1st level limiter limits requests to APIs (Loyalty, Customer, etc...) = 20RPS | |
// 2nd level limiter limits requests to FS app = 100RPS | |
const appThrottler = new Throttler(100); | |
// Requests added to loyaltyThrottler must follow the 20 per LoyaltyAPi and 100 per App rate limits. | |
const loyaltyThrottler = (new Throttler(20)).chain(appLimiter); | |
// Requests added to customersThrottler must follow the 15 per CustomerAPi and 100 per App rate limits. | |
const customersThrottler = (new Throttler(15)).chain(appLimiter); | |
// walk through imported accounts | |
// 1. create loyalty account if it missing in one of merchants | |
// 2. adjust points if the same loyalty account exists in both merchants: SQ1 & SQ2 | |
const accounts = retrieveLoyaltyAccountsIterator(['SQ1', 'SQ2']) | |
for account in [...accounts] | |
// check if loyalty account exists in corresponding Merchant (no API calls) | |
const source = getLoyaltyAccount(account, 'SQ1'); | |
const target = getLoyaltyAccount(account, 'SQ2'); | |
// loyalty account exists in 'SQ1' -> replicate to 'SQ2' | |
if (source && !target) { | |
return replicateLoyaltyAccount(account, 'SQ2', source.balance); | |
} | |
// loyalty account exists in 'SQ2' -> replicate to 'SQ1' | |
if (target && !source) { | |
return replicateLoyaltyAccount(account, 'SQ1', target.balance); | |
} | |
// loyalty account exists in both square merchants -> calculate and adjust new balance | |
return adjustBalances(account, 'SQ1', 'SQ2'); | |
endfor | |
} | |
function replicateLoyaltyAccount(account, targetMerchantId, balance) { | |
// since the time difference between calls to importLoyaltyAccounts() and current function may be significant | |
// we call LoyaltyApi in order to make sure there is no loyalty account created during this time range | |
// note: in order to reduce the Nr of API calls, we're considering to reverse the sequence, | |
// from: search -> on404(create) | |
// to: try(create) -> catch(retrieve), there is very low chance to hit the catch branch | |
let loyaltyAccount = loyaltyThrottler.schedule(() => LoyaltyApi.searchLoyaltyAccounts(account.phoneNumber)); | |
if (!loyaltyAccount) { | |
const customer = replicatePaymentCustomer(account); | |
loyaltyAccount = loyaltyThrottler.schedule(() => LoyaltyApi.createLoyaltyAccount({ ...account, customerId: customer.id })); | |
} | |
if (balance !== loyaltyAccount.balance) { | |
const diff = balance - loyaltyAccount.balance; | |
loyaltyThrottler.schedule(() => LoyaltyApi.adjustPoints(loyaltyAccount, diff)); | |
} | |
} | |
function adjustBalances(account, aMerchantId, bMerchantId) { | |
const balance = calculateNewBalance(account, aMerchantId, bMerchantId); | |
loyaltyThrottler.schedule(() => LoyaltyApi.adjustPoints(accountA, balance)); | |
loyaltyThrottler.schedule(() => LoyaltyApi.adjustPoints(accountB, balance)); | |
} | |
// replicate the Customer associated with loyalty account | |
function replicatePaymentCustomer(sourceLoyaltyAccount, sourceMerchantId, targetMerchantId) { | |
// get the original customer, assiciated with source loyalty account | |
const aCustomer = customersThrottler.schedule(() => CustomerApi.retrieveCustomer(sourceMerchantId, sourceLoyaltyAccount.customerId)); | |
// replicate customer to target square merchant | |
return customersThrottler.schedule(() => CustomerApi.createPaymentCustomer( | |
targetMerchantId, | |
pick(sourceCustomer, 'givenName, familyName, nickname, companyName, emailAddress, address, phoneNumber, birthday, referenceId, note') | |
)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment