Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.Services.Optimization.Billing/BillingEngine/BillingEngine.cs @ 9653

Last change on this file since 9653 was 9653, checked in by spimming, 11 years ago

#1888:

  • Set flag to indicate a modified model object
  • Add dao query method to specify includes as parameter
  • cleaned up the using of namespaces to qualify types
File size: 6.3 KB
Line 
1
2using System;
3using System.Collections.Generic;
4using System.Configuration;
5using System.Diagnostics;
6using System.Linq;
7using System.Threading;
8using HeuristicLab.Services.Optimization.Billing.Business;
9using HeuristicLab.Services.Optimization.Billing.Interfaces;
10using HeuristicLab.Services.Optimization.Billing.Model;
11namespace HeuristicLab.Services.Optimization.Billing.BillingEngine {
12  public class BillingEngine {
13    private bool stop;
14    private AutoResetEvent waitHandle;
15    private TimeSpan interval;
16    private DateTime currentDate;
17
18    private IOptimizationBilling billingService;
19    public IOptimizationBilling BillingService {
20      get {
21        if (billingService == null) {
22          billingService = new BillingService();
23        }
24        return billingService;
25      }
26      set { billingService = value; }
27    }
28
29    private IInvoiceFormattingEngine invoiceFormattingEngine;
30    public IInvoiceFormattingEngine InvoiceFormattingEngine {
31      get {
32        if (invoiceFormattingEngine == null) {
33          invoiceFormattingEngine = new PlainTextInvoiceFormattingEngine();
34        }
35        return invoiceFormattingEngine;
36      }
37      set { invoiceFormattingEngine = value; }
38    }
39
40    public BillingEngine() {
41      stop = false;
42      interval = TimeSpan.Parse(ConfigurationManager.AppSettings["BillingEngineInterval"]);
43      waitHandle = new AutoResetEvent(true);
44    }
45
46    public void StopBillingEngine() {
47      stop = true;
48      waitHandle.Set();
49    }
50
51    public void Run() {
52      while (!stop) {
53        try {
54          Trace.WriteLine("[BillingEngine] Start billing cycle");
55          currentDate = DateTime.Now.Date;
56          Trace.WriteLine(string.Format("[BillingEngine] Current date: {0}", currentDate));
57          IList<Order> activeOrders = BillingService.GetOrdersByState(OrderState.Active);
58          Trace.WriteLine(string.Format("[BillingEngine] Processing {0} active orders.", activeOrders.Count));
59          foreach (Order order in activeOrders) {
60            if (!order.NextBillableDay.HasValue) {
61              // An invoice has never been generated from this order
62              order.NextBillableDay = currentDate;
63              order.EntityState = State.Modified;
64            }
65
66            if (order.NextBillableDay >= currentDate) {
67              // TODO: Embed everything in a transaction
68
69              // Collect Usage Data
70              //IList<UsageRecord> usageRecrods = BillingService.GetUsageRecords(order.User.Name, order.LastBillableDay.Value, currentDate);
71
72              // Collect Invoice Data
73              Invoice invoice = new Invoice();
74              invoice.Order = order;
75              invoice.User = order.User;
76              invoice.Due = currentDate.AddMonths(1);
77              invoice.InvoiceDate = currentDate;
78              invoice.Status = InvoiceStatus.Open;
79              invoice.InvoiceLines = new List<InvoiceLine>();
80              foreach (OrderLine orderLine in order.OrderLines) {
81                InvoiceLine invoiceLine = new InvoiceLine();
82                invoiceLine.Invoice = invoice;
83                invoiceLine.Product = orderLine.Product;
84                invoiceLine.ProductPrice = orderLine.ProductPrice;
85                invoiceLine.Quantity = orderLine.Quantity;
86                invoice.InvoiceLines.Add(invoiceLine);
87              }
88
89              InvoiceLine usageCharges = new InvoiceLine();
90              usageCharges.Invoice = invoice;
91              usageCharges.Product = billingService.GetProductByName("Oaas Usage Charges").First();
92              usageCharges.ProductPrice = 999.99;
93              usageCharges.Quantity = 1;
94              invoice.InvoiceLines.Add(usageCharges);
95
96              // Bill Post Processing: Apply Discounts or Promotions
97              // add discounts, sum up items to sub-total, calc. tax -> total current charges
98              // maybe use windows workflow foundation for this task
99
100              // Invoice Formatting Engine: Generate Invoice
101              invoice.InvoiceDocument = InvoiceFormattingEngine.Generate(invoice);
102
103              UpdateBillingState(order);
104              billingService.UpdateOrder(order);
105              billingService.SaveInvoice(invoice);
106            }
107          }
108
109          Trace.WriteLine("[BillingEngine] Finished billing cycle");
110        }
111        catch (Exception e) {
112          Trace.WriteLine(string.Format("[BillingEngine] The following exception occured: {0}", e.ToString()));
113        }
114        waitHandle.WaitOne(interval);
115      }
116      waitHandle.Close();
117    }
118
119    private void UpdateBillingState(Order order) {
120      if (order.BillingType == BillingType.Pre) {
121        throw new Exception("This billing type is currently not supported: " + order.BillingType);
122      }
123
124      order.LastBillableDay = currentDate;
125      DateTime nextBillingDay = CalculateNextBillingDate(order);
126
127      if (order.ActiveUntil.HasValue && order.ActiveUntil == currentDate) {
128        order.State = OrderState.Finished;
129        order.NextBillableDay = null;
130      } else if (order.ActiveUntil.HasValue && order.ActiveUntil < nextBillingDay) {
131        order.NextBillableDay = order.ActiveUntil;
132      } else {
133        order.NextBillableDay = nextBillingDay;
134      }
135
136      order.EntityState = State.Modified;
137    }
138
139    private DateTime CalculateNextBillingDate(Order order) {
140      DateTime nextBillingDay = currentDate;
141
142      if (order.BillingPeriod == BillingPeriod.Weekly) {
143        nextBillingDay = Next(currentDate, DayOfWeek.Sunday);
144      } else if (order.BillingPeriod == BillingPeriod.Monthly) {
145        DateTime endOfNextMonth = new DateTime(
146          currentDate.AddMonths(1).Year,
147          currentDate.AddMonths(1).Month,
148          DateTime.DaysInMonth(currentDate.AddMonths(1).Year, currentDate.AddMonths(1).Month));
149        nextBillingDay = endOfNextMonth;
150      } else if (order.BillingPeriod == BillingPeriod.Yearly) {
151        nextBillingDay = new DateTime(currentDate.AddYears(1).Year, 12, 31);
152      }
153
154      return nextBillingDay;
155    }
156
157    private DateTime Next(DateTime from, DayOfWeek dayOfWeek) {
158      int start = (int)from.DayOfWeek;
159      int target = (int)dayOfWeek;
160      if (target <= start)
161        target += 7;
162      return from.AddDays(target - start);
163    }
164  }
165}
Note: See TracBrowser for help on using the repository browser.