Subversion Repositories SmartDukaan

Rev

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

Rev 37353 Rev 37354
Line 84... Line 84...
84
 
84
 
85
    /** Source/createdBy label for leads captured by the AI assistant. */
85
    /** Source/createdBy label for leads captured by the AI assistant. */
86
    private static final String AI_LEAD_SOURCE = "AI Assistant";
86
    private static final String AI_LEAD_SOURCE = "AI Assistant";
87
 
87
 
88
    /**
88
    /**
89
     * Assignee used for AI leads only when no active Sales L1 can be resolved from cs.position.
89
     * Assignee used for AI leads only when no active BGC L1 can be resolved from cs.position.
90
     * Same auth id the web capture has always routed to, so intake never fails on an empty pool.
90
     * Same auth id the web capture has always routed to, so intake never fails on an empty pool.
91
     */
91
     */
92
    private static final int AI_LEAD_FALLBACK_ASSIGNEE = 53;
92
    private static final int AI_LEAD_FALLBACK_ASSIGNEE = 53;
93
 
93
 
94
    @Autowired
94
    @Autowired
Line 805... Line 805...
805
        String recordingUrl = aiLeadRequest.getRecordingUrl();
805
        String recordingUrl = aiLeadRequest.getRecordingUrl();
806
        if (recordingUrl != null && !recordingUrl.trim().isEmpty()) {
806
        if (recordingUrl != null && !recordingUrl.trim().isEmpty()) {
807
            lead.setRecordingUrl(recordingUrl.trim());
807
            lead.setRecordingUrl(recordingUrl.trim());
808
        }
808
        }
809
 
809
 
810
        // Auto-assign to a randomly picked active Sales L1 so AI leads spread across the field team
810
        // Auto-assign to a randomly picked active BGC L1 so AI leads spread across the lead desk
811
        lead.setAssignTo(resolveAiLeadAssignee());
811
        lead.setAssignTo(resolveAiLeadAssignee());
812
        lead.setAuthId(lead.getAssignTo());
812
        lead.setAuthId(lead.getAssignTo());
813
 
813
 
814
        lead.setCreatedTimestamp(LocalDateTime.now());
814
        lead.setCreatedTimestamp(LocalDateTime.now());
815
        lead.setUpdatedTimestamp(LocalDateTime.now());
815
        lead.setUpdatedTimestamp(LocalDateTime.now());
Line 819... Line 819...
819
        return responseSender.ok(lead.getId());
819
        return responseSender.ok(lead.getId());
820
 
820
 
821
    }
821
    }
822
 
822
 
823
    /**
823
    /**
824
     * Picks the owner for an incoming AI lead: a uniformly random <b>active</b> Sales L1 from
824
     * Picks the owner for an incoming AI lead: a uniformly random <b>active</b> BGC L1 from
825
     * cs.position (category {@link ProfitMandiConstants#TICKET_CATEGORY_SALES}, escalation L1).
825
     * cs.position (category {@link ProfitMandiConstants#TICKET_CATEGORY_BGC}, escalation L1).
826
     * <p>
826
     * <p>
-
 
827
     * BGC is the desk that works AI/inbound leads before they reach field sales, and BGC L1-L3 is
827
     * Sales L1 is the same position that drives Lead Management visibility, so the chosen user sees
828
     * already one of the groups offered in the Lead Management "Assign To" list, so a BGC L1 owner
828
     * the lead in their own list and their L2/L3 managers see it in their downline. Inactive users
829
     * is a valid assignee the team can see and reassign. Field Sales (category
-
 
830
     * {@link ProfitMandiConstants#TICKET_CATEGORY_SALES}) is deliberately NOT the pool here.
-
 
831
     * <p>
829
     * are filtered out here because {@code getAuthUserByCategoryId(int, EscalationType)} does not
832
     * Inactive users are filtered out because {@code getAuthUserByCategoryId(int, EscalationType)}
830
     * filter on active, and an inactive owner would strand the lead. Ids are already distinct per
833
     * does not filter on active, and an inactive owner would strand the lead. Ids are already
831
     * user, so holding several regional positions does not raise a person's odds of being picked.
834
     * distinct per user, so holding several regional positions does not raise a person's odds.
832
     */
835
     */
833
    private int resolveAiLeadAssignee() {
836
    private int resolveAiLeadAssignee() {
834
        List<AuthUser> salesL1 = csService.getAuthUserByCategoryId(
837
        List<AuthUser> bgcL1 = csService.getAuthUserByCategoryId(
835
                ProfitMandiConstants.TICKET_CATEGORY_SALES, EscalationType.L1);
838
                ProfitMandiConstants.TICKET_CATEGORY_BGC, EscalationType.L1);
836
 
839
 
837
        List<AuthUser> eligible = salesL1 == null ? Collections.<AuthUser>emptyList()
840
        List<AuthUser> eligible = bgcL1 == null ? Collections.<AuthUser>emptyList()
838
                : salesL1.stream()
841
                : bgcL1.stream()
839
                        .filter(x -> Boolean.TRUE.equals(x.isActive()))
842
                        .filter(x -> Boolean.TRUE.equals(x.isActive()))
840
                        .collect(Collectors.toList());
843
                        .collect(Collectors.toList());
841
 
844
 
842
        if (eligible.isEmpty()) {
845
        if (eligible.isEmpty()) {
843
            LOGGER.warn("AI lead intake: no active Sales L1 in cs.position, falling back to auth id {}",
846
            LOGGER.warn("AI lead intake: no active BGC L1 in cs.position, falling back to auth id {}",
844
                    AI_LEAD_FALLBACK_ASSIGNEE);
847
                    AI_LEAD_FALLBACK_ASSIGNEE);
845
            return AI_LEAD_FALLBACK_ASSIGNEE;
848
            return AI_LEAD_FALLBACK_ASSIGNEE;
846
        }
849
        }
847
 
850
 
848
        AuthUser assignee = eligible.get(ThreadLocalRandom.current().nextInt(eligible.size()));
851
        AuthUser assignee = eligible.get(ThreadLocalRandom.current().nextInt(eligible.size()));
849
        LOGGER.info("AI lead intake: assigned to Sales L1 {} ({}) picked from {} eligible",
852
        LOGGER.info("AI lead intake: assigned to BGC L1 {} ({}) picked from {} eligible",
850
                assignee.getId(), assignee.getFullName(), eligible.size());
853
                assignee.getId(), assignee.getFullName(), eligible.size());
851
        return assignee.getId();
854
        return assignee.getId();
852
    }
855
    }
853
 
856
 
854
    @RequestMapping(value = "/getPartnersList", method = RequestMethod.GET)
857
    @RequestMapping(value = "/getPartnersList", method = RequestMethod.GET)