From 940b70cf4c54adc8a01c8c33842578abea830967 Mon Sep 17 00:00:00 2001 From: Julien Moutinho Date: Wed, 4 Feb 2026 00:10:43 +0100 Subject: [PATCH] maint/correctness(Work): use sum type for ScopeId --- literate-business.cabal | 1 + src/Literate/Database.hs | 46 ++ src/Literate/Document/Type.hs | 1 + src/Literate/Invoice.hs | 17 +- src/Literate/Invoice/HTML.hs | 30 +- tests/Tests/Accounting.hs | 59 +-- tests/Tests/Invoice.hs | 718 ++--------------------------- tests/Tests/Invoice/org3sale1.html | 2 +- tests/Tests/Invoice/org3sale2.html | 2 +- tests/Tests/Invoice/org3sale3.html | 2 +- tests/Tests/Work.hs | 675 +++++++++++++++++++++++++++ 11 files changed, 821 insertions(+), 732 deletions(-) create mode 100644 tests/Tests/Work.hs diff --git a/literate-business.cabal b/literate-business.cabal index 8543a3a..10f2650 100644 --- a/literate-business.cabal +++ b/literate-business.cabal @@ -138,6 +138,7 @@ test-suite literate-business-tests Tests.Invoice Tests.Organization Tests.Utils.Tests + Tests.Work build-depends: , filepath diff --git a/src/Literate/Database.hs b/src/Literate/Database.hs index 43cb5bf..c3cb561 100644 --- a/src/Literate/Database.hs +++ b/src/Literate/Database.hs @@ -1,4 +1,50 @@ +{-# LANGUAGE DeriveAnyClass #-} + module Literate.Database where +import Data.List qualified as List + +import Literate.Document qualified as Doc +import Literate.Prelude + class Get to from where get :: from -> to + +newtype Ors a = Ors {unOrs :: Set a} + deriving (Eq, Ord, Show, Generic) + deriving newtype (NFData) + +instance (Ord a, Doc.ToInline a) => Doc.ToInline (Ors a) where + toInline xs = + xs + & unOrs + & toList + <&> Doc.toInline + & List.intersperse " | " + & Doc.toInline + +instance Ord a => IsList (Ors a) where + type Item (Ors a) = a + fromList = Ors . fromList + toList = toList . unOrs + +newtype Ands a = Ands {unAnds :: Set a} + deriving (Eq, Ord, Show, Generic) + deriving newtype (NFData) + +instance Ord a => IsList (Ands a) where + type Item (Ands a) = a + fromList = Ands . fromList + toList = toList . unAnds + +instance (Ord a, Doc.ToInline a) => Doc.ToInline (Ands a) where + toInline xs = + xs + & unAnds + & toList + <&> Doc.toInline + & List.intersperse " & " + & Doc.toInline + +data Boolean a = BooleanTrue a | BooleanFalse a + deriving (Eq, Ord, Show, Generic, NFData) diff --git a/src/Literate/Document/Type.hs b/src/Literate/Document/Type.hs index 7357dc6..4e94bff 100644 --- a/src/Literate/Document/Type.hs +++ b/src/Literate/Document/Type.hs @@ -341,6 +341,7 @@ instance ToBlock Dict where toBlock = BlockDict instance ToBlock (Container Block) where toBlock = BlockDiv instance ToBlock Flex where toBlock = BlockFlex instance ToBlock Inline where toBlock = BlockPara +instance ToBlock [Inline] where toBlock = BlockPara . toInline instance ToBlock Int where toBlock i = i & show & toBlock instance ToBlock Integer where toBlock i = i & show & toBlock instance ToBlock List where toBlock = BlockList diff --git a/src/Literate/Invoice.hs b/src/Literate/Invoice.hs index 3ef704c..2ab2f8b 100644 --- a/src/Literate/Invoice.hs +++ b/src/Literate/Invoice.hs @@ -8,6 +8,7 @@ module Literate.Invoice where import Literate.Accounting.Amount import Literate.Accounting.Quantity import Literate.Accounting.Unit +import Literate.Database import Literate.Document qualified as Doc import Literate.Organization import Literate.Prelude @@ -15,7 +16,7 @@ import Literate.Time type InvoiceScope = [Text] -data Invoice actionId entId invId = Invoice +data Invoice scopeId actionId entId invId = Invoice { invoiceId :: invId , invoiceType :: InvoiceType , invoiceEmittedOn :: LocalTime @@ -26,14 +27,14 @@ data Invoice actionId entId invId = Invoice , -- , invoiceItems :: [InvoiceItem (UnitName "€" :/: UnitName "h") (UnitName "h")] invoiceRates :: Map actionId (Amount 100 (UnitName "€" :/: UnitName "h")) , invoiceMentions :: [InvoiceMention] - , invoiceWorks :: [Work actionId] + , invoiceWorks :: [Work scopeId actionId] } deriving (Eq, Show) invoice :: Ord actionId => Enum entId => - invId -> Invoice actionId entId invId + invId -> Invoice scopeId actionId entId invId invoice invoiceId = Invoice { invoiceId @@ -48,12 +49,12 @@ invoice invoiceId = , invoiceWorks = [] } -data Work actionId = Work +data Work scopeId actionId = Work { workDescription :: Doc.Inline , workDate :: LocalTime , workDuration :: Amount 100 (UnitName "h") , workAction :: actionId - , workScope :: [Text] + , workScope :: Ands scopeId , workReferences :: [URL] } deriving (Eq, Show) @@ -72,8 +73,8 @@ data InvoiceMention | InvoiceMentionIndemnitéTaux (Amount 100 (UnitName "%")) deriving (Eq, Ord, Show, Generic, NFData) -data InvoiceItem actionId rate qty = InvoiceItem - { invoiceItemScope :: [Text] +data InvoiceItem scopeId actionId rate qty = InvoiceItem + { invoiceItemScope :: Ands scopeId , invoiceItemAction :: actionId , invoiceItemType :: InvoiceItemType , invoiceItemPeriod :: Period @@ -83,7 +84,7 @@ data InvoiceItem actionId rate qty = InvoiceItem deriving (Eq, Show) type Euro = Amount 100 (UnitName "€") -invoiceItemTotal :: InvoiceItem actionId rate qty -> Euro +invoiceItemTotal :: InvoiceItem scopeId actionId rate qty -> Euro invoiceItemTotal InvoiceItem{..} = let (res, _actualFrac) = invoiceItemRate diff --git a/src/Literate/Invoice/HTML.hs b/src/Literate/Invoice/HTML.hs index 4702462..521f9c2 100644 --- a/src/Literate/Invoice/HTML.hs +++ b/src/Literate/Invoice/HTML.hs @@ -104,12 +104,12 @@ instance QuantFact qf => Doc.ToBlock (Quantity qf) where toBlock x = Doc.BlockPara $ x & Doc.toInline invoiceIdInline :: - forall actionId entId invId. + forall scopeId actionId entId invId. Get (Organization entId) entId => Get (Entity entId) entId => Enum invId => Doc.ToInline entId => - Invoice actionId entId invId -> + Invoice scopeId actionId entId invId -> Doc.Inline invoiceIdInline inv = [ "org" @@ -131,21 +131,23 @@ invoiceIdInline inv = instance ( Get (Organization entId) entId , Get (Entity entId) entId + , Ord scopeId , Show actionId , Ord actionId , Enum entId , Enum invId + , Doc.ToInline scopeId , Doc.ToInline actionId , Doc.ToInline entId ) => - HTMLIOable (Invoice actionId entId invId) + HTMLIOable (Invoice scopeId actionId entId invId) where htmlIO inv = do -- FixMe(portability): this absolute path is not portable out of my system dataPath <- Self.getDataDir <&> File.normalise -- paperCSS <- dataPath "styles" "Paper.css" & BS.readFile <&> Text.decodeUtf8 -- invoiceCSS <- dataPath "styles" "Invoice.css" & BS.readFile <&> Text.decodeUtf8 - let invSummary :: [InvoiceItem _ _ _] = + let invSummary :: [InvoiceItem _ _ _ _] = invoiceSummary (inv & invoiceRates) (inv & invoiceWorks) & foldMap (foldMap pure) let invSummaryQuantityTotal :: Accounting.Quantity 100 = @@ -368,7 +370,7 @@ instance , Doc.tableCellJustify = Doc.JustifyCenter } , Doc.tableCell - { Doc.tableCellContent = invItem & invoiceItemScope & pathToBlock + { Doc.tableCellContent = invItem & invoiceItemScope & Doc.toInline & Doc.toBlock , Doc.tableCellJustify = Doc.JustifyStart } , Doc.tableCell @@ -467,12 +469,11 @@ instance , Doc.tableCellJustify = Doc.JustifyCenter } , Doc.tableCell - { Doc.tableCellContent = - work & workDuration & Doc.toBlock + { Doc.tableCellContent = work & workDuration & Doc.toBlock , Doc.tableCellJustify = Doc.JustifyEnd } , Doc.tableCell - { Doc.tableCellContent = work & workScope & pathToBlock + { Doc.tableCellContent = work & workScope & Doc.toInline & Doc.toBlock , Doc.tableCellJustify = Doc.JustifyStart } , Doc.tableCell @@ -523,19 +524,14 @@ instance else Doc.PageSideRight } } - where - pathToBlock segs = - [ seg & Doc.toInline - | seg <- segs - ] - & List.intersperse " / " - & Doc.toInline - & Doc.toBlock invoiceSummary :: + Ord scopeId => Show actionId => Ord actionId => - _ -> [Work actionId] -> Map [Text] (Map actionId (InvoiceItem actionId _ _)) + Map actionId (Amount 100 unit) -> + [Work scopeId actionId] -> + Map (Ands scopeId) (Map actionId (InvoiceItem scopeId actionId _ _)) invoiceSummary invRates works = Map.unionsWith ( Map.unionWith diff --git a/tests/Tests/Accounting.hs b/tests/Tests/Accounting.hs index a620746..f8ab064 100644 --- a/tests/Tests/Accounting.hs +++ b/tests/Tests/Accounting.hs @@ -5,15 +5,17 @@ module Tests.Accounting where import Literate.Accounting import Literate.Accounting.PlanComptableGénéral qualified as PCG +import Literate.Database import Literate.Invoice -import Literate.Organization import Literate.Prelude -import Tests.Invoice qualified as Invoice -import Tests.Organization qualified as Orga + +import Tests.Invoice +import Tests.Organization +import Tests.Work data Account = Account - { accountOwner :: Maybe Orga.EntityId - , accountScope :: Set (Set Scope) + { accountOwner :: Maybe EntityId + , accountScope :: Set (Set ScopeId) , accountPCG :: Maybe PCG.PCG } deriving (Eq, Ord, Show, Generic, NFData) @@ -24,15 +26,6 @@ account = , accountPCG = Nothing } -newtype Ors a = Ors {ors :: Set a} - deriving (Eq, Ord, Show, Generic) - deriving newtype (NFData) -newtype Ands a = Ands {ands :: Set a} - deriving (Eq, Ord, Show, Generic) - deriving newtype (NFData) -data Boolean a = BooleanTrue a | BooleanFalse a - deriving (Eq, Ord, Show, Generic, NFData) - data Meta = Meta { metaCause :: Ands (Ors Cause) @@ -42,9 +35,9 @@ data Meta data Cause = Cause - { causeEntity :: Maybe Orga.EntityId + { causeEntity :: Maybe EntityId , causePeriod :: Maybe Period - , causeInvoice :: Maybe Invoice.InvoiceId + , causeInvoice :: Maybe InvoiceId } deriving (Eq, Ord, Show, Generic, NFData) cause = @@ -65,45 +58,57 @@ instance FromRational Amounts where accounting :: [Movement Cause Account Amounts] accounting = [ Movement - { moveDescription = "" - , moveDate = "2026-01-27" - , movePostings = equalPostings account{accountOwner = Just Orga.EntityUpwork} account{accountOwner = Just Orga.EntityJulmInfo} 174.30 + { moveDescription = "Liquidation" , moveMeta = [] + , moveDate = "2026-01-27" + , movePostings = equalPostings account{accountOwner = Just EntityUpwork} account{accountOwner = Just EntityJulmInfo} 174.30 } , Movement { moveDescription = "" + , moveMeta = + [ cause{causeInvoice = Just Invoice_org3sale2} + ] , moveDate = "2026-01-28" - , movePostings = equalPostings account{accountOwner = Just Orga.EntityNixOSFoundationNGITeam} account{accountOwner = Just Orga.EntityJulmInfo} 2000.00 - , moveMeta = [] + , movePostings = equalPostings account{accountOwner = Just EntityNixOSFoundationNGITeam} account{accountOwner = Just EntityJulmInfo} 2000.00 } , Movement { moveDescription = "" + , moveMeta = + [ cause{causeInvoice = Just Invoice_org3sale1} + ] , moveDate = "2026-01-29" - , movePostings = equalPostings account{accountOwner = Just Orga.EntityNixOSFoundationNGITeam} account{accountOwner = Just Orga.EntityJulmInfo} 4643.75 - , moveMeta = [] + , movePostings = equalPostings account{accountOwner = Just EntityNixOSFoundationNGITeam} account{accountOwner = Just EntityJulmInfo} 4643.75 } , Movement { moveDescription = "Cotisation URSSAF" , moveMeta = [ cause - { causeEntity = Just Orga.EntityUrssaf + { causeEntity = Just EntityUrssaf , causePeriod = Just Period{periodBeginning = "2026-01-01", periodEnd = "2026-01-31"} } ] , moveDate = "2026-02-01" , movePostings = [ Posting - { postingAccount = account{accountOwner = Just Orga.EntityJulmInfo} + { postingAccount = + account + { accountOwner = Just EntityJulmInfo + , accountPCG = Just PCG.pcg2025_5121 + } , postingFlow = FlowOrigin 1691.00 , postingMeta = [] } , Posting - { postingAccount = account{accountOwner = Just Orga.EntityUrssaf} + { postingAccount = + account + { accountOwner = Just EntityUrssaf + , accountPCG = Just PCG.pcg2025_6451 + } , postingFlow = FlowTarget 1677.00 , postingMeta = [] } , Posting - { postingAccount = account{accountOwner = Just Orga.EntityUrssaf} + { postingAccount = account{accountOwner = Just EntityUrssaf} , postingFlow = FlowTarget 14.00 , postingMeta = [] } diff --git a/tests/Tests/Invoice.hs b/tests/Tests/Invoice.hs index 9435147..7765773 100644 --- a/tests/Tests/Invoice.hs +++ b/tests/Tests/Invoice.hs @@ -9,7 +9,6 @@ import Data.Text.Lazy qualified as Text.Lazy import Data.Time.Clock qualified as Time import Data.Time.LocalTime qualified as Time import Test.Syd (Spec, describe, goldenByteStringBuilderFile, it) -import Tests.Organization qualified as Orga import Tests.Utils.Tests (goldenPath) import Text.Blaze.Renderer.Text qualified as Blaze.Text import Text.Blaze.Renderer.Utf8 qualified as Blaze @@ -17,20 +16,21 @@ import Prelude ((*)) import Literate.Accounting (Amount, Unit (UnitName)) import Literate.Database -import Literate.Document qualified as Doc import Literate.Document.HTML qualified as HTML import Literate.Invoice import Literate.Invoice.HTML (invoiceIdInline) import Literate.Invoice.HTML qualified as HTML import Literate.Prelude +import Tests.Organization +import Tests.Work + spec :: HasCallStack => Spec spec = - -- aroundAll readDicts do describe "Invoice" do forM_ invoices \invId -> do let - inv = invId & get @(Invoice ActionId Orga.EntityId InvoiceId) + inv = invId & get @(Invoice ScopeId ActionId EntityId InvoiceId) idS = inv & invoiceIdInline @@ -42,636 +42,6 @@ spec = goldenByteStringBuilderFile outPath do inv & HTML.htmlIO <&> Blaze.renderMarkupBuilder -works_NGIpkgs :: [Work ActionId] -works_NGIpkgs = - [ Work - { workDate = "2025-11-06" - , workDuration = 0.5 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = ["https://meet.google.com/hii-druc-tjp"] - , workDescription = "first meeting" - } - , Work - { workDate = "2025-11-06" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] - , workDescription = "focus on the hardest part first" - } - , Work - { workDate = "2025-11-07" - , workDuration = 8 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] - , workDescription = "continuing to package Bonfire deps" - } - , Work - { workDate = "2025-11-08" - , workDuration = 0.1 - , workAction = Action_Development - , workScope = ["Nixpkgs", "opencv"] - , workReferences = ["https://github.com/NixOS/nixpkgs/pull/459592"] - , workDescription = "fix opencv in nixpkgs" - } - , Work - { workDate = "2025-11-09" - , workDuration = 8 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] - , workDescription = "continue to fix deps" - } - , Work - { workDate = "2025-11-09" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] - , workDescription = "continue to fix deps" - } - , Work - { workDate = "2025-11-11" - , workDuration = 6 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] - , workDescription = "continue to fix deps" - } - , Work - { workDate = "2025-11-12" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] - , workDescription = "continue to fix deps" - } - , Work - { workDate = "2025-11-14" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812"] - , workDescription = "continue to fix deps and move into ngipkgs" - } - , Work - { workDate = "2025-11-14" - , workDuration = 1 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-weekly-review-34-2ab59d49e1be80939503c655b009e934"] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2025-11-15" - , workDuration = 6 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "finish to build Bonfire and start to fix runtime bugs" - } - , Work - { workDate = "2025-11-16" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812#issuecomment-3537609170"] - , workDescription = "workaround and contribute upstream" - } - , Work - { workDate = "2025-11-17" - , workDuration = 8 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "add updateScript and fix opencv" - } - , Work - { workDate = "2025-11-19" - , workDuration = 8 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812#issuecomment-3554376221"] - , workDescription = "continue to fix startup crashes" - } - , Work - { workDate = "2025-11-21" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "begin to package yarn assets. Upstream likes convoluted code and fake libraries." - } - , Work - { workDate = "2025-11-21" - , workDuration = 1 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2025-11-21" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "continue to package assets" - } - , Work - { workDate = "2025-11-23" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "continue to package assets and try to get Bonfire to work" - } - , Work - { workDate = "2025-11-24" - , workDuration = 10 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/surface-ui/surface/issues/762#issuecomment-3577030748"] - , workDescription = "continue to solve problems with Bonfire packaging" - } - , Work - { workDate = "2025-11-27" - , workDuration = 8 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812#issuecomment-3584319056"] - , workDescription = "successfully auto-update and build Bonfire" - } - , Work - { workDate = "2025-11-28" - , workDuration = 1 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-weekly-review-36-2b959d49e1be80fa823cd4d83581fda5#2b959d49e1be80fc85eed38c9a9dca86"] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2025-11-29" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "begin the service module" - } - , Work - { workDate = "2025-12-02" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "continue the service module" - } - , Work - { workDate = "2025-12-03" - , workDuration = 8 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "first working service module" - } - , Work - { workDate = "2025-12-04" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1871"] - , workDescription = "improve service module" - } - , Work - { workDate = "2025-12-05" - , workDuration = 1 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-weekly-review-36-2b959d49e1be80fa823cd4d83581fda5"] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2025-12-05" - , workDuration = 0.5 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1954"] - , workDescription = "meeting" - } - , Work - { workDate = "2025-12-06" - , workDuration = 2 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "prepare wednesday meeting" - } - , Work - { workDate = "2025-12-07" - , workDuration = 4 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "prepare demo for wednesday meeting" - } - , Work - { workDate = "2025-12-08" - , workDuration = 4 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1891"] - , workDescription = "prepare demo for wednesday meeting" - } - , Work - { workDate = "2025-12-09" - , workDuration = 4 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1891"] - , workDescription = "continue to document" - } - , Work - { workDate = "2025-12-10" - , workDuration = 2 - , workAction = Action_Review - , workScope = ["NGIpkgs"] - , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-best-practices-for-NixOS-modules-implementation-2c559d49e1be80a8a499f21abb203d6f"] - , workDescription = "visio on “best practices”" - } - , Work - { workDate = "2025-12-12" - , workDuration = 1 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "weekly visio meeting" - } - , Work - { workDate = "2025-12-11" - , workDuration = 8 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "continue to document" - } - , Work - { workDate = "2025-12-12" - , workDuration = 4 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "continue to document" - } - , Work - { workDate = "2025-12-13" - , workDuration = 2 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = - [ "setup sphinx like " - , Doc.InlineLink - { Doc.inlineLinkTarget = "https://nix.dev" - , Doc.inlineLinkText = "nix.dev" - } - , " for the manuals" - ] - } - , Work - { workDate = "2025-12-13" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/bonfire-networks/bonfire-app/issues/1670#issuecomment-3650762914"] - , workDescription = "update to latest; overcoming new bugs introduced by upstream" - } - , Work - { workDate = "2025-12-15" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "improving the update script and still overcoming upstream bugs" - } - , Work - { workDate = "2025-12-16" - , workDuration = 3 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "overcoming bugs, again" - } - , Work - { workDate = "2025-12-16" - , workDuration = 2 - , workAction = Action_Review - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "visio to review PRs" - } - , Work - { workDate = "2025-12-16" - , workDuration = 2 - , workAction = Action_Review - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "visio to review PRs" - } - , Work - { workDate = "2025-12-17" - , workDuration = 1.5 - , workAction = Action_Review - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "visio to review PRs" - } - , Work - { workDate = "2025-12-18" - , workDuration = 1 - , workAction = Action_Review - , workScope = ["NGIpkgs", "dnsvizor"] - , workReferences = [] - , workDescription = "review linj’s PR" - } - , Work - { workDate = "2025-12-19" - , workDuration = 1.5 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2025-12-21" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = - [ "fix bug using " - , "__structuredAttrs" & Doc.InlineCode - ] - } - , Work - { workDate = "2025-12-23" - , workDuration = 4 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "improve building the manuals" - } - , Work - { workDate = "2025-12-23" - , workDuration = 2 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "address reviewers’ concerns" - } - , Work - { workDate = "2025-12-24" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "update Bonfire and report issues upstream" - } - , Work - { workDate = "2025-12-24" - , workDuration = 4 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "document" - } - , Work - { workDate = "2025-12-24" - , workDuration = 2 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "update Bonfire to fix bugs" - } - , Work - { workDate = "2025-12-25" - , workDuration = 2 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "document" - } - , Work - { workDate = "2025-12-25" - , workDuration = 6 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/bonfire-networks/bonfire-app/issues/1698#issuecomment-3692147409"] - , workDescription = "update and fix bugs" - } - , Work - { workDate = "2025-12-26" - , workDuration = 1 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "update to fix bugs" - } - , Work - { workDate = "2025-12-28" - , workDuration = 6 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] - , workReferences = [] - , workDescription = "document" - } - , Work - { workDate = "2025-12-29" - , workDuration = 2 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "add more tests" - } - , Work - { workDate = "2025-12-29" - , workDuration = 0.5 - , workAction = Action_Review - , workScope = ["NGIpkgs", "Funkwhale"] -- goes into NGI Review - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1707#discussion_r2651644145"] - , workDescription = "" - } - , Work - { workDate = "2025-12-30" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "BEAM"] - , workReferences = [] - , workDescription = ["improve ", Doc.InlineCode "buildMix", " & ", Doc.InlineCode "mixRelease", " for packaging Elixir software"] - } - , Work - { workDate = "2026-01-01" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "support other flavours" - } - , Work - { workDate = "2026-01-03" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "support other flavours, and make update more resilient" - } - , Work - { workDate = "2026-01-04" - , workDuration = 2 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "provide upstream with reproducers" - } - , Work - { workDate = "2026-01-05" - , workDuration = 2 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "update to latest version" - } - , Work - { workDate = "2026-01-07" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = [] - , workDescription = "fix updating" - } - , Work - { workDate = "2026-01-07" - , workDuration = 1 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] -- goes into NGI Core - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1891"] - , workDescription = "address reviewer’s comment" - } - , Work - { workDate = "2026-01-09" - , workDuration = 2 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] -- goes into NGI Core - , workReferences = [] - , workDescription = "address reviewer’s comments" - } - , Work - { workDate = "2026-01-09" - , workDuration = 2 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Bonfire"] - , workReferences = ["https://github.com/bonfire-networks/bonfire-app/issues/1730"] - , workDescription = "answer upstream’s questions" - } - , Work - { workDate = "2026-01-11" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "dnsvizor"] - , workReferences = [] - , workDescription = ["replace ", Doc.InlineCode "hillingar", " to package MirageOS unikernels"] - } - , Work - { workDate = "2026-01-09" - , workDuration = 2 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2026-01-12" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "dnsvizor"] - , workReferences = ["https://github.com/ju1m/ngipkgs/commits/dnsvizor/"] - , workDescription = ["remove the need for ", Doc.InlineCode "--allow-import-from-derivation"] - } - , Work - { workDate = "2026-01-12" - , workDuration = 6 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] -- goes into NGI Core - , workReferences = [] - , workDescription = "render options" - } - , Work - { workDate = "2026-01-13" - , workDuration = 1 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] -- goes into NGI Core - , workReferences = [] - , workDescription = "update" - } - , Work - { workDate = "2026-01-16" - , workDuration = 2 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2026-01-19" - , workDuration = 2 - , workAction = Action_Documentation - , workScope = ["NGIpkgs", "Manuals"] -- goes into NGI Core - , workReferences = [] - , workDescription = "split into several PDF" - } - , Work - { workDate = "2026-01-22" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Manuals"] -- goes into NGI Core - , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/2010"] - , workDescription = "address reviewers’ concerns" - } - , Work - { workDate = "2026-01-23" - , workDuration = 1.5 - , workAction = Action_Organization - , workScope = ["NGIpkgs"] - , workReferences = [] - , workDescription = "weekly meeting" - } - , Work - { workDate = "2026-01-25" - , workDuration = 4 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Seppo"] - , workReferences = [] - , workDescription = "begin packaging" - } - , Work - { workDate = "2026-01-26" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Seppo"] - , workReferences = [] - , workDescription = "continue packaging" - } - , Work - { workDate = "2026-01-27" - , workDuration = 5 - , workAction = Action_Development - , workScope = ["NGIpkgs", "Seppo"] - , workReferences = [] - , workDescription = "continue packaging" - } - ] - data InvoiceId = Invoice_0 | Invoice_org3sale1 @@ -679,28 +49,7 @@ data InvoiceId | Invoice_org3sale3 deriving (Eq, Ord, Show, Generic, Enum, NFData) -invoiceRate_NGIpkgs = - [ Action_Organization := 31.25 - , Action_Development := 31.25 - , Action_Documentation := 31.25 - , Action_Review := 31.25 - ] - -data ActionId - = Action_Organization - | Action_Development - | Action_Documentation - | Action_Review - deriving (Eq, Ord, Show, Generic, Enum, NFData) - -instance Doc.ToInline ActionId where - toInline = \case - Action_Development -> "development" - Action_Documentation -> "documentation" - Action_Organization -> "organization" - Action_Review -> "review" - -instance Get (Invoice ActionId Orga.EntityId InvoiceId) InvoiceId where +instance Get (Invoice ScopeId ActionId EntityId InvoiceId) InvoiceId where get invoiceId = case invoiceId of Invoice_0 -> Invoice @@ -709,8 +58,8 @@ instance Get (Invoice ActionId Orga.EntityId InvoiceId) InvoiceId where , invoiceOrders = [] , invoiceEmittedOn , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay) - , invoiceIssuer = Orga.EntityJulmInfo - , invoiceRecipient = Orga.EntityJulmInfo + , invoiceIssuer = EntityJulmInfo + , invoiceRecipient = EntityJulmInfo , invoiceRates = [Action_Development := 0] , invoiceMentions = [ InvoiceMentionTVANonApplicable @@ -737,22 +86,27 @@ instance Get (Invoice ActionId Orga.EntityId InvoiceId) InvoiceId where , invoiceOrders = ["Contract n°2025-24"] , invoiceEmittedOn , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay) - , invoiceIssuer = Orga.EntityJulmInfo - , invoiceRecipient = Orga.EntityNixOSFoundationNGITeam - , invoiceRates = invoiceRate_NGIpkgs + , invoiceIssuer = EntityJulmInfo + , invoiceRecipient = EntityNixOSFoundationNGITeam + , invoiceRates = + [ Action_Organization := 31.25 + , Action_Development := 31.25 + , Action_Documentation := 31.25 + , Action_Review := 31.25 + ] , invoiceMentions = [ InvoiceMentionTVANonApplicable , InvoiceMentionIndemnitéForfaitaire , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%")) ] , invoiceWorks = - works_NGIpkgs + works & List.filter \work -> and $ list [ work & workDate & (>= "2025-11-06") , work & workDate & (<= "2025-12-22") - , work & workScope & (/= ["NGIpkgs", "Manuals"]) + , work & workScope & (/= [Scope_NGIpkgs_Manuals]) ] } where @@ -764,28 +118,33 @@ instance Get (Invoice ActionId Orga.EntityId InvoiceId) InvoiceId where , invoiceOrders = ["contract n°2026-03"] , invoiceEmittedOn , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay) - , invoiceIssuer = Orga.EntityJulmInfo - , invoiceRecipient = Orga.EntityNixOSFoundationNGITeam - , invoiceRates = invoiceRate_NGIpkgs + , invoiceIssuer = EntityJulmInfo + , invoiceRecipient = EntityNixOSFoundationNGITeam + , invoiceRates = + [ Action_Organization := 31.25 + , Action_Development := 31.25 + , Action_Documentation := 31.25 + , Action_Review := 31.25 + ] , invoiceMentions = [ InvoiceMentionTVANonApplicable , InvoiceMentionIndemnitéForfaitaire , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%")) ] , invoiceWorks = - works_NGIpkgs + works & List.filter \work -> and $ [ work & workDate & (>= "2025-12-23") , work & workDate & (<= "2026-12-31") - , work & workScope & (/= ["NGIpkgs", "Manuals"]) - , work & workScope & (/= ["NGIpkgs", "Funkwhale"]) + , work & workScope & (/= [Scope_NGIpkgs_Manuals]) + , work & workScope & (/= [Scope_NGIpkgs, Scope_Funkwhale]) , not $ and $ [ work & workDate & (>= "2026-01-09") , work & workDate & (<= "2026-01-28") , work & workAction & (== Action_Organization) - , work & workScope & (== ["NGIpkgs"]) + , work & workScope & (== [Scope_NGIpkgs]) ] & list ] @@ -800,35 +159,40 @@ instance Get (Invoice ActionId Orga.EntityId InvoiceId) InvoiceId where , invoiceOrders = ["contract n°2026-FixMe"] , invoiceEmittedOn , invoicePaymentDueBefore = invoiceEmittedOn & Time.addLocalTime (31 * Time.nominalDay) - , invoiceIssuer = Orga.EntityJulmInfo - , invoiceRecipient = Orga.EntityNixOSFoundationNGITeam - , invoiceRates = invoiceRate_NGIpkgs + , invoiceIssuer = EntityJulmInfo + , invoiceRecipient = EntityNixOSFoundationNGITeam + , invoiceRates = + [ Action_Organization := 31.25 + , Action_Development := 31.25 + , Action_Documentation := 31.25 + , Action_Review := 31.25 + ] , invoiceMentions = [ InvoiceMentionTVANonApplicable , InvoiceMentionIndemnitéForfaitaire , InvoiceMentionIndemnitéTaux (12.15 :: Amount 100 (UnitName "%")) ] , invoiceWorks = - works_NGIpkgs + works & List.filter \work -> or $ [ and $ [ work & workDate & (>= "2026-01-21") , work & workDate & (<= "2026-12-31") - , work & workScope & (== ["NGIpkgs", "Manuals"]) + , work & workScope & (== [Scope_NGIpkgs_Manuals]) ] & list , and $ [ work & workDate & (>= "2025-12-29") , work & workDate & (<= "2026-12-31") - , work & workScope & (== ["NGIpkgs", "Funkwhale"]) + , work & workScope & (== [Scope_NGIpkgs, Scope_Funkwhale]) ] & list , and $ [ work & workDate & (>= "2026-01-09") , work & workDate & (<= "2026-01-28") , work & workAction & (== Action_Organization) - , work & workScope & (== ["NGIpkgs"]) + , work & workScope & (== [Scope_NGIpkgs]) ] & list ] diff --git a/tests/Tests/Invoice/org3sale1.html b/tests/Tests/Invoice/org3sale1.html index 75c45b2..43c2aa7 100644 --- a/tests/Tests/Invoice/org3sale1.html +++ b/tests/Tests/Invoice/org3sale1.html @@ -1,2 +1,2 @@ -julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24

Invoice

InvoiceIdentifier:

org3sale1

InvoiceType:

sale

InvoiceOrders:
-

Contract n°2025-24

InvoiceEmittedOn:

2026-01-22

InvoicePaymentDueBefore:

2026-02-22

Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Seller:
Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Admin:
Name:

Julien Moutinho

Email:
Buyer:
Name:

Nix@NGI Team

Email:
Admin:
Name:

Daniel Ramirez

Email:

Grand totals

Time frame

Workload

To pay (excl. taxes)

2025-11-06

2025-12-21

148.60 h

4643.75 €

Mandatory legal notices

—

VAT not applicable, art. 293 B of the French General Tax Code.

—

Fixed compensation for recovery costs in case of late payment: 40.00 €

—

Late payment penalty rate (applicable from 2026-02-23): 12.15 % × unpaid amount × number of days late / 365.25

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24

1/5

Summary

#

Type

Scope

Action

Time frame

Rate

(excl. taxes.)

Quantity

Total

(excl. taxes.)

1

service

NGIpkgs

organization

2025-11-06

2025-12-19

31.25 € / h

7.00 h

(4.71%)

218.75 €

2

service

NGIpkgs

review

2025-12-10

2025-12-17

31.25 € / h

7.50 h

(5.05%)

234.38 €

3

service

NGIpkgs / Bonfire

development

2025-11-06

2025-12-21

31.25 € / h

133.00 h

(89.5%)

4156.25 €

4

service

NGIpkgs / dnsvizor

review

2025-12-18

2025-12-18

31.25 € / h

1.00 h

(0.67%)

31.25 €

5

service

Nixpkgs / opencv

development

2025-11-08

2025-11-08

31.25 € / h

0.10 h

(0.07%)

3.12 €

2/5

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Summary

Details

#

Date

Duration

Scope

Action

References

Description

1

2025-11-06

0.50 h

NGIpkgs

organization

first meeting

2

2025-11-06

4.00 h

NGIpkgs / Bonfire

development

focus on the hardest part first

3

2025-11-07

8.00 h

NGIpkgs / Bonfire

development

continuing to package Bonfire deps

4

2025-11-08

0.10 h

Nixpkgs / opencv

development

fix opencv in nixpkgs

5

2025-11-09

8.00 h

NGIpkgs / Bonfire

development

continue to fix deps

6

2025-11-09

4.00 h

NGIpkgs / Bonfire

development

continue to fix deps

7

2025-11-11

6.00 h

NGIpkgs / Bonfire

development

continue to fix deps

8

2025-11-12

4.00 h

NGIpkgs / Bonfire

development

continue to fix deps

9

2025-11-14

5.00 h

NGIpkgs / Bonfire

development

continue to fix deps and move into ngipkgs

11

2025-11-15

6.00 h

NGIpkgs / Bonfire

development

finish to build Bonfire and start to fix runtime bugs

12

2025-11-16

4.00 h

NGIpkgs / Bonfire

development

workaround and contribute upstream

13

2025-11-17

8.00 h

NGIpkgs / Bonfire

development

add updateScript and fix opencv

14

2025-11-19

8.00 h

NGIpkgs / Bonfire

development

continue to fix startup crashes

15

2025-11-21

4.00 h

NGIpkgs / Bonfire

development

begin to package yarn assets. Upstream likes convoluted code and fake libraries.

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Details

3/5

#

Date

Duration

Scope

Action

References

Description

16

2025-11-21

1.00 h

NGIpkgs

organization

weekly meeting

17

2025-11-21

4.00 h

NGIpkgs / Bonfire

development

continue to package assets

18

2025-11-23

4.00 h

NGIpkgs / Bonfire

development

continue to package assets and try to get Bonfire to work

19

2025-11-24

10.00 h

NGIpkgs / Bonfire

development

continue to solve problems with Bonfire packaging

20

2025-11-27

8.00 h

NGIpkgs / Bonfire

development

successfully auto-update and build Bonfire

22

2025-11-29

5.00 h

NGIpkgs / Bonfire

development

begin the service module

23

2025-12-02

4.00 h

NGIpkgs / Bonfire

development

continue the service module

24

2025-12-03

8.00 h

NGIpkgs / Bonfire

development

first working service module

25

2025-12-04

5.00 h

NGIpkgs / Bonfire

development

improve service module

28

2025-12-12

1.00 h

NGIpkgs

organization

weekly visio meeting

29

2025-12-13

5.00 h

NGIpkgs / Bonfire

development

update to latest; overcoming new bugs introduced by upstream

30

2025-12-15

4.00 h

NGIpkgs / Bonfire

development

improving the update script and still overcoming upstream bugs

4/5

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Details

#

Date

Duration

Scope

Action

References

Description

31

2025-12-16

3.00 h

NGIpkgs / Bonfire

development

overcoming bugs, again

32

2025-12-16

2.00 h

NGIpkgs

review

visio to review PRs

33

2025-12-16

2.00 h

NGIpkgs

review

visio to review PRs

34

2025-12-17

1.50 h

NGIpkgs

review

visio to review PRs

35

2025-12-18

1.00 h

NGIpkgs / dnsvizor

review

review linj’s PR

36

2025-12-19

1.50 h

NGIpkgs

organization

weekly meeting

37

2025-12-21

4.00 h

NGIpkgs / Bonfire

development

fix bug using __structuredAttrs

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Details

5/5

\ No newline at end of file +julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24

Invoice

InvoiceIdentifier:

org3sale1

InvoiceType:

sale

InvoiceOrders:
-

Contract n°2025-24

InvoiceEmittedOn:

2026-01-22

InvoicePaymentDueBefore:

2026-02-22

Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Seller:
Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Admin:
Name:

Julien Moutinho

Email:
Buyer:
Name:

Nix@NGI Team

Email:
Admin:
Name:

Daniel Ramirez

Email:

Grand totals

Time frame

Workload

To pay (excl. taxes)

2025-11-06

2025-12-21

148.60 h

4643.75 €

Mandatory legal notices

—

VAT not applicable, art. 293 B of the French General Tax Code.

—

Fixed compensation for recovery costs in case of late payment: 40.00 €

—

Late payment penalty rate (applicable from 2026-02-23): 12.15 % × unpaid amount × number of days late / 365.25

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24

1/5

Summary

#

Type

Scope

Action

Time frame

Rate

(excl. taxes.)

Quantity

Total

(excl. taxes.)

1

service

Bonfire & NGIpkgs

development

2025-11-06

2025-12-21

31.25 € / h

133.00 h

(89.5%)

4156.25 €

2

service

DNSvizor & NGIpkgs

review

2025-12-18

2025-12-18

31.25 € / h

1.00 h

(0.67%)

31.25 €

3

service

NGIpkgs

organization

2025-11-06

2025-12-19

31.25 € / h

7.00 h

(4.71%)

218.75 €

4

service

NGIpkgs

review

2025-12-10

2025-12-17

31.25 € / h

7.50 h

(5.05%)

234.38 €

5

service

Nixpkgs & OpenCV

development

2025-11-08

2025-11-08

31.25 € / h

0.10 h

(0.07%)

3.12 €

2/5

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Summary

Details

#

Date

Duration

Scope

Action

References

Description

1

2025-11-06

0.50 h

NGIpkgs

organization

first meeting

2

2025-11-06

4.00 h

Bonfire & NGIpkgs

development

focus on the hardest part first

3

2025-11-07

8.00 h

Bonfire & NGIpkgs

development

continuing to package Bonfire deps

4

2025-11-08

0.10 h

Nixpkgs & OpenCV

development

fix opencv in nixpkgs

5

2025-11-09

8.00 h

Bonfire & NGIpkgs

development

continue to fix deps

6

2025-11-09

4.00 h

Bonfire & NGIpkgs

development

continue to fix deps

7

2025-11-11

6.00 h

Bonfire & NGIpkgs

development

continue to fix deps

8

2025-11-12

4.00 h

Bonfire & NGIpkgs

development

continue to fix deps

9

2025-11-14

5.00 h

Bonfire & NGIpkgs

development

continue to fix deps and move into ngipkgs

11

2025-11-15

6.00 h

Bonfire & NGIpkgs

development

finish to build Bonfire and start to fix runtime bugs

12

2025-11-16

4.00 h

Bonfire & NGIpkgs

development

workaround and contribute upstream

13

2025-11-17

8.00 h

Bonfire & NGIpkgs

development

add updateScript and fix opencv

14

2025-11-19

8.00 h

Bonfire & NGIpkgs

development

continue to fix startup crashes

15

2025-11-21

4.00 h

Bonfire & NGIpkgs

development

begin to package yarn assets. Upstream likes convoluted code and fake libraries.

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Details

3/5

#

Date

Duration

Scope

Action

References

Description

16

2025-11-21

1.00 h

NGIpkgs

organization

weekly meeting

17

2025-11-21

4.00 h

Bonfire & NGIpkgs

development

continue to package assets

18

2025-11-23

4.00 h

Bonfire & NGIpkgs

development

continue to package assets and try to get Bonfire to work

19

2025-11-24

10.00 h

Bonfire & NGIpkgs

development

continue to solve problems with Bonfire packaging

20

2025-11-27

8.00 h

Bonfire & NGIpkgs

development

successfully auto-update and build Bonfire

22

2025-11-29

5.00 h

Bonfire & NGIpkgs

development

begin the service module

23

2025-12-02

4.00 h

Bonfire & NGIpkgs

development

continue the service module

24

2025-12-03

8.00 h

Bonfire & NGIpkgs

development

first working service module

25

2025-12-04

5.00 h

Bonfire & NGIpkgs

development

improve service module

28

2025-12-12

1.00 h

NGIpkgs

organization

weekly visio meeting

29

2025-12-13

5.00 h

Bonfire & NGIpkgs

development

update to latest; overcoming new bugs introduced by upstream

30

2025-12-15

4.00 h

Bonfire & NGIpkgs

development

improving the update script and still overcoming upstream bugs

4/5

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Details

#

Date

Duration

Scope

Action

References

Description

31

2025-12-16

3.00 h

Bonfire & NGIpkgs

development

overcoming bugs, again

32

2025-12-16

2.00 h

NGIpkgs

review

visio to review PRs

33

2025-12-16

2.00 h

NGIpkgs

review

visio to review PRs

34

2025-12-17

1.50 h

NGIpkgs

review

visio to review PRs

35

2025-12-18

1.00 h

DNSvizor & NGIpkgs

review

review linj’s PR

36

2025-12-19

1.50 h

NGIpkgs

organization

weekly meeting

37

2025-12-21

4.00 h

Bonfire & NGIpkgs

development

fix bug using __structuredAttrs

julminfo - 2026-01-22 - Invoice #org3sale1 - Contract n°2025-24 — Details

5/5

\ No newline at end of file diff --git a/tests/Tests/Invoice/org3sale2.html b/tests/Tests/Invoice/org3sale2.html index 2ee0dfb..94e8bb4 100644 --- a/tests/Tests/Invoice/org3sale2.html +++ b/tests/Tests/Invoice/org3sale2.html @@ -1,2 +1,2 @@ -julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03

Invoice

InvoiceIdentifier:

org3sale2

InvoiceType:

sale

InvoiceOrders:
-

contract n°2026-03

InvoiceEmittedOn:

2026-01-27

InvoicePaymentDueBefore:

2026-02-27

Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Seller:
Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Admin:
Name:

Julien Moutinho

Email:
Buyer:
Name:

Nix@NGI Team

Email:
Admin:
Name:

Daniel Ramirez

Email:

Grand totals

Time frame

Workload

To pay (excl. taxes)

2025-12-23

2026-01-27

64.00 h

2000.00 €

Mandatory legal notices

—

VAT not applicable, art. 293 B of the French General Tax Code.

—

Fixed compensation for recovery costs in case of late payment: 40.00 €

—

Late payment penalty rate (applicable from 2026-02-28): 12.15 % × unpaid amount × number of days late / 365.25

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03

1/4

Summary

#

Type

Scope

Action

Time frame

Rate

(excl. taxes.)

Quantity

Total

(excl. taxes.)

1

service

NGIpkgs / BEAM

development

2025-12-30

2025-12-30

31.25 € / h

4.00 h

(6.25%)

125.00 €

2

service

NGIpkgs / Bonfire

development

2025-12-23

2026-01-09

31.25 € / h

36.00 h

(56.25%)

1125.00 €

3

service

NGIpkgs / Seppo

development

2026-01-25

2026-01-27

31.25 € / h

14.00 h

(21.88%)

437.50 €

4

service

NGIpkgs / dnsvizor

development

2026-01-11

2026-01-12

31.25 € / h

10.00 h

(15.62%)

312.50 €

2/4

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03 — Summary

Details

#

Date

Duration

Scope

Action

References

Description

1

2025-12-23

2.00 h

NGIpkgs / Bonfire

development

address reviewers’ concerns

2

2025-12-24

4.00 h

NGIpkgs / Bonfire

development

update Bonfire and report issues upstream

3

2025-12-24

2.00 h

NGIpkgs / Bonfire

development

update Bonfire to fix bugs

4

2025-12-25

6.00 h

NGIpkgs / Bonfire

development

update and fix bugs

5

2025-12-26

1.00 h

NGIpkgs / Bonfire

development

update to fix bugs

6

2025-12-29

2.00 h

NGIpkgs / Bonfire

development

add more tests

7

2025-12-30

4.00 h

NGIpkgs / BEAM

development

improve buildMix & mixRelease for packaging Elixir software

8

2026-01-01

4.00 h

NGIpkgs / Bonfire

development

support other flavours

9

2026-01-03

4.00 h

NGIpkgs / Bonfire

development

support other flavours, and make update more resilient

10

2026-01-04

2.00 h

NGIpkgs / Bonfire

development

provide upstream with reproducers

11

2026-01-05

2.00 h

NGIpkgs / Bonfire

development

update to latest version

12

2026-01-07

5.00 h

NGIpkgs / Bonfire

development

fix updating

13

2026-01-09

2.00 h

NGIpkgs / Bonfire

development

answer upstream’s questions

14

2026-01-11

5.00 h

NGIpkgs / dnsvizor

development

replace hillingar to package MirageOS unikernels

15

2026-01-12

5.00 h

NGIpkgs / dnsvizor

development

remove the need for --allow-import-from-derivation

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03 — Details

3/4

#

Date

Duration

Scope

Action

References

Description

16

2026-01-25

4.00 h

NGIpkgs / Seppo

development

begin packaging

17

2026-01-26

5.00 h

NGIpkgs / Seppo

development

continue packaging

18

2026-01-27

5.00 h

NGIpkgs / Seppo

development

continue packaging

4/4

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03 — Details

\ No newline at end of file +julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03

Invoice

InvoiceIdentifier:

org3sale2

InvoiceType:

sale

InvoiceOrders:
-

contract n°2026-03

InvoiceEmittedOn:

2026-01-27

InvoicePaymentDueBefore:

2026-02-27

Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Seller:
Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Admin:
Name:

Julien Moutinho

Email:
Buyer:
Name:

Nix@NGI Team

Email:
Admin:
Name:

Daniel Ramirez

Email:

Grand totals

Time frame

Workload

To pay (excl. taxes)

2025-12-23

2026-01-27

64.00 h

2000.00 €

Mandatory legal notices

—

VAT not applicable, art. 293 B of the French General Tax Code.

—

Fixed compensation for recovery costs in case of late payment: 40.00 €

—

Late payment penalty rate (applicable from 2026-02-28): 12.15 % × unpaid amount × number of days late / 365.25

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03

1/4

Summary

#

Type

Scope

Action

Time frame

Rate

(excl. taxes.)

Quantity

Total

(excl. taxes.)

1

service

BEAM & NGIpkgs

development

2025-12-30

2025-12-30

31.25 € / h

4.00 h

(6.25%)

125.00 €

2

service

Bonfire & NGIpkgs

development

2025-12-23

2026-01-09

31.25 € / h

36.00 h

(56.25%)

1125.00 €

3

service

DNSvizor & NGIpkgs

development

2026-01-11

2026-01-12

31.25 € / h

10.00 h

(15.62%)

312.50 €

4

service

NGIpkgs & Seppo

development

2026-01-25

2026-01-27

31.25 € / h

14.00 h

(21.88%)

437.50 €

2/4

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03 — Summary

Details

#

Date

Duration

Scope

Action

References

Description

1

2025-12-23

2.00 h

Bonfire & NGIpkgs

development

address reviewers’ concerns

2

2025-12-24

4.00 h

Bonfire & NGIpkgs

development

update Bonfire and report issues upstream

3

2025-12-24

2.00 h

Bonfire & NGIpkgs

development

update Bonfire to fix bugs

4

2025-12-25

6.00 h

Bonfire & NGIpkgs

development

update and fix bugs

5

2025-12-26

1.00 h

Bonfire & NGIpkgs

development

update to fix bugs

6

2025-12-29

2.00 h

Bonfire & NGIpkgs

development

add more tests

7

2025-12-30

4.00 h

BEAM & NGIpkgs

development

improve buildMix & mixRelease for packaging Elixir software

8

2026-01-01

4.00 h

Bonfire & NGIpkgs

development

support other flavours

9

2026-01-03

4.00 h

Bonfire & NGIpkgs

development

support other flavours, and make update more resilient

10

2026-01-04

2.00 h

Bonfire & NGIpkgs

development

provide upstream with reproducers

11

2026-01-05

2.00 h

Bonfire & NGIpkgs

development

update to latest version

12

2026-01-07

5.00 h

Bonfire & NGIpkgs

development

fix updating

13

2026-01-09

2.00 h

Bonfire & NGIpkgs

development

answer upstream’s questions

14

2026-01-11

5.00 h

DNSvizor & NGIpkgs

development

replace hillingar to package MirageOS unikernels

15

2026-01-12

5.00 h

DNSvizor & NGIpkgs

development

remove the need for --allow-import-from-derivation

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03 — Details

3/4

#

Date

Duration

Scope

Action

References

Description

16

2026-01-25

4.00 h

NGIpkgs & Seppo

development

begin packaging

17

2026-01-26

5.00 h

NGIpkgs & Seppo

development

continue packaging

18

2026-01-27

5.00 h

NGIpkgs & Seppo

development

continue packaging

4/4

julminfo - 2026-01-27 - Invoice #org3sale2 - contract n°2026-03 — Details

\ No newline at end of file diff --git a/tests/Tests/Invoice/org3sale3.html b/tests/Tests/Invoice/org3sale3.html index fba9f92..11db5b4 100644 --- a/tests/Tests/Invoice/org3sale3.html +++ b/tests/Tests/Invoice/org3sale3.html @@ -1,2 +1,2 @@ -julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe

Invoice

InvoiceIdentifier:

org3sale3

InvoiceType:

sale

InvoiceOrders:
-

contract n°2026-FixMe

InvoiceEmittedOn:

2026-01-28

InvoicePaymentDueBefore:

2026-02-28

Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Seller:
Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Admin:
Name:

Julien Moutinho

Email:
Buyer:
Name:

Nix@NGI Team

Email:
Admin:
Name:

Daniel Ramirez

Email:

Grand totals

Time frame

Workload

To pay (excl. taxes)

2025-12-29

2026-01-23

10.00 h

312.50 €

Mandatory legal notices

—

VAT not applicable, art. 293 B of the French General Tax Code.

—

Fixed compensation for recovery costs in case of late payment: 40.00 €

—

Late payment penalty rate (applicable from 2026-03-01): 12.15 % × unpaid amount × number of days late / 365.25

julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe

1/3

Summary

#

Type

Scope

Action

Time frame

Rate

(excl. taxes.)

Quantity

Total

(excl. taxes.)

1

service

NGIpkgs

organization

2026-01-09

2026-01-23

31.25 € / h

5.50 h

(55.0%)

171.88 €

2

service

NGIpkgs / Funkwhale

review

2025-12-29

2025-12-29

31.25 € / h

0.50 h

(5.0%)

15.62 €

3

service

NGIpkgs / Manuals

development

2026-01-22

2026-01-22

31.25 € / h

4.00 h

(40.0%)

125.00 €

2/3

julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe — Summary

Details

#

Date

Duration

Scope

Action

References

Description

1

2025-12-29

0.50 h

NGIpkgs / Funkwhale

review

2

2026-01-09

2.00 h

NGIpkgs

organization

weekly meeting

3

2026-01-16

2.00 h

NGIpkgs

organization

weekly meeting

4

2026-01-22

4.00 h

NGIpkgs / Manuals

development

address reviewers’ concerns

5

2026-01-23

1.50 h

NGIpkgs

organization

weekly meeting

julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe — Details

3/3

\ No newline at end of file +julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe

Invoice

InvoiceIdentifier:

org3sale3

InvoiceType:

sale

InvoiceOrders:
-

contract n°2026-FixMe

InvoiceEmittedOn:

2026-01-28

InvoicePaymentDueBefore:

2026-02-28

Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Seller:
Name:

julminfo

Address:

3, place du Monument

Mairie - Bureau 1

23340 Gentioux-Pigerolles France

SIREN:

942798083

IBAN:

FR18 2004 1010 0820 3735 3D02 912

Admin:
Name:

Julien Moutinho

Email:
Buyer:
Name:

Nix@NGI Team

Email:
Admin:
Name:

Daniel Ramirez

Email:

Grand totals

Time frame

Workload

To pay (excl. taxes)

2025-12-29

2026-01-23

10.00 h

312.50 €

Mandatory legal notices

—

VAT not applicable, art. 293 B of the French General Tax Code.

—

Fixed compensation for recovery costs in case of late payment: 40.00 €

—

Late payment penalty rate (applicable from 2026-03-01): 12.15 % × unpaid amount × number of days late / 365.25

julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe

1/3

Summary

#

Type

Scope

Action

Time frame

Rate

(excl. taxes.)

Quantity

Total

(excl. taxes.)

1

service

Funkwhale & NGIpkgs

review

2025-12-29

2025-12-29

31.25 € / h

0.50 h

(5.0%)

15.62 €

2

service

NGIpkgs

organization

2026-01-09

2026-01-23

31.25 € / h

5.50 h

(55.0%)

171.88 €

3

service

NGIpkgs Manuals

development

2026-01-22

2026-01-22

31.25 € / h

4.00 h

(40.0%)

125.00 €

2/3

julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe — Summary

Details

#

Date

Duration

Scope

Action

References

Description

1

2025-12-29

0.50 h

Funkwhale & NGIpkgs

review

2

2026-01-09

2.00 h

NGIpkgs

organization

weekly meeting

3

2026-01-16

2.00 h

NGIpkgs

organization

weekly meeting

4

2026-01-22

4.00 h

NGIpkgs Manuals

development

address reviewers’ concerns

5

2026-01-23

1.50 h

NGIpkgs

organization

weekly meeting

julminfo - 2026-01-28 - Invoice #org3sale3 - contract n°2026-FixMe — Details

3/3

\ No newline at end of file diff --git a/tests/Tests/Work.hs b/tests/Tests/Work.hs new file mode 100644 index 0000000..39abfa1 --- /dev/null +++ b/tests/Tests/Work.hs @@ -0,0 +1,675 @@ +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} + +module Tests.Work where + +import Literate.Document qualified as Doc +import Literate.Invoice +import Literate.Prelude + +data ScopeId + = Scope_BEAM + | Scope_Bonfire + | Scope_DNSvizor + | Scope_Funkwhale + | Scope_NGIpkgs + | Scope_NGIpkgs_Manuals + | Scope_Nixpkgs + | Scope_OpenCV + | Scope_Seppo + deriving (Eq, Ord, Show, Generic, NFData) +instance Doc.ToInline ScopeId where + toInline = \case + Scope_BEAM -> "BEAM" + Scope_Bonfire -> "Bonfire" + Scope_DNSvizor -> "DNSvizor" + Scope_Funkwhale -> "Funkwhale" + Scope_NGIpkgs -> "NGIpkgs" + Scope_NGIpkgs_Manuals -> "NGIpkgs Manuals" + Scope_Nixpkgs -> "Nixpkgs" + Scope_OpenCV -> "OpenCV" + Scope_Seppo -> "Seppo" + +data ActionId + = Action_Organization + | Action_Development + | Action_Documentation + | Action_Review + deriving (Eq, Ord, Show, Generic, Enum, NFData) +instance Doc.ToInline ActionId where + toInline = \case + Action_Development -> "development" + Action_Documentation -> "documentation" + Action_Organization -> "organization" + Action_Review -> "review" + +works :: [Work ScopeId ActionId] +works = + [ Work + { workDate = "2025-11-06" + , workDuration = 0.5 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = ["https://meet.google.com/hii-druc-tjp"] + , workDescription = "first meeting" + } + , Work + { workDate = "2025-11-06" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] + , workDescription = "focus on the hardest part first" + } + , Work + { workDate = "2025-11-07" + , workDuration = 8 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] + , workDescription = "continuing to package Bonfire deps" + } + , Work + { workDate = "2025-11-08" + , workDuration = 0.1 + , workAction = Action_Development + , workScope = [Scope_Nixpkgs, Scope_OpenCV] + , workReferences = ["https://github.com/NixOS/nixpkgs/pull/459592"] + , workDescription = "fix opencv in nixpkgs" + } + , Work + { workDate = "2025-11-09" + , workDuration = 8 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] + , workDescription = "continue to fix deps" + } + , Work + { workDate = "2025-11-09" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] + , workDescription = "continue to fix deps" + } + , Work + { workDate = "2025-11-11" + , workDuration = 6 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] + , workDescription = "continue to fix deps" + } + , Work + { workDate = "2025-11-12" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ju1m/bonfire-app/commits/nix"] + , workDescription = "continue to fix deps" + } + , Work + { workDate = "2025-11-14" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812"] + , workDescription = "continue to fix deps and move into ngipkgs" + } + , Work + { workDate = "2025-11-14" + , workDuration = 1 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-weekly-review-34-2ab59d49e1be80939503c655b009e934"] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2025-11-15" + , workDuration = 6 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "finish to build Bonfire and start to fix runtime bugs" + } + , Work + { workDate = "2025-11-16" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812#issuecomment-3537609170"] + , workDescription = "workaround and contribute upstream" + } + , Work + { workDate = "2025-11-17" + , workDuration = 8 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "add updateScript and fix opencv" + } + , Work + { workDate = "2025-11-19" + , workDuration = 8 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812#issuecomment-3554376221"] + , workDescription = "continue to fix startup crashes" + } + , Work + { workDate = "2025-11-21" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "begin to package yarn assets. Upstream likes convoluted code and fake libraries." + } + , Work + { workDate = "2025-11-21" + , workDuration = 1 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2025-11-21" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "continue to package assets" + } + , Work + { workDate = "2025-11-23" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "continue to package assets and try to get Bonfire to work" + } + , Work + { workDate = "2025-11-24" + , workDuration = 10 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/surface-ui/surface/issues/762#issuecomment-3577030748"] + , workDescription = "continue to solve problems with Bonfire packaging" + } + , Work + { workDate = "2025-11-27" + , workDuration = 8 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1812#issuecomment-3584319056"] + , workDescription = "successfully auto-update and build Bonfire" + } + , Work + { workDate = "2025-11-28" + , workDuration = 1 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-weekly-review-36-2b959d49e1be80fa823cd4d83581fda5#2b959d49e1be80fc85eed38c9a9dca86"] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2025-11-29" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "begin the service module" + } + , Work + { workDate = "2025-12-02" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "continue the service module" + } + , Work + { workDate = "2025-12-03" + , workDuration = 8 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "first working service module" + } + , Work + { workDate = "2025-12-04" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1871"] + , workDescription = "improve service module" + } + , Work + { workDate = "2025-12-05" + , workDuration = 1 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-weekly-review-36-2b959d49e1be80fa823cd4d83581fda5"] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2025-12-05" + , workDuration = 0.5 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1954"] + , workDescription = "meeting" + } + , Work + { workDate = "2025-12-06" + , workDuration = 2 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "prepare wednesday meeting" + } + , Work + { workDate = "2025-12-07" + , workDuration = 4 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "prepare demo for wednesday meeting" + } + , Work + { workDate = "2025-12-08" + , workDuration = 4 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1891"] + , workDescription = "prepare demo for wednesday meeting" + } + , Work + { workDate = "2025-12-09" + , workDuration = 4 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1891"] + , workDescription = "continue to document" + } + , Work + { workDate = "2025-12-10" + , workDuration = 2 + , workAction = Action_Review + , workScope = [Scope_NGIpkgs] + , workReferences = ["https://www.notion.so/nixos-foundation/Nix-NGI-best-practices-for-NixOS-modules-implementation-2c559d49e1be80a8a499f21abb203d6f"] + , workDescription = "visio on “best practices”" + } + , Work + { workDate = "2025-12-12" + , workDuration = 1 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "weekly visio meeting" + } + , Work + { workDate = "2025-12-11" + , workDuration = 8 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "continue to document" + } + , Work + { workDate = "2025-12-12" + , workDuration = 4 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "continue to document" + } + , Work + { workDate = "2025-12-13" + , workDuration = 2 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = + [ "setup sphinx like " + , Doc.InlineLink + { Doc.inlineLinkTarget = "https://nix.dev" + , Doc.inlineLinkText = "nix.dev" + } + , " for the manuals" + ] + } + , Work + { workDate = "2025-12-13" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/bonfire-networks/bonfire-app/issues/1670#issuecomment-3650762914"] + , workDescription = "update to latest; overcoming new bugs introduced by upstream" + } + , Work + { workDate = "2025-12-15" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "improving the update script and still overcoming upstream bugs" + } + , Work + { workDate = "2025-12-16" + , workDuration = 3 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "overcoming bugs, again" + } + , Work + { workDate = "2025-12-16" + , workDuration = 2 + , workAction = Action_Review + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "visio to review PRs" + } + , Work + { workDate = "2025-12-16" + , workDuration = 2 + , workAction = Action_Review + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "visio to review PRs" + } + , Work + { workDate = "2025-12-17" + , workDuration = 1.5 + , workAction = Action_Review + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "visio to review PRs" + } + , Work + { workDate = "2025-12-18" + , workDuration = 1 + , workAction = Action_Review + , workScope = [Scope_NGIpkgs, Scope_DNSvizor] + , workReferences = [] + , workDescription = "review linj’s PR" + } + , Work + { workDate = "2025-12-19" + , workDuration = 1.5 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2025-12-21" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = + [ "fix bug using " + , "__structuredAttrs" & Doc.InlineCode + ] + } + , Work + { workDate = "2025-12-23" + , workDuration = 4 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "improve building the manuals" + } + , Work + { workDate = "2025-12-23" + , workDuration = 2 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "address reviewers’ concerns" + } + , Work + { workDate = "2025-12-24" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "update Bonfire and report issues upstream" + } + , Work + { workDate = "2025-12-24" + , workDuration = 4 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "document" + } + , Work + { workDate = "2025-12-24" + , workDuration = 2 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "update Bonfire to fix bugs" + } + , Work + { workDate = "2025-12-25" + , workDuration = 2 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "document" + } + , Work + { workDate = "2025-12-25" + , workDuration = 6 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/bonfire-networks/bonfire-app/issues/1698#issuecomment-3692147409"] + , workDescription = "update and fix bugs" + } + , Work + { workDate = "2025-12-26" + , workDuration = 1 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "update to fix bugs" + } + , Work + { workDate = "2025-12-28" + , workDuration = 6 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] + , workReferences = [] + , workDescription = "document" + } + , Work + { workDate = "2025-12-29" + , workDuration = 2 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "add more tests" + } + , Work + { workDate = "2025-12-29" + , workDuration = 0.5 + , workAction = Action_Review + , workScope = [Scope_NGIpkgs, Scope_Funkwhale] -- goes into NGI Review + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1707#discussion_r2651644145"] + , workDescription = "" + } + , Work + { workDate = "2025-12-30" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_BEAM] + , workReferences = [] + , workDescription = ["improve ", Doc.InlineCode "buildMix", " & ", Doc.InlineCode "mixRelease", " for packaging Elixir software"] + } + , Work + { workDate = "2026-01-01" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "support other flavours" + } + , Work + { workDate = "2026-01-03" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "support other flavours, and make update more resilient" + } + , Work + { workDate = "2026-01-04" + , workDuration = 2 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "provide upstream with reproducers" + } + , Work + { workDate = "2026-01-05" + , workDuration = 2 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "update to latest version" + } + , Work + { workDate = "2026-01-07" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = [] + , workDescription = "fix updating" + } + , Work + { workDate = "2026-01-07" + , workDuration = 1 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] -- goes into NGI Core + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/1891"] + , workDescription = "address reviewer’s comment" + } + , Work + { workDate = "2026-01-09" + , workDuration = 2 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] -- goes into NGI Core + , workReferences = [] + , workDescription = "address reviewer’s comments" + } + , Work + { workDate = "2026-01-09" + , workDuration = 2 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Bonfire] + , workReferences = ["https://github.com/bonfire-networks/bonfire-app/issues/1730"] + , workDescription = "answer upstream’s questions" + } + , Work + { workDate = "2026-01-11" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_DNSvizor] + , workReferences = [] + , workDescription = ["replace ", Doc.InlineCode "hillingar", " to package MirageOS unikernels"] + } + , Work + { workDate = "2026-01-09" + , workDuration = 2 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2026-01-12" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_DNSvizor] + , workReferences = ["https://github.com/ju1m/ngipkgs/commits/dnsvizor/"] + , workDescription = ["remove the need for ", Doc.InlineCode "--allow-import-from-derivation"] + } + , Work + { workDate = "2026-01-12" + , workDuration = 6 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] -- goes into NGI Core + , workReferences = [] + , workDescription = "render options" + } + , Work + { workDate = "2026-01-13" + , workDuration = 1 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] -- goes into NGI Core + , workReferences = [] + , workDescription = "update" + } + , Work + { workDate = "2026-01-16" + , workDuration = 2 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2026-01-19" + , workDuration = 2 + , workAction = Action_Documentation + , workScope = [Scope_NGIpkgs_Manuals] -- goes into NGI Core + , workReferences = [] + , workDescription = "split into several PDF" + } + , Work + { workDate = "2026-01-22" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs_Manuals] -- goes into NGI Core + , workReferences = ["https://github.com/ngi-nix/ngipkgs/pull/2010"] + , workDescription = "address reviewers’ concerns" + } + , Work + { workDate = "2026-01-23" + , workDuration = 1.5 + , workAction = Action_Organization + , workScope = [Scope_NGIpkgs] + , workReferences = [] + , workDescription = "weekly meeting" + } + , Work + { workDate = "2026-01-25" + , workDuration = 4 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Seppo] + , workReferences = [] + , workDescription = "begin packaging" + } + , Work + { workDate = "2026-01-26" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Seppo] + , workReferences = [] + , workDescription = "continue packaging" + } + , Work + { workDate = "2026-01-27" + , workDuration = 5 + , workAction = Action_Development + , workScope = [Scope_NGIpkgs, Scope_Seppo] + , workReferences = [] + , workDescription = "continue packaging" + } + ] -- 2.49.0