How would I go about generating a unique receipt number in the following range:
GA00000-GZ99999? I am not allowed to use the 'I' and 'O' letters so GI00000-GI99999 & GO00000-GO99999 would be excluded.
Ideally, I'd like to create this in T-SQL but can also do it in VB.Net. This number will be stored in SQL and I can access it prior to generating the next one. They do not have to be sequential.
Thanks.
Create an array
of all characters that are permitted as the first digit.
For any numeric receipt id n
the receipt code will be G
+ array[n/1000000]
+ n % 1000000
.
keep a suffix pointer. when your index wraps over 99999, increment it. Check for your special cases and exhaustion (e.g. Z).
Here's a VB.NET version to get the next sequential number, given the previous one. I think I covered all the cases.
Private Const FirstReceiptNumber As String = "GA00000"
Public Function GenerateReceiptNumber(ByVal lastNumber As String) As String
If lastNumber.Length <> 7 Then
Throw New ArgumentException("Incorrect length", "lastNumber")
End If
If lastNumber.StartsWith("G") = False Then
Throw New ArgumentException("Incorrect start character", "lastNumber")
End If
Dim letterPortion As Char = lastNumber.Chars(1)
If letterPortion < "A"c Or letterPortion > "Z"c Then
Throw New ArgumentException("Non-letter second character", "lastNumber")
End If
If letterPortion = "I"c Or letterPortion = "O"c Then
Throw New ArgumentException("Invalid second character", "lastNumber")
End If
Dim numericPortionString As String = lastNumber.Substring(2)
Dim numericPortion As Integer
If Integer.TryParse(numericPortionString, numericPortion) = False Then
Throw New ArgumentException("Invalid numeric portion", "lastNumber")
End If
If numericPortion = 99999 Then
If letterPortion = "Z"c Then
Throw New ArgumentException("No more receipt numbers possible", "lastNumber")
End If
numericPortion = 0
letterPortion = letterPortion + Chr(1)
If letterPortion = "I"c Or letterPortion = "O"c Then
letterPortion = letterPortion + Chr(1)
End If
Else
numericPortion = numericPortion + 1
End If
Return String.Format("G{0}{1:00000}", letterPortion, numericPortion)
End Function
I decided to do it as the following:
CREATE FUNCTION [dbo].[fn_generateReceiptNumber]()
RETURNS NCHAR(7)
AS
BEGIN
-- Declare the return variable here
DECLARE @result NCHAR(7);
DECLARE @prefix NCHAR(1);
DECLARE @suffix INT;
DECLARE @currentMax NCHAR(7);
SELECT @currentMax = MAX(ISNULL(fp.CustomReceiptNo, 'GA00001')) FROM dbo.FinPayment fp;
SELECT @prefix = SUBSTRING(@currentMax,2,1);
SELECT @suffix = CAST(SUBSTRING(@currentMax,3,7) AS INT);
IF((@suffix + 1) > 99999)
BEGIN
SELECT @suffix = 0;
END
ELSE
BEGIN
SELECT @suffix = @suffix + 1;
END
IF(@suffix = 0)
BEGIN
IF(@prefix = 'Z')
BEGIN
RETURN -1;
END
ELSE
BEGIN
IF(NCHAR(UNICODE(@prefix)+1) IN ('I', 'O'))
BEGIN
SELECT @prefix = NCHAR(UNICODE(@prefix)+2);
END
ELSE
BEGIN
SELECT @prefix = NCHAR(UNICODE(@prefix)+1);
END
END
END
-- Return the result of the function
SELECT @result = NCHAR(71) + @prefix + CAST(RIGHT('00000' + RTRIM(@suffix), 5) AS NCHAR(5));
RETURN @result;
END
GO
Thank you everyone for the input.
Steve.