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