5.10.1. Controllers for Invoices
The controller of the invoice module must be able to return data for both invoice headers and the associated invoice lines. The same applies to the methods for adding, editing and deleting records.
[Authorize(Roles = "manager")]public class InvoiceController : Controller{private DbModel db = new DbModel();// display viewpublic ActionResult Index(){return View();}// Receiving data in the JSON format for the main gridpublic ActionResult GetData(int? rows, int? page, string sidx, string sord,string searchField, string searchString, string searchOper){// get the page number, the number of data displayedint pageNo = page ?? 1;int limit = rows ?? 20;// calculate offsetint offset = (pageNo - 1) * limit;// building a request for receipt of invoicesvar invoicesQuery =from invoice in db.INVOICESwhere (invoice.INVOICE_DATE >= AppVariables.StartDate) &&(invoice.INVOICE_DATE <= AppVariables.FinishDate)select new{INVOICE_ID = invoice.INVOICE_ID,CUSTOMER_ID = invoice.CUSTOMER_ID,CUSTOMER_NAME = invoice.CUSTOMER.NAME,INVOICE_DATE = invoice.INVOICE_DATE,TOTAL_SALE = invoice.TOTAL_SALE,PAID = invoice.PAID};// adding a search condition to the query, if it is produced// for different fields, different comparison operators// are available when searchingif (searchField == "CUSTOMER_NAME"){switch (searchOper){case "eq": // equalinvoicesQuery = invoicesQuery.Where(c => c.CUSTOMER_NAME == searchString);break;case "bw": // starting withinvoicesQuery = invoicesQuery.Where(c => c.CUSTOMER_NAME.StartsWith(searchString));break;case "cn": // containinginvoicesQuery = invoicesQuery.Where(c => c.CUSTOMER_NAME.Contains(searchString));break;}}if (searchField == "INVOICE_DATE"){var dateValue = DateTime.Parse(searchString);switch (searchOper){case "eq": // =invoicesQuery = invoicesQuery.Where(c => c.INVOICE_DATE == dateValue);break;case "lt": // <invoicesQuery = invoicesQuery.Where(c => c.INVOICE_DATE < dateValue);break;case "le": // <=invoicesQuery = invoicesQuery.Where(c => c.INVOICE_DATE <= dateValue);break;case "gt": // >invoicesQuery = invoicesQuery.Where(c => c.INVOICE_DATE > dateValue);break;case "ge": // >=invoicesQuery = invoicesQuery.Where(c => c.INVOICE_DATE >= dateValue);break;}}if (searchField == "PAID"){int iVal = (searchString == "on") ? 1 : 0;invoicesQuery = invoicesQuery.Where(c => c.PAID == iVal);}// get the total number of invoicesint totalRows = invoicesQuery.Count();// add sortingswitch (sord){case "asc":invoicesQuery = invoicesQuery.OrderBy(invoice => invoice.INVOICE_DATE);break;case "desc":invoicesQuery = invoicesQuery.OrderByDescending(invoice => invoice.INVOICE_DATE);break;}// get invoice listvar invoices = invoicesQuery.Skip(offset).Take(limit).ToList();// calculate the total number of pagesint totalPages = totalRows / limit + 1;// create the result for jqGridvar result = new{page = pageNo,total = totalPages,records = totalRows,rows = invoices};// convert the result to JSONreturn Json(result, JsonRequestBehavior.AllowGet);}// Receiving data in the form of JSON for the detail gridpublic ActionResult GetDetailData(int? invoice_id){// build a LINQ query for receiving invoice items// filtered by invoice idvar lines =from line in db.INVOICE_LINESwhere line.INVOICE_ID == invoice_idselect new{INVOICE_LINE_ID = line.INVOICE_LINE_ID,INVOICE_ID = line.INVOICE_ID,PRODUCT_ID = line.PRODUCT_ID,Product = line.PRODUCT.NAME,Quantity = line.QUANTITY,Price = line.SALE_PRICE,Total = line.QUANTITY * line.SALE_PRICE};// get invoice position listvar invoices = lines.ToList();// create the result for jqGridvar result = new{rows = invoices};// convert the result to JSONreturn Json(result, JsonRequestBehavior.AllowGet);}// Add new invoice[HttpPost][ValidateAntiForgeryToken]public ActionResult Create([Bind(Include = "CUSTOMER_ID,INVOICE_DATE")] INVOICE invoice){// check the correctness of the modelif (ModelState.IsValid){try{var INVOICE_ID = new FbParameter("INVOICE_ID", FbDbType.Integer);var CUSTOMER_ID = new FbParameter("CUSTOMER_ID", FbDbType.Integer);var INVOICE_DATE = new FbParameter("INVOICE_DATE",FbDbType.TimeStamp);// initialize parameters queryINVOICE_ID.Value = db.NextValueFor("GEN_INVOICE_ID");CUSTOMER_ID.Value = invoice.CUSTOMER_ID;INVOICE_DATE.Value = invoice.INVOICE_DATE;// execute stored proceduredb.Database.ExecuteSqlCommand("EXECUTE PROCEDURE SP_ADD_INVOICE(@INVOICE_ID, @CUSTOMER_ID, @INVOICE_DATE)",INVOICE_ID,CUSTOMER_ID,INVOICE_DATE);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}else {string messages = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));// return error in JSON formatreturn Json(new { error = messages });}}// Edit invoice[HttpPost][ValidateAntiForgeryToken]public ActionResult Edit([Bind(Include = "INVOICE_ID,CUSTOMER_ID,INVOICE_DATE")] INVOICE invoice){// check the correctness of the modelif (ModelState.IsValid){try{var INVOICE_ID = new FbParameter("INVOICE_ID", FbDbType.Integer);var CUSTOMER_ID = new FbParameter("CUSTOMER_ID", FbDbType.Integer);var INVOICE_DATE = new FbParameter("INVOICE_DATE",FbDbType.TimeStamp);// initialize parameters queryINVOICE_ID.Value = invoice.INVOICE_ID;CUSTOMER_ID.Value = invoice.CUSTOMER_ID;INVOICE_DATE.Value = invoice.INVOICE_DATE;// execute stored proceduredb.Database.ExecuteSqlCommand("EXECUTE PROCEDURE SP_EDIT_INVOICE(@INVOICE_ID, @CUSTOMER_ID, @INVOICE_DATE)",INVOICE_ID,CUSTOMER_ID,INVOICE_DATE);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}else {string messages = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));// return error in JSON formatreturn Json(new { error = messages });}}// Delete invoice[HttpPost][ValidateAntiForgeryToken]public ActionResult Delete(int id){try{var INVOICE_ID = new FbParameter("INVOICE_ID", FbDbType.Integer);// initialize parameters queryINVOICE_ID.Value = id;// execute stored proceduredb.Database.ExecuteSqlCommand("EXECUTE PROCEDURE SP_DELETE_INVOICE(@INVOICE_ID)",INVOICE_ID);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}// Payment of invoice[HttpPost][ValidateAntiForgeryToken]public ActionResult Pay(int id){try{var INVOICE_ID = new FbParameter("INVOICE_ID", FbDbType.Integer);// initialize parameters queryINVOICE_ID.Value = id;// execute stored proceduredb.Database.ExecuteSqlCommand("EXECUTE PROCEDURE SP_PAY_FOR_INOVICE(@INVOICE_ID)",INVOICE_ID);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}// Add invoice position[HttpPost][ValidateAntiForgeryToken]public ActionResult CreateDetail([Bind(Include = "INVOICE_ID,PRODUCT_ID,QUANTITY")] INVOICE_LINE invoiceLine){// check the correctness of the modelif (ModelState.IsValid){try{var INVOICE_ID = new FbParameter("INVOICE_ID", FbDbType.Integer);var PRODUCT_ID = new FbParameter("PRODUCT_ID", FbDbType.Integer);var QUANTITY = new FbParameter("QUANTITY", FbDbType.Integer);// initialize parameters queryINVOICE_ID.Value = invoiceLine.INVOICE_ID;PRODUCT_ID.Value = invoiceLine.PRODUCT_ID;QUANTITY.Value = invoiceLine.QUANTITY;// execute stored proceduredb.Database.ExecuteSqlCommand(""EXECUTE PROCEDURE SP_ADD_INVOICE_LINE(@INVOICE_ID, @PRODUCT_ID, @QUANTITY)",INVOICE_ID,PRODUCT_ID,QUANTITY);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}else {string messages = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));// return error in JSON formatreturn Json(new { error = messages });}}// Edit invoice position[HttpPost][ValidateAntiForgeryToken]public ActionResult EditDetail([Bind(Include = "INVOICE_LINE_ID,INVOICE_ID,PRODUCT_ID,QUANTITY")]INVOICE_LINE invoiceLine){// check the correctness of the modelif (ModelState.IsValid){try{// Create parametersvar INVOICE_LINE_ID = new FbParameter("INVOICE_LINE_ID",FbDbType.Integer);var QUANTITY = new FbParameter("QUANTITY", FbDbType.Integer);// initialize parameters queryINVOICE_LINE_ID.Value = invoiceLine.INVOICE_LINE_ID;QUANTITY.Value = invoiceLine.QUANTITY;// execute stored proceduredb.Database.ExecuteSqlCommand("EXECUTE PROCEDURE SP_EDIT_INVOICE_LINE(@INVOICE_LINE_ID, @QUANTITY)",INVOICE_LINE_ID,QUANTITY);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}else {string messages = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));// return error in JSON formatreturn Json(new { error = messages });}}// Delete invoice position[HttpPost][ValidateAntiForgeryToken]public ActionResult DeleteDetail(int id){try{// create parametersvar INVOICE_LINE_ID = new FbParameter("INVOICE_LINE_ID",FbDbType.Integer);// initialize parameters queryINVOICE_LINE_ID.Value = id;// execute stored proceduredb.Database.ExecuteSqlCommand("EXECUTE PROCEDURE SP_DELETE_INVOICE_LINE(@INVOICE_LINE_ID)",INVOICE_LINE_ID);// return success in JSON formatreturn Json(true);}catch (Exception ex){// return error in JSON formatreturn Json(new { error = ex.Message });}}protected override void Dispose(bool disposing){if (disposing){db.Dispose();}base.Dispose(disposing);}}
The GetDetailData method for retrieving the list of lines in an invoice lacks the code for page-by-page navigation. Realistically, a typical invoice does not have enough lines to justify using page-by-page navigation for them. Omitting it simplifies and speeds up the code.
In our project, all data modification operations are performed in stored procedures, but you could do the same work using Entity Framework. DDL code for the stored procedures can be found in the database creation script in an earlier chapter and also in the .zip archives of all the DDL scripts:
https://github.com/sim1984/example-db_2_5/archive/1.0.zip
or https://github.com/sim1984/example-db_3_0/archive/1.0.zip
