Subversion Repositories SmartDukaan

Rev

Blame | Last modification | View Log | RSS feed

package com.spice.profitmandi.common.util;

import java.util.regex.Pattern;

/**
 * Reads the parts of a GSTIN that other data is supposed to agree with.
 *
 * <p>A GSTIN is 15 characters: a two digit state code, the holder's ten character PAN, an entity number, a
 * fixed 'Z', and a check character. The state code is therefore the authority on which state a party belongs
 * to - a separately stored state id is a copy that can drift, and has.
 */
public final class GstinUtil {

    private static final Pattern GSTIN = Pattern.compile("^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][0-9A-Z]Z[0-9A-Z]$");

    private GstinUtil() {
    }

    /** Trims and upper-cases, so a value typed with stray spaces or in lower case still compares equal. */
    public static String normalise(String gstin) {
        if (gstin == null) {
            return null;
        }
        String trimmed = gstin.replace("\t", "").replace(" ", " ").trim().toUpperCase();
        return trimmed.isEmpty() ? null : trimmed;
    }

    public static boolean isBlank(String gstin) {
        return normalise(gstin) == null;
    }

    /** True only for a value of the exact shape the GST authority issues. */
    public static boolean isValidFormat(String gstin) {
        String normalised = normalise(gstin);
        return normalised != null && GSTIN.matcher(normalised).matches();
    }

    /** The two digit state code, e.g. "07" for Delhi. Null unless the GSTIN is well formed. */
    public static String stateCodeOf(String gstin) {
        return isValidFormat(gstin) ? normalise(gstin).substring(0, 2) : null;
    }

    /** The PAN embedded in the GSTIN. Null unless the GSTIN is well formed. */
    public static String panOf(String gstin) {
        return isValidFormat(gstin) ? normalise(gstin).substring(2, 12) : null;
    }

    /**
     * Whether two parties are registered in the same state, which is what decides CGST+SGST against IGST.
     * Null unless both GSTINs are well formed - an unknown answer, never a false "same".
     */
    public static Boolean sameState(String oneGstin, String otherGstin) {
        String one = stateCodeOf(oneGstin);
        String other = stateCodeOf(otherGstin);
        return one == null || other == null ? null : one.equals(other);
    }
}