public async Task <Invoice> UpdateInvoice(Invoice invoice, EditInvoiceModel model) { // get team out of invoice var team = invoice.Team; // find account var account = await _dbContext.FinancialAccounts .FirstOrDefaultAsync(a => a.Team.Id == team.Id && a.Id == model.AccountId); if (account == null) { throw new ArgumentException("Account Id not found for this team.", nameof(model.AccountId)); } if (!account.IsActive) { throw new ArgumentException("Account is inactive.", nameof(model.AccountId)); } // find coupon Coupon coupon = null; if (model.CouponId > 0) { coupon = await _dbContext.Coupons .FirstOrDefaultAsync(c => c.Team.Id == team.Id && c.Id == model.CouponId); } // TODO: Consider modifying items instead of replacing // remove old items _dbContext.LineItems.RemoveRange(invoice.Items); // update invoice invoice.Account = account; invoice.Coupon = coupon; invoice.CustomerAddress = model.Customer.Address; invoice.CustomerEmail = model.Customer.Email; invoice.CustomerName = model.Customer.Name; invoice.CustomerCompany = model.Customer.Company; invoice.Memo = model.Memo; invoice.ManualDiscount = model.ManualDiscount; invoice.TaxPercent = model.TaxPercent; invoice.DueDate = model.DueDate; // increase draft count invoice.DraftCount++; // add line items var items = model.Items.Select(i => new LineItem() { Amount = i.Amount, Description = i.Description, Quantity = i.Quantity, TaxExempt = i.TaxExempt, Total = i.Quantity * i.Amount, }); invoice.Items = items.ToList(); // add attachments var attachments = model.Attachments.Select(a => new InvoiceAttachment() { Identifier = a.Identifier, FileName = a.FileName, ContentType = a.ContentType, Size = a.Size, }); invoice.Attachments = attachments.ToList(); // editing a sent invoice will modify the link id if (invoice.Sent) { SetInvoiceKey(invoice); } invoice.UpdateCalculatedValues(); return(invoice); }
public async Task <IActionResult> Edit(int id) { // look for invoice var invoice = await _dbContext.Invoices .Include(i => i.Account) .Include(i => i.Coupon) .Include(i => i.Items) .Include(i => i.Attachments) .Where(i => i.Team.Slug == TeamSlug) .FirstOrDefaultAsync(i => i.Id == id); if (invoice == null) { return(NotFound()); } // fetch team data var team = await _dbContext.Teams .Include(t => t.Accounts) .Include(t => t.Coupons) .FirstOrDefaultAsync(t => t.Slug == TeamSlug); ViewBag.Team = new { team.Id, team.Name, team.Slug, team.ContactEmail, team.ContactPhoneNumber }; ViewBag.Accounts = team.Accounts .Where(a => a.IsActive) .Select(a => new { a.Id, a.Name, a.Description, a.IsDefault, a.Chart, a.Account, a.SubAccount, a.Project, }); // include all active coupons, and the currently selected coupon ViewBag.Coupons = team.Coupons .Where(c => c.ExpiresAt == null || c.ExpiresAt >= DateTime.UtcNow.ToPacificTime().Date || c.Id == invoice.Coupon?.Id) .Select(c => new { c.Id, c.Name, c.Code, c.DiscountAmount, c.DiscountPercent, c.ExpiresAt, }); // build model for view var model = new EditInvoiceModel() { AccountId = invoice.Account?.Id ?? 0, CouponId = invoice.Coupon?.Id ?? 0, ManualDiscount = invoice.ManualDiscount, DueDate = invoice.DueDate, TaxPercent = invoice.TaxPercent, Memo = invoice.Memo, Customer = new EditInvoiceCustomerModel() { Name = invoice.CustomerName, Address = invoice.CustomerAddress, Email = invoice.CustomerEmail, Company = invoice.CustomerCompany, }, Items = invoice.Items.Select(i => new EditInvoiceItemModel() { Amount = i.Amount, Description = i.Description, Quantity = i.Quantity, TaxExempt = i.TaxExempt, Total = i.Amount * i.Quantity, }).ToList(), Attachments = invoice.Attachments.Select(a => new EditInvoiceAttachmentModel() { Identifier = a.Identifier, FileName = a.FileName, ContentType = a.ContentType, Size = a.Size, }).ToList() }; // add other relevant data ViewBag.Id = id; ViewBag.Sent = invoice.Sent; return(View(model)); }
public async Task <IActionResult> Edit(int id, [FromBody] EditInvoiceModel model) { var user = await _userManager.GetUserAsync(User); // find item var invoice = await _dbContext.Invoices .Include(i => i.Items) .Include(i => i.Attachments) .Include(i => i.Team) .Where(i => i.Team.Slug == TeamSlug) .FirstOrDefaultAsync(i => i.Id == id); if (invoice == null) { return(NotFound()); } // validate model if (!ModelState.IsValid) { return(new JsonResult(new { success = false, errorMessage = "Errors found in request", modelState = ModelState })); } try { await _invoiceService.UpdateInvoice(invoice, model); } catch (ArgumentException ex) { ModelState.AddModelError(ex.ParamName, ex.Message); return(new JsonResult(new { success = false, errorMessage = "Errors found in request", modelState = ModelState })); } // record action var action = new History() { Type = HistoryActionTypes.InvoiceEdited.TypeCode, ActionDateTime = DateTime.UtcNow, Actor = user.Name, }; invoice.History.Add(action); // save to db _dbContext.SaveChanges(); return(new JsonResult(new { success = true })); }
public async Task <IActionResult> Edit(int id, [FromBody] EditInvoiceModel model) { var team = await GetAuthorizedTeam(); // find item var invoice = await _dbContext.Invoices .Include(i => i.Items) .Include(i => i.Attachments) .Include(i => i.Team) .Where(i => i.Team.Id == team.Id) .FirstOrDefaultAsync(i => i.Id == id); if (invoice == null) { return(NotFound()); } // validate model if (!ModelState.IsValid) { return(new BadRequestObjectResult(new { success = false, errorMessage = "Errors found in request", modelState = ModelState })); } try { await _invoiceService.UpdateInvoice(invoice, model); } catch (ArgumentException ex) { ModelState.AddModelError(ex.ParamName, ex.Message); return(new BadRequestObjectResult(new { success = false, errorMessage = "Errors found in request", modelState = ModelState })); } // record action var action = new History() { Type = HistoryActionTypes.InvoiceEdited.TypeCode, ActionDateTime = DateTime.UtcNow, }; invoice.History.Add(action); await _dbContext.SaveChangesAsync(); // build response, send possible new link var response = new EditInvoiceResult { Success = true, Id = invoice.Id, }; if (invoice.Sent) { response.PaymentLink = Url.Action("Pay", "Payments", new { id = invoice.LinkId }); } return(new JsonResult(response)); }