Skip to content
KumarNitish007Public

About

Indian business essentials for .NET - GSTIN (with checksum), PAN, TAN, Aadhaar, IFSC validation; lakh/crore formatting and amount in words; GST calculation; financial years. NuGet package.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

IndiaKit

IndiaKit

Indian business essentials for .NET: validate GSTIN (with its check digit), PAN, TAN, Aadhaar, IFSC, PIN codes and mobile numbers; format rupees the Indian way (₹12,34,567.00 · ₹4.2 L · "Rupees … Only"); calculate GST; work with financial years. Zero dependencies on .NET 8, culture-independent, AOT- and trimming-friendly.

CI Targets Tests License: MIT

Why

Every Indian ERP, invoicing or KYC system rewrites the same helpers, usually with a regex that accepts GSTINs with typos, ToString("N2") that groups digits the Western way on Linux servers, and an amount-in-words function copied from a forum. IndiaKit does these properly, once, with tests:

  • Real checksums, not just regexes. GSTIN uses the GSTN mod-36 check digit and Aadhaar the Verhoeff algorithm. The test suite proves every single-character typo in a GSTIN (all 525 of them) and every adjacent-digit swap in an Aadhaar number is caught.
  • Errors you can show users. Check() says what's wrong: "Invalid check digit: expected 'V', got 'X'. Check for a typo."
  • Same output on every server. Lakh/crore grouping is implemented directly, not borrowed from the OS culture (en-IN data differs between Windows, ICU and invariant-mode containers).

Install

dotnet add package IndiaKit
dotnet add package IndiaKit.FluentValidation   # optional: FluentValidation rules

Quick tour

using IndiaKit.Identifiers;
using IndiaKit.Money;
using IndiaKit.Gst;
using IndiaKit.Dates;

Gstin.Check("27AAPFU0939F1ZV");            // Valid
Gstin.Check("27AAPFU0939F1ZX");            // Invalid check digit: expected 'V', got 'X'. Check for a typo.

var gstin = Gstin.Parse("27 aapfu 0939f 1zv");   // spaces / lower case tolerated
// 27AAPFU0939F1ZV -> Maharashtra, PAN AAPFU0939F (Firm)

Aadhaar.Mask("2341 2341 2346");            // XXXX XXXX 2346
IndianMobile.ToE164("098765 43210");       // +919876543210
Ifsc.BankCode("HDFC0001234");              // HDFC

Rupees.Format(12345678.9m);                // ₹1,23,45,678.90
Rupees.FormatCompact(4_250_000m);          // ₹42.5 L
Rupees.ToWords(118000m);                   // Rupees One Lakh Eighteen Thousand Only

var interState = GstCalculator.IsInterState(supplierStateCode: "27", placeOfSupplyStateCode: gstin.StateCode);
GstCalculator.Calculate(100_000m, 18m, interState);
// Taxable 100000.00 + CGST 9000.00 + SGST 9000.00 = 118000.00
GstCalculator.FromInclusive(1180m, 18m, interState: true);
// Taxable 1000.00 + IGST 180.00 = 1180.00

var fy = FinancialYear.For(new DateTime(2026, 10, 12));
// FY 2026-27 | AY 2027-28 | Q3 | invoice prefix INV/2026-27/

That output is real: it's samples/IndiaKit.Sample, which you can run with dotnet run --project samples/IndiaKit.Sample.

Validation in ASP.NET Core

DataAnnotations (included in the main package). Empty values pass, so combine with [Required] when needed:

using IndiaKit.Validation;

public sealed class VendorForm
{
    [Required, Gstin] public string? Gstin { get; set; }
    [Pan]             public string? Pan { get; set; }
    [IndianMobile]    public string? Mobile { get; set; }
    [Pincode(ErrorMessage = "Enter a 6-digit PIN code")] public string? Pin { get; set; }
}

Errors carry the precise reason ("Invalid check digit: expected 'V', got 'X'") unless you set ErrorMessage. Available: [Gstin], [Pan], [Tan], [Aadhaar], [Ifsc], [Pincode], [IndianMobile].

FluentValidation (IndiaKit.FluentValidation, works with FluentValidation 11 and 12):

using IndiaKit.FluentValidation;

RuleFor(v => v.Gstin).NotEmpty().GstinInState(v => v.StateCode);  // "GSTIN is registered in Maharashtra, not Karnataka."
RuleFor(v => v.Pan).Pan();
RuleFor(v => v.Mobile).IndianMobile();

API overview

Area Types Highlights
Identifiers Gstin, Pan, Tan, Aadhaar, Ifsc, Pincode, IndianMobile, Verhoeff Check (reason), IsValid, TryParse / Parse; GSTIN → state, PAN, entity number; PAN → holder type; masking; E.164 mobiles
GST GstCalculator, GstLine, GstBreakup, GstStates per-line rounding to paise, CGST/SGST split that always reconciles, inclusive-price back-calculation, state-code table with names and abbreviations
Money Rupees Format, FormatCompact (K / L / Cr), ToWords, NumberToWords
Dates FinancialYear For(date), Current (IST), Start/End, assessment year, QuarterOf, MonthOf, parsing "FY 2026-27" / "2026-27"

GST rates: accepts 0, 0.25, 3, 5, 18 and 40%, plus 12% and 28% so that invoices dated before the September 2025 rate rationalisation can still be calculated.

Privacy: only the format of an Aadhaar number is checked, never whether it was issued. Aadhaar and PAN are sensitive personal data: store them encrypted and display them masked (Aadhaar.Mask, Pan.Mask).

Design notes

  • readonly struct value types for Gstin, Pan and FinancialYear: no allocations beyond the normalised string, equality by value.
  • Multi-targets netstandard2.0 (.NET Framework 4.6.1+, Xamarin, Unity) and net8.0, which is marked IsTrimmable and IsAotCompatible.
  • Packages ship with SourceLink, deterministic builds, symbol packages (.snupkg) and XML docs, and use package validation to guard the public API.

Contributing / releasing

dotnet test                       # 105 tests
dotnet pack -c Release -o artifacts

Releases are published from GitHub Actions with NuGet Trusted Publishing (OIDC). No API key is stored in the repository: pushing a tag v1.2.3 builds, tests, packs and publishes both packages.

License

MIT © Nitish Kumar. More projects: github.com/KumarNitish007

About

Indian business essentials for .NET - GSTIN (with checksum), PAN, TAN, Aadhaar, IFSC validation; lakh/crore formatting and amount in words; GST calculation; financial years. NuGet package.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages