summaryrefslogtreecommitdiff
path: root/product/client/server
diff options
context:
space:
mode:
Diffstat (limited to 'product/client/server')
-rw-r--r--product/client/server/domain/AnonymousVisitor.cs (renamed from product/client/server/domain/accounting/AnonymousVisitor.cs)2
-rw-r--r--product/client/server/domain/Calendar.cs (renamed from product/client/server/domain/accounting/Calendar.cs)2
-rw-r--r--product/client/server/domain/payroll/Annually.cs12
-rw-r--r--product/client/server/domain/payroll/BaseDenominator.cs26
-rw-r--r--product/client/server/domain/payroll/Calendar.cs26
-rw-r--r--product/client/server/domain/payroll/Compensation.cs25
-rw-r--r--product/client/server/domain/payroll/Denominator.cs11
-rw-r--r--product/client/server/domain/payroll/Fraction.cs10
-rw-r--r--product/client/server/domain/payroll/Frequency.cs9
-rw-r--r--product/client/server/domain/payroll/Grant.cs62
-rw-r--r--product/client/server/domain/payroll/History.cs47
-rw-r--r--product/client/server/domain/payroll/Money.cs32
-rw-r--r--product/client/server/domain/payroll/Monthly.cs12
-rw-r--r--product/client/server/domain/payroll/One.cs20
-rw-r--r--product/client/server/domain/payroll/Third.cs7
-rw-r--r--product/client/server/domain/payroll/Twelfth.cs7
-rw-r--r--product/client/server/domain/payroll/Unit.cs28
-rw-r--r--product/client/server/domain/payroll/UnitPrice.cs17
-rw-r--r--product/client/server/domain/payroll/Units.cs30
-rw-r--r--product/client/server/domain/payroll/Vest.cs26
-rw-r--r--product/client/server/server.csproj17
21 files changed, 295 insertions, 133 deletions
diff --git a/product/client/server/domain/accounting/AnonymousVisitor.cs b/product/client/server/domain/AnonymousVisitor.cs
index a745d18..77fa23e 100644
--- a/product/client/server/domain/accounting/AnonymousVisitor.cs
+++ b/product/client/server/domain/AnonymousVisitor.cs
@@ -1,7 +1,7 @@
using System;
using gorilla.commons.utility;
-namespace presentation.windows.server.domain.accounting
+namespace presentation.windows.server.domain
{
public class AnonymousVisitor<T> : Visitor<T>
{
diff --git a/product/client/server/domain/accounting/Calendar.cs b/product/client/server/domain/Calendar.cs
index bffb078..d52b826 100644
--- a/product/client/server/domain/accounting/Calendar.cs
+++ b/product/client/server/domain/Calendar.cs
@@ -1,7 +1,7 @@
using System;
using Gorilla.Commons.Utility;
-namespace presentation.windows.server.domain.accounting
+namespace presentation.windows.server.domain
{
static public class Calendar
{
diff --git a/product/client/server/domain/payroll/Annually.cs b/product/client/server/domain/payroll/Annually.cs
new file mode 100644
index 0000000..e01a832
--- /dev/null
+++ b/product/client/server/domain/payroll/Annually.cs
@@ -0,0 +1,12 @@
+using Gorilla.Commons.Utility;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public class Annually : Frequency
+ {
+ public Date next(Date from_date)
+ {
+ return from_date.plus_years(1);
+ }
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/BaseDenominator.cs b/product/client/server/domain/payroll/BaseDenominator.cs
new file mode 100644
index 0000000..61fb846
--- /dev/null
+++ b/product/client/server/domain/payroll/BaseDenominator.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using gorilla.commons.utility;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public class BaseDenominator : Denominator
+ {
+ readonly int denominator;
+
+ protected BaseDenominator(int denominator)
+ {
+ this.denominator = denominator;
+ }
+
+ public IEnumerable<int> each_possible_value()
+ {
+ for (var i = 0; i < denominator; i++) yield return i;
+ }
+
+ public void each(Action<int> action)
+ {
+ each_possible_value().each(x => action(x));
+ }
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Calendar.cs b/product/client/server/domain/payroll/Calendar.cs
deleted file mode 100644
index 07f5d63..0000000
--- a/product/client/server/domain/payroll/Calendar.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using Gorilla.Commons.Utility;
-
-namespace presentation.windows.server.domain.payroll
-{
- static public class Calendar
- {
- static Func<Date> date = () => DateTime.Now.Date;
- static Func<Date> default_date = () => DateTime.Now.Date;
-
- static public void stop(Func<Date> new_date)
- {
- date = new_date;
- }
-
- static public void start()
- {
- date = default_date;
- }
-
- static public Date now()
- {
- return date();
- }
- }
-} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Compensation.cs b/product/client/server/domain/payroll/Compensation.cs
index 692b512..46423e4 100644
--- a/product/client/server/domain/payroll/Compensation.cs
+++ b/product/client/server/domain/payroll/Compensation.cs
@@ -5,19 +5,13 @@ using Gorilla.Commons.Utility;
namespace presentation.windows.server.domain.payroll
{
- public class Compensation
+ public class Compensation : Visitable<Grant>
{
- Money salary = Money.Zero;
IList<Grant> grants = new List<Grant>();
- public void increase_salary_to(Money newSalary)
+ public void issue_grant(Money grant_value, UnitPrice price, Fraction portion_to_issue_at_each_vest, Frequency frequency)
{
- salary = newSalary;
- }
-
- public void issue_grant(Money grant_value, UnitPrice price)
- {
- grants.Add(Grant.New(grant_value, price));
+ grants.Add(Grant.New(grant_value, price, portion_to_issue_at_each_vest, frequency));
}
public Grant grant_for(Date date)
@@ -25,13 +19,16 @@ namespace presentation.windows.server.domain.payroll
return grants.Single(x => x.was_issued_on(date));
}
- public Money how_much_will_they_take_home_in(int year)
+ public Money unvested_balance(Date on_date)
{
var total = Money.Zero;
- grants
- .Where(x => x.will_vest_in(year))
- .each(x => total = total.Plus(x.vesting_amount()));
- return total.Plus(salary);
+ accept(new AnonymousVisitor<Grant>(grant => total = total.plus(grant.balance(on_date))));
+ return total;
+ }
+
+ public void accept(Visitor<Grant> visitor)
+ {
+ grants.each(x => visitor.visit(x));
}
}
} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Denominator.cs b/product/client/server/domain/payroll/Denominator.cs
new file mode 100644
index 0000000..53e967d
--- /dev/null
+++ b/product/client/server/domain/payroll/Denominator.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public interface Denominator
+ {
+ IEnumerable<int> each_possible_value();
+ void each(Action<int> action);
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Fraction.cs b/product/client/server/domain/payroll/Fraction.cs
new file mode 100644
index 0000000..3043e19
--- /dev/null
+++ b/product/client/server/domain/payroll/Fraction.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public interface Fraction
+ {
+ void each(Action<int> action);
+ int of(int number);
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Frequency.cs b/product/client/server/domain/payroll/Frequency.cs
new file mode 100644
index 0000000..1001e29
--- /dev/null
+++ b/product/client/server/domain/payroll/Frequency.cs
@@ -0,0 +1,9 @@
+using Gorilla.Commons.Utility;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public interface Frequency
+ {
+ Date next(Date from_date);
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Grant.cs b/product/client/server/domain/payroll/Grant.cs
index 613fdd7..b44dd89 100644
--- a/product/client/server/domain/payroll/Grant.cs
+++ b/product/client/server/domain/payroll/Grant.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using gorilla.commons.utility;
using Gorilla.Commons.Utility;
namespace presentation.windows.server.domain.payroll
@@ -7,48 +6,77 @@ namespace presentation.windows.server.domain.payroll
public class Grant
{
Date issued_on;
- IList<Unit> units_issued = new List<Unit>();
+ History<UnitPrice> price_history = new History<UnitPrice>();
+ Units units = Units.Empty;
+ List<Vest> expirations = new List<Vest>();
- static public Grant New(Money purchase_amount, UnitPrice price)
+ static public Grant New(Money purchase_amount, UnitPrice price, Fraction portion, Frequency frequency)
{
var grant = new Grant
{
issued_on = Calendar.now(),
};
- price.purchase_units(purchase_amount).each(x => grant.add(x));
+ grant.change_unit_price_to(price);
+ grant.purchase(purchase_amount);
+ grant.apply_vesting_frequency(portion, frequency);
return grant;
}
- public void change_unit_price_to(UnitPrice new_price)
+ Grant() {}
+
+ public virtual void change_unit_price_to(UnitPrice new_price)
{
- units_issued.each(x => x.change_price(new_price));
+ price_history.record(new_price);
}
- public bool was_issued_on(Date date)
+ public virtual bool was_issued_on(Date date)
{
return issued_on.Equals(date);
}
- public Money current_value()
+ public virtual Money balance()
+ {
+ return balance(Calendar.now());
+ }
+
+ public virtual Money balance(Date on_date)
+ {
+ return unit_price(on_date).total_value_of(units_remaining(on_date));
+ }
+
+ Units units_remaining(Date on_date)
+ {
+ var remaining = Units.Empty;
+ foreach (var expiration in expirations)
+ {
+ remaining = remaining.combined_with(expiration.unvested_units(units, on_date));
+ }
+ return remaining;
+ }
+
+ void purchase(Money amount)
{
- var total = Money.Zero;
- units_issued.each(x => total = total.Plus(x.current_value()));
- return total;
+ units = units.combined_with(current_unit_price().purchase_units(amount));
}
- void add(Unit unit)
+ UnitPrice current_unit_price()
{
- units_issued.Add(unit);
+ return unit_price(Calendar.now());
}
- public bool will_vest_in(int year)
+ UnitPrice unit_price(Date on_date)
{
- return true;
+ return price_history.recorded(on_date);
}
- public Money vesting_amount()
+ void apply_vesting_frequency(Fraction portion, Frequency frequency)
{
- return current_value().divided_by(3);
+ var next_date = issued_on.minus_days(1);
+ portion.each(x =>
+ {
+ next_date = frequency.next(next_date);
+ expirations.Add(new Vest(portion, next_date));
+ });
}
}
} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/History.cs b/product/client/server/domain/payroll/History.cs
index 3ad2c3a..7aaaf66 100644
--- a/product/client/server/domain/payroll/History.cs
+++ b/product/client/server/domain/payroll/History.cs
@@ -1,26 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
using Gorilla.Commons.Utility;
namespace presentation.windows.server.domain.payroll
{
- public class History
+ public class History<T>
{
- Date dateOfChange;
- UnitPrice adjustedPrice;
+ Stack<Event<T>> events = new Stack<Event<T>>();
- History() {}
+ public void record(T change)
+ {
+ events.Push(new Event<T>(change));
+ }
- static public History New(UnitPrice newPrice)
+ public T recorded(Date date)
{
- return new History
- {
- dateOfChange = Calendar.now(),
- adjustedPrice = newPrice,
- };
+ return events.Where(x => x.occurred_on_or_before(date)).Max();
}
- public UnitPrice Adjustment()
+ class Event<K> : IComparable<Event<K>>
{
- return adjustedPrice;
+ public Event(K adjustment)
+ {
+ date_of_change = Calendar.now();
+ this.adjustment = adjustment;
+ }
+
+ K adjustment;
+ Date date_of_change;
+
+ public int CompareTo(Event<K> other)
+ {
+ return date_of_change.CompareTo(other.date_of_change);
+ }
+
+ public bool occurred_on_or_before(Date date)
+ {
+ return date_of_change.Equals(date) || date_of_change.is_before(date);
+ }
+
+ static public implicit operator K(Event<K> eventA)
+ {
+ return eventA.adjustment;
+ }
}
}
} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Money.cs b/product/client/server/domain/payroll/Money.cs
index 15bf1d4..6c538f7 100644
--- a/product/client/server/domain/payroll/Money.cs
+++ b/product/client/server/domain/payroll/Money.cs
@@ -1,10 +1,11 @@
using System;
+using gorilla.commons.utility;
namespace presentation.windows.server.domain.payroll
{
public class Money : IEquatable<Money>
{
- public double value { get; private set; }
+ double value;
static public Money Zero = new Money(0);
Money(double value)
@@ -17,16 +18,21 @@ namespace presentation.windows.server.domain.payroll
return new Money(raw);
}
- public Money Plus(Money otherMoney)
+ public virtual Money plus(Money other)
{
- return value + otherMoney.value;
+ return value + other.value;
}
- public bool Equals(Money other)
+ public virtual Money minus(Money other)
+ {
+ return value - other.value;
+ }
+
+ public virtual bool Equals(Money other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
- return other.value == value;
+ return other.value.Equals(value);
}
public override bool Equals(object obj)
@@ -42,24 +48,14 @@ namespace presentation.windows.server.domain.payroll
return value.GetHashCode();
}
- static public bool operator ==(Money left, Money right)
- {
- return Equals(left, right);
- }
-
- static public bool operator !=(Money left, Money right)
- {
- return !Equals(left, right);
- }
-
public override string ToString()
{
- return value.ToString("c");
+ return "{0:C}".format(value);
}
- public Money divided_by(int denominator)
+ public Units at_price(double price)
{
- return new Money(value/denominator);
+ return Units.New((int)(value / price));
}
}
} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Monthly.cs b/product/client/server/domain/payroll/Monthly.cs
new file mode 100644
index 0000000..189a68a
--- /dev/null
+++ b/product/client/server/domain/payroll/Monthly.cs
@@ -0,0 +1,12 @@
+using Gorilla.Commons.Utility;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public class Monthly : Frequency
+ {
+ public Date next(Date from_date)
+ {
+ return from_date.add_months(1);
+ }
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/One.cs b/product/client/server/domain/payroll/One.cs
new file mode 100644
index 0000000..c3475d7
--- /dev/null
+++ b/product/client/server/domain/payroll/One.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Linq;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public class One<T> : Fraction where T : Denominator, new()
+ {
+ T denominator = new T();
+
+ public void each(Action<int> action)
+ {
+ denominator.each(x => action(x));
+ }
+
+ public int of(int number)
+ {
+ return number / denominator.each_possible_value().Count();
+ }
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Third.cs b/product/client/server/domain/payroll/Third.cs
new file mode 100644
index 0000000..b1b545d
--- /dev/null
+++ b/product/client/server/domain/payroll/Third.cs
@@ -0,0 +1,7 @@
+namespace presentation.windows.server.domain.payroll
+{
+ public class Third : BaseDenominator
+ {
+ public Third() : base(3) {}
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Twelfth.cs b/product/client/server/domain/payroll/Twelfth.cs
new file mode 100644
index 0000000..ade8a09
--- /dev/null
+++ b/product/client/server/domain/payroll/Twelfth.cs
@@ -0,0 +1,7 @@
+namespace presentation.windows.server.domain.payroll
+{
+ public class Twelfth : BaseDenominator
+ {
+ public Twelfth() : base(12) {}
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Unit.cs b/product/client/server/domain/payroll/Unit.cs
deleted file mode 100644
index 8e5a94e..0000000
--- a/product/client/server/domain/payroll/Unit.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Collections.Generic;
-
-namespace presentation.windows.server.domain.payroll
-{
- public class Unit
- {
- UnitPrice current_price;
- IList<History> history = new List<History>();
-
- static public Unit New(UnitPrice price)
- {
- var unit = new Unit();
- unit.change_price(price);
- return unit;
- }
-
- public void change_price(UnitPrice new_price)
- {
- current_price = new_price ?? 0;
- history.Add(History.New(new_price));
- }
-
- public Money current_value()
- {
- return current_price.to_money();
- }
- }
-} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/UnitPrice.cs b/product/client/server/domain/payroll/UnitPrice.cs
index 293ab17..0f1c450 100644
--- a/product/client/server/domain/payroll/UnitPrice.cs
+++ b/product/client/server/domain/payroll/UnitPrice.cs
@@ -1,10 +1,8 @@
-using System.Collections.Generic;
-
namespace presentation.windows.server.domain.payroll
{
public class UnitPrice
{
- double price;
+ readonly double price;
UnitPrice(double price)
{
@@ -16,19 +14,14 @@ namespace presentation.windows.server.domain.payroll
return new UnitPrice(raw);
}
- public IEnumerable<Unit> purchase_units(Money amount)
- {
- for (var i = 0; i < number_of_units(amount); i++) yield return Unit.New(this);
- }
-
- double number_of_units(Money amount)
+ public Units purchase_units(Money amount)
{
- return amount.value/price;
+ return amount.at_price(price);
}
- public Money to_money()
+ public virtual Money total_value_of(Units units)
{
- return price;
+ return units.value_at(price);
}
}
} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Units.cs b/product/client/server/domain/payroll/Units.cs
new file mode 100644
index 0000000..c14c931
--- /dev/null
+++ b/product/client/server/domain/payroll/Units.cs
@@ -0,0 +1,30 @@
+namespace presentation.windows.server.domain.payroll
+{
+ public class Units
+ {
+ static public readonly Units Empty = new Units();
+ Units() {}
+
+ static public Units New(int units)
+ {
+ return new Units {units = units};
+ }
+
+ public Money value_at(double price)
+ {
+ return price*units;
+ }
+
+ public Units combined_with(Units other)
+ {
+ return New(units + other.units);
+ }
+
+ public Units reduced_by(Fraction portion)
+ {
+ return New(portion.of(units));
+ }
+
+ int units;
+ }
+} \ No newline at end of file
diff --git a/product/client/server/domain/payroll/Vest.cs b/product/client/server/domain/payroll/Vest.cs
new file mode 100644
index 0000000..82b796a
--- /dev/null
+++ b/product/client/server/domain/payroll/Vest.cs
@@ -0,0 +1,26 @@
+using Gorilla.Commons.Utility;
+
+namespace presentation.windows.server.domain.payroll
+{
+ public class Vest
+ {
+ Fraction portion;
+ Date vesting_date;
+
+ public Vest(Fraction portion, Date vesting_date)
+ {
+ this.portion = portion;
+ this.vesting_date = vesting_date;
+ }
+
+ public Units unvested_units(Units total_units, Date date)
+ {
+ return expires_before(date) ? Units.Empty : total_units.reduced_by(portion);
+ }
+
+ bool expires_before(Date date)
+ {
+ return vesting_date.is_before(date);
+ }
+ }
+} \ No newline at end of file
diff --git a/product/client/server/server.csproj b/product/client/server/server.csproj
index f8a5b5f..be66b57 100644
--- a/product/client/server/server.csproj
+++ b/product/client/server/server.csproj
@@ -111,9 +111,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ConfigureApplicationDirectory.cs" />
- <Compile Include="domain\accounting\AnonymousVisitor.cs" />
+ <Compile Include="domain\AnonymousVisitor.cs" />
<Compile Include="domain\accounting\BOED.cs" />
- <Compile Include="domain\accounting\Calendar.cs" />
+ <Compile Include="domain\Calendar.cs" />
<Compile Include="domain\accounting\ConversionRatio.cs" />
<Compile Include="domain\accounting\DateRange.cs" />
<Compile Include="domain\accounting\Deposit.cs" />
@@ -132,6 +132,17 @@
<Compile Include="domain\accounting\TransactionType.cs" />
<Compile Include="domain\accounting\Withdrawal.cs" />
<Compile Include="domain\Identifiable.cs" />
+ <Compile Include="domain\payroll\Annually.cs" />
+ <Compile Include="domain\payroll\BaseDenominator.cs" />
+ <Compile Include="domain\payroll\Denominator.cs" />
+ <Compile Include="domain\payroll\Fraction.cs" />
+ <Compile Include="domain\payroll\Frequency.cs" />
+ <Compile Include="domain\payroll\Monthly.cs" />
+ <Compile Include="domain\payroll\One.cs" />
+ <Compile Include="domain\payroll\Third.cs" />
+ <Compile Include="domain\payroll\Twelfth.cs" />
+ <Compile Include="domain\payroll\Units.cs" />
+ <Compile Include="domain\payroll\Vest.cs" />
<Compile Include="handlers\AddNewFamilyMemberHandler.cs" />
<Compile Include="orm\mappings\DetailAccountMapping.cs" />
<Compile Include="ServerBootstrapper.cs" />
@@ -140,12 +151,10 @@
<Compile Include="domain\accounting\Currency.cs" />
<Compile Include="domain\accounting\UnitOfMeasure.cs" />
<Compile Include="domain\Entity.cs" />
- <Compile Include="domain\payroll\Calendar.cs" />
<Compile Include="domain\payroll\Compensation.cs" />
<Compile Include="domain\payroll\Grant.cs" />
<Compile Include="domain\payroll\History.cs" />
<Compile Include="domain\payroll\Money.cs" />
- <Compile Include="domain\payroll\Unit.cs" />
<Compile Include="domain\payroll\UnitPrice.cs" />
<Compile Include="domain\Person.cs" />
<Compile Include="handlers\FindAllFamilyHandler.cs" />