{-# LANGUAGE OverloadedLists #-} module Literate.Invoice.Invoice where import Country qualified import Literate.Accounting.Math import Literate.Document qualified as Doc import Literate.Document.HTML qualified as HTML import Literate.Organization import Literate.Prelude import Literate.Time data InvoiceId = InvoiceId { invoiceIdRecipient :: Organization , invoiceIdType :: InvoiceType , invoiceIdCount :: Natural } deriving (Eq, Ord, Show) instance Doc.ToInline InvoiceId where toInline i = [ "org" , i & invoiceIdRecipient & orgEntity & entityId & Doc.toInline , case i & invoiceIdType of InvoiceTypeProForma -> "pro-forma" InvoiceTypeSale -> "sale" InvoiceTypeVoucher -> "voucher" , i & invoiceIdCount & show & Doc.toInline ] & Doc.Inlines type Invoices = Map InvoiceId Invoice type InvoiceAction = [Text] type InvoiceScope = [Text] data Invoice = Invoice { invoiceEmittedOn :: LocalTime , invoiceOrders :: [Doc.Inline] , invoicePaymentDueBefore :: LocalTime , invoiceIssuer :: Organization , invoiceRecipient :: Organization , -- , invoiceItems :: [InvoiceItem (UnitName "€" :/: UnitName "h") (UnitName "h")] invoiceRates :: Map InvoiceAction (Amount 100 (UnitName "€" :/: UnitName "h")) , invoiceMentions :: [InvoiceMention] , invoiceLogs :: [InvoiceLog] } deriving (Eq, Show) invoice = Invoice { invoiceEmittedOn = "2000-01-01" , invoiceOrders = [] , invoicePaymentDueBefore = "2000-01-31" , invoiceIssuer = organization , invoiceRecipient = organization , invoiceRates = [] , invoiceMentions = [] , invoiceLogs = [] } data InvoiceLog = InvoiceLog { invoiceLogDescription :: Doc.Inline , invoiceLogDate :: LocalTime , invoiceLogDuration :: Amount 100 (UnitName "h") , invoiceLogAction :: [Text] , invoiceLogScope :: [Text] , invoiceLogReferences :: [URL] } deriving (Eq, Show) data InvoiceType = InvoiceTypeSale | InvoiceTypeProForma | InvoiceTypeVoucher deriving (Eq, Ord, Show) data InvoiceMention = InvoiceMentionTVANonApplicable | InvoiceMentionIndemnitéForfaitaire | InvoiceMentionIndemnitéTaux (Amount 100 (UnitName "%")) deriving (Eq, Ord, Show) data InvoiceItem rate qty = InvoiceItem { invoiceItemScope :: [Text] , invoiceItemAction :: [Text] , invoiceItemType :: InvoiceItemType , 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 invoiceItem = InvoiceItem { invoiceItemScope = [] , invoiceItemAction = [] , invoiceItemType = InvoiceItemTypeItem , invoiceItemPeriod = Period{periodBeginning = "2000-01-01", periodEnd = "2000-01-01"} , invoiceItemRate = 0 , invoiceItemQuantity = 0 } data InvoiceItemType = InvoiceItemTypeItem | InvoiceItemTypeService deriving (Eq, Ord, Show) data Period = Period { periodBeginning :: LocalTime , periodEnd :: LocalTime } deriving (Eq, Ord, Show)