
    t ojJ1                        d dl mZ d dl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mZmZmZ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 Z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)confirm_create_budget_account)confirm_create_category)%seed_credit_card_candidates_from_rows)confirm_annual_budget_planget_annual_budget_assistantget_budget_planning_matrixpreview_annual_budget_plan&preview_budget_planning_excel_template)calculate_annual_and_reserveconfirm_budget_transaction)connect_memory)apply_migrationsget_schema_versionc                 @    t                      } t          |            | S )N)r   r   )conns    *tests/unit/test_sprint17d_annual_budget.pydbr      s     DTK    c                    t          | dddd          d         }t          | ddd          d         }t          | d	d
d          d         }|||fS )NHaushaltcheckingCHF)nameaccount_typecurrency	entity_idWohnenexpense)r   category_typeLohnincome)r   r   )r   accountr    r#   s       r   setupr%      sr    +D:Waot2u2uvv  xC  DG%dXPY,Z,Z[[\ghG$TFX+V+VWWXcdFGV##r   r    
2026-05-12r$   strcategorypayeeamounttx_typedatec                6    t          | ||||||d|dd	          S )Nr   manual)	
account_idtransaction_typetransaction_datedescriptionr)   amount_originalcurrency_originalcategory_idsource_typer   )r   r$   r(   r)   r*   r+   r,   s          r   bookr7   $   sW    %d7X_uy  KP  [`  u{  RW  hp  AI  -J  -J  K  K  Kr   returnNonec                 B   t                      } t          |           dk    sJ d |                     d          D             }d |                     d          D             }h d|k    sJ h d|k    sJ |                     d                                          sJ d S )	N1   c                    h | ]
}|d          S r    .0rows     r   	<setcomp>zWtest_migration_49_is_additive_and_supports_immutable_budget_versions.<locals>.<setcomp>+   s    mmmVmmmr   z,PRAGMA table_info(budget_recurring_payments)c                    h | ]
}|d          S r=   r>   r?   s     r   rB   zWtest_migration_49_is_additive_and_supports_immutable_budget_versions.<locals>.<setcomp>,   s    ```CCK```r   z$PRAGMA table_info(budget_plan_items)>   data_versionplanning_typedue_months_jsonplanning_cadence>   	item_typemanual_overriderG   calculation_basiszQSELECT name FROM sqlite_master WHERE type='table' AND name='budget_plan_versions')r   r   executefetchone)r   recurring_columnsplan_columnss      r   Dtest_migration_49_is_additive_and_supports_immutable_budget_versionsrO   (   s    44Dd##r))))mm=k0l0lmmm``4<<8^+_+_```LSSSWhhhhhTTTXddddd<<klluuwwwwwwwr   c                     ddl m}  t           | d          d           | d           | d          fk    sJ t           | d          d           | d           | d	          fk    sJ d S )
Nr   Decimal1298.75	quarterly5195.00z432.9166666666666666666666667z120.00yearlyz10.00)decimalrR   r   rQ   s    r   Atest_quarterly_and_yearly_payments_are_never_multiplied_by_twelverX   2   s    '	(:(:KHHWWU^M_M_ahah  jI  bJ  bJ  MK  K  K  K  K'(9(98DDQYIZIZ\c\cdk\l\lHmmmmmmmr   c            
         t          t                      i           } | d         du sJ | d         du sJ | d         ddddd	d
dddk    sJ d | d         D             ddhk    sJ d S )Nproductive_mutationFconfirm_availablecontrolsz	114569.39z	148775.40z34206.01z2850.50rS   rU   z432.92z1984.67)annual_expenses_chfannual_income_chfannual_surplus_chfmonthly_surplus_chfmortgage_payment_chfmortgage_annual_chfmortgage_monthly_reserve_chfsource_monthly_rest_chfc                    h | ]
}|d          S )coder>   )r@   items     r   rB   z\test_xls_control_calculation_corrects_quarterly_mortgage_and_monthly_rest.<locals>.<setcomp>B   s    :::TDL:::r   	conflictsquarterly_as_monthlymonthly_rest_wrong)r   r   )previews    r   Itest_xls_control_calculation_corrects_quarterly_mortgage_and_monthly_restrl   8   s    4RTT2>>G()U2222&'50000:*( ))(0Y	# #     ;:W[%9:::?UWk>lllllllr   c            
        t                      } t          |           \  }}dd|ddg ddddd	d
g dddddddddgddddddg ddg}t          | d|d          }|d         ddddk    sJ t          | |d                   }|d          d!k    sJ t          | |d                   }|d"         |d"         k    sJ t	          j        t          j                  5  |                     d#|d"         f           d d d            n# 1 swxY w Y   |                     d$|d"         f          	                                }t	          j        t          j                  5  |                     d%|d&         f           d d d            n# 1 swxY w Y   t	          j        t          j                  5  |                     d'|d&         f           d d d            n# 1 swxY w Y   t	          j        t          j                  5  |                     d(|d"         f           d d d            n# 1 swxY w Y   t	          j        t          j                  5  |                     d)|d*         f           d d d            n# 1 swxY w Y   t          | ||d+ddd,-           t          | |dd	d./           t          | dd01          }|d2         d3         dk    sJ |d4         d5         dk    sJ |d6         d5         J |d6         d7         J t          | dd01          }	t          fd8|	d9         D                       }
|
d:         J |
d;         d<k    sJ |
d=                             d>          sJ t          |d?                   d@k    sJ |dA         g k    sJ dB|vsJ dC|vsJ |dD         g k    sJ |dE         dE         d0k    sJ |dF         i k    sJ d S )GNr"   r#   z10000.00monthlysafe)r   position_typer5   payment_amount_chfcadence
due_months	certaintyHypothek
fixed_costrS   rT   )      	      T)r   rp   r5   rq   rr   rs   rt   rI   Ferienone_time_seasonalz5000.00one_time   variableETFsavings_investmentz500.00)r   rp   rq   rr   rs   rt   2026)year	positionsreviewz	120000.00z16195.00z	103805.00)planned_income_chfplanned_expense_chfplanned_surplus_chfpayloadversion_number   r   zCUPDATE budget_plan_versions SET version_number=2 WHERE version_id=?zPSELECT version_item_id FROM budget_plan_version_items WHERE version_id=? LIMIT 1zKUPDATE budget_plan_version_items SET name='changed' WHERE version_item_id=?version_item_idz=DELETE FROM budget_plan_version_items WHERE version_item_id=?a  INSERT INTO budget_plan_version_items(
                 version_item_id,version_id,position_type,name,payment_amount_text,cadence,
                 due_months_json,annual_amount_text,monthly_reserve_text,calculation_basis,
                 certainty,manual_override,created_at)
               VALUES ('extra',?,'fixed_cost','extra','1.00','yearly','[]','1.00','0.08',
                       'not allowed','safe',0,'2026-01-01')z6UPDATE audit_log SET action='changed' WHERE audit_id=?audit_idArbeitgeberz
2026-01-25)r+   r,   z
2026-03-31r,   z2026-03r   current_monthplanr   actual
income_chfforecastexpense_chfc              3  4   K   | ]}|d          k    |V  dS )r5   Nr>   )r@   rA   r    s     r   	<genexpr>zctest_plan_actual_and_forecast_are_separate_and_confirm_creates_immutable_version.<locals>.<genexpr>x   s2      RR3C4F'4Q4Q34Q4Q4Q4QRRr   rowsforecast_display_chfbudget_year_chfz10195.00forecast_basisu   Noch nicht verlässlichsummary_kpisrw   planning_stepsmonthly_closeclosingoptimization_hintsmonthsections)r   r%   r
   r   pytestraisessqlite3IntegrityErrorrK   rL   r7   r   r	   next
startswithlen)r   r$   r#   r   rk   resultagainversion_item	assistantmatrixhousingr    s              @r   Ptest_plan_actual_and_forecast_are_separate_and_confirm_creates_immutable_versionr   E   s   44D$T{{GWf(6ak  yB  RT  ci  	j  	jl7js  AL  \i  \i  \i  x~  SW  	X  	X,?PWox  FP  ab  `c  r|  	}  	})=U]js  DF  U[  	\  	\	I )Y/W/WXXG8{[e  J  !K  !K  K  K  K  K'gi.@AAF"#q((((&tWY-?@@E!44444	w-	.	. t tZ]cdo]p\rssst t t t t t t t t t t t t t t<<Z		  hjj  
w-	.	. 
 
Y+,.	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
w-	.	. 
 
K+,.	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
w-	.	. 	
 	
? K "	
 	
 	
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 
w-	.	. f fMPVWaPbOdeeef f f f f f f f f f f f f f fwz8R^____wY\JJJJ+DvYWWWIV12kAAAAX|,
::::Z .666Z /777'6SSSFRRRR&.RRRRRG)*222$%3333#$//0IJJJJJy())Q....%&",,,,)++++I%%%%)*b0000Wg&)3333Z B&&&&&&sZ   DDDF		FF2GG #G H//H36H3JJ	Jc            	        t                      } t          |           \  }}}t          d          D ]}t          | ||dd           t          d          D ]}t          | ||ddd           |                     d	           |                     d
           |                     d           |                     dd           |                                  t          | d|ddd           t          | ddddgdd           |                     d                                          }|                     d|d         f           |                                  t          | dd          }|d         d          g k    sJ |d         d!         d"k    sJ |d         d#         du sJ |d$         d%         J |d$         d&         J |d$         d'         du sJ d S )(Nrw   Applez20.00   Netflixz22.90z
2026-05-09r   zINSERT INTO platforms(platform_id,name,platform_type,created_at) VALUES ('synthetic-card-platform','Synthetic','bank','2026-01-01')a
  INSERT INTO accounts(
             account_id,platform_id,account_name,account_type,currency,portfolio_bucket,created_at)
           VALUES ('synthetic-card','synthetic-card-platform','Synthetic card','credit_card',
                   'CHF','liability','2026-01-01')a  INSERT INTO budget_accounts(
             budget_account_id,linked_account_id,name,account_type,currency,created_at,updated_at)
           VALUES ('synthetic-card','synthetic-card','Synthetic card','credit_card','CHF',
                   '2026-01-01','2026-01-01')a  INSERT INTO household_account_source_mappings(
             mapping_id,contract_version,source_type,source_reference_hash,budget_account_id,
             canonical_account_id,reference_hint,is_active,created_at,updated_at)
           VALUES ('synthetic-card-map','household_import_v1','visa_credit_card',?,
                   'synthetic-card','synthetic-card','synthetic',1,'2026-01-01','2026-01-01'))@1111111111111111111111111111111111111111111111111111111111111111zsynthetic-cardzCard purchasesz4348.40z
2026-07-10z
2026-07-20zVISECA Zahlungz-3238.20)DatumBeschreibungBetragzcard.csvF)source_file_labelmigros_coveredzsSELECT transaction_candidate_id FROM budget_transaction_candidates WHERE lower(description) LIKE '%viseca%' LIMIT 1zUPDATE budget_transaction_candidates SET classification='credit_card_payment',status='needs_review',merchant='VISECA' WHERE transaction_candidate_id=?transaction_candidate_idr   2026-05r   coveragegapsstatuspartialfree_investable_availabler   free_plannable_chfr   is_estimate)	r   r%   ranger7   rK   commitr   rL   r   )r   r$   r    _income_	candidater   s          r   9test_recurring_hints_do_not_block_the_household_year_restr      s   44D %dGWg1XX 7 7T7GWg66661XX L LT7GYlKKKKKLL	M   	LL	6   	LL	1   	LL	a
 	   	KKMMM*:ILYYYY)$<Yiu  2A  2A  1B  V`  qv  w  w  w  w  S  T  T  ]  ]  _  _ILL  j  mv  wQ  mR  lT  U  U  UKKMMM+DvYWWWIZ (B....Z *i7777Z !<=FFFFZ !56>>>Z /777Z /5888888r   c                 &   t                      } t          |           \  }}}t          dd          D ]}t          | ||ddd|dd           t	          | |d	d
dddddd           t          | dd          }|d         d         du sJ |d         d         J |d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ |d         d         dd dd!gk    sJ |d"         d#         d$         d%         dk    sJ d S )&Nr   r   Categorizedz50.00z2026-02dz-20r   r    z
2026-04-10Uncategorizedz100.00r   r.   )r/   r0   r1   r2   r)   r3   r4   r6   r   z2026-04r   r   reliableFr   r   r   r   quality_label	teilweisecategory_coverage_percentz60.00r    uncategorized_confirmed_expensesuG   Bestätigte Ausgaben sind noch keiner kanonischen Kategorie zugeordnet.)rf   message
amount_chfdata_qualitymaterial_gapsr   rf   )r   r%   r   r7   r   r   )r   r$   r    r   r   r   s         r   Btest_uncategorized_confirmed_expense_is_reported_as_a_coverage_gapr      s   44D %dGWgq! Z ZT7G]GBX%BXBXBXBXYYYYY! ) ,*$'!&#		
 		
   ,DvYWWWIZ ,5555Z /777Z *i7777Z 1[@@@@Z !<=HHHHZ (6`"	
 	
-     ^$_5a8@Dfffffffr   c                 P   t                      } t          |           \  }}}|                     d||f           |                                  t	          | dd          }|d         d         du sJ |d         d         J |d	         d
         dk    sJ |d	         d         sJ d S )Nu  INSERT INTO budget_transactions(
             budget_transaction_id,account_id,category_id,transaction_date,transaction_type,
             description,amount_original,currency_original,amount_chf,fx_status,status,source_type,
             created_at,updated_at)
           VALUES ('missing-fx',?,?, '2026-05-12','expense','Fremdwährung ohne CHF',
                   '500.00','USD',NULL,'missing','confirmed','import_candidate',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)r   r   r   r   r   Fr   r   labelu#   Noch nicht verlässlich berechenbarr   )r   r%   rK   r   r   )r   r$   r    r   r   s        r   ?test_material_chf_import_gap_returns_understandable_uncertaintyr      s    44D %dGWgLL	x 
'   	KKMMM+DvYWWWIZ ,5555Z !56>>>^$W-1VVVVV^$_555555r   )r    r&   )r$   r'   r(   r'   r)   r'   r*   r'   r+   r'   r,   r'   )r8   r9   )#
__future__r   r   r   'jarvis_finance.services.budget_accountsr   )jarvis_finance.services.budget_categoriesr   &jarvis_finance.services.budget_importsr   'jarvis_finance.services.budget_planningr   r   r	   r
   r   (jarvis_finance.services.budget_recurringr   +jarvis_finance.services.budget_transactionsr   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r   r%   r7   rO   rX   rl   r   r   r   r   r>   r   r   <module>r      s   " " " " " "   Q Q Q Q Q Q M M M M M M X X X X X X              R Q Q Q Q Q R R R R R R : : : : : : R R R R R R R R  $ $ $K K K K Kx x x xn n n n
m 
m 
m 
m=' =' =' ='@+9 +9 +9 +9\!g !g !g !gH6 6 6 6 6 6r   