
    nj#                       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$d*d Z%d*d!Z&d*d"Z'd*d#Z(d*d$Z)dS )+    )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   yearvalueslist[dict[str, str | None]]c                T    t          | ||d          }t          | |d                   S )N)r5   r6   payload)r   r   )r   r5   r6   previews       r   save_prior_yearr;   C   s.    (/O/OPPG%dGI,>???r   returnNonec                    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_chfz0.00r5   c                     i | ]}|d          |S r%    .0rows     r   
<dictcomp>z^test_prior_year_batch_keeps_blank_and_explicit_zero_distinct_and_auditable.<locals>.<dictcomp>X       @@@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 rE   rF   rG   s     r   rJ   z^test_prior_year_batch_keeps_blank_and_explicit_zero_distinct_and_auditable.<locals>.<dictcomp>p   rK   r   isz%(py1)s is %(py4)s)r   r&   r   r;   r   
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanationexecute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_auditablerv   H   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                 >   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            d S # 1 swxY w Y   d S )Nr5   r@   rO   rQ   rR   rU   rV   2024z240.00rA   rC   available_yearsinz%(py1)s in %(py4)sz	past year)match9999)r   r&   r   rd   re   rf   rg   rh   r;   pytestraisesr   )r   rk   r%   rq   rr   rs   rt   ru   s           r   Ftest_default_and_additional_past_years_work_but_future_year_is_blockedr   x   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 2 2 2s   3FFFc                    t                      } t          |           \  }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  }d.d/|iz  }t          t          j        |                    d x}x}	x}x}x}x}x}}|d0         }t          |d*                   t          d1          z  d2z                      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}
}	d3}|d4         }	||	v }
|
slt          j
        d5|
fd6||	f          t          j        |          t          j        |	          d!z  }d"d#|iz  }t          t          j        |                    d x}x}
}	d7}|d8         }	||	v}
|
slt          j
        d9|
fd:||	f          t          j        |          t          j        |	          d!z  }d"d#|iz  }t          t          j        |                    d x}x}
}	d S );Nr@   z2400.00rA   )100200300400r^   )start2026-02d-28
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)r5   current_monthcomparison_yearc              3  4   K   | ]}|d          k    |V  dS r%   NrF   rH   itemr%   s     r   	<genexpr>zTtest_forecast_uses_confirmed_actuals_plus_deterministic_rest_only.<locals>.<genexpr>   2      UU$}2E2T2Tt2T2T2T2TUUr   rL   z250.00z1050.00remaining_month_partscovered_complete_months)01020304rO   rQ   rR   rU   rV   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py2rT   rV   py8py10py11py13py15zassert %(py18)spy18deviation_percent2400d   zcomparison_year=2025data_explorer_urlrz   r|   Aboforecast_basis)not in)z%(py1)s not in %(py4)s)r   r&   r;   	enumerater4   r   r	   nextr   rd   re   rf   rg   rh   quantize@py_builtinslocals_should_repr_global_name)r   r$   monthr(   matrixrI   averageexpectedrq   rr   rs   rt   ru   @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           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-31rY   z
2026-02-15r   r   z2026-02r5   r   c              3  4   K   | ]}|d          k    |V  dS r   rF   r   s     r   r   z]test_forecast_is_missing_until_three_complete_months_and_never_zero_filled.<locals>.<genexpr>   r   r   rL   forecast_reliableFra   rc   rR   rU   rV   r   r   r   
evaluationu+   Vergleichswert für 2025 noch nicht erfasstrO   rQ   rZ   forecast_year_chf)
r   r&   r4   r	   r   rd   re   rf   rg   rh   )
r   r$   r   rI   rq   rr   rs   rt   ru   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            	     n   t                      } t          |           \  }}t          | ddd          d         }t          | d|dd|ddg           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!   r"   r    r@   1000.00rA   z3000.00r^      r   r   r   rY   z200.00z
2026-05-31r   r   r   rZ   r   r   r   r   r   rO   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py6)sr   expected_percentr   r   rT   rV   assert %(py8)sr   )r   r&   r   r;   ranger4   r	   r   r   rd   re   r   r   r   rf   rg   rh   )r   r$   rl   rm   r   r   rZ   r   r   rr   r   ru   @py_format9s                r   Atest_total_percent_comes_from_total_sums_not_category_percentagesr      s   44D&t,,J$zI>> F !;;")<<	
   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            	     &   t                      } t          |           \  }}t          | d|ddg           t          dd          D ]}t	          | ||d|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   rA   r^   r   r   r   r   rY   r   r   r   )r%   r5   r   r   forecast_remaining_chfr   rO   )z0%(py0)s == %(py6)s
{%(py6)s = %(py2)s(%(py4)s)
}
reconciledr   r   r   r   covered_complete_month_count   rQ   rR   rU   rV   confirmed_transaction_countexcluded_transfer_countr   c              3     K   | ]}d |v V  	dS )	RecurringNrF   )rH   r   s     r   r   zWtest_explorer_explanation_reconciles_exactly_with_displayed_forecast.<locals>.<genexpr>   s'      IIt{d"IIIIIIr   
exclusionsz,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}any)r   r   rT   )r   r&   r;   r   r4   r
   r   rd   re   r   r   r   rf   rg   rh   r   )r   r$   r%   r   explanationr   rr   r   r   ru   r   rq   rs   rt   s                 r   Dtest_explorer_explanation_reconciles_exactly_with_displayed_forecastr      s   44D,T22JD&;i#X#X"YZZZq! V VT:{4JE4J4J4J4JHUUUUz;gFFF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   r7   )r<   r=   )*
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriterd   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;   rv   r   r   r   r   r   rF   r   r   <module>r      s   " " " " " "                      ! ! ! ! ! ! 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@ @ @ @
-< -< -< -<`2 2 2 2!. !. !. !.H9 9 9 9"D D D D:J J J J J Jr   