]> Git — Sourcephile - tmp/julm/literate-invoice.git/blob - src/Literate/Invoice.hs
maint/correctness(Work): use sum type for ScopeId
[tmp/julm/literate-invoice.git] / src / Literate / Invoice.hs
1 {-# LANGUAGE DeriveAnyClass #-}
2 {-# LANGUAGE OverloadedLists #-}
3 {-# LANGUAGE QuantifiedConstraints #-}
4 {-# LANGUAGE UndecidableInstances #-}
5
6 module Literate.Invoice where
7
8 import Literate.Accounting.Amount
9 import Literate.Accounting.Quantity
10 import Literate.Accounting.Unit
11 import Literate.Database
12 import Literate.Document qualified as Doc
13 import Literate.Organization
14 import Literate.Prelude
15 import Literate.Time
16
17 type InvoiceScope = [Text]
18
19 data Invoice scopeId actionId entId invId = Invoice
20 { invoiceId :: invId
21 , invoiceType :: InvoiceType
22 , invoiceEmittedOn :: LocalTime
23 , invoiceOrders :: [Doc.Inline]
24 , invoicePaymentDueBefore :: LocalTime
25 , invoiceIssuer :: entId
26 , invoiceRecipient :: entId
27 , -- , invoiceItems :: [InvoiceItem (UnitName "€" :/: UnitName "h") (UnitName "h")]
28 invoiceRates :: Map actionId (Amount 100 (UnitName "€" :/: UnitName "h"))
29 , invoiceMentions :: [InvoiceMention]
30 , invoiceWorks :: [Work scopeId actionId]
31 }
32 deriving (Eq, Show)
33
34 invoice ::
35 Ord actionId =>
36 Enum entId =>
37 invId -> Invoice scopeId actionId entId invId
38 invoice invoiceId =
39 Invoice
40 { invoiceId
41 , invoiceType = InvoiceTypeSale
42 , invoiceEmittedOn = "2000-01-01"
43 , invoiceOrders = []
44 , invoicePaymentDueBefore = "2000-01-31"
45 , invoiceIssuer = toEnum 0
46 , invoiceRecipient = toEnum 0
47 , invoiceRates = []
48 , invoiceMentions = []
49 , invoiceWorks = []
50 }
51
52 data Work scopeId actionId = Work
53 { workDescription :: Doc.Inline
54 , workDate :: LocalTime
55 , workDuration :: Amount 100 (UnitName "h")
56 , workAction :: actionId
57 , workScope :: Ands scopeId
58 , workReferences :: [URL]
59 }
60 deriving (Eq, Show)
61
62 data WorkActionId
63 = WorkAction
64
65 data InvoiceType
66 = InvoiceTypeSale
67 | InvoiceTypeProForma
68 | InvoiceTypeVoucher
69 deriving (Eq, Ord, Show, Generic, NFData)
70 data InvoiceMention
71 = InvoiceMentionTVANonApplicable
72 | InvoiceMentionIndemnitéForfaitaire
73 | InvoiceMentionIndemnitéTaux (Amount 100 (UnitName "%"))
74 deriving (Eq, Ord, Show, Generic, NFData)
75
76 data InvoiceItem scopeId actionId rate qty = InvoiceItem
77 { invoiceItemScope :: Ands scopeId
78 , invoiceItemAction :: actionId
79 , invoiceItemType :: InvoiceItemType
80 , invoiceItemPeriod :: Period
81 , invoiceItemRate :: Amount 100 rate
82 , invoiceItemQuantity :: Amount 100 qty
83 }
84 deriving (Eq, Show)
85 type Euro = Amount 100 (UnitName "€")
86
87 invoiceItemTotal :: InvoiceItem scopeId actionId rate qty -> Euro
88 invoiceItemTotal InvoiceItem{..} =
89 let (res, _actualFrac) =
90 invoiceItemRate
91 & amountQuantity
92 & fraction (invoiceItemQuantity & amountQuantity & quantityToRatio)
93 in Amount res
94
95 data InvoiceItemType
96 = InvoiceItemTypeItem
97 | InvoiceItemTypeService
98 deriving (Eq, Ord, Show)
99
100 data Period = Period
101 { periodBeginning :: LocalTime
102 , periodEnd :: LocalTime
103 }
104 deriving (Eq, Ord, Show, Generic, NFData)