public ServiceResult<Bill> AddBill(string name, decimal amount, BillFrequency frequency, DateTime startDate, DateTime endDate, int? billGroupId = null, int? categoryId = null, int? vendorId = null, DateTime? secondaryStartDate = null, DateTime? secondaryEndDate = null) { var result = new ServiceResult<Bill>(); // TODO do we need to handle a case where billGroupId = 0 if (billGroupId.HasValue && billGroupId.Value == 0) billGroupId = null; if (categoryId.HasValue && categoryId.Value == 0) categoryId = null; if (vendorId.HasValue && vendorId.Value == 0) vendorId = null; // does the bill group exist? if (billGroupId.HasValue) { var billGroupResult = GetBillGroup(billGroupId.Value); if (billGroupResult.HasErrors) { result.AddErrors(billGroupResult); } } // does the category exist? if (categoryId.HasValue) { var categoryResult = _categoryService.GetCategory(categoryId.Value); if (categoryResult.HasErrors) { result.AddErrors(categoryResult); } } // does the vendor exist? if (vendorId.HasValue) { var vendorResult = _vendorService.GetVendor(vendorId.Value); if (vendorResult.HasErrors) { result.AddErrors(vendorResult); } } // does the startDate come before the endDate? if (endDate < startDate) result.AddError(ErrorType.Generic, "Start date {0} must come before End date {1}", startDate.ToString(), endDate.ToString()); // does the secondary startDate come before the secondary endDate? if (secondaryStartDate.HasValue && secondaryEndDate.HasValue) { if (secondaryEndDate.Value < secondaryStartDate.Value) { result.AddError(ErrorType.Generic, "Secondary Start date {0} must come before Secondary End date {1}", secondaryStartDate.ToString(), secondaryEndDate.ToString()); } } // are both secondary startDate and secondary endDate provided? if ((secondaryStartDate.HasValue && !secondaryEndDate.HasValue) || (!secondaryStartDate.HasValue && secondaryEndDate.HasValue)) { result.AddError(ErrorType.Generic, "Both Secondary Start date and Secondary End date should be provided: {0} & {1}", secondaryStartDate.ToString(), secondaryEndDate.ToString()); } // any errors thus far? if (result.HasErrors) return result; // create bill var bill = new Bill() { Name = name, Amount = amount, BillGroupId = billGroupId, CategoryId = categoryId, VendorId = vendorId, StartDate = startDate, EndDate = endDate, RecurrenceFrequency = frequency, StartDate2 = secondaryStartDate, EndDate2 = secondaryEndDate }; _db.Insert<Bill>(bill); // create bill transactions int count = 0; var billTransactions = new List<BillTransaction>(); DateTime cur = new DateTime(startDate.Year, startDate.Month, startDate.Day); while (cur <= endDate) { BillTransaction trx = new BillTransaction() { BillId = bill.Id, Amount = amount, OriginalAmount = amount, CategoryId = categoryId, OriginalCategoryId = categoryId, VendorId = vendorId, OriginalVendorId = vendorId, Timestamp = cur, OriginalTimestamp = cur }; billTransactions.Add(trx); count++; if (frequency == 0) cur = endDate.AddDays(1); else if (frequency > 0) cur = startDate.AddDays(count * (int)frequency); else cur = startDate.AddMonths(count * -1 * (int)frequency); } if (secondaryStartDate.HasValue) { if (secondaryEndDate.HasValue) endDate = secondaryEndDate.Value; count = 0; cur = new DateTime(secondaryStartDate.Value.Year, secondaryStartDate.Value.Month, secondaryStartDate.Value.Day); while (cur <= endDate) { BillTransaction trx = new BillTransaction() { BillId = bill.Id, Amount = amount, OriginalAmount = amount, CategoryId = categoryId, OriginalCategoryId = categoryId, VendorId = vendorId, OriginalVendorId = vendorId, Timestamp = cur, OriginalTimestamp = cur }; billTransactions.Add(trx); count++; if (frequency == 0) cur = endDate.AddDays(1); else if (frequency > 0) cur = secondaryStartDate.Value.AddDays(count * (int)frequency); else cur = secondaryStartDate.Value.AddMonths(count * -1 * (int)frequency); } } _db.Insert<BillTransaction>(billTransactions); result.Result = bill; return result; }
public ServiceResult<Bill> UpdateBill(int billId, string name, decimal amount, BillFrequency frequency, DateTime startDate, DateTime endDate, int? billGroupId = null, int? categoryId = null, int? vendorId = null, DateTime? secondaryStartDate = null, DateTime? secondaryEndDate = null, bool updateExisting = false) { var result = new ServiceResult<Bill>(); var billResult = GetBill(billId); if (billResult.HasErrors) { result.AddErrors(billResult); return result; } // if the new value is 0, that means set it to null if (billGroupId.HasValue && billGroupId.Value == 0) billGroupId = null; if (categoryId.HasValue && categoryId.Value == 0) categoryId = null; if (vendorId.HasValue && vendorId.Value == 0) vendorId = null; // do the new BillGroup, Category and Vendor exist? if (billGroupId.HasValue) { var billGroupResult = GetBillGroup(billGroupId.Value); if (billGroupResult.HasErrors) { result.AddErrors(billGroupResult); return result; } } if (categoryId.HasValue) { var categoryResult = _categoryService.GetCategory(categoryId.Value); if (categoryResult.HasErrors) { result.AddErrors(categoryResult); return result; } } if (vendorId.HasValue) { var vendorResult = _vendorService.GetVendor(vendorId.Value); if (vendorResult.HasErrors) { result.AddErrors(vendorResult); return result; } } // TODO handle updateExisting //if (updateExisting) //{ // if (bill.StartDate != startDate || bill.EndDate != endDate || bill.RecurrenceFrequency != frequency || bill.StartDate2 != secondaryStartDate || bill.EndDate2 != secondaryEndDate) // { // List<BillTransaction> existing = _billTransactionRepository.GetMany(x => x.BillId == billId).ToList(); // List<BillTransaction> expected = new List<BillTransaction>(); // #region Generate expected transactions // int count = 0; // DateTime cur = new DateTime(startDate.Year, startDate.Month, startDate.Day); // while (cur <= endDate) // { // BillTransaction trx = new BillTransaction() // { // Amount = amount, // OriginalAmount = amount, // CategoryId = categoryId, // OriginalCategoryId = categoryId, // VendorId = vendorId, // OriginalVendorId = vendorId, // Timestamp = cur, // OriginalTimestamp = cur // }; // expected.Add(trx); // count++; // if (frequency == 0) // cur = endDate.AddDays(1); // else if (frequency > 0) // cur = startDate.AddDays(count * frequency); // else // cur = startDate.AddMonths(count * -1 * frequency); // } // if (secondaryStartDate.HasValue) // { // if (secondaryEndDate.HasValue) // endDate = secondaryEndDate.Value; // count = 0; // cur = new DateTime(secondaryStartDate.Value.Year, secondaryStartDate.Value.Month, secondaryStartDate.Value.Day); // while (cur <= endDate) // { // BillTransaction trx = new BillTransaction() // { // Amount = amount, // OriginalAmount = amount, // CategoryId = categoryId, // OriginalCategoryId = categoryId, // VendorId = vendorId, // OriginalVendorId = vendorId, // Timestamp = cur, // OriginalTimestamp = cur // }; // expected.Add(trx); // count++; // if (frequency == 0) // cur = endDate.AddDays(1); // else if (frequency > 0) // cur = secondaryStartDate.Value.AddDays(count * frequency); // else // cur = secondaryStartDate.Value.AddMonths(count * -1 * frequency); // } // } // #endregion // List<BillTransaction> reused = new List<BillTransaction>(); // while (existing.Any() && expected.Any()) // { // var existingProjections = existing.Select(e => new // { // Item = e, // Comparisons = expected.Select(x => new // { // Item = x, // Days = Math.Abs((x.Timestamp - e.Timestamp).TotalDays) // }) // }); // var bestExisting = existingProjections.OrderBy(x => x.Comparisons.Min(y => y.Days)).FirstOrDefault(); // if (bestExisting != null) // { // // shift existing record's timestamp to closest match in expected // var bestMatch = bestExisting.Comparisons.OrderBy(x => x.Days).FirstOrDefault().Item; // bestExisting.Item.Timestamp = bestMatch.Timestamp; // bestExisting.Item.OriginalTimestamp = bestMatch.OriginalTimestamp; // expected.Remove(bestMatch); // existing.Remove(bestExisting.Item); // reused.Add(bestExisting.Item); // } // } // // delete unused transactions // var complete = reused.Union(expected).Select(x => x.Id); // _billTransactionRepository.Delete(x => x.BillId == billId && !complete.Contains(x.Id)); // //reused.ForEach(x => bill.BillTransactions.Add(x)); // expected.ForEach(x => bill.BillTransactions.Add(x)); // } // if (bill.Amount != amount || bill.CategoryId != categoryId || bill.VendorId != vendorId) // { // var billTransasctions = _billTransactionRepository.GetMany(x => x.BillId == billId); // if (billTransasctions != null) // { // foreach (var trx in billTransasctions) // { // if (bill.Amount != amount) // { // // only update a transaction amount if it hadn't been edited from it's original value (ie don't change modified amounts) // if (trx.Amount == trx.OriginalAmount) // trx.Amount = amount; // trx.OriginalAmount = amount; // } // if (bill.CategoryId != categoryId) // trx.CategoryId = categoryId; // if (bill.VendorId != vendorId) // trx.VendorId = vendorId; // } // } // } //} billResult.Result.Name = name; billResult.Result.Amount = amount; billResult.Result.RecurrenceFrequency = frequency; billResult.Result.StartDate = startDate; billResult.Result.EndDate = endDate; billResult.Result.BillGroupId = billGroupId; billResult.Result.CategoryId = categoryId; billResult.Result.VendorId = vendorId; billResult.Result.StartDate2 = secondaryStartDate; billResult.Result.EndDate2 = secondaryEndDate; _db.Update<Bill>(billResult.Result); result.Result = billResult.Result; return result; }