
    Yaj02                       d dl 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mZmZmZ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mZ d Zd Z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dZ&ddZ'ddZ(dS )    )annotations)dateN)HTTPException)confirm_create_budget_account)confirm_create_category)	archive_recurring_payment confirm_manual_recurring_payment"confirm_recurring_candidate_action#detect_recurring_payment_candidatesget_recurring_dashboardlist_recurring_warningsnext_expected_date preview_manual_recurring_payment"preview_recurring_candidate_actionconfirm_budget_transaction)connect_memory)apply_migrationsget_schema_versionc                 @    t                      } t          |            | S )N)r   r   )conns    /tests/unit/test_fixed_costs_subscriptions_v1.pydbr      s    D-d333D[    c                    t          | dddd          d         }t          | 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_idzElektronische Medienexpense)r   category_typezEssen & HaushaltVersicherungen)r   r   )r   
account_idmediafood	insurances        r   setupr*      s    .tjZdrw5x5xyy  {F  GJ#D3I\e*f*fgghstE"42DW`)a)abbcnoD'7GZc.d.deefqrIudI--r   r#   c                D    t          | ||||p|||d|d          d         S )Nr   )r&   transaction_typetransaction_datedescriptionpayeeamount_originalcurrency_originalcategory_idr"   r   )r   r&   r2   merchantamountdaydesctx_types           r   txr8   &   sk    %d:[bx{  MQ  M]  U]  hp  EK  bg  xC  -D  -D  E  E  FQ  R  Rr   pendingc                v    |                      dd| d|                     dd          |||||||f           d S )Na  
        INSERT INTO budget_transaction_candidates(transaction_candidate_id, source_file_label, source_type, transaction_date, description, merchant, amount_original, currency_original, proposed_category_id, confidence, requires_review, status, classification, created_at)
        VALUES (?, 'test.csv', 'csv_seed', ?, ?, ?, ?, 'CHF', ?, '0.80', 1, ?, ?, '2026-01-01T00:00:00Z')
    cand__ )executereplace)r   r2   r3   r4   r5   statusclassifications          r   	candidaterB   *   se    LL  #(
"
"S
"
"
*
*3
4
4c8XvWbdjlz	{} } } } }r   returnNonec                    t                      } t          |           dk    sJ d |                     d                                          D             }|d                                         dk    sJ |d                                         dk    sJ |d                                         dk    sJ |d                                         dk    sJ |d	                                         dk    sJ |d
                                         dk    sJ d|                     d                                          d         v sJ d S )N&   c                ,    i | ]}|d          |d         S )r   type .0rs     r   
<dictcomp>z_test_schema_38_creates_decimal_text_recurring_table_with_user_facing_fields.<locals>.<dictcomp>4   s"    rrrQAfIqyrrrr   z,PRAGMA table_info(budget_recurring_payments)expected_amount_textTEXTamount_tolerance_pcttolerance_percenttolerance_amount_textmerchant_namerecurring_typeignoredzUSELECT sql FROM sqlite_master WHERE type='table' AND name='budget_recurring_payments'sql)r   r   r>   fetchallupperfetchone)r   colss     r   Ktest_schema_38_creates_decimal_text_recurring_table_with_user_facing_fieldsr[   1   s|   44Dd##r))))rr$,,7e*f*f*o*o*q*qrrrD&'--//69999&'--//69999#$**,,6666'(..00F:::: &&((F2222 !''))V3333%|}}  G  G  I  I  JO  P  P  P  P  P  P  Pr   c            	        t                      } t          |           \  }}}}dD ]}t          | ||dd|           dD ]}t          | ||dd|           dD ]}t          | ||dd	|           d
D ]}t          | ||dd|           t          | ||dddd           t          | |ddd           t	          | d          }d |d         D             }|d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ d|vsJ d|vsJ d|vsJ d S ) Nz
2026-01-05
2026-02-05
2026-03-05Netflix19.90)z
2025-03-01
2026-03-01zHouse Insurancez1200.00)z
2026-01-15z
2026-04-15z
2026-07-15zMusic Schoolz300.00)
2026-01-03z
2026-02-03z
2026-03-03Migrosz150.00zTrue Wealthz500.00
2026-01-10zInvestment Transfer)r6   OpenAI20.00
2026-04-05z
2026-08-01todayc                     i | ]}|d          |S r   rI   rK   cs     r   rM   ztest_detection_finds_monthly_subscription_yearly_insurance_quarterly_payment_and_excludes_migros_transfer_investment.<locals>.<dictcomp>H       888aQvY888r   
candidates	frequencymonthlyrT   subscriptionyearly
fixed_cost	quarterly)r   r*   r8   rB   r   )r   accountr'   r(   r)   dresultnamess           r   ttest_detection_finds_monthly_subscription_yearly_insurance_quarterly_payment_and_excludes_migros_transfer_investmentr{   >   s   44D5;;0%y7hhD'5R[]dfg9h9h9h9h)hh2dGYHY[dfg+h+h+h+h7nnD'5R`bjlm9n9n9n9n7ggD'4QY[cef9g9g9g9gtWi,MbccccdE8Wl;;;0\JJJF886,#7888EK(I5555,-????"#K0H<<<<"#$45EEEE -<<<<5    5    %%%%%%r   c            	        t                      } t          |           \  }}}}dD ]}t          | ||dd|           t          | d          }d |d         D             }|d         d         d	k    sJ |d         d
         dk    sJ |                     d                                          }|d         dk    sJ |                     d                                          d         dk    sJ d S )N)rc   z
2026-02-20z
2026-04-11zOpenAI ChatGPTrg   z
2026-05-01ri   c                     i | ]}|d          |S rl   rI   rm   s     r   rM   zatest_detection_finds_irregular_recurring_candidate_but_does_not_auto_activate.<locals>.<dictcomp>Z   ro   r   rp   rq   	irregularrT   rs   zHSELECT status FROM budget_recurring_payments WHERE name='OpenAI ChatGPT'r@   rB   zNSELECT COUNT(*) FROM budget_transactions WHERE source_type='recurring_payment'r   )r   r*   r8   r   r>   rY   )	r   rw   r'   _food
_insurancerx   ry   rz   rows	            r   Mtest_detection_finds_irregular_recurring_candidate_but_does_not_auto_activater   T   s   44DU4[[2%
7 ? ?
4%!17A>>>>0\JJJF886,#7888E!";/;>>>>!"#34FFFF
,,a
b
b
k
k
m
mCx=K''''<<hiirrttuvw{|||||||r   c            	         t                      } t          |           \  }}}}dD ]}t          | ||dd|           t          | d          }|d         g k    sJ |                     d                                          d         dk    sJ d S )	Nr]   r`   ra   
2026-04-01ri   rp   z.SELECT COUNT(*) FROM budget_recurring_paymentsr   )r   r*   r8   r   r>   rY   )r   rw   r'   r   r   rx   	dashboards          r   @test_dashboard_read_does_not_silently_create_detected_candidatesr   c   s    44DU4[[2%
7 8 8
4%GQ7777'LAAAI\"b((((<<HIIRRTTUVW[\\\\\\\r   c            
        t                      } t          |           \  }}}}dD ]}t          | ||dd|           t          | d          d         d         }t	          | |d         d	d
d          }|d         du sJ t          | |d                   }|d         dk    sJ t          | d          d         }	|	d         d         dk    sJ |	d         d         dk    sJ |	d         d         dk    sJ |                     d                                          d         dk    sJ t          | d|ddd
dd          }
t          | |
d                   }|d         dk    sJ t          | |d         ddi          d         d k    sJ t	          | |d         d!d"i          }t          | |d                   }|d         d#k    sJ d S )$Nr]   r`   ra   r   ri   rp   r   candidate_idactivaters   actionrT   requires_explicit_confirmTpayloadr@   	confirmedz
2026-04-10activebudget_month_chfbudget_year_chfz238.80>SELECT COUNT(*) FROM audit_log WHERE action LIKE 'recurring_%'   z
Manual Aboz10.00rr      r   r2   rN   rq   rT   expected_day_of_monthr"   notesz
not neededarchivedr   ignorerU   )r   r*   r8   r   r   r
   r   r>   rY   r   r	   r   )r   rw   r'   r   r   rx   candpreviewry   r   manual_previewmanualignored_previewrU   s                 r   4test_review_activate_ignore_manual_archive_and_auditr   n   sS   44DU4[[2%
7hhD'5R[]dfg9h9h9h9h.t<HHHVWXYD0tN7KXb  wE  NF  NF  G  GG./47777/gi6HIIF({****$T>>>xHF!9X(****!9'(G3333!9&'83333<<XYYbbddefgklllll5d\bg  BI  Xa  uC  ^_  =`  =`  a  aN-dN94MNNF({****$T6++>,@WXXYabfppppp8tN?SV^`hUijjO0y7QRRG8	))))))r   c            
     \   t                      } t          |           \  }}}}dD ]}t          | ||dd|           t          | d          d         d         }t	          | |d         d	d
d          }t          | |d                    t	          | |d         ddddd
d          }t          | |d                   }	|	d         dk    sJ |                     d|d         f                                          }
|
d         dk    sJ |
d         dk    sJ t	          | |d         ddi          }t          | |d                   }|d         dk    sJ t          | |d         ddi          }|d         dk    sJ |                     d                                          d         dk    sJ d S )Nr]   r`   ra   r   ri   rp   r   r   r   rs   r   r   editzNetflix Premiumz21.90rr   )r   r   rN   rq   rT   r@   r   zUSELECT name, expected_amount_text FROM budget_recurring_payments WHERE recurring_id=?r   rN   r   pausepausedr   doner   r      )	r   r*   r8   r   r   r
   r>   rY   r   )r   rw   r'   r   r   rx   r   r   edit_previeweditedr   pause_previewr   r   s                 r   Etest_confirmed_candidate_can_be_edited_paused_and_archived_with_auditr      s;   44DU4[[2%
7hhD'5R[]dfg9h9h9h9h.t<HHHVWXYD0tN7KXb  wE  NF  NF  G  GG&tWY-?@@@5dD<P]cm~  Y`  ox  LZ  S[  S[  \  \L/l96MNNF({****
,,nqu  wE  rF  qH  I  I  R  R  T  TCv;+++++%&'11116tT.=QT\^eSfggM/mI6NOOF(x''''(tN/CgvEVWWHH++++<<XYYbbddefgklllllllr   c                 @   t                      } t          |           \  }}}}t          | d|ddddddd          }t          | |d	                   d
         }t	          | ||ddd           t          | d|ddddd          }t          | |d	                    dD ]}t	          | ||dd|           t          | d           t          | d          }	d |	D             }
d|
v sJ d|
v sJ d|
v sJ d|
v sJ t          t          ddd          dd          dk    sJ d S )Nr`   ra   rr   rs      5   )r   r2   rN   rq   rT   r   rP   date_tolerance_daysr   r"   z25.00r_   zNet flixr   )re   z
2026-02-10z
2026-03-10Spotifyz12.00r   ri   z
2026-05-20c                    h | ]
}|d          S )r@   rI   )rK   ws     r   	<setcomp>zRtest_warnings_missing_amount_changed_and_duplicate_subscription.<locals>.<setcomp>   s    ...(...r   missingamount_changednew_candidatepossible_duplicate_subscriptioni  rh   )	r   r*   r   r	   r8   r   r   r   r   )r   rw   r'   r   r   r   recurring_idpreview2rx   warningsstatusess              r   ?test_warnings_missing_amount_changed_and_duplicate_subscriptionr      s   44DU4[[2%
.tiX]w~  NW  ky  TU  or  KL  6M  6M  N  NG3D'):LMMkZLtWeY>>>/zZ_  zA  PY  m{  VW  7X  7X  Y  YH$T8I+>???7hhD'5R[]dfg9h9h9h9h'LAAAA&t<@@@H..X...H    x''''h&&&&,8888d4A..	1==MMMMMMr   c            
        t                      } t          |           \  }}}t          | dddddd          }t          | |d                    t	          | |ddd           t          | d	
          }|d         d         J |d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ |d         d         dk    sJ |d         d         d         d         dk    sJ |d         d         d         dk    sJ ddlm} t          fd || dd          d         D                       }|d         dk    sJ d|v sJ dd l	m
}  || dd!          }	|	d"         d#         dk    sJ t          d$ |	d%         D                       sJ dd&lm}
  |
| d'          }|d(         dk    sJ |d)         dk    sJ d*|v sJ d S )+Nr`   rg   rr   rs   r   r   r   r^   rb   ri   	analyticsfixed_cost_quote_percentsubscriptions_year_chfz240.00kpismonthly_fixed_costs_chfannual_fixed_costs_chfactive_recurring_countr   open_candidate_countr   largest_fixed_costsr   category_breakdownknown_recurring_month_chf)get_budget_planning_matrixc              3  4   K   | ]}|d          k    |V  dS )r2   NrI   )rK   rL   r'   s     r   	<genexpr>zVtest_integrations_dashboard_budgetplanning_and_data_explorer_fields.<locals>.<genexpr>   s]        G  GQlmn{l|  AF  mF  mFq  mF  mF  mF  mF  G  Gr   2026z2026-02)yearcurrent_monthrows)get_budget_data_explorer)r   rT   filtersrT   c              3  .   K   | ]}|d          dk    V  dS )rT   rs   NrI   rJ   s     r   r   zVtest_integrations_dashboard_budgetplanning_and_data_explorer_fields.<locals>.<genexpr>   s-      WWq!"n4WWWWWWr   transactions)get_budget_overview)monthfixed_costs_month_chfopen_fixed_cost_candidate_count missing_fixed_cost_payment_count)r   r*   r   r	   r8   r   'jarvis_finance.services.budget_planningr   next,jarvis_finance.services.budget_data_explorerr   all'jarvis_finance.services.budget_overviewr   )r   rw   r   r   r   dashr   r   r   explorerr   overviewr'   s               @r   Ctest_integrations_dashboard_budgetplanning_and_data_explorer_fieldsr      s   44DU4[[2%
.tiX]w~  NW  ky  TU  6V  6V  W  WG$T79+=>>>tWeY>>>"4|<<<D78DDD56(BBBB<12g====<01X====<01Q6666<./14444<-.q1&9YFFFF$%a()DEPPPPRRRRRR
  G  G  G  G44TV_```agh  G  G  G  G  GC*+w6666%,,,,UUUUUU''6.YYYHI/0NBBBBWWh~>VWWWWWWWWKKKKKK""4y999H+,777756!;;;;-999999r   c            
         t                      } t          |           \  }}}}t          j        t                    5  t          | d|dddd           d d d            d S # 1 swxY w Y   d S )NBadz-1rr   rs   )r   r2   rN   rq   rT   )r   r*   pytestraisesr   r   )r   _accountr'   r   r   s        r   ,test_invalid_manual_recurring_values_blockedr      s    44DeDkk35%	}	%	% n n(emq  AJ  ^l  0m  0m  	n  	n  	nn n n n n n n n n n n n n n n n n ns   A  A$'A$)Nr#   )r9   N)rC   rD   ))
__future__r   datetimer   r   fastapir   'jarvis_finance.services.budget_accountsr   )jarvis_finance.services.budget_categoriesr   (jarvis_finance.services.budget_recurringr   r	   r
   r   r   r   r   r   r   +jarvis_finance.services.budget_transactionsr   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r   r*   r8   rB   r[   r{   r   r   r   r   r   r   r   rI   r   r   <module>r      s?   " " " " " "        ! ! ! ! ! ! Q Q Q Q Q Q M M M M M M
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 S R R R R R : : : : : : R R R R R R R RA A A. . .R R R R} } } }
P 
P 
P 
P& & & &,} } } }] ] ] ]* * * *2m m m m,N N N N&: : : :@n n n n n nr   