Subversion Repositories SmartDukaan

Rev

Rev 37180 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.spice.profitmandi.service;

import com.spice.profitmandi.dao.enumuration.dtr.AgendaType;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;

public class AgendaRuleDecisionTest {

    private static Map<String, Double> params(Object... kv) {
        Map<String, Double> m = new HashMap<>();
        for (int i = 0; i < kv.length; i += 2) {
            m.put((String) kv[i], ((Number) kv[i + 1]).doubleValue());
        }
        return m;
    }

    private static Map<String, Double> salesDefaults() {
        return params("flagPct", 40, "clearPct", 75, "baselineDays", 90, "windowDays", 30);
    }

    private static AgendaRuleDecider.Inputs baseInputs() {
        AgendaRuleDecider.Inputs in = new AgendaRuleDecider.Inputs();
        in.fofoId = 1;
        in.revival = false;
        in.storeActivatedRecently = false;
        in.minInvestment = 300000;
        in.shortPercentage = 10d;
        in.baselineAmt = 300000; // monthlyBaseline = 100000
        in.currentAmt = 100000;
        in.lastBillDaysAgo = 3;
        in.oldestLoanAgeDays = null;
        in.pendingLoanAmt = 0;
        return in;
    }

    private static Map<AgendaType, AgendaRuleDecider.Decision> decide(AgendaRuleDecider.Inputs in) {
        return AgendaRuleDecider.decide(in,
                params("shortPct", 50), salesDefaults(), params("gapDays", 15), params("loanAgeDays", 20));
    }

    @Test
    public void salesHysteresisHoldsBetweenBarriers() {
        AgendaRuleDecider.Inputs in = baseInputs();
        in.currentAmt = 60000; // 60% of baseline: between 40 and 75
        assertEquals(AgendaRuleDecider.Action.LEAVE, decide(in).get(AgendaType.LOW_SALES).action);
    }

    @Test
    public void salesFlagsBelow40AndClearsAbove75() {
        AgendaRuleDecider.Inputs in = baseInputs();
        in.currentAmt = 39999;
        assertEquals(AgendaRuleDecider.Action.OPEN, decide(in).get(AgendaType.LOW_SALES).action);
        in.currentAmt = 75001;
        assertEquals(AgendaRuleDecider.Action.CLOSE, decide(in).get(AgendaType.LOW_SALES).action);
    }

    @Test
    public void salesSkipsOnZeroBaselineAndYoungStores() {
        AgendaRuleDecider.Inputs in = baseInputs();
        in.baselineAmt = 0;
        in.currentAmt = 0;
        assertEquals(AgendaRuleDecider.Action.LEAVE, decide(in).get(AgendaType.LOW_SALES).action);
        AgendaRuleDecider.Inputs young = baseInputs();
        young.storeActivatedRecently = true;
        young.currentAmt = 0;
        assertEquals(AgendaRuleDecider.Action.LEAVE, decide(young).get(AgendaType.LOW_SALES).action);
    }

    @Test
    public void rulesKeepTheirOwnLifecycleUnderRevival() {
        // Revival suppression is display-layer only (filterVisibleForVisit) —
        // the decider evaluates every rule on data regardless of revival.
        AgendaRuleDecider.Inputs in = baseInputs();
        in.revival = true;
        in.lastBillDaysAgo = 200;
        in.shortPercentage = 90d;
        in.currentAmt = 0;
        in.oldestLoanAgeDays = 45;
        in.pendingLoanAmt = 10000;
        Map<AgendaType, AgendaRuleDecider.Decision> d = decide(in);
        assertEquals(AgendaRuleDecider.Action.OPEN, d.get(AgendaType.LOW_PURCHASE).action);
        assertEquals(AgendaRuleDecider.Action.OPEN, d.get(AgendaType.LOW_INVESTMENT).action);
        assertEquals(AgendaRuleDecider.Action.OPEN, d.get(AgendaType.LOW_SALES).action);
        assertEquals(AgendaRuleDecider.Action.OPEN, d.get(AgendaType.CREDIT_DUES).action);
        assertEquals(AgendaRuleDecider.Action.OPEN, d.get(AgendaType.REVIVAL).action);
    }

    @Test
    public void purchaseFlagsAtGapAndNeverBilled() {
        AgendaRuleDecider.Inputs in = baseInputs();
        in.lastBillDaysAgo = 15; // exactly gapDays
        assertEquals(AgendaRuleDecider.Action.OPEN, decide(in).get(AgendaType.LOW_PURCHASE).action);
        in.lastBillDaysAgo = null; // never billed, non-revival
        assertEquals(AgendaRuleDecider.Action.OPEN, decide(in).get(AgendaType.LOW_PURCHASE).action);
        in.lastBillDaysAgo = 14;
        assertEquals(AgendaRuleDecider.Action.CLOSE, decide(in).get(AgendaType.LOW_PURCHASE).action);
    }

    @Test
    public void creditFlagsAtExactThreshold() {
        AgendaRuleDecider.Inputs in = baseInputs();
        in.oldestLoanAgeDays = 20;
        in.pendingLoanAmt = 50000;
        assertEquals(AgendaRuleDecider.Action.OPEN, decide(in).get(AgendaType.CREDIT_DUES).action);
        in.oldestLoanAgeDays = 19;
        assertEquals(AgendaRuleDecider.Action.CLOSE, decide(in).get(AgendaType.CREDIT_DUES).action);
    }

    @Test
    public void investmentUsesFiftyTriggerAndSkipsWhenUncomputable() {
        AgendaRuleDecider.Inputs in = baseInputs();
        in.shortPercentage = 51d;
        assertEquals(AgendaRuleDecider.Action.OPEN, decide(in).get(AgendaType.LOW_INVESTMENT).action);
        in.shortPercentage = 50d;
        assertEquals(AgendaRuleDecider.Action.CLOSE, decide(in).get(AgendaType.LOW_INVESTMENT).action);
        in.shortPercentage = null;
        assertEquals(AgendaRuleDecider.Action.LEAVE, decide(in).get(AgendaType.LOW_INVESTMENT).action);
    }
}