Reward campaign assessment

mail@pastecode.io avatar
unknown
javascript
3 years ago
11 kB
3
Indexable
Never
 const rewardCampaigns = await rewardCampaignRepository.findByCampaignId(campaignId);

if (rewardCampaigns.length <= 0) {
    console.info(`Reward campaign: Campaign id '${campaignId}' has no reward to evaluate.`);
    return;
}

rewardCampaigns.sort((a, b) => a.sequence - b.sequence); // Sort by increasing sequence

let action = 'continue';

for (const rewardCampaign of rewardCampaigns) {
    if (action === 'stop') {
        break;
    }

    if (!validateCampaignStatus(rewardCampaign)) continue;
    if (!validateCampaignDate(rewardCampaign)) continue;

    if (!await validateDailyCampaignCap(rewardCampaign)) continue;
    if (!await validateWeeklyCampaignCap(rewardCampaign)) continue;
    if (!await validateTotalCampaignCap(rewardCampaign)) continue;

    const piiFieldsEncrypted = encryptPiiFields(email, phone, id);
    if (!await validateDailyIndividualCap(rewardCampaign, piiFieldsEncrypted)) continue;
    if (!await validateWeeklyIndividualCap(rewardCampaign, piiFieldsEncrypted)) continue;
    if (!await validateTotalIndividualCap(rewardCampaign, piiFieldsEncrypted)) continue;

    // Evaluate criteria rules
    const rewardCampaignCriteria = await rewardCampaignCriteriaRepository.where({
        reward_campaign_id: rewardCampaign.id,
        is_deleted: false
    });

    if (!rewardCampaignCriteria || rewardCampaignCriteria.length <= 0) {
        console.warn(`Reward campaign: No criteria found for reward campaign id ${rewardCampaign.id} (${rewardCampaign.salesforce_id}).`);
        continue;
    }

    rewardCampaignCriteria.sort((a, b) => a.sequence - b.sequence); // Sort by increasing sequence

    let isEligible = false;
    for (const criteria of rewardCampaignCriteria) {
        // If there are no rules then award the reward directly
        if (!criteria.rules) {
            isEligible = true;
        }
        else {
            // If there are rules but its status is 'Inactive' then also award the reward directly
            const rules = JSON.parse(criteria.rules);
            if (rules.status.toLowerCase() === 'inactive') {
                isEligible = true;
            }
            else {
                for (const subCriteria of rules.criteria) {
                    const registrationFormField = await registrationFormFieldRepository.findBySalesforceId(subCriteria.resource.questionId);
                    if (!registrationFormField) {
                        isEligible = false;
                        console.warn(`Reward campaign: Not found registration form field '${subCriteria.resource.questionId}'.`);
                        break;
                    }

                    // Only evaluate if the form id match the config form id in rewards_campaign_criteria
                    const criteriaRegistrationFormSalesforceId = subCriteria.resource.formId;
                    if (criteriaRegistrationFormSalesforceId !== registrationFormSalesforceId) {
                        isEligible = false;
                        break;
                    }

                    const questionCode = registrationFormField.code;
                    const dataType = registrationFormField.data_type;
                    const correctAnswer = subCriteria.value;
                    const operator = subCriteria.operator;

                    // If PII fields question code (name, email, phone, id) are setup
                    // then add {question_code, answer} pair for evaluation
                    switch (questionCode) {
                        case 'name':
                            userQuestionsAndAnswers.push({
                                question_code: 'name',
                                answer: name
                            });
                            break;
                        case 'email':
                            userQuestionsAndAnswers.push({
                                question_code: 'email',
                                answer: email
                            });
                            break;
                        case 'phone':
                            userQuestionsAndAnswers.push({
                                question_code: 'phone',
                                answer: phone
                            });
                            break;

                        case 'id':
                            userQuestionsAndAnswers.push({
                                question_code: 'id',
                                answer: id
                            });
                            break;
                    }

                    const isAnswerCorrected = checkUserAnswer(questionCode, correctAnswer, userQuestionsAndAnswers, dataType, operator);
                    if (rules.criteriaType.toLowerCase() === 'all') {
                        if (!isAnswerCorrected) {
                            console.warn(`Reward campaign: Incorrect answer for question code '${questionCode}' the correct answer is '${correctAnswer}', submitted answer was ${JSON.stringify(userQuestionsAndAnswers)} \nOperator is '${operator}', data type is '${dataType}'.`);
                            isEligible = false;
                            break;
                        }

                        isEligible = true;
                    }
                    else if (rules.criteriaType.toLowerCase() === 'any') {
                        if (isAnswerCorrected) {
                            isEligible = true;
                            break;
                        }
                    }
                }
            }
        }

        if (isEligible) {
            const rewardCampaignQualifier = await rewardCampaignQualifierRepository.insert({
                reward_campaign_id: criteria.reward_campaign_id,
                registration_form_response_id: registrationFormResponseId,
                registrant_name: name,
                pii_email_token: piiEmailToken,
                pii_phone_token: piiPhoneToken,
                pii_id_token: piiIdToken,
                remarks: '',
                sync_to_salesforce: 'pending',
                is_voided: false
            });

            if (rewardCampaign.action_when_qualified === 'stop') { // If the qualifier is inserted then check if should process the next reward campaign
                action = 'stop';
            }

            const rewards = JSON.parse(criteria.rewards);
            for (const item of rewards) {
                const rewardId = item.rewardData.Reward_Catalog__c;
                const quantity = item.rewardData.Quantity__c ? parseInt(item.rewardData.Quantity__c) : 0;

                const reward = await rewardRepository.findBySalesforceId(rewardId);
                if (!reward || reward.status.toLowerCase() !== 'published') {
                    console.info(`Reward campaign: Reward id '${rewardId}' not found or it is not currently in 'published' status`);
                    continue;
                }

                console.info(`Reward campaign: Evaluating reward '${reward.title}'.\n${JSON.stringify(reward)}`);

                switch (reward.type.toLowerCase()) {
                    case 'e-voucher':
                        // TODO: logic for e-voucher
                        break;
                    case 'promo-code':
                        // TODO: logic for promo-code
                        break;
                    case 'lucky-draw-chance':
                        console.info(`Reward campaign: Issuing ${quantity} lucky draw chance(s) for campaign id ${campaignId}.`);
                        if (quantity > 0) {
                            for (let i = 1; i <= quantity; i++) {
                                await luckyDrawChanceRepository.insert({
                                    campaign_id: campaignId,
                                    reward_campaign_qualifier_id: rewardCampaignQualifier.id,
                                    registration_form_response_id: registrationFormResponseId,
                                    reward_id: reward.id,
                                    pii_email_token: piiEmailToken,
                                    pii_phone_token: piiPhoneToken,
                                    pii_id_token: piiIdToken,
                                    valid_from: reward.effective_from,
                                    valid_to: reward.effective_to || null,
                                    status: 'active'
                                });
                            }
                        }
                        break;
                    default:
                        // Count reward issued and check if it exceeded reward cap
                        const rewardsIssued = await rewardIssuedRepository.where({reward_id: reward.id});

                        if (Number.isInteger(reward.cap)) {
                            let totalRewardsIssued = 0;
                            if (rewardsIssued.length > 0) {
                                rewardsIssued.forEach(i => {
                                    totalRewardsIssued += i.quantity
                                });
                            }

                            if (totalRewardsIssued >= reward.cap) {
                                console.warn(`Reward campaign: Exceeded reward cap (limit: ${reward.cap}). \nReward id: '${reward.id}', title: '${reward.title}'.`);
                                break;
                            }
                        }

                        const newRewardIssued = await rewardIssuedRepository.insert({
                            reward_campaign_id: criteria.reward_campaign_id,
                            reward_campaign_qualifier_id: rewardCampaignQualifier.id,
                            reward_id: reward.id,
                            type: reward.type,
                            registrant_name: name,
                            pii_email_token: piiEmailToken,
                            pii_phone_token: piiPhoneToken,
                            pii_id_token: piiIdToken,
                            valid_from: reward.effective_from,
                            valid_to: reward.effective_to || null,
                            quantity: quantity,
                            remarks: '',
                            sync_to_salesforce: 'pending',
                            status: 'issued'
                        });
                        console.info(`Reward campaign: Issued 1 reward. \n${JSON.stringify(newRewardIssued)}`);
                        break;
                }
            }
        }
        else {
            console.warn(`Reward campaign: Not eligible for criteria ${JSON.stringify(criteria)}.`);
        }
    }
}

await registrationFormResponseRepository.update(registrationFormResponseId, {'sync_to_salesforce': 'sync-waiting'});

// Send message to Salesforce queue
await queueService.sendToQueue(
    JSON.stringify({salesforcePayload, messageId: uuidv4()}),
    'registration_sync',
    config.salesforce.queue.url,
    config.salesforce.queue.delaySeconds,
    true
);

return true;