Subversion Repositories SmartDukaan

Rev

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

Rev 37070 Rev 37668
Line 183... Line 183...
183
			result = false;
183
			result = false;
184
		}
184
		}
185
		return result;
185
		return result;
186
	}
186
	}
187
	
187
	
-
 
188
	/** Characters of a GSTIN, in the order the checksum weights them. */
-
 
189
	private static final String GSTIN_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
 
190
 
-
 
191
	/**
-
 
192
	 * 2-digit state code, 10-char PAN (5 letters, 4 digits, 1 letter), entity number,
-
 
193
	 * the literal Z, then the checksum character.
-
 
194
	 */
-
 
195
	private static final java.util.regex.Pattern GSTIN_PATTERN =
-
 
196
			java.util.regex.Pattern.compile("^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$");
-
 
197
 
-
 
198
	/** State codes issued by GSTN: 01-38, plus 97 (other territory) and 99 (centre). */
-
 
199
	private static final java.util.regex.Pattern GSTIN_STATE_CODE =
-
 
200
			java.util.regex.Pattern.compile("^(0[1-9]|[12][0-9]|3[0-8]|97|99)$");
-
 
201
 
-
 
202
	/**
-
 
203
	 * Whether a GSTIN is well formed: shape, a real state code, and the mod-36 checksum in the
-
 
204
	 * 15th character. A blank is still allowed - the field is optional for stores that have no
-
 
205
	 * registration - so callers that need one present must check for that themselves.
-
 
206
	 * <p>
-
 
207
	 * It used to accept any 15-character string, which let a pincode ({@code 110095}, rejected
-
 
208
	 * only for being 6 characters) and outright junk ({@code Hdjiekwbdbsjskz}) reach
-
 
209
	 * fofo_store.gst_number, where billing reads it. NIC then rejects the invoice and the goods
-
 
210
	 * cannot ship. The checksum is worth having on top of the shape: of 1,570 well-formed
-
 
211
	 * partner GSTINs on record exactly one fails it, so it costs nothing and catches the
-
 
212
	 * transposed or O-for-0 typo that the pattern alone cannot see.
-
 
213
	 */
188
	public static boolean isValidGstNumber(String gstNumber) {
214
	public static boolean isValidGstNumber(String gstNumber) {
189
		if(gstNumber == null || gstNumber.isEmpty() || gstNumber.length() == 15) {
215
		if(gstNumber == null || gstNumber.trim().isEmpty()) {
190
			return true;
216
			return true;
191
		}
217
		}
-
 
218
		String gstin = normalizeGstNumber(gstNumber);
-
 
219
		if(!GSTIN_PATTERN.matcher(gstin).matches()) {
192
		return false;
220
			return false;
-
 
221
		}
-
 
222
		if(!GSTIN_STATE_CODE.matcher(gstin.substring(0, 2)).matches()) {
-
 
223
			return false;
-
 
224
		}
-
 
225
		return gstin.charAt(14) == gstinChecksum(gstin);
-
 
226
	}
-
 
227
 
-
 
228
	/** Trimmed and upper-cased, so the same registration is never stored two ways. */
-
 
229
	public static String normalizeGstNumber(String gstNumber) {
-
 
230
		return gstNumber == null ? null : gstNumber.trim().toUpperCase();
-
 
231
	}
-
 
232
 
-
 
233
	/**
-
 
234
	 * GSTN's mod-36 check character over the first 14 characters: each is weighted 1, 2, 1, 2 ...
-
 
235
	 * and the two digits of each product are added separately before the total is complemented.
-
 
236
	 */
-
 
237
	private static char gstinChecksum(String gstin) {
-
 
238
		int total = 0;
-
 
239
		for(int i = 0; i < 14; i++) {
-
 
240
			int product = GSTIN_ALPHABET.indexOf(gstin.charAt(i)) * (i % 2 == 0 ? 1 : 2);
-
 
241
			total += product / 36 + product % 36;
-
 
242
		}
-
 
243
		return GSTIN_ALPHABET.charAt((36 - total % 36) % 36);
193
	}
244
	}
194
	
245
	
195
	public static List<String> getDuplicateElements(List<String> elements){
246
	public static List<String> getDuplicateElements(List<String> elements){
196
		List<String> duplicates = new ArrayList<>();
247
		List<String> duplicates = new ArrayList<>();
197
		for(int i = 0; i < elements.size(); i++){
248
		for(int i = 0; i < elements.size(); i++){