Changeset 9641
- Timestamp:
- 06/18/13 11:39:31 (11 years ago)
- Location:
- branches/OaaS
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/OaaS/HeuristicLab.Services.Optimization.Billing.Test/DDLScript.sql
r9619 r9641 79 79 create table [dbo].[Users] ( 80 80 [UserId] [bigint] not null identity, 81 [ContactInformationId] [bigint] not null, 81 82 [Name] [nvarchar](max) null, 82 83 primary key ([UserId]) … … 91 92 alter table [dbo].[UsageRecords] add constraint [UsageRecord_Product] foreign key ([ProductId]) references [dbo].[Products]([ProductId]); 92 93 alter table [dbo].[UsageRecords] add constraint [UsageRecord_User] foreign key ([UserId]) references [dbo].[Users]([UserId]); 94 alter table [dbo].[Users] add constraint [User_ContactInformation] foreign key ([ContactInformationId]) references [dbo].[ContactInformations]([ContactInformationId]); 93 95 alter table [dbo].[PaymentInformations] add constraint [User_PaymentInformation] foreign key ([UserId]) references [dbo].[Users]([UserId]); -
branches/OaaS/HeuristicLab.Services.Optimization.Billing/BillingEngine/BillingEngine.cs
r9619 r9641 53 53 try { 54 54 Trace.WriteLine("[BillingEngine] Start billing cycle"); 55 //currentDate = DateTime.Parse(DateTime.Now.ToShortDateString());56 55 currentDate = DateTime.Now.Date; 57 56 Trace.WriteLine(string.Format("[BillingEngine] Current date: {0}", currentDate)); … … 60 59 foreach (Order order in activeOrders) { 61 60 if (!order.NextBillableDay.HasValue) { 62 // there has never been an invoicegenerated from this order61 // An invoice has never been generated from this order 63 62 order.NextBillableDay = currentDate; 64 63 } … … 83 82 invoiceLine.Product = orderLine.Product; 84 83 invoiceLine.ProductPrice = orderLine.ProductPrice; 85 invoiceLine.Quantity = invoiceLine.Quantity;84 invoiceLine.Quantity = orderLine.Quantity; 86 85 invoice.InvoiceLines.Add(invoiceLine); 87 86 } … … 90 89 usageCharges.Invoice = invoice; 91 90 usageCharges.Product = billingService.GetProductByName("Oaas Usage Charges").First(); 92 usageCharges.ProductPrice = 999.99;91 usageCharges.ProductPrice = -999.99; 93 92 usageCharges.Quantity = 1; 94 93 invoice.InvoiceLines.Add(usageCharges); 95 94 96 95 // Bill Post Processing: Apply Discounts or Promotions 97 // eg. add discounts98 // sum up items to sub-total, calc. tax -> total current charges96 // add discounts, sum up items to sub-total, calc. tax -> total current charges 97 // maybe use windows workflow foundation for this task 99 98 100 99 // Invoice Formatting Engine: Generate Invoice … … 117 116 118 117 private void UpdateBillingState(Order order) { 119 if (order.ActiveUntil != null && order.ActiveUntil == order.NextBillableDay) { 120 order.NextBillableDay = null; 121 order.State = OrderState.Finished; 118 if (order.BillingType == BillingType.Pre) { 119 throw new Exception("This billing type is currently not supported: " + order.BillingType); 122 120 } 123 121 124 122 DateTime nextBillingDay = CalculateNextBillingDate(order); 125 123 126 if (order.ActiveUntil != null && order.ActiveUntil < nextBillingDay) { 124 if (order.ActiveUntil.HasValue && order.ActiveUntil == currentDate) { 125 order.State = OrderState.Finished; 126 order.NextBillableDay = null; 127 } else if (order.ActiveUntil.HasValue && order.ActiveUntil < nextBillingDay) { 128 order.NextBillableDay = order.ActiveUntil; 129 } else { 127 130 order.NextBillableDay = nextBillingDay; 128 131 } … … 133 136 134 137 if (order.BillingPeriod == BillingPeriod.Weekly) { 135 nextBillingDay = nextBillingDay.AddDays(7);138 nextBillingDay = Next(currentDate, DayOfWeek.Sunday); 136 139 } else if (order.BillingPeriod == BillingPeriod.Monthly) { 137 if (order.BillingType == BillingType.Pre) { 138 nextBillingDay = nextBillingDay.AddDays(DateTime.DaysInMonth(nextBillingDay.Year, nextBillingDay.Month) + 1); 139 } else if (order.BillingType == BillingType.Post) { 140 if (nextBillingDay.Month == 12) { 141 nextBillingDay = nextBillingDay.AddDays(DateTime.DaysInMonth(nextBillingDay.Year + 1, 1) + 1); 142 } else { 143 nextBillingDay = nextBillingDay.AddDays(DateTime.DaysInMonth(nextBillingDay.Year, nextBillingDay.Month + 1) + 1); 144 } 145 } 140 DateTime endOfNextMonth = new DateTime( 141 currentDate.AddMonths(1).Year, 142 currentDate.AddMonths(1).Month, 143 DateTime.DaysInMonth(currentDate.AddMonths(1).Year, currentDate.AddMonths(1).Month)); 144 nextBillingDay = endOfNextMonth; 146 145 } else if (order.BillingPeriod == BillingPeriod.Yearly) { 147 if (order.BillingType == BillingType.Pre) { 148 nextBillingDay = new DateTime(DateTime.Now.Year + 1, 1, 1); 149 } else if (order.BillingType == BillingType.Post) { 150 nextBillingDay = new DateTime(DateTime.Now.Year + 1, 12, 31); 151 } 146 nextBillingDay = new DateTime(currentDate.AddYears(1).Year, 12, 31); 152 147 } 153 148 154 149 return nextBillingDay; 155 150 } 151 152 private DateTime Next(DateTime from, DayOfWeek dayOfWeek) { 153 int start = (int)from.DayOfWeek; 154 int target = (int)dayOfWeek; 155 if (target <= start) 156 target += 7; 157 return from.AddDays(target - start); 158 } 156 159 } 157 160 } -
branches/OaaS/HeuristicLab.Services.Optimization.Billing/BillingEngine/InvoiceTemplate.txt
r9619 r9641 7 7 8 8 ------------------------------------------------------------------------------- 9 TAX INVOICE #{INVOICE_ID}9 TAX INVOICE #{INVOICE_ID} 10 10 ------------------------------------------------------------------------------- 11 11 To: … … 17 17 Date: {INVOICE_DATE} 18 18 Order Number: {ORDER_ID} 19 User: {USER_NAME} 19 20 Payment Terms: {PAYMENT_TERMS} 20 21 Payment Due: {PAYMENT_DUE} … … 26 27 #BEGIN {ITEM} {PRODUCT_NAME} {QUANTITY} {PRODUCT_PRICE} {PRODUCT_TOTAL} #END 27 28 28 **---------------------------------------------------------------------------** 29 ------------------------------------------------------------------------------- 29 30 SUB-TOTAL CHARGES: {INVOICE_SUB_TOTAL} 30 31 TAX: {INVOICE_TAX} -
branches/OaaS/HeuristicLab.Services.Optimization.Billing/BillingEngine/PlainTextInvoiceFormattingEngine.cs
r9619 r9641 8 8 9 9 namespace HeuristicLab.Services.Optimization.Billing.BillingEngine { 10 class PlainTextInvoiceFormattingEngine : IInvoiceFormattingEngine { 10 public enum PlainTextInvoiceFormat { 11 TXT, 12 RTF, 13 PDF 14 } 15 16 public class PlainTextInvoiceFormattingEngine : IInvoiceFormattingEngine { 11 17 private const string defaultTemplatePath = @"BillingEngine\InvoiceTemplate.txt"; 12 18 private string template; 13 19 private string invoiceText; 20 private PlainTextInvoiceFormat invoiceFormat; 14 21 private string invoiceOutputPath; 15 22 16 23 public PlainTextInvoiceFormattingEngine() 17 : this(defaultTemplatePath ) {24 : this(defaultTemplatePath, PlainTextInvoiceFormat.RTF) { 18 25 19 26 } 20 27 21 public PlainTextInvoiceFormattingEngine(string templatePath ) {28 public PlainTextInvoiceFormattingEngine(string templatePath, PlainTextInvoiceFormat format) { 22 29 if (!File.Exists(templatePath)) { 23 30 throw new FileNotFoundException("Cannot find template file", templatePath); 24 31 } 25 32 template = File.ReadAllText(templatePath); 33 34 if (format == PlainTextInvoiceFormat.PDF) { 35 throw new Exception("PDF invoice format is currently not supported"); 36 } 37 invoiceFormat = format; 26 38 } 27 39 … … 31 43 invoiceText = invoiceText.Replace("{INVOICE_ID}", invoice.InvoiceId.ToString()); 32 44 33 // TODO: Replace ContactInformation 45 invoiceText = invoiceText.Replace("{ORGANIZATION_NAME}", invoice.User.ContactInformation.OrganizationName); 46 invoiceText = invoiceText.Replace("{FIRSTNAME}", invoice.User.ContactInformation.FirstName); 47 invoiceText = invoiceText.Replace("{LASTNAME}", invoice.User.ContactInformation.LastName); 48 invoiceText = invoiceText.Replace("{STREET}", invoice.User.ContactInformation.Street); 49 invoiceText = invoiceText.Replace("{POSTAL_CODE}", invoice.User.ContactInformation.PostalCode); 50 invoiceText = invoiceText.Replace("{CITY}", invoice.User.ContactInformation.City); 34 51 35 52 invoiceText = invoiceText.Replace("{INVOICE_DATE}", invoice.InvoiceDate.ToString("dd.MM.yyyy")); 36 53 invoiceText = invoiceText.Replace("{ORDER_ID}", invoice.OrderId.ToString()); 54 invoiceText = invoiceText.Replace("{USER_NAME}", invoice.User.Name); 37 55 invoiceText = invoiceText.Replace("{PAYMENT_TERMS}", "2% 10, net 30 days"); 38 56 invoiceText = invoiceText.Replace("{PAYMENT_DUE}", invoice.Due.Date.ToString("dd.MM.yyyy")); 39 57 40 // TODO: Replace InvoiceLines 41 int itemNo = 1; 42 InvoiceLine lastInvoiceLine = invoice.InvoiceLines.Last(); 43 foreach (InvoiceLine invoiceLine in invoice.InvoiceLines) { 44 // copy template text for OrderLine 45 int first = invoiceText.IndexOf("#BEGIN"); 46 int last = invoiceText.LastIndexOf("#END"); 47 string orderLineText = invoiceText.Substring(first, last + 6 - first); 58 int itemNo = invoice.InvoiceLines.Count; 59 int first = invoiceText.IndexOf("#BEGIN"); 60 int last = invoiceText.LastIndexOf("#END"); 61 string orderLineTextTemplate = invoiceText.Substring(first, last + 6 - first); 62 invoiceText = invoiceText.Remove(first, last + 6 - first); 63 foreach (InvoiceLine invoiceLine in invoice.InvoiceLines.Reverse()) { 64 string invoiceLineText = string.Copy(orderLineTextTemplate); 48 65 49 // remove #BEGIN tag 50 invoiceText = invoiceText.Remove(first, 7); 51 invoiceText = invoiceText.Remove(last, 3); 66 invoiceLineText = invoiceLineText.Replace("{ITEM}", (itemNo).ToString().PadRight(5)); 67 itemNo--; 68 invoiceLineText = invoiceLineText.Replace("{PRODUCT_NAME}", invoiceLine.Product.Name.PadRight(39)); 69 invoiceLineText = invoiceLineText.Replace("{QUANTITY}", invoiceLine.Quantity.ToString().PadRight(9)); 70 invoiceLineText = invoiceLineText.Replace("{PRODUCT_PRICE}", invoiceLine.ProductPrice.ToString("C2").PadLeft(10)); 71 double totalPrice = invoiceLine.Quantity * invoiceLine.ProductPrice; 72 invoiceLineText = invoiceLineText.Replace("{PRODUCT_TOTAL}", totalPrice.ToString("C2").PadLeft(11)); 52 73 53 // replace text 54 invoiceText = invoiceText.Replace("{ITEM}", (++itemNo).ToString()); 55 invoiceText = invoiceText.Replace("{PRODUCT_NAME}", invoiceLine.Product.Name); 56 invoiceText = invoiceText.Replace("{QUANTITY}", invoiceLine.Quantity.ToString()); 57 invoiceText = invoiceText.Replace("{PRODUCT_PRICE}", invoiceLine.ProductPrice.ToString()); 58 invoiceText = invoiceText.Replace("{PRODUCT_TOTAL}", string.Format("{0}", invoiceLine.Quantity + invoiceLine.ProductPrice)); 74 invoiceLineText = invoiceLineText.Remove(invoiceLineText.IndexOf("#BEGIN"), 7); 75 invoiceLineText = invoiceLineText.Remove(invoiceLineText.IndexOf("#END"), 4); 59 76 60 if (!invoiceLine.Equals(lastInvoiceLine)) { 61 // remove #BEGIN tag and insert template text for next OrderLine 62 invoiceText = invoiceText.Replace("#END", Environment.NewLine + orderLineText); 63 } else { 64 // remove #END tag 65 invoiceText = invoiceText.Replace("#END", ""); 66 } 77 invoiceText = invoiceText.Insert(first, invoiceLineText); 67 78 } 68 79 69 invoiceText = invoiceText.Replace("{INVOICE_SUB_TOTAL}", string.Format("{0}", invoice.Total - invoice.Tax)); 70 invoiceText = invoiceText.Replace("{INVOICE_TAX}", invoice.Tax.ToString()); 71 invoiceText = invoiceText.Replace("{INVOICE_TOTAL}", invoice.Total.ToString()); 72 invoiceText = invoiceText.Replace("{INVOICE_DATE}", invoice.InvoiceDate.ToString()); 80 invoiceText = invoiceText.Replace("{INVOICE_SUB_TOTAL}", string.Format("{0:C2}", invoice.Total - invoice.Tax).PadLeft(18)); 81 invoiceText = invoiceText.Replace("{INVOICE_TAX}", invoice.Tax.ToString("C2").PadLeft(12)); 82 invoiceText = invoiceText.Replace("{INVOICE_TOTAL}", invoice.Total.ToString("C2").PadLeft(14)); 73 83 74 invoiceOutputPath = string.Format("{0}_{1}_{2}.rtf", invoice.InvoiceId, invoice.InvoiceDate.ToString("yyyMMdd"), "{CUSTOMER}"); 75 string invoiceOutputPathRTF = string.Format("{0}_{1}_{2}.rtf", invoice.InvoiceId, invoice.InvoiceDate.ToString("yyyMMdd"), "{CUSTOMER}"); 76 string invoiceOutputPathTXT = string.Format("{0}_{1}_{2}.txt", invoice.InvoiceId, invoice.InvoiceDate.ToString("yyyMMdd"), "{CUSTOMER}"); 84 if (invoiceFormat == PlainTextInvoiceFormat.RTF) { 85 invoiceOutputPath = string.Format("{0}_{1}_{2}.rtf", invoice.InvoiceId, invoice.InvoiceDate.ToString("yyyMMdd"), "{CUSTOMER}"); 77 86 78 RichTextBox richTextBox = new RichTextBox(); 79 richTextBox.Text = invoiceText; 80 richTextBox.SelectAll(); 81 richTextBox.SelectionFont = new Font("Consolas", 10, FontStyle.Regular); 82 //richTextBox.Text = invoiceText; 83 File.WriteAllText(invoiceOutputPathRTF, richTextBox.Rtf); 87 RichTextBox richTextBox = new RichTextBox(); 88 richTextBox.Text = invoiceText; 89 richTextBox.SelectAll(); 90 richTextBox.SelectionFont = new Font("Consolas", 10, FontStyle.Regular); 84 91 85 File.WriteAllText(invoiceOutputPathTXT, invoiceText); 92 File.WriteAllText(invoiceOutputPath, richTextBox.Rtf); 93 } else if (invoiceFormat == PlainTextInvoiceFormat.TXT) { 94 invoiceOutputPath = string.Format("{0}_{1}_{2}.txt", invoice.InvoiceId, invoice.InvoiceDate.ToString("yyyMMdd"), "{CUSTOMER}"); 95 96 File.WriteAllText(invoiceOutputPath, invoiceText); 97 } else if (invoiceFormat == PlainTextInvoiceFormat.PDF) { 98 throw new Exception("PDF invoice format is currently not supported"); 99 } 86 100 87 101 return invoiceOutputPath; -
branches/OaaS/HeuristicLab.Services.Optimization.Billing/DataAccess/BillingContext.cs
r9619 r9641 85 85 internal UserConfiguration() { 86 86 this.HasMany(u => u.PaymentInformation).WithRequired(pi => pi.User).HasForeignKey(pi => pi.UserId); 87 this.HasRequired(u => u.ContactInformation).WithMany().HasForeignKey(u => u.ContactInformationId); 87 88 } 88 89 } … … 97 98 protected override void Seed(BillingContext context) { 98 99 Product p1 = new Product() { 99 Name = "OaaS B Asic Service Charge",100 Name = "OaaS Basic Service Charge", 100 101 Description = "Create and run your experiments within HeuristicLab Hive", 101 102 Price = 20.0, … … 137 138 LastName = "Mustermann", 138 139 Email = "max.mustermann@fh-hagenberg.at", 139 OrganizationName = "University of Applied Sciences Upper Austria School of Informatics/Communications/Media",140 OrganizationName = "University of Applied Sciences Upper Austria " + Environment.NewLine + "School of Informatics/Communications/Media", 140 141 Street = "Softwarepark 11", 141 142 PostalCode = "4232", 142 City = "Hagenberg" 143 City = "Hagenberg", 143 144 }; 144 145 145 146 ci1 = context.ContactInformations.Add(ci1); 147 u1.ContactInformation = ci1; 148 149 ContactInformation ci2 = new ContactInformation() { 150 FirstName = "Max", 151 LastName = "Mustermann", 152 Email = "max.mustermann@fh-hagenberg.at", 153 OrganizationName = "University of Applied Sciences Upper Austria " + Environment.NewLine + "School of Informatics/Communications/Media", 154 Street = "Softwarepark 11", 155 PostalCode = "4232", 156 City = "Hagenberg", 157 }; 158 159 ci2 = context.ContactInformations.Add(ci2); 160 u2.ContactInformation = ci2; 146 161 147 162 Order o1 = new Order() { -
branches/OaaS/HeuristicLab.Services.Optimization.Billing/DataAccess/BillingDao.cs
r9619 r9641 109 109 .Include(o => o.OrderLines) 110 110 .Include(o => o.User) 111 .Include(o => o.User.ContactInformation) 111 112 .Include(o => o.Invoices) 112 113 .Include(o => o.OrderLines.Select(ol => ol.Product)) -
branches/OaaS/HeuristicLab.Services.Optimization.Billing/Model/Model.cs
r9619 r9641 7 7 * Note: enum support 8 8 * Although we use EF5 enums are not supported as we target .NET 4.0. 9 * Therefor we use the following workaround:9 * Therefore we use the following workaround: 10 10 * Just create an int property on your class to represent the int value of the enum. 11 11 * That's the property that EF should map, then have a "mini wrapper" property to allow you to use the enum … … 70 70 public class User { 71 71 public long UserId { get; set; } 72 public long ContactInformationId { get; set; } 72 73 public string Name { get; set; } 73 74 74 75 public virtual IList<PaymentInformation> PaymentInformation { get; set; } 75 76 public virtual ContactInformation ContactInformation { get; set; } 76 77 } 77 78
Note: See TracChangeset
for help on using the changeset viewer.