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 Text.Printf qualified as Printf
12 import Prelude qualified
14 import Literate.Database
15 import Literate.Document qualified as Doc
16 import Literate.Prelude
18 data URL = URL {unURL :: Text}
19 deriving (Eq, Ord, Show, Generic, NFData)
20 instance IsString URL where
21 fromString = URL . fromString
22 instance Doc.ToInline URL where
23 toInline = unURL >>> Doc.Target >>> Doc.inlineLinkExplicit
29 deriving (Eq, Ord, Show, Generic, NFData)
30 instance IsString Email where
32 case s & fromString & Text.split (== '@') of
33 [emailLocal, emailServer] -> Email{..}
34 _ -> Prelude.error $ "IsString Email: " <> s
35 instance Doc.ToBlock Email where
36 toBlock = Doc.toBlock . Doc.toInline
37 instance Doc.ToInline Email where
40 { Doc.inlineLinkText =
41 [ eml & emailLocal & Doc.toInline
43 , eml & emailServer & Doc.toInline
46 , Doc.inlineLinkTarget =
57 data Entity entId = Entity
59 , entityAddress :: Maybe Address
60 , entityEmail :: Maybe Email
61 , entityIBAN :: Maybe IBAN
62 , entityName :: Maybe Text
63 , entityPhone :: Maybe Phone
64 , entitySIREN :: Maybe Text
66 deriving (Eq, Ord, Show, Generic, NFData)
67 entity :: entId -> Entity entId
71 , entityAddress = Nothing
72 , entityEmail = Nothing
73 , entityIBAN = Nothing
74 , entityName = Nothing
75 , entityPhone = Nothing
76 , entitySIREN = Nothing
81 data Organization entId
84 , orgParts :: [(Role, Organization entId)]
86 deriving (Eq, Ord, Show, Generic, NFData)
87 instance Doc.ToBlock (Entity entId) where
94 [ [ "Name" := addr & Doc.toBlock
95 | addr <- ent & entityName & maybeToList
97 , [ "Address" := addr & Doc.toBlock
98 | addr <- ent & entityAddress & maybeToList
100 , [ "SIREN" := siren & Doc.toBlock
101 | siren <- ent & entitySIREN & maybeToList
103 , [ "Email" := email & Doc.toBlock
104 | email <- ent & entityEmail & maybeToList
106 , [ "Phone" := phone & Doc.toBlock
107 | phone <- ent & entityPhone & maybeToList
109 , [ "IBAN" := iban & Doc.toBlock
110 | iban <- ent & entityIBAN & maybeToList
114 instance Get (Entity entId) entId => Doc.ToBlock (Organization entId) where
118 [ Doc.toBlock $ org & orgEntity & get @(Entity entId)
121 [ role & Doc.toInline := part & Doc.toBlock
122 | (role, part) <- org & orgParts
127 | Text.null role = "" :: Doc.Inline
129 Doc.classes @Doc.Inline ["entity-role"] $
130 "(" <> Doc.toInline role <> ")"
132 data Address = Address
133 { addressText :: [Text]
134 , addressZipCode :: ZipCode
135 , addressCity :: City
136 , addressCountry :: Country.Country
138 deriving (Eq, Ord, Show, Generic, NFData)
139 instance Doc.ToBlock Address where
141 Doc.classes ["address"] $
145 | t <- addr & addressText
151 $ [ addr & addressZipCode & Doc.toInline
152 , addr & addressCity & Doc.toInline
153 , addr & addressCountry & Country.encodeEnglish & Doc.toInline
159 , addressZipCode = ""
161 , addressCountry = Country.france
167 -- | International Bank Account Number
169 { ibanCountry :: Country.Country
170 , ibanCheckDigits :: Natural
171 , ibanBasicBankAccountNumber :: Text
173 deriving (Eq, Ord, Show, Generic, NFData)
175 instance Doc.ToBlock IBAN where
177 [ iban & ibanCountry & Country.alphaTwoUpper & Doc.toInline
178 , iban & ibanCheckDigits & (Printf.printf "%02d" :: _ -> String) & Doc.toInline
180 , iban & ibanBasicBankAccountNumber & Text.chunksOf 4 & Text.intercalate " " & Doc.toInline