@@ -62,7 +62,7 @@ func Parse(f io.Reader) (types.ParsedResources, error) {
6262 return types.ParsedResources {}, fmt .Errorf ("error parsing transactions: %w" , err )
6363 }
6464
65- err = parseAllocations (& resources , budget .MonthlyBudgets , envelopeIDNames )
65+ err = parseMonthlyBudgets (& resources , budget .MonthlyBudgets , envelopeIDNames )
6666 if err != nil {
6767 return types.ParsedResources {}, fmt .Errorf ("error parsing budget allocations: %w" , err )
6868 }
@@ -339,29 +339,55 @@ func parseTransactions(resources *types.ParsedResources, transactions []Transact
339339 return nil
340340}
341341
342- func parseAllocations (resources * types.ParsedResources , allocations []MonthlyBudget , envelopeIDNames IDToEnvelopes ) error {
343- for _ , monthBudget := range allocations {
342+ func parseMonthlyBudgets (resources * types.ParsedResources , monthlyBudgets []MonthlyBudget , envelopeIDNames IDToEnvelopes ) error {
343+ for _ , monthBudget := range monthlyBudgets {
344344 month , err := time .Parse ("2006-01-02" , monthBudget .Month )
345345 if err != nil {
346346 return fmt .Errorf ("could not parse date: %w" , err )
347347 }
348348
349- for _ , allocation := range monthBudget .MonthlySubCategoryBudgets {
350- // Ignore the ones that are zero
351- if allocation .Budgeted .IsZero () {
352- continue
349+ for _ , subCategoryBudget := range monthBudget .MonthlySubCategoryBudgets {
350+ // If something is budgeted, create an allocation for it
351+ if ! subCategoryBudget .Budgeted .IsZero () {
352+ resources .Allocations = append (resources .Allocations , types.Allocation {
353+ Model : models.Allocation {
354+ AllocationCreate : models.AllocationCreate {
355+ Month : month ,
356+ Amount : subCategoryBudget .Budgeted ,
357+ },
358+ },
359+ Category : envelopeIDNames [subCategoryBudget .CategoryID ].Category ,
360+ Envelope : envelopeIDNames [subCategoryBudget .CategoryID ].Envelope ,
361+ })
353362 }
354363
355- resources .Allocations = append (resources .Allocations , types.Allocation {
356- Model : models.Allocation {
357- AllocationCreate : models.AllocationCreate {
358- Month : month ,
359- Amount : allocation .Budgeted ,
364+ // If the overspendHandling is configured, work with it
365+ if ! (subCategoryBudget .OverspendingHandling == "" ) {
366+ // This might actually be needed in some use cases, but I could not find one
367+ // when implementing, so we're skipping it here.
368+ if strings .HasPrefix (subCategoryBudget .CategoryID , "Category/PreYNABDebt" ) {
369+ continue
370+ }
371+
372+ // There's two modes in YNAB4: Confined, which equals AFFECT_ENVELOPE in EZ
373+ // and "AffectsBuffer", which equals AFFECT_AVAILABLE in EZ.
374+ // Since AFFECT_AVAILABLE is the default, we can skip everything that does not
375+ // lead to AFFECT_ENVELOPE.
376+ if subCategoryBudget .OverspendingHandling != "Confined" {
377+ continue
378+ }
379+
380+ resources .MonthConfigs = append (resources .MonthConfigs , types.MonthConfig {
381+ Model : models.MonthConfig {
382+ MonthConfigCreate : models.MonthConfigCreate {
383+ OverspendMode : "AFFECT_ENVELOPE" ,
384+ },
385+ Month : month ,
360386 },
361- } ,
362- Category : envelopeIDNames [allocation .CategoryID ].Category ,
363- Envelope : envelopeIDNames [ allocation . CategoryID ]. Envelope ,
364- })
387+ Category : envelopeIDNames [ subCategoryBudget . CategoryID ]. Category ,
388+ Envelope : envelopeIDNames [subCategoryBudget .CategoryID ].Envelope ,
389+ })
390+ }
365391 }
366392 }
367393
0 commit comments