{-# LANGUAGE OverloadedLists #-} module Literate.Invoice.Invoice where import Data.Text qualified as Text import Literate.Accounting.Math import Literate.Document qualified as Doc import Literate.Document.HTML qualified as HTML import Literate.Prelude import Literate.Time data Id = Id {unId :: Natural} deriving (Eq, Ord, Show) instance HTML.ToMarkup Id where toMarkup i = i & unId & HTML.toHtml instance Doc.ToInline Id where toInline i = i & unId & show & Doc.toInline data InvoiceId = InvoiceId { invoiceIdBuyer :: Entity , invoiceIdCount :: Natural } deriving (Eq, Ord, Show) instance Doc.ToInline InvoiceId where toInline i = Doc.Inlines [ "ent" , i & invoiceIdBuyer & entityId & Doc.toInline , "inv" , i & invoiceIdCount & show & Doc.toInline ] instance HTML.ToMarkup InvoiceId where toMarkup InvoiceId{..} = "ent" <> (invoiceIdBuyer & entityId & HTML.toMarkup) <> "inv" <> (invoiceIdCount & HTML.toMarkup) type Invoices = Map InvoiceId Invoice type EntityId = Id type Email = Text data Entity = Entity { entityId :: EntityId , entityName :: Text , entityEmail :: Maybe Email , entityAddress :: Address , entitySIREN :: Maybe Text } deriving (Eq, Ord, Show) entity = Entity { entityId = Id 0 , entityName = "" , entityAddress = address , entityEmail = Nothing , entitySIREN = Nothing } data Address = Address { addressText :: [Text] , addressZipCode :: ZipCode , addressCity :: City , addressCountry :: Country } deriving (Eq, Ord, Show) address = Address { addressText = [] , addressZipCode = "" , addressCity = "" , addressCountry = "" } type ZipCode = Text type City = Text type Country = Text data Invoice = Invoice { invoiceCreation :: LocalTime , invoiceIssuer :: Entity , invoiceRecipient :: Entity , invoiceCustomer :: Entity , invoiceObjet :: Text , invoiceDetails :: Text , invoiceItems :: [InvoiceItem (UnitName "€" :/: UnitName "h") (UnitName "h")] , invoiceMentions :: [InvoiceMention] } invoice = Invoice { invoiceCreation = "2000-01-01" , invoiceIssuer = entity , invoiceRecipient = entity , invoiceCustomer = entity , invoiceObjet = "" , invoiceDetails = "" , invoiceItems = [] , invoiceMentions = [] } data InvoiceMention = InvoiceMentionTVANonApplicable deriving (Eq, Ord, Show) data InvoiceItem rate qty = InvoiceItem { invoiceItemDescription :: Doc.Block , invoiceItemPeriod :: Period , invoiceItemRate :: Amount 100 rate , invoiceItemQuantity :: Amount 100 qty } deriving (Eq, Show) invoiceItemTotal :: InvoiceItem rate qty -> Amount 100 (UnitName "€") invoiceItemTotal InvoiceItem{..} = let (res, _actualFrac) = invoiceItemRate & amountQuantity & fraction (invoiceItemQuantity & amountQuantity & quantityToRatio) in Amount res data Period = Period { periodBegin :: LocalTime , periodEnd :: LocalTime } deriving (Eq, Ord, Show)