Subversion Repositories SmartDukaan

Rev

Rev 37128 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37128 Rev 37154
Line 2117... Line 2117...
2117
        LocalDateTime now = LocalDateTime.now();
2117
        LocalDateTime now = LocalDateTime.now();
2118
        LocalDateTime thirtyDaysAgo = now.minusDays(30);
2118
        LocalDateTime thirtyDaysAgo = now.minusDays(30);
2119
        LocalDateTime sixtyDaysAgo = now.minusDays(60);
2119
        LocalDateTime sixtyDaysAgo = now.minusDays(60);
2120
        long threshold = 99_999L;
2120
        long threshold = 99_999L;
2121
 
2121
 
-
 
2122
        // Include REVIVAL now so previously-downgraded stores can be promoted back to ACTIVE
-
 
2123
        // when they resume billing above the threshold in the last 30 days.
2122
        List<FofoStore> candidates = fofoStoreRepository.selectAllFranchiseStores().stream()
2124
        List<FofoStore> candidates = fofoStoreRepository.selectAllFranchiseStores().stream()
2123
                .filter(s -> s.isActive() && !s.isInternal() && !s.isClosed())
2125
                .filter(s -> s.isActive() && !s.isInternal() && !s.isClosed())
2124
                .filter(s -> s.getActivationType() == ActivationType.ACTIVE
2126
                .filter(s -> s.getActivationType() == ActivationType.ACTIVE
2125
                        || s.getActivationType() == ActivationType.FOCUS)
2127
                        || s.getActivationType() == ActivationType.FOCUS
-
 
2128
                        || s.getActivationType() == ActivationType.REVIVAL)
2126
                .collect(Collectors.toList());
2129
                .collect(Collectors.toList());
2127
 
2130
 
2128
        if (candidates.isEmpty()) {
2131
        if (candidates.isEmpty()) {
2129
            LOGGER.info("updatePartnerActivationTypeByMonthlySale: no candidate stores");
2132
            LOGGER.info("updatePartnerActivationTypeByMonthlySale: no candidate stores");
2130
            return;
2133
            return;
Line 2134... Line 2137...
2134
        Set<Integer> met30 = orderRepository.selectFofoIdsWithMtdBillingAboveThreshold(ids, thirtyDaysAgo, now, threshold);
2137
        Set<Integer> met30 = orderRepository.selectFofoIdsWithMtdBillingAboveThreshold(ids, thirtyDaysAgo, now, threshold);
2135
        Set<Integer> met60 = orderRepository.selectFofoIdsWithMtdBillingAboveThreshold(ids, sixtyDaysAgo, now, threshold);
2138
        Set<Integer> met60 = orderRepository.selectFofoIdsWithMtdBillingAboveThreshold(ids, sixtyDaysAgo, now, threshold);
2136
 
2139
 
2137
        int toFocus = 0;
2140
        int toFocus = 0;
2138
        int toRevival = 0;
2141
        int toRevival = 0;
-
 
2142
        int toActive = 0;
2139
        for (FofoStore store : candidates) {
2143
        for (FofoStore store : candidates) {
2140
            int id = store.getId();
2144
            int id = store.getId();
2141
            boolean below30 = !met30.contains(id);
2145
            boolean above30 = met30.contains(id);
-
 
2146
            boolean below30 = !above30;
2142
            boolean below60 = !met60.contains(id);
2147
            boolean below60 = !met60.contains(id);
2143
            ActivationType current = store.getActivationType();
2148
            ActivationType current = store.getActivationType();
2144
            ActivationType target = current;
2149
            ActivationType target = current;
2145
 
2150
 
-
 
2151
            // Promotion — asymmetric windows by current status:
-
 
2152
            //   FOCUS   → ACTIVE if billed > ₹99,999 in the last 30 days (recent activity required)
-
 
2153
            //   REVIVAL → ACTIVE if billed > ₹99,999 in the last 60 days (deeper trouble, so any
-
 
2154
            //             sign of life in the last 2 months earns a promotion)
-
 
2155
            // Evaluated ahead of the downgrade rules so a recently-billing REVIVAL isn't held at
-
 
2156
            // REVIVAL by the below60 rule below.
-
 
2157
            if (current == ActivationType.FOCUS && above30) {
-
 
2158
                target = ActivationType.ACTIVE;
-
 
2159
            } else if (current == ActivationType.REVIVAL && met60.contains(id)) {
-
 
2160
                target = ActivationType.ACTIVE;
2146
            if (below60) {
2161
            } else if (below60) {
2147
                target = ActivationType.REVIVAL;
2162
                target = ActivationType.REVIVAL;
2148
            } else if (below30 && current == ActivationType.ACTIVE) {
2163
            } else if (below30 && current == ActivationType.ACTIVE) {
2149
                target = ActivationType.FOCUS;
2164
                target = ActivationType.FOCUS;
2150
            }
2165
            }
2151
 
2166
 
2152
            if (target != current) {
2167
            if (target != current) {
-
 
2168
                // Safety guard only applies to downgrades — never auto-downgrade a store that
-
 
2169
                // has never billed yet. Promotions to ACTIVE always allowed (billing observed).
-
 
2170
                if (target != ActivationType.ACTIVE) {
2153
                LocalDateTime firstBillingDate = transactionRepository.getFirstBillingDate(id);
2171
                    LocalDateTime firstBillingDate = transactionRepository.getFirstBillingDate(id);
2154
                if (firstBillingDate == null) {
2172
                    if (firstBillingDate == null) {
2155
                    LOGGER.info("Skip auto-downgrade fofoId={} code={}: first billing pending",
2173
                        LOGGER.info("Skip auto-downgrade fofoId={} code={}: first billing pending",
2156
                            id, store.getCode());
2174
                                id, store.getCode());
2157
                    continue;
2175
                        continue;
-
 
2176
                    }
2158
                }
2177
                }
2159
                LOGGER.info("Auto-downgrade fofoId={} code={} from {} to {} (below30={}, below60={})",
2178
                LOGGER.info("Auto-{} fofoId={} code={} from {} to {} (above30={}, below60={})",
-
 
2179
                        target == ActivationType.ACTIVE ? "promote" : "downgrade",
2160
                        id, store.getCode(), current, target, below30, below60);
2180
                        id, store.getCode(), current, target, above30, below60);
2161
                store.setActivationType(target);
2181
                store.setActivationType(target);
2162
                fofoStoreRepository.persist(store);
2182
                fofoStoreRepository.persist(store);
2163
                if (target == ActivationType.FOCUS) {
2183
                if (target == ActivationType.FOCUS) {
2164
                    toFocus++;
2184
                    toFocus++;
2165
                } else {
2185
                } else if (target == ActivationType.REVIVAL) {
2166
                    toRevival++;
2186
                    toRevival++;
-
 
2187
                } else if (target == ActivationType.ACTIVE) {
-
 
2188
                    toActive++;
2167
                }
2189
                }
2168
            }
2190
            }
2169
        }
2191
        }
2170
        LOGGER.info("updatePartnerActivationTypeByMonthlySale done: scanned={}, toFocus={}, toRevival={}",
2192
        LOGGER.info("updatePartnerActivationTypeByMonthlySale done: scanned={}, toFocus={}, toRevival={}, toActive={}",
2171
                candidates.size(), toFocus, toRevival);
2193
                candidates.size(), toFocus, toRevival, toActive);
2172
    }
2194
    }
2173
 
2195
 
2174
    public void sendAgeingReport() throws Exception {
2196
    public void sendAgeingReport() throws Exception {
2175
        sendAgeingReport("kamini.sharma@smartdukaan.com", "tarun.verma@smartdukaan.com", "niranjan.kala@smartdukaan.com", "kuldeep.kumar@smartdukaan.com");
2197
        sendAgeingReport("kamini.sharma@smartdukaan.com", "tarun.verma@smartdukaan.com", "niranjan.kala@smartdukaan.com", "kuldeep.kumar@smartdukaan.com");
2176
    }
2198
    }