/
Types.hs
201 lines (157 loc) · 6.21 KB
/
Types.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
{-# Language DeriveDataTypeable #-}
module Types(
module Types,
module Type.Base,
module Type.WorkPatronage,
module Type.Allocation,
module Type.Disbursal
) where
import Data.Ratio ((%))
import qualified Data.Map as M
import qualified Data.Set as S
import Type.Base
import Type.WorkPatronage
import Type.Allocation
import Type.Disbursal
data PatronageWeights = PatronageWeights { -- wght
workw::Rational,
skillWeightedWorkw::Rational,
seniorityw::Rational,
qualityw::Rational,
revenueGeneratedw::Rational
} deriving (Show, Eq, Ord, Data, Typeable)
data MemberEquityAction = MemberEquityAction { -- acn
actionType::EquityActionType,
amount::Money,
performedOn::Day
} deriving (Show, Read, Eq, Ord, Data, Typeable)
data EquityActionType = --migrate all actions in db, + name changes
BuyIn |
AllocatePatronageRebate |
DistributeInstallment |
EarnInterest |
DistributeOnDeparture |
DistributeOnDissolution |
DistributeMilestone |
AllocateDelayedNonQualified
deriving (Show, Read, Eq, Ord, Data, Typeable)
acnEffectiveAmount :: MemberEquityAction -> Money
acnEffectiveAmount MemberEquityAction{ actionType = actionType, amount = amount }
| S.member
actionType
(S.fromList
[BuyIn, AllocatePatronageRebate, EarnInterest, AllocateDelayedNonQualified]) =
amount
| otherwise = -amount
data MemberEquityAccount = MemberEquityAccount { -- acct
ida::Integer,
accountType::EquityAccountType
} deriving (Show, Read, Eq, Ord, Data, Typeable)
data EquityAccountType = BuyInAcct | RollingPatronageAcct
deriving (Show, Read, Eq, Ord, Data, Typeable)
data Member = Member { -- mbr
firstName::String,
lastName::String,
memberId::Integer,
acceptedOn::Day
} deriving (Show, Eq, Ord, Data, Typeable)
mbrSeniorityLevel :: Member -> Day -> SeniorityMappings -> SeniorityLevel
mbrSeniorityLevel Member{acceptedOn=acceptedOn} now snrtyMap =
let years = diffYears acceptedOn now
in M.foldlWithKey
(\lvlSoFar SeniorityMappingEntry{snrtyMpEntStart=start} lvl ->
if years > start then lvl else lvlSoFar)
1
snrtyMap
mbrSeniorityLevelFor :: Member -> FiscalPeriod -> SeniorityMappings -> SeniorityLevel
mbrSeniorityLevelFor m FiscalPeriod{start=start} mp =
mbrSeniorityLevel m (toDay start) mp
diffYears :: Day -> Day -> Integer
diffYears earlier later =
year later - year earlier
where year d = let (y,_,_) = toGregorian d in y
data FinancialResults = FinancialResults { -- rslt
over::FiscalPeriod,
surplus::Money, --net-inc
allocatedOn::Maybe Day -- REMOVE
} deriving (Show, Read, Eq, Ord, Data, Typeable)
data Cooperative = Cooperative { -- cp
cooperativeId::Integer,
name::String,
username::OpenID,
usageStart::Day,
usageEnd::Maybe Day,
fiscalCalendarType::FiscalCalendarType
} deriving (Show, Read, Eq, Ord, Data, Typeable)
data SeniorityMappingEntry = SeniorityMappingEntry {
snrtyMpEntStart::Years
} deriving (Show, Read, Eq, Ord, Data, Typeable)
type SeniorityLevel = Integer
type SeniorityMappings = M.Map SeniorityMappingEntry SeniorityLevel
data FiscalCalendarType = FiscalCalendarType{ -- clTp
startf::Month,
periodTypef::PeriodType
} deriving (Show, Read, Eq, Ord, Data, Typeable)
type OpenID = String
type Money = Integer
data GregorianDuration = GregorianDuration Years Months
deriving (Show, Read, Eq, Ord, Data, Typeable)
type Years = Integer
type Months = Integer
type DisbursalSchedule = [(GregorianDuration, Rational)]
data AllocationMethod =
ProductiveHours | Wages | SimpleMix | SeniorityMix | ElaborateMix
deriving (Show, Read, Eq, Ord, Data, Typeable)
data PatronageFieldDetail = PatronageFieldDetail {
ptrngFldLabel::String
} deriving (Show, Read, Eq, Ord, Data, Typeable)
workFieldDetail = PatronageFieldDetail "work"
skillWeightedWorkFieldDetail = PatronageFieldDetail "skillWeightedWork"
seniorityFieldDetail = PatronageFieldDetail "seniority"
qualityFieldDetail = PatronageFieldDetail "quality"
revenueGeneratedFieldDetail = PatronageFieldDetail "revenueGenerated"
instance Default GregorianDuration where
def = GregorianDuration 0 0
instance Default AllocationMethod where
def = ProductiveHours
instance Default EquityActionType where
def = AllocatePatronageRebate
instance Default PatronageWeights where
def = PatronageWeights{workw=1,skillWeightedWorkw=def,seniorityw=def,qualityw=def,
revenueGeneratedw=def}
instance Default MemberEquityAction where
def = MemberEquityAction{actionType=def, amount=def,performedOn=def}
instance Default EquityAccountType where
def = RollingPatronageAcct
instance Default MemberEquityAccount where
def = MemberEquityAccount{ida=1,accountType=def}
instance Default Member where
def = Member{firstName=def,lastName=def,memberId=1,acceptedOn=def}
instance Default FinancialResults where
def = FinancialResults{over=def,surplus=def,allocatedOn=Nothing}
instance Default FiscalCalendarType where
def = FiscalCalendarType{startf=1,periodTypef=def}
instance Default Cooperative where
def = Cooperative{cooperativeId=1,name=def,username=def,usageStart=def,
usageEnd=Nothing,fiscalCalendarType=def}
-- sample data
(f1,f2) =
(def{start=(GregorianMonth 2012 1)},
def{start=(GregorianMonth 2011 1)})::(FiscalPeriod,FiscalPeriod)
(m1, m2, m3) =
(Member "John" "Smith" 1 (fromGregorian 2010 1 1),
Member "Kanishka" "Azimi" 2 (fromGregorian 2011 1 1),
Member "Dave" "Jackson" 3 (fromGregorian 2009 3 30))::(Member,Member,Member)
pw1 = def{workw=7%10,skillWeightedWorkw=3%10}::PatronageWeights
coop1 = def{name="Coop1",username="https://www.google.com/profiles/102678013619698873278",
usageStart=fromGregorian 2010 1 1}
settings1 = (SimpleMix,
pw1,
[(GregorianDuration 1 0, 6%10), (GregorianDuration 1 6, 4%10)])
-- add seniority levels
memPatronage1 = (M.fromList
[ (m1, [WorkPatronage 5 4 3 2 1 f2])
, (m2, [WorkPatronage 10 20 30 40 50 f2])
, (m3, [WorkPatronage 100 200 300 400 500 f2]) ])
res1 = [FinancialResults
def{start=GregorianMonth 2012 1} 200 $ Just (fromGregorian 2011 1 2)]