Free cookie consent management tool by TermsFeed Policy Generator

Changeset 9641


Ignore:
Timestamp:
06/18/13 11:39:31 (9 years ago)
Author:
spimming
Message:

#1888:

  • Users now contain ContactInformation
  • Fixed formatting in invoice template
  • Fixed calculation for next invoice date
  • Worked on indentation for invoice fields
Location:
branches/OaaS
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branches/OaaS/HeuristicLab.Services.Optimization.Billing.Test/DDLScript.sql

    r9619 r9641  
    7979create table [dbo].[Users] (
    8080    [UserId] [bigint] not null identity,
     81    [ContactInformationId] [bigint] not null,
    8182    [Name] [nvarchar](max) null,
    8283    primary key ([UserId])
     
    9192alter table [dbo].[UsageRecords] add constraint [UsageRecord_Product] foreign key ([ProductId]) references [dbo].[Products]([ProductId]);
    9293alter table [dbo].[UsageRecords] add constraint [UsageRecord_User] foreign key ([UserId]) references [dbo].[Users]([UserId]);
     94alter table [dbo].[Users] add constraint [User_ContactInformation] foreign key ([ContactInformationId]) references [dbo].[ContactInformations]([ContactInformationId]);
    9395alter 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  
    5353        try {
    5454          Trace.WriteLine("[BillingEngine] Start billing cycle");
    55           //currentDate = DateTime.Parse(DateTime.Now.ToShortDateString());
    5655          currentDate = DateTime.Now.Date;
    5756          Trace.WriteLine(string.Format("[BillingEngine] Current date: {0}", currentDate));
     
    6059          foreach (Order order in activeOrders) {
    6160            if (!order.NextBillableDay.HasValue) {
    62               // there has never been an invoice generated from this order
     61              // An invoice has never been generated from this order
    6362              order.NextBillableDay = currentDate;
    6463            }
     
    8382                invoiceLine.Product = orderLine.Product;
    8483                invoiceLine.ProductPrice = orderLine.ProductPrice;
    85                 invoiceLine.Quantity = invoiceLine.Quantity;
     84                invoiceLine.Quantity = orderLine.Quantity;
    8685                invoice.InvoiceLines.Add(invoiceLine);
    8786              }
     
    9089              usageCharges.Invoice = invoice;
    9190              usageCharges.Product = billingService.GetProductByName("Oaas Usage Charges").First();
    92               usageCharges.ProductPrice = 999.99;
     91              usageCharges.ProductPrice = -999.99;
    9392              usageCharges.Quantity = 1;
    9493              invoice.InvoiceLines.Add(usageCharges);
    9594
    9695              // Bill Post Processing: Apply Discounts or Promotions
    97               // eg. add discounts
    98               // sum up items to sub-total, calc. tax -> total current charges
     96              // add discounts, sum up items to sub-total, calc. tax -> total current charges
     97              // maybe use windows workflow foundation for this task
    9998
    10099              // Invoice Formatting Engine: Generate Invoice
     
    117116
    118117    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);
    122120      }
    123121
    124122      DateTime nextBillingDay = CalculateNextBillingDate(order);
    125123
    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 {
    127130        order.NextBillableDay = nextBillingDay;
    128131      }
     
    133136
    134137      if (order.BillingPeriod == BillingPeriod.Weekly) {
    135         nextBillingDay = nextBillingDay.AddDays(7);
     138        nextBillingDay = Next(currentDate, DayOfWeek.Sunday);
    136139      } 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;
    146145      } 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);
    152147      }
    153148
    154149      return nextBillingDay;
    155150    }
     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    }
    156159  }
    157160}
  • branches/OaaS/HeuristicLab.Services.Optimization.Billing/BillingEngine/InvoiceTemplate.txt

    r9619 r9641  
    77
    88-------------------------------------------------------------------------------
    9                           TAX INVOICE #{INVOICE_ID}
     9                             TAX INVOICE #{INVOICE_ID}
    1010-------------------------------------------------------------------------------
    1111To:
     
    1717Date:          {INVOICE_DATE}
    1818Order Number:  {ORDER_ID}
     19User:          {USER_NAME}
    1920Payment Terms: {PAYMENT_TERMS}
    2021Payment Due:   {PAYMENT_DUE}
     
    2627#BEGIN {ITEM} {PRODUCT_NAME} {QUANTITY} {PRODUCT_PRICE} {PRODUCT_TOTAL} #END
    2728
    28 **---------------------------------------------------------------------------**
     29-------------------------------------------------------------------------------
    2930SUB-TOTAL CHARGES:                                          {INVOICE_SUB_TOTAL}
    3031TAX:                                                              {INVOICE_TAX}
  • branches/OaaS/HeuristicLab.Services.Optimization.Billing/BillingEngine/PlainTextInvoiceFormattingEngine.cs

    r9619 r9641  
    88
    99namespace 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 {
    1117    private const string defaultTemplatePath = @"BillingEngine\InvoiceTemplate.txt";
    1218    private string template;
    1319    private string invoiceText;
     20    private PlainTextInvoiceFormat invoiceFormat;
    1421    private string invoiceOutputPath;
    1522
    1623    public PlainTextInvoiceFormattingEngine()
    17       : this(defaultTemplatePath) {
     24      : this(defaultTemplatePath, PlainTextInvoiceFormat.RTF) {
    1825
    1926    }
    2027
    21     public PlainTextInvoiceFormattingEngine(string templatePath) {
     28    public PlainTextInvoiceFormattingEngine(string templatePath, PlainTextInvoiceFormat format) {
    2229      if (!File.Exists(templatePath)) {
    2330        throw new FileNotFoundException("Cannot find template file", templatePath);
    2431      }
    2532      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;
    2638    }
    2739
     
    3143      invoiceText = invoiceText.Replace("{INVOICE_ID}", invoice.InvoiceId.ToString());
    3244
    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);
    3451
    3552      invoiceText = invoiceText.Replace("{INVOICE_DATE}", invoice.InvoiceDate.ToString("dd.MM.yyyy"));
    3653      invoiceText = invoiceText.Replace("{ORDER_ID}", invoice.OrderId.ToString());
     54      invoiceText = invoiceText.Replace("{USER_NAME}", invoice.User.Name);
    3755      invoiceText = invoiceText.Replace("{PAYMENT_TERMS}", "2% 10, net 30 days");
    3856      invoiceText = invoiceText.Replace("{PAYMENT_DUE}", invoice.Due.Date.ToString("dd.MM.yyyy"));
    3957
    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);
    4865
    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));
    5273
    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);
    5976
    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);
    6778      }
    6879
    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));
    7383
    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}");
    7786
    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);
    8491
    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      }
    86100
    87101      return invoiceOutputPath;
  • branches/OaaS/HeuristicLab.Services.Optimization.Billing/DataAccess/BillingContext.cs

    r9619 r9641  
    8585      internal UserConfiguration() {
    8686        this.HasMany(u => u.PaymentInformation).WithRequired(pi => pi.User).HasForeignKey(pi => pi.UserId);
     87        this.HasRequired(u => u.ContactInformation).WithMany().HasForeignKey(u => u.ContactInformationId);
    8788      }
    8889    }
     
    9798      protected override void Seed(BillingContext context) {
    9899        Product p1 = new Product() {
    99           Name = "OaaS BAsic Service Charge",
     100          Name = "OaaS Basic Service Charge",
    100101          Description = "Create and run your experiments within HeuristicLab Hive",
    101102          Price = 20.0,
     
    137138          LastName = "Mustermann",
    138139          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",
    140141          Street = "Softwarepark 11",
    141142          PostalCode = "4232",
    142           City = "Hagenberg"
     143          City = "Hagenberg",
    143144        };
    144145
    145146        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;
    146161
    147162        Order o1 = new Order() {
  • branches/OaaS/HeuristicLab.Services.Optimization.Billing/DataAccess/BillingDao.cs

    r9619 r9641  
    109109          .Include(o => o.OrderLines)
    110110          .Include(o => o.User)
     111          .Include(o => o.User.ContactInformation)
    111112          .Include(o => o.Invoices)
    112113          .Include(o => o.OrderLines.Select(ol => ol.Product))
  • branches/OaaS/HeuristicLab.Services.Optimization.Billing/Model/Model.cs

    r9619 r9641  
    77   * Note: enum support
    88   * 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:
    1010   * Just create an int property on your class to represent the int value of the enum.
    1111   * That's the property that EF should map, then have a "mini wrapper" property to allow you to use the enum
     
    7070  public class User {
    7171    public long UserId { get; set; }
     72    public long ContactInformationId { get; set; }
    7273    public string Name { get; set; }
    7374
    7475    public virtual IList<PaymentInformation> PaymentInformation { get; set; }
    75 
     76    public virtual ContactInformation ContactInformation { get; set; }
    7677  }
    7778
Note: See TracChangeset for help on using the changeset viewer.