/// <summary> /// Generate an email content based on the time and the bill statement. /// </summary> /// <param name="bill"></param> /// <param name="month"></param> /// <param name="year"></param> /// <returns></returns> public Email GenerateEmail(BillStatement bill, int month, int year) { string emailTemplate = DomainResources.BILLING_STATEMENT_EMAIL_TEMPLATE; string subject = $"Billing statement for {month}-{year}"; string content = emailTemplate .Replace("{name}", bill.Customer.Name) .Replace("{address}", bill.Customer.Address) .Replace("{city}", bill.Customer.City) .Replace("{state}", bill.Customer.Address) .Replace("{zip}", bill.Customer.Address) .Replace("{bill_month}", month + "-" + year) .Replace("{amount_due}", bill.AmountDue.ToString("C")); return(new Email(subject, content, bill.Customer, bill)); }
/// <summary> /// Generate the bill for a customer. /// Note: /// this action is idempotent. If the bill is generated, it will be retrieved. /// </summary> /// <param name="cust"></param> /// <param name="month"></param> /// <param name="year"></param> /// <returns></returns> public BillStatement GenerateBill(Customer cust, int month, int year) { string billedCustomerKey = $"{month}_{year}_{cust.CustomerId}"; // if the bill is not generated, create it if (billedCustomerByTime[billedCustomerKey] == null) { decimal? amountDue = GetAmountDue(cust, month, year); BillStatement bill = new BillStatement(cust, month, year, amountDue.GetValueOrDefault()); cust.MonthlyStatements.Add(bill); customerRepository.SaveOrUpdate(cust); //remember customer bill statement for the month billedCustomerByTime[billedCustomerKey] = bill; return(bill); } // if the bill has been generated, just retrieve it. return(billedCustomerByTime[billedCustomerKey]); }
/// <summary> /// Generate and send the bill to all active customers for the month and year. /// Note: /// This action is idempotent. If customer has already been emailed, the system will not send duplicate email. /// </summary> /// <param name="month">the month to bill customer.</param> /// <param name="year">the year to bill customer.</param> public void SendBillToActiveCustomers(int month, int year) { // Billing service does not support future date if (!DateTimeHelper.IsInFuture(month, year)) { ISet <Email> emails = new HashSet <Email>(); string datetimeStamp = $"{month}_{year}"; IList <Customer> allActiveCustomers = this.customerRepository.GetAllActiveCustomers(); foreach (Customer customer in allActiveCustomers) { try { BillStatement bill = GenerateBill(customer, month, year); // only send email if we have not done that. string emailedCustomerKey = $"{customer.CustomerId}_{month}_{year}"; if (!emailedCustomerByTime.ContainsKey(emailedCustomerKey)) { Email email = GenerateEmail(bill, month, year); // remember the customer who was emailed emailedCustomerByTime[emailedCustomerKey] = email; emails.Add(email); } } //Should not block the whole billing cycle if a customer failed catch (Exception ex) { Logger.Error(ex); Logger.Error($"Unable to generate bill for {customer.CustomerId}:{customer.Name} for the {month}-{year}"); } } //storing the generated email for reporting purpose invoiceGeneratedByTime[datetimeStamp] = emails; emailRepository.SendMultiple(emails); } }