Subversion Repositories SmartDukaan

Rev

Blame | Last modification | View Log | RSS feed

package com.spice.profitmandi.service.lms;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * What an LMS call or disposition attempt produced, in terms a controller can map onto its own
 * module's response envelope.
 *
 * <p>The LMS is now driven from two WARs with different response conventions — {@code
 * ResponseSender}'s {@code ProfitMandiResponse} in profitmandi-fofo, and both that and v2's {@code
 * ApiResponse} in profitmandi-web. The services below the controllers therefore say what happened
 * rather than how to say it, and each controller renders it its own way.
 */
public final class LmsOutcome {

    public enum Status {
        /** Proceed; {@link #data} carries the payload. */
        OK,
        /** The lead or call does not exist. */
        NOT_FOUND,
        /** Understood but declined — DND, calling hours, no endpoint, a vendor error, bad input. */
        REFUSED,
        /** No agent could be resolved from the request. */
        UNAUTHORIZED,
        /** The call belongs to somebody else. */
        FORBIDDEN,
        /** Server-placed calling is not configured in this environment. */
        UNAVAILABLE
    }

    public final Status status;

    /**
     * Machine-readable refusal reason — DND, OUTSIDE_HOURS, NO_NUMBER, NO_ENDPOINT, PLACE_FAILED,
     * INVALID. Null on success. The client branches on this; {@link #message} is for the human.
     */
    public final String code;

    public final String message;

    public final Map<String, Object> data = new LinkedHashMap<>();

    private LmsOutcome(Status status, String code, String message) {
        this.status = status;
        this.code = code;
        this.message = message;
    }

    static LmsOutcome ok() {
        return new LmsOutcome(Status.OK, null, null);
    }

    static LmsOutcome notFound(String message) {
        return new LmsOutcome(Status.NOT_FOUND, null, message);
    }

    static LmsOutcome refused(String code, String message) {
        return new LmsOutcome(Status.REFUSED, code, message);
    }

    static LmsOutcome invalid(String message) {
        return new LmsOutcome(Status.REFUSED, "INVALID", message);
    }

    static LmsOutcome unauthorized() {
        return new LmsOutcome(Status.UNAUTHORIZED, null, "Not signed in");
    }

    static LmsOutcome forbidden() {
        return new LmsOutcome(Status.FORBIDDEN, null, "That call is not yours");
    }

    static LmsOutcome unavailable(String message) {
        return new LmsOutcome(Status.UNAVAILABLE, null, message);
    }

    LmsOutcome with(String key, Object value) {
        data.put(key, value);
        return this;
    }

    public boolean isOk() {
        return status == Status.OK;
    }

    /**
     * The refusal as a 200-style body: {@code {ok:false, code, reason}}.
     *
     * <p>The pre-check answers this way rather than with a 4xx because "this retailer is on the DND
     * register" is a normal answer to "may I dial?", not a client error — and the caller needs the
     * code to decide what to show.
     */
    public Map<String, Object> asRefusalBody() {
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("ok", false);
        body.put("code", code);
        body.put("reason", message);
        return body;
    }
}