1 {-# LANGUAGE DeriveAnyClass #-}
2 {-# LANGUAGE OverloadedLists #-}
3 {-# LANGUAGE StandaloneDeriving #-}
4 {-# LANGUAGE UndecidableInstances #-}
6 module Literate.Organization where
8 import Country qualified
9 import Country.Identifier qualified as Country
10 import Data.Text qualified as Text
11 import Literate.Document qualified as Doc
12 import Literate.Document.HTML qualified as HTML
13 import Literate.Prelude
14 import Text.Printf qualified as Printf
15 import Prelude qualified
18 data EntityId = EntityId {unEntityId :: Natural}
19 deriving (Eq, Ord, Show, Generic, NFData)
20 instance HTML.ToMarkup EntityId where
21 toMarkup i = i & unEntityId & HTML.toHtml
22 instance Doc.ToInline EntityId where
23 toInline i = i & unEntityId & show & Doc.toInline
26 type family EntityOf (a :: Type) :: Type
28 class GetEntity entId where
29 getEntity :: entId -> Entity entId
31 data URL = URL {unURL :: Text}
32 deriving (Eq, Ord, Show, Generic, NFData)
33 instance IsString URL where
34 fromString = URL . fromString
35 instance Doc.ToInline URL where
36 toInline = unURL >>> Doc.Target >>> Doc.inlineLinkExplicit
42 deriving (Eq, Ord, Show, Generic, NFData)
43 instance IsString Email where
45 case s & fromString & Text.split (== '@') of
46 [emailLocal, emailServer] -> Email{..}
47 _ -> Prelude.error $ "IsString Email: " <> s
48 instance Doc.ToBlock Email where
49 toBlock = Doc.toBlock . Doc.toInline
50 instance Doc.ToInline Email where
53 { Doc.inlineLinkText =
54 [ eml & emailLocal & Doc.toInline
56 , eml & emailServer & Doc.toInline
59 , Doc.inlineLinkTarget =
70 data Entity entId = Entity
72 , entityAddress :: Maybe Address
73 , entityEmail :: Maybe Email
74 , entityIBAN :: Maybe IBAN
75 , entityName :: Maybe Text
76 , entityPhone :: Maybe Phone
77 , entitySIREN :: Maybe Text
79 deriving (Eq, Ord, Show, Generic, NFData)
80 entity :: entId -> Entity entId
84 , entityAddress = Nothing
85 , entityEmail = Nothing
86 , entityIBAN = Nothing
87 , entityName = Nothing
88 , entityPhone = Nothing
89 , entitySIREN = Nothing
93 class GetOrganization entId where
94 getOrganization :: entId -> Organization entId
95 data Organization entId
98 , orgParts :: [(Role, Organization entId)]
100 deriving (Eq, Ord, Show, Generic, NFData)
102 instance Doc.ToBlock (Entity entId) where
109 [ [ "Name" := addr & Doc.toBlock
110 | addr <- ent & entityName & maybeToList
112 , [ "Address" := addr & Doc.toBlock
113 | addr <- ent & entityAddress & maybeToList
115 , [ "SIREN" := siren & Doc.toBlock
116 | siren <- ent & entitySIREN & maybeToList
118 , [ "Email" := email & Doc.toBlock
119 | email <- ent & entityEmail & maybeToList
121 , [ "Phone" := phone & Doc.toBlock
122 | phone <- ent & entityPhone & maybeToList
124 , [ "IBAN" := iban & Doc.toBlock
125 | iban <- ent & entityIBAN & maybeToList
129 instance GetEntity entId => Doc.ToBlock (Organization entId) where
133 [ Doc.toBlock $ org & orgEntity & getEntity
136 [ role & Doc.toInline := part & Doc.toBlock
137 | (role, part) <- org & orgParts
142 | Text.null role = "" :: Doc.Inline
144 Doc.classes @Doc.Inline ["entity-role"] $
145 "(" <> Doc.toInline role <> ")"
147 data Address = Address
148 { addressText :: [Text]
149 , addressZipCode :: ZipCode
150 , addressCity :: City
151 , addressCountry :: Country.Country
153 deriving (Eq, Ord, Show, Generic, NFData)
154 instance Doc.ToBlock Address where
156 Doc.classes ["address"] $
160 | t <- addr & addressText
166 $ [ addr & addressZipCode & Doc.toInline
167 , addr & addressCity & Doc.toInline
168 , addr & addressCountry & Country.encodeEnglish & Doc.toInline
174 , addressZipCode = ""
176 , addressCountry = Country.france
182 -- | International Bank Account Number
184 { ibanCountry :: Country.Country
185 , ibanCheckDigits :: Natural
186 , ibanBasicBankAccountNumber :: Text
188 deriving (Eq, Ord, Show, Generic, NFData)
190 instance Doc.ToBlock IBAN where
192 [ iban & ibanCountry & Country.alphaTwoUpper & Doc.toInline
193 , iban & ibanCheckDigits & (Printf.printf "%02d" :: _ -> String) & Doc.toInline
195 , iban & ibanBasicBankAccountNumber & Text.chunksOf 4 & Text.intercalate " " & Doc.toInline