Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have one application having invoice number.invoice textbox having auto increment value initial as "1". Now I want invoice number should be started fresh for every financial year.

What I have tried:

C#
private void FillInvoiceID()
    {
        string con = ConfigurationManager.AppSettings["FilePath"].ToString();
        OleDbConnection c1 = new OleDbConnection(con);
        if (c1.State == ConnectionState.Open)
        {
            c1.Close();
        }
        c1.Open();
        string retInvoiceIDQuery = "SELECT Max(INVOICENO) as INVOICENO FROM TAXINVOICE";
        OleDbCommand commd = new OleDbCommand(retInvoiceIDQuery, c1);
        OleDbDataAdapter datadp = new OleDbDataAdapter(commd);
        DataTable datset = new DataTable();
        datadp.Fill(datset);
        if (datset.Rows[0][0] != null && string.IsNullOrEmpty(datset.Rows[0][0].ToString()))
        {
            datset.Rows[0][0] = "0";
        }

        invoice = Convert.ToInt32(datset.Rows[0]["INVOICENO"].ToString()) + 1;
        txtInvoice.Text = invoice.ToString();
        c1.Close();
    }
Posted
Updated 8-Mar-17 7:29am
v2
Comments
Karthik_Mahalingam 8-Mar-17 1:30am    
then it will have duplicate invoice rite ?
[no name] 8-Mar-17 19:17pm    
This is the obvious problem. Invoice #xxx2323. What year was that?
Er. Puneet Goel 8-Mar-17 1:42am    
So if you start with 1, every year it will start repeating. So you can go for Year_InvoiceNo like 2017-10000, 2017-10001 etc.
Jignesh Khant 8-Mar-17 1:46am    
You can rename the existing table and recreate the same table at start of financial year. By doing this you can start invoice number from 1 but you cannot have last financial years data.
Tomas Takac 8-Mar-17 2:32am    
What I would do is to create a table InvoiceNumbers(FiscalYear, CurrentInvoiceNumber). To get next invoice number you need to read the current invoice number from the table for the current fiscal year, increment it by 1 and then update the table with that new number. Please make sure this runs in a transaction and you place an update lock on the table while reading it. Then you are free to use this invoice number as you please.

1 solution

Here is a solution that uses an identity column and triggers and in theory should work well in a multi-user environment (unlike solutions that read the current max invoice number).
I have an invoice table that contains at least:
SQL
create table invoice
(
	id int identity(1,1),
	invoicedate date,
	invoiceNumber varchar(20)
)

Note that I have an id column that SQL is going to automatically increment for me but I also have an invoiceNumber column which will contain the contrived invoice number starting at 1 each year.

I also need a table to track the maximum id per year.
SQL
create table invoiceYears
(
	invoiceYear int NOT NULL,
	maxid int
)
I then create a TRIGGER on the invoice table to "calculate" the contrived invoiceNumber each time an invoice is inserted into the table.
SQL
CREEATE TRIGGER trig ON [dbo].invoice 
AFTER INSERT
AS
	declare @invid int;
	declare @invyear int;
	declare @invnum varchar(20);


	select @invid=i.id from inserted i;	
	select @invyear=datepart(YEAR, i.invoicedate) from inserted i;	

	if exists (SELECT TOP 1 invoiceYear FROM invoiceYears WHERE invoiceYear = @invyear)
	BEGIN
		UPDATE invoiceYears set maxid = @invid WHERE invoiceYear = @invyear
	END
	ELSE
	BEGIN
		INSERT INTO invoiceYears values (@invyear, @invid)
	END

	UPDATE inv SET invoiceNumber = 'ABC-' + CAST(@invyear AS VARCHAR(4)) + '-' + CAST(inv.id - ISNULL(IY.maxid, 0) AS varchar(20))
	FROM invoice inv
	LEFT OUTER JOIN invoiceYears IY ON IY.invoiceYear = @invyear - 1
	WHERE inv.id = @invid

GO

Note that it will insert a new row into this table at the change of the year. If your financial year does not start on 1st January of each year you will need to replace the DATEPART with the calculation of the financial year.

Other things to note:
- Because I've used a trigger then this isn't the most performant method to use in a high volume scenario.
- It won't work if you "skip" a year - unless you manually update the invoiceYears table
- I would normally leave the formatting of the invoice number to the presentation layer - if this is removed from the trigger then it performs better on inserts with only a minor extra overhead on reads.
- See the comments from Tomas above regarding transactions and locks - I haven't put these into the solution (for the sake of keeping as a simple example)
 
Share this answer
 
v2
Comments
Dave Kreskowiak 8-Mar-17 13:55pm    
Just a thought, but wouldn't it be easier to RESEED the autonumber field to something like 201700000001?
CHill60 8-Mar-17 17:13pm    
OMG - I'm showing my age - given that DBCC CHECKIDENT (Transact-SQL)[^] came in with 2008!
I agree - it would be the better solution - the only difference being - when would the OP run this? Personally I would have (and always did have) "year end procedures" that set up the database for the next fiscal year. Re-seeding also takes away the issues I noted. A virtual 5 (for now - unless you post the alternative solution :-) )
Dave Kreskowiak 9-Mar-17 7:40am    
No alternate solution here.
I was thinking year-end procedures myself.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900