
    oj10                    $   d dl mZ d dlZd dlmc mZ d dlm	Z	 d dl
Z
d dlmZ d dlmZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZmZmZ d dlmZ d dlmZ d Z d*d+dZ!	 d,d-dZ"d.dZ#d/d!Z$d0d"Z%d0d#Z&d0d$Z'd0d%Z(d0d&Z)d0d'Z*d0d(Z+d0d)Z,dS )1    )annotationsN)Decimal)HTTPException)confirm_create_budget_account)confirm_create_category)%seed_credit_card_candidates_from_rows)get_budget_planning_matrix!get_category_forecast_explanationconfirm_budget_transaction)confirm_prior_year_actualsget_prior_year_actualspreview_prior_year_actuals)connect_memory)apply_migrationsc                 @    t                      } t          |            | S )N)r   r   )conns    W/home/agent/.hermes/repos/FinanceManager/tests/unit/test_budget_planning_forecast_v1.pydbr      s     DTK    Essen & Haushaltnamestrc                p    t          | dddd          d         }t          | |dd          d         }||fS )NHaushaltcheckingCHF)r   account_typecurrency	entity_idexpenser   category_type)r   r   )r   r   
account_idcategory_ids       r   setup_categoryr&      sa    .ZUKK  J *	22  K {""r   r!   r$   r%   	booked_onamounttx_typec                6    t          | |||dd|d|dd	          S )Nzconfirmed bookingProviderr   manual)	r$   transaction_typetransaction_datedescriptionpayeeamount_originalcurrency_originalr%   source_typer   )r   r$   r%   r'   r(   r)   s         r   book_expenser4   +   s>     &$ ' ).%!&&#
	
 
	
  r   startendreturnNonec                n    |                      dd| d| ||df           |                                  d S )NzINSERT INTO budget_import_sessions(
             import_session_id,file_period_start,file_period_end,status,created_at,updated_at)
           VALUES (?,?,?,?,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)z	coverage--candidates_created)executecommit)r   r5   r6   s      r   mark_import_coverager>   C   sP    LL	C 
#U	"	"S	"	"E30DE	   	KKMMMMMr   yearvalueslist[dict[str, str | None]]c                T    t          | ||d          }t          | |d                   S )Nr?   r@   payload)r   r   )r   r?   r@   previews       r   save_prior_yearrF   M   s.    (/O/OPPG%dGI,>???r   c                    t                      } t          |           \  }}t          | ddd          d         }t          | d|dd|ddg          }t	          | d	          }d
 |d         D             }|d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}||         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}||         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}||         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}||         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}| 
                    d                                          d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}t          | d|d d|ddg           t	          | d	          }d |d         D             }||         d         }d }||u }	|	slt          j        d |	fd!||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}||         d         }d }||u }	|	slt          j        d |	fd!||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}|d         d         }d}||k    }	|	slt          j        d|	fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j	        |                    d x}x}	}d S )"NFreizeitr!   r"   r    2025z1200.00r%   
amount_chf0.00r?   c                     i | ]}|d          |S r%    .0rows     r   
<dictcomp>z^test_prior_year_batch_keeps_blank_and_explicit_zero_distinct_and_auditable.<locals>.<dictcomp>b       @@@S@@@r   rowsstatus	confirmed==z%(py1)s == %(py4)spy1py4assert %(py6)spy6annual_actual_chfmonthly_average_chf100.00totalsrecorded_category_count   missing_category_count   )>=)z%(py1)s >= %(py4)szFSELECT COUNT(*) FROM audit_log WHERE action='prior_year_actuals_saved'r   c                     i | ]}|d          |S rO   rP   rQ   s     r   rT   z^test_prior_year_batch_keeps_blank_and_explicit_zero_distinct_and_auditable.<locals>.<dictcomp>z   rU   r   isz%(py1)s is %(py4)s)r   r&   r   rF   r   
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanationr<   fetchone)r   _accountfirstsecondresultactualsby_id@py_assert0@py_assert3@py_assert2@py_format5@py_format7s               r   Jtest_prior_year_batch_keeps_blank_and_explicit_zero_distinct_and_auditabler   R   s   44D$T**OHe$zI>> F !;;"&99	
 F %T777G@@@@@E(*{*{**********{*********{***************************<+,9	9,	9999999999,	99999,9999	999999999999999999999999999<-.:(:.(::::::::::.(:::::.::::(:::::::::::::::::::::::::::=,-77-7777777777-77777-7777777777777777777777777777777=./969/69999999999/699999/99996999999999999999999999999999801>Y>1Y>>>>>>>>>>1Y>>>>>1>>>>Y>>>>>>>>>>>>>>>>>>>>>>>>>>>823?x?3x??????????3x?????3????x???????????????????????????867<1<71<<<<<<<<<<71<<<<<7<<<<1<<<<<<<<<<<<<<<<<<<<<<<<<<<856;!;6!;;;;;;;;;;6!;;;;;6;;;;!;;;;;;;;;;;;;;;;;;;;;;;;;;;<<P hjj                q                         !66"&99	
   %T777G@@@@@E<+,44,4444444444,44444,4444444444444444444444444444444<-.6$6.$6666666666.$66666.6666$666666666666666666666666666801;V;1V;;;;;;;;;;1V;;;;;1;;;;V;;;;;;;;;;;;;;;;;;;;;;;;;;;867<1<71<<<<<<<<<<71<<<<<7<<<<1<<<<<<<<<<<<<<<<<<<<<<<<<<<856;!;6!;;;;;;;;;;6!;;;;;6;;;;!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;r   c                 d   t                      } t          |           \  }}t          |           d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d|d	d
g           d}t          | d          d         }||v }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          j
        t          d          5  t          | d           d d d            n# 1 swxY w Y   t          j
        t          d          5  t          | ddz  g d           d d d            n# 1 swxY w Y   t          j
        t          d          5  t          | d|dd
gd           d d d            d S # 1 swxY w Y   d S )Nr?   rI   rY   r[   r\   r_   r`   2024z240.00rJ   rM   available_yearsinz%(py1)s in %(py4)sz	past year)match99999i  rC   znon-negative CHF1e999999)r   r&   r   rn   ro   rp   rq   rr   rF   pytestraisesr   r   )r   rt   r%   rz   r{   r|   r}   r~   s           r   Ftest_default_and_additional_past_years_work_but_future_year_is_blockedr      s]   44D*400Hk!$''/969/69999999999/699999/99996999999999999999999999999999D&;h#W#W"XYYYQ+Dv>>>?PQQ6QQQQQQQQQQQ6QQQQQQ6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ	}K	8	8	8 2 2t&11112 2 2 2 2 2 2 2 2 2 2 2 2 2 2	}K	8	8	8 M M"4#*)K)KLLLM M M M M M M M M M M M M M M	},>	?	?	? 
 
"S](^(^'_``	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s6   3FFF7GG!G H%%H),H)c                 2   t                      } t          |           \  }t          | dd           t          | dddg           t	          dd          D ]\  }}t          | |d	|d
d|           t          | |dd           t          | |ddd           t          | ddddgdd           t          | ddd          }t          fd|d         D                       }t          d          }t          d          |t          |d                   z  z   }|d         }g d }	||	k    }
|
slt          j        d!|
fd"||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	|d&         }d}	||	k    }
|
slt          j        d!|
fd"||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	|d'         }d}	||	k    }
|
slt          j        d!|
fd"||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	|d(         }|                    t          d)                    d*}	||	k    }
|
slt          j        d!|
fd"||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	|d+         }d}	||	k    }
|
slt          j        d!|
fd"||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	|d,         }t          |          }	|d(         }t          |          }d}t          |          }||z
  }|	|k    }|st          j        d!|fd-|	|f          d.t!          j                    v st          j        t                    rt          j        t                    nd.t          j        |          t          j        |	          d.t!          j                    v st          j        t                    rt          j        t                    nd.t          j        |          t          j        |          d.t!          j                    v st          j        t                    rt          j        t                    nd.t          j        |          t          j        |          d/	z  }d0d1|iz  }t          t          j        |                    d x}x}	x}x}x}x}x}}|d2         }t          |d,                   t          d3          z  d4z                      t          d)                    d*}	||	k    }
|
slt          j        d!|
fd"||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	d5}|d6         }	||	v }
|
slt          j        d7|
fd8||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	d9}|d:         }	||	v}
|
slt          j        d;|
fd<||	f          t          j        |          t          j        |	          d#z  }d$d%|iz  }t          t          j        |                    d x}x}
}	d S )=N
2026-01-01
2026-04-30rI   z2400.00rJ   )100200300400rh   r5   2026-02d-28z
2026-05-1550.00z
2026-05-16z999.00transfer)r)   zAbo-Kandidat)DatumBeschreibungBetragzvisa.csvF)source_file_labelmigros_covered20262026-05)r?   current_monthcomparison_yearc              3  4   K   | ]}|d          k    |V  dS r%   NrP   rR   itemr%   s     r   	<genexpr>zTtest_forecast_uses_confirmed_actuals_plus_deterministic_rest_only.<locals>.<genexpr>   2      UU$}2E2T2Tt2T2T2T2TUUr   rV   250.00z1050.00remaining_month_partscovered_complete_months)01020304rY   r[   r\   r_   r`   actual_year_to_date_chfused_monthly_average_chfforecast_display_chf0.01z.2fcomparison_year_actual_chfdeviation_chf)z~%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == (%(py10)s
{%(py10)s = %(py6)s(%(py8)s)
} - %(py15)s
{%(py15)s = %(py11)s(%(py13)s)
})r   )	py0py2r^   r`   py8py10py11py13py15zassert %(py18)spy18deviation_percent2400d   zcomparison_year=2025data_explorer_urlr   r   Aboforecast_basis)not in)z%(py1)s not in %(py4)s)r   r&   r>   rF   	enumerater4   r   r	   nextr   rn   ro   rp   rq   rr   quantize@py_builtinslocals_should_repr_global_name)r   r$   monthr(   matrixrS   averageexpectedrz   r{   r|   r}   r~   @py_assert1@py_assert7@py_assert9@py_assert12@py_assert14@py_assert16@py_assert5@py_format17@py_format19r%   s                         @r   Atest_forecast_uses_confirmed_actuals_plus_deterministic_rest_onlyr      s	   44D,T22J|\:::D&;i#X#X"YZZZ"#?qIII T TvT:{4JE4J4J4J4JFSSSSz;gFFFz;hPZ[[[[)8	T	TU$	    (	  F UUUUvUUU
U
UChGy!!Ggc:Q6R.S.S$SSH()E-E-E-EE)-EEEEEEEEEEE)-EEEEEE)EEEE-EEEEEEEEEEEEEEEEEEEEEEEEEEEE()6Y6)Y6666666666)Y66666)6666Y666666666666666666666666666)*6h6*h6666666666*h66666*6666h666666666666666666666666666%&UX->->wv-O-O*U*UU&*UUUUUUUUUUU&*UUUUUU&UUUU*UUUUUUUUUUUUUUUUUUUUUUUUUUUU+,9	9,	9999999999,	99999,9999	999999999999999999999999999'e7'((eC8N4OeG4O,P,Pe[deSZ[dSeSee,PSe,ee(,eeeeeeeeeee(,eeeeeeeeeeeee7eeeee7eeeeee'eeee(eeeeeeeeeeeGeeeeeGeeeeee4Oeeee,PeeeeeeeeeeeSZeeeeeSZeeeeee[deeeeSeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"#  B733G+H+H7SY??+Z]`+`*j*jkrsykzkz*{*{  (B  (B  B#  (B  B  B  B  B  B  B  B  B  B  B#  (B  B  B  B  B  B#  B  B  B  B  (B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B  B!=S)<%==!%===========!%======!====%============================-,--5-----------5------5----------------------------------r   c                    t                      } t          |           \  }}t          | dd           t          dd          D ]}t	          | ||d|ddd           t          | |d	d
dddddd           t          | dd          }|d         d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         d         }d }||u }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         d          }d }||u }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d!         d"         d#         }d$}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d S )%Nr   
2026-03-31rh      r   r   z-20r   r!   z
2026-04-10Uncategorizedrc   r   r,   )r$   r-   r.   r/   r0   r1   r2   r3   r   2026-04r?   r   rd   r   r   rY   r[   r\   r_   r`   unrepresented_actual_chfunrepresented_transaction_countforecast_year_chfrk   rm   r   quality_warningscode"expenses_outside_active_categories)r   r&   r>   ranger4   r   r	   rn   ro   rp   rq   rr   )
r   r$   r%   r   r   rz   r{   r|   r}   r~   s
             r   Htest_primary_totals_include_unrepresented_expenses_and_withhold_forecastr      s   44D,T22J|\:::q! U UT:{4JE4J4J4J4JGTTTT$ ) ,*$'!&#		
 		
   (6SSSF(56B(B6(BBBBBBBBBB6(BBBBB6BBBB(BBBBBBBBBBBBBBBBBBBBBBBBBBB(67C8C78CCCCCCCCCC78CCCCC7CCCC8CCCCCCCCCCCCCCCCCCCCCCCCCCC(=>C!C>!CCCCCCCCCC>!CCCCC>CCCC!CCCCCCCCCCCCCCCCCCCCCCCCCCC(/08D80D88888888880D8888808888D888888888888888888888888888(O,44,4444444444,44444,4444444444444444444444444444444$%b)&1Y5YY15YYYYYYYYYYY15YYYYYY1YYYY5YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYr   c            	     6  
 t                      } t          |           \  }
t          | dd           t          dd          D ]}t	          | |
d|ddd           t          | d	d
          }t          
fd|d         D                       }|d         }g }||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         }d}||u }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         }d }||u }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d S )Nz
2026-01-10z
2026-03-20rh   r   r   r   z-15rc   r   r   r   c              3  4   K   | ]}|d          k    |V  dS r   rP   r   s     r   r   zUtest_partial_import_ranges_never_count_as_complete_forecast_months.<locals>.<genexpr>   r   r   rV   r   rY   r[   r\   r_   r`   forecast_reliableFrk   rm   r   )r   r&   r>   r   r4   r	   r   rn   ro   rp   rq   rr   )r   r$   r   r   rS   rz   r{   r|   r}   r~   r%   s             @r   Btest_partial_import_ranges_never_count_as_complete_forecast_monthsr      s   44D,T22J|\:::q! V VT:{4JE4J4J4J4JHUUUU'6SSSF
UUUUvUUU
U
UC()/R/)R//////////)R/////)////R///////////////////////////"#,u,#u,,,,,,,,,,#u,,,,,#,,,,u,,,,,,,,,,,,,,,,,,,,,,,,,,,%&.$.&$..........&$.....&....$.............................r   c                 "  	 t                      } t          |           \  }	t          | |	dd           t          | |	dd           t          | dd          }t	          	fd|d	         D                       }|d
         }d}||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}|d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}|d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}|d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}|d         d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}d S )Nz
2026-01-31rc   z
2026-02-15r   r   z2026-02r   c              3  4   K   | ]}|d          k    |V  dS r   rP   r   s     r   r   z]test_forecast_is_missing_until_three_complete_months_and_never_zero_filled.<locals>.<genexpr>   r   r   rV   r   Frk   rm   r\   r_   r`   r   r   r   
evaluationu+   Vergleichswert für 2025 noch nicht erfasstrY   r[   rd   r   )
r   r&   r4   r	   r   rn   ro   rp   rq   rr   )
r   r$   r   rS   rz   r{   r|   r}   r~   r%   s
            @r   Jtest_forecast_is_missing_until_three_complete_months_and_never_zero_filledr      s   44D,T22Jz;hGGGz;gFFF'6SSSF
UUUUvUUU
U
UC"#,u,#u,,,,,,,,,,#u,,,,,#,,,,u,,,,,,,,,,,,,,,,,,,,,,,,,,,%&.$.&$..........&$.....&....$...........................'4'4''''''''''4'''''''''4'''''''''''''''''''''''''''"#+t+#t++++++++++#t+++++#++++t+++++++++++++++++++++++++++|M MM MMMMMMMMMMM MMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMM(/08D80D88888888880D8888808888D88888888888888888888888888888r   c            	        t                      } t          |           \  }t          | dd           t          | ddd          d         fd|                     d                                          D             }t          | d	|           t          d
d          D ]2}t          | |d|ddd           t          | |d|ddd           3t          | |dd           t          | dd          }|d         }t          |d                   t          |d                   z  t          d          z                      t          d                    }|d         }t          |          }||k    }	|	st          j        d|	fd||f          dt          j                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          dt          j                    v st          j        |          rt          j        |          nddz  }
d d!|
iz  }t%          t          j        |                    d x}x}}	d S )"Nr   r   rH   r!   r"   r    c                    g | ]P}t          |d                    t          |d                    k    rdnt          |d                    k    rdnddQS )r%   1000.00z3000.00rL   rJ   )r   )rR   rS   ru   rv   s     r   
<listcomp>zUtest_total_percent_comes_from_total_sums_not_category_percentages.<locals>.<listcomp>   s     6 6 6  s=122 s=)**e33 	 s=)**f44 Y		
 		
6 6 6r   zWSELECT category_id FROM budget_categories WHERE is_active=1 AND category_type='expense'rI   rh      r   r   r   rc   z200.00z
2026-05-31r   r   r   rd   r   r   r   r   r   rY   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py6)sr   expected_percentr   r   r^   r`   assert %(py8)sr   )r   r&   r>   r   r<   fetchallrF   r   r4   r	   r   r   rn   ro   r   r   r   rp   rq   rr   )r   r$   comparison_valuesr   r   rd   r   r   r{   r   r~   @py_format9ru   rv   s               @@r   Atest_total_percent_comes_from_total_sums_not_category_percentagesr      s   44D&t,,J|\:::$zI>> F6 6 6 6 6 <<e
 

(**6 6 6 D&"3444q! Q QT:u.De.D.D.D.DhOOOT:v/Eu/E/E/E/ExPPPPz5,AAA'6SSSFHF'((
&56
7
7	8
%..	 hwv	 
 -.C7.//C/3CCCCCCCCCCC/3CCCCCCCCCCCCC7CCCCC7CCCCCC.CCCC/CCCCCCCCCCC3CCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCr   c            	     P   t                      } t          |           \  }}t          | dd           t          | d|ddg           t	          dd          D ]\  }}t          | ||d	|d
d|           t          | ||dd           t          | |dd          }t          |d                   t          |d                   z   }|d         }t          |          }||k    }	|	st          j	        d|	fd||f          dt          j                    v st          j        |          rt          j        |          nddt          j                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          dz  }
dd|
iz  }t          t          j        |                    d x}	x}}|d         }d}||k    }|slt          j	        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}|d          }d!}||k    }|slt          j	        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}|d"         }d#}||k    }|slt          j	        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}d$ |d%         D             }	t!          |	          }|sd&d't          j                    v st          j        t                     rt          j        t                     nd't          j        |	          t          j        |          d(z  }t          t          j        |                    d x}	}d S ))Nr   r   rI   r   rJ   )33.00r   z34.00rh   r   r   r   r   z
2026-04-15z1.00r   )r%   r?   r   r   forecast_remaining_chfr   rY   )z0%(py0)s == %(py6)s
{%(py6)s = %(py2)s(%(py4)s)
}
reconciledr   r   r   r   covered_complete_month_count   r[   r\   r_   r`   confirmed_transaction_countr   excluded_transfer_countr   c              3     K   | ]}d |v V  	dS )	RecurringNrP   )rR   r   s     r   r   zWtest_explorer_explanation_reconciles_exactly_with_displayed_forecast.<locals>.<genexpr>0  s'      IIt{d"IIIIIIr   
exclusionsz,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}any)r   r   r^   )r   r&   r>   rF   r   r4   r
   r   rn   ro   r   r   r   rp   rq   rr   r  )r   r$   r%   r   r(   explanationr   r{   r   r   r~   r   rz   r|   r}   s                  r   Dtest_explorer_explanation_reconciles_exactly_with_displayed_forecastr	    s   44D,T22J|\:::D&;i#X#X"YZZZ"#>aHHH T TvT:{4JE4J4J4J4JFSSSSz;fEEE3+FF  K %>?@@7,-D D J "--@!AB!ABBB:BBBBBBBBBBB:BBBBBBBBBBBBB:BBBBB:BBBBBBBBBBBBBBBBBBBBBBBB!ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB56;!;6!;;;;;;;;;;6!;;;;;6;;;;!;;;;;;;;;;;;;;;;;;;;;;;;;;;45::5::::::::::5:::::5:::::::::::::::::::::::::::::::016Q61Q66666666661Q6666616666Q666666666666666666666666666II{</HIIII3IIIIIIIIIIIIIIII3IIIII3IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIr   )r   )r   r   )r!   )
r$   r   r%   r   r'   r   r(   r   r)   r   )r5   r   r6   r   r7   r8   )r?   r   r@   rA   )r7   r8   )-
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewritern   decimalr   r   fastapir   'jarvis_finance.services.budget_accountsr   )jarvis_finance.services.budget_categoriesr   &jarvis_finance.services.budget_importsr   'jarvis_finance.services.budget_planningr	   r
   +jarvis_finance.services.budget_transactionsr   *jarvis_finance.services.prior_year_actualsr   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r&   r4   r>   rF   r   r   r   r   r   r   r   r	  rP   r   r   <module>r     sW   " " " " " "                      ! ! ! ! ! ! Q Q Q Q Q Q M M M M M M X X X X X X        S R R R R R         
 ; : : : : : > > > > > >  	# 	# 	# 	# 	#$     0   @ @ @ @
-< -< -< -<`
 
 
 
"". ". ". ".JZ Z Z Z</ / / /9 9 9 9"#D #D #D #DLJ J J J J Jr   