]> Git — Sourcephile - tmp/julm/literate-invoice.git/blob - tests/Tests/Invoice.hs
maint/correctness(Work): use sum type for ScopeId
[tmp/julm/literate-invoice.git] / tests / Tests / Invoice.hs
1 {-# LANGUAGE DeriveAnyClass #-}
2 {-# LANGUAGE OverloadedLists #-}
3 {-# LANGUAGE OverloadedStrings #-}
4
5 module Tests.Invoice where
6
7 import Data.List qualified as List
8 import Data.Text.Lazy qualified as Text.Lazy
9 import Data.Time.Clock qualified as Time
10 import Data.Time.LocalTime qualified as Time
11 import Test.Syd (Spec, describe, goldenByteStringBuilderFile, it)
12 import Tests.Utils.Tests (goldenPath)
13 import Text.Blaze.Renderer.Text qualified as Blaze.Text
14 import Text.Blaze.Renderer.Utf8 qualified as Blaze
15 import Prelude ((*))
16
17 import Literate.Accounting (Amount, Unit (UnitName))
18 import Literate.Database
19 import Literate.Document.HTML qualified as HTML
20 import Literate.Invoice
21 import Literate.Invoice.HTML (invoiceIdInline)
22 import Literate.Invoice.HTML qualified as HTML
23 import Literate.Prelude
24
25 import Tests.Organization
26 import Tests.Work
27
28 spec :: HasCallStack => Spec
29 spec =
30 describe "Invoice" do
31 forM_ invoices \invId -> do
32 let
33 inv = invId & get @(Invoice ScopeId ActionId EntityId InvoiceId)
34 idS =
35 inv
36 & invoiceIdInline
37 & HTML.toHtml
38 & Blaze.Text.renderMarkup
39 & Text.Lazy.unpack
40 outPath <- goldenPath idS "html"
41 it idS do
42 goldenByteStringBuilderFile outPath do
43 inv & HTML.htmlIO <&> Blaze.renderMarkupBuilder
44
45 data InvoiceId
46 = Invoice_0
47 | Invoice_org3sale1
48 | Invoice_org3sale2
49 | Invoice_org3sale3
50 deriving (Eq, Ord, Show, Generic, Enum, NFData)
51
52 instance Get (Invoice ScopeId ActionId EntityId InvoiceId) InvoiceId where
53 get invoiceId = case invoiceId of
54 Invoice_0 ->
55 Invoice
56 { invoiceId
57 , invoiceType = InvoiceTypeSale
58 , invoiceOrders = []
59 , invoiceEmittedOn
60 , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay)
61 , invoiceIssuer = EntityJulmInfo
62 , invoiceRecipient = EntityJulmInfo
63 , invoiceRates = [Action_Development := 0]
64 , invoiceMentions =
65 [ InvoiceMentionTVANonApplicable
66 , InvoiceMentionIndemnitéForfaitaire
67 , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%"))
68 ]
69 , invoiceWorks =
70 [ Work
71 { workDate = "2000-01-01"
72 , workDuration = 1
73 , workAction = Action_Development
74 , workScope = []
75 , workReferences = []
76 , workDescription = ""
77 }
78 ]
79 }
80 where
81 invoiceEmittedOn = "2026-01-22"
82 Invoice_org3sale1 ->
83 Invoice
84 { invoiceId
85 , invoiceType = InvoiceTypeSale
86 , invoiceOrders = ["Contract n°2025-24"]
87 , invoiceEmittedOn
88 , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay)
89 , invoiceIssuer = EntityJulmInfo
90 , invoiceRecipient = EntityNixOSFoundationNGITeam
91 , invoiceRates =
92 [ Action_Organization := 31.25
93 , Action_Development := 31.25
94 , Action_Documentation := 31.25
95 , Action_Review := 31.25
96 ]
97 , invoiceMentions =
98 [ InvoiceMentionTVANonApplicable
99 , InvoiceMentionIndemnitéForfaitaire
100 , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%"))
101 ]
102 , invoiceWorks =
103 works
104 & List.filter \work ->
105 and $
106 list
107 [ work & workDate & (>= "2025-11-06")
108 , work & workDate & (<= "2025-12-22")
109 , work & workScope & (/= [Scope_NGIpkgs_Manuals])
110 ]
111 }
112 where
113 invoiceEmittedOn = "2026-01-22"
114 Invoice_org3sale2 ->
115 Invoice
116 { invoiceId
117 , invoiceType = InvoiceTypeSale
118 , invoiceOrders = ["contract n°2026-03"]
119 , invoiceEmittedOn
120 , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay)
121 , invoiceIssuer = EntityJulmInfo
122 , invoiceRecipient = EntityNixOSFoundationNGITeam
123 , invoiceRates =
124 [ Action_Organization := 31.25
125 , Action_Development := 31.25
126 , Action_Documentation := 31.25
127 , Action_Review := 31.25
128 ]
129 , invoiceMentions =
130 [ InvoiceMentionTVANonApplicable
131 , InvoiceMentionIndemnitéForfaitaire
132 , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%"))
133 ]
134 , invoiceWorks =
135 works
136 & List.filter \work ->
137 and $
138 [ work & workDate & (>= "2025-12-23")
139 , work & workDate & (<= "2026-12-31")
140 , work & workScope & (/= [Scope_NGIpkgs_Manuals])
141 , work & workScope & (/= [Scope_NGIpkgs, Scope_Funkwhale])
142 , not $
143 and $
144 [ work & workDate & (>= "2026-01-09")
145 , work & workDate & (<= "2026-01-28")
146 , work & workAction & (== Action_Organization)
147 , work & workScope & (== [Scope_NGIpkgs])
148 ]
149 & list
150 ]
151 & list
152 }
153 where
154 invoiceEmittedOn = "2026-01-27"
155 Invoice_org3sale3 ->
156 Invoice
157 { invoiceId
158 , invoiceType = InvoiceTypeSale
159 , invoiceOrders = ["contract n°2026-FixMe"]
160 , invoiceEmittedOn
161 , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay)
162 , invoiceIssuer = EntityJulmInfo
163 , invoiceRecipient = EntityNixOSFoundationNGITeam
164 , invoiceRates =
165 [ Action_Organization := 31.25
166 , Action_Development := 31.25
167 , Action_Documentation := 31.25
168 , Action_Review := 31.25
169 ]
170 , invoiceMentions =
171 [ InvoiceMentionTVANonApplicable
172 , InvoiceMentionIndemnitéForfaitaire
173 , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%"))
174 ]
175 , invoiceWorks =
176 works
177 & List.filter \work ->
178 or $
179 [ and $
180 [ work & workDate & (>= "2026-01-21")
181 , work & workDate & (<= "2026-12-31")
182 , work & workScope & (== [Scope_NGIpkgs_Manuals])
183 ]
184 & list
185 , and $
186 [ work & workDate & (>= "2025-12-29")
187 , work & workDate & (<= "2026-12-31")
188 , work & workScope & (== [Scope_NGIpkgs, Scope_Funkwhale])
189 ]
190 & list
191 , and $
192 [ work & workDate & (>= "2026-01-09")
193 , work & workDate & (<= "2026-01-28")
194 , work & workAction & (== Action_Organization)
195 , work & workScope & (== [Scope_NGIpkgs])
196 ]
197 & list
198 ]
199 & list
200 }
201 where
202 invoiceEmittedOn = "2026-01-28"
203
204 invoices :: [InvoiceId]
205 invoices = enumAll