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