main
1using System.Collections.Generic;
2
3namespace solidware.financials.service.domain.payroll
4{
5 public class Grant
6 {
7 Date issued_on;
8 History<UnitPrice> price_history = new History<UnitPrice>();
9 Units units = Units.Empty;
10 List<Vest> expirations = new List<Vest>();
11
12 static public Grant New(Money purchase_amount, UnitPrice price, Fraction portion, Frequency frequency)
13 {
14 var grant = new Grant
15 {
16 issued_on = Calendar.today(),
17 };
18 grant.change_unit_price_to(price);
19 grant.purchase(purchase_amount);
20 grant.apply_vesting_frequency(portion, frequency);
21 return grant;
22 }
23
24 Grant() {}
25
26 public virtual void change_unit_price_to(UnitPrice new_price)
27 {
28 price_history.record(new_price);
29 }
30
31 public virtual bool was_issued_on(Date date)
32 {
33 return issued_on.Equals(date);
34 }
35
36 public virtual Money balance()
37 {
38 return balance(Calendar.today());
39 }
40
41 public virtual Money balance(Date on_date)
42 {
43 return unit_price(on_date).total_value_of(units_remaining(on_date));
44 }
45
46 Units units_remaining(Date on_date)
47 {
48 var remaining = Units.Empty;
49 foreach (var expiration in expirations)
50 {
51 remaining = remaining.combined_with(expiration.unvested_units(units, on_date));
52 }
53 return remaining;
54 }
55
56 void purchase(Money amount)
57 {
58 units = units.combined_with(current_unit_price().purchase_units(amount));
59 }
60
61 UnitPrice current_unit_price()
62 {
63 return unit_price(Calendar.today());
64 }
65
66 UnitPrice unit_price(Date on_date)
67 {
68 return price_history.recorded(on_date);
69 }
70
71 void apply_vesting_frequency(Fraction portion, Frequency frequency)
72 {
73 var next_date = issued_on.minus_days(1);
74 portion.each(x =>
75 {
76 next_date = frequency.next(next_date);
77 expirations.Add(new Vest(portion, next_date));
78 });
79 }
80 }
81}