
    aj:                        d dl mZ d dlZd dlmc m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 d dlmZmZ d d	lmZ d d
lmZ d Zd ZddZddZddZddZdS )    )annotationsN)confirm_create_budget_account)confirm_create_category)confirm_budget_plan_item)confirm_budget_transaction)get_budget_status_by_category)get_budget_dashboard_cockpitget_budget_vs_actual_analysis)connect_memory)apply_migrationsc                 @    t                      } t          |            | S )N)r   r   )conns    k/home/agent/.hermes/worktrees/FinanceManager-test-baseline/tests/unit/test_budget_analytics_dashboard_v2.pydbr      s     DTK    c           
     t   t          | dddd          d         }t          | dddd	d
d          d         }t          | dddddd          d         }t          | dddddd          d         }t          | d|ddddd           t          | d|ddddd           t          | d|ddddd           ||||fS )NHaushaltcheckingCHF)nameaccount_typecurrency	entity_idEssen & Haushaltexpensez#22c55ebasket
   )r   category_typecoloricon
sort_orderzGesundheit / Medizinz#ef4444heart   zLohn Marcelincomez#38bdf8wallet   z	Food Planz2026-01100.00monthlymanual)r   category_id
plan_monthmonthly_amount_chfcadencesource_typezHealth Planz50.00zSalary Plan300.00)r   r   r   r   accountfoodhealthsalarys        r   seed_budgetr5      s   +D:Waot2u2uvv  xC  DG"42DW`kt  G  WY  *Z  *Z  [  [  \g  hD$T4J]fqz  EL  \^  ,_  ,_  `  `  al  mF$TMT\gp  {C  ST  ,U  ,U  V  V  Wb  cFTK\e  ~F  S\  mu  $v  $v  w  w  wTM&`i  BI  V_  px  $y  $y  z  z  zTM&`i  BJ  W`  qy  $z  $z  {  {  {D&&((r   r1   strr2   r3   r4   returnNonec                   t          | |ddddd|d           t          | |ddd	d	d
d|d           t          | |dddddd|d           t          | |ddddd|d           t          | |ddddd|d           |                     d|f           |                     d|f           |                     d|f           |                                  d S )Nr$   z
2026-05-25Lohnr/   r   )
account_idtransaction_typetransaction_datedescriptionamount_originalcurrency_originalr*   r   z
2026-05-03Migros120.00)r;   r<   r=   r>   payeer?   r@   r*   z
2026-05-10Apothekez40.00z
2026-02-10z
Migros Febz80.00z
2025-05-10Altjahr999.00a  INSERT INTO budget_transactions(budget_transaction_id, account_id, category_id, transaction_date, transaction_type, description, amount_original, currency_original, amount_chf, fx_status, source_type, status, created_at, updated_at) VALUES ('tx_transfer', ?, NULL, '2026-05-11', 'transfer', 'Umbuchung', '777.00', 'CHF', '777.00', 'not_needed', 'manual', 'confirmed', '2026', '2026')aP  INSERT INTO budget_transaction_candidates(transaction_candidate_id, source_type, source_file_label, transaction_date, description, merchant, amount_original, currency_original, proposed_category_id, status, created_at, updated_at) VALUES ('cand_open','csv','x','2026-05-12','Candidate','Migros','888.00','CHF',?,'pending','2026','2026')ab  INSERT INTO budget_transaction_candidates(transaction_candidate_id, source_type, source_file_label, transaction_date, description, merchant, amount_original, currency_original, proposed_category_id, status, created_at, updated_at) VALUES ('cand_covered','csv','x','2026-05-13','Covered Migros','Migros','999.00','CHF',?,'covered_by_migros','2026','2026'))r   executecommitr0   s        r   seed_transactionsrI      s   tGQYo{  MS  hp  GL  ]c  &d  &d  e  e  etGQZp|  NV  ai  ~F  ]b  sw  &x  &x  y  y  ytGQZp|  NX  cm  BI  `e  v|  &}  &}  ~  ~  ~tGQZp|  NZ  ov  MR  cg  &h  &h  i  i  itGQZp|  NW  lt  KP  ae  &f  &f  g  g  gLL  S  V]  U_  `  `  `LL  d  gk  fm  n  n  nLL  v  y}  x  @  @  @KKMMMMMr   c                H   t                      }t          |          \  }}}}t          |||||           t          |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         }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}	}d |f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         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:d"d#t	          j        |          iz  }t          t	          j        |                    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 )&N2026-05)monthpurposemonthly_cockpit==z%(py1)s == %(py4)spy1py4assert %(py6)spy6rL   kpisincome_current_month_chfr/   expense_current_month_chfz160.00net_cashflow_current_month_chf140.00budget_consumption_percentz106.67savings_rate_percentz46.67
open_todosreview_candidatesr&   c              3  |   K   | ]7}d t          |          vo!dt          |          vodt          |          vV  8dS )888.00rF   777.00N)r6   ).0sections     r   	<genexpr>zftest_budget_dashboard_cockpit_is_monthly_and_excludes_candidates_transfers_and_2025.<locals>.<genexpr>:   sk        G  Gryxs7||+mG0LmQYadelamamQm  G  G  G  G  G  Gr   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}all)py0py2rT   top_expense_categoriesr   categoryr   critical_categoriesassert %(py1)srS   monthly_cashflow
income_chf)r   r5   rI   r	   
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanationrf   @py_builtinslocals_should_repr_global_name)budget_reference_dater   r1   r2   r3   r4   result@py_assert0@py_assert3@py_assert2@py_format5@py_format7@py_assert1@py_format2s                 r   Stest_budget_dashboard_cockpit_is_monthly_and_excludes_candidates_transfers_and_2025r   +   s    44D$/$5$5!GT66dGT66:::)$i@@@F)1 11 11111111111 1111111111 1111111111111111111111111111'?'i'?i''''''''''?i'''''?''''i'''''''''''''''''''''''''''&>45AA5AAAAAAAAAA5AAAAA5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&>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&>:;GxG;xGGGGGGGGGG;xGGGGG;GGGGxGGGGGGGGGGGGGGGGGGGGGGGGGGG&>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&>01<W<1W<<<<<<<<<<1W<<<<<1<<<<W<<<<<<<<<<<<<<<<<<<<<<<<<<<, 3499499999999994999994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 G  G  E  ~F  G  G  G  G3  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G3  G  G  G  G  G3  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G*+A.z:P>PP:>PPPPPPPPPPP:>PPPPPP:PPPP>PPPPPPPPPPPPPPPPPPPPPPPPPPPP'((((((((((((((((((((((((($%l3?x?3x??????????3x?????3????x?????????????????????????????r   c                   t                      }t          |          \  }}}t          ||||           t          |d          }t	          f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         }t          |          }d}||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        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}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}t          |          }||v}	|	st          j        d|	fd||f          t          j        |          dt          j                    v st          j        t                    rt          j        t                    ndd t          j                    v st          j        |          rt          j        |          nd t          j        |          d!z  }d"d#|iz  }t          t          j	        |                    d x}x}	}d S )$N2026yearc              3  4   K   | ]}|d          k    |V  dS )r*   N )rc   rr2   s     r   re   z_test_budget_status_rows_are_operational_category_control_with_monthly_detail.<locals>.<genexpr>G   s2      @@!q'74'?'?A'?'?'?'?@@r   rM   category_controlrO   rQ   rR   rU   rV   budget_monthr'   budget_yearz1200.00actual_current_monthrB   actual_year_to_datez200.00monthly_analysis   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)slen)rg   rh   rT   py7zassert %(py9)spy9   
actual_chfrF   not inz4%(py1)s not in %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}r6   food_rowrS   py3rT   rV   assert %(py8)spy8)r   r5   rI   r   nextro   rp   rq   rr   rs   r   rt   ru   rv   r6   )rw   r   r1   r3   r4   rowsr   ry   rz   r{   r|   r}   r~   @py_assert6@py_assert5@py_format8@py_format10@py_format9r2   s                     @r   Ltest_budget_status_rows_are_operational_category_control_with_monthly_detailr   @   s    44D$/$5$5!GT66dGT66:::(F;;;D@@@@t@@@@@HI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4444N#/x/#x//////////#x/////#////x///////////////////////////M"/i/"i//////////"i/////"////i///////////////////////////*+7x7+x7777777777+x77777+7777x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)*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*+23+,,22,2222222222,2222222222223222223222222+2222,222222222222222222222222222222222&'*<8DHD8HDDDDDDDDDD8HDDDDD8DDDDHDDDDDDDDDDDDDDDDDDDDDDDDDDD(3x==(8=((((((((((8=(((((8(((((((((((3(((((3(((((((((((((x(((((x((((((=(((((((((((((((((((((((((((((r   c                4   t                      }t          |          \  }}}}t          |||||           t          |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}||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:ddt	          j        |          iz  }t          t	          j        |                    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         }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         }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         }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          }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          |          }||v}	|	st	          j        d#|	fd$||f          t	          j        |          d%t          j                    v st	          j        t                    rt	          j        t                    nd%d&t          j                    v st	          j        |          rt	          j        |          nd&t	          j        |          d'z  }d(d)|iz  }t          t	          j        |                    d x}x}	}d*}t          |          }||v}	|	st	          j        d#|	fd$||f          t	          j        |          d%t          j                    v st	          j        t                    rt	          j        t                    nd%d&t          j                    v st	          j        |          rt	          j        |          nd&t	          j        |          d'z  }d(d)|iz  }t          t	          j        |                    d x}x}	}d+}t          |          }||v}	|	st	          j        d#|	fd$||f          t	          j        |          d%t          j                    v st	          j        t                    rt	          j        t                    nd%d&t          j                    v st	          j        |          rt	          j        |          nd&t	          j        |          d'z  }d(d)|iz  }t          t	          j        |                    d x}x}	}d S ),Nr   r   rM   plan_vs_reality_analysisrO   rQ   rR   rU   rV   r   chart_libraryz
native-svgempty_stateF)is)z%(py1)s is %(py4)sbudget_vs_actual_by_categoryrl   rS   top_overrunsr   rj   r   cashflow_by_monthr   rL   rK   net_cashflow_chfr[   category_donuttrend_by_monthcumulative_net_chfz60.00rb   r   r   r6   rx   r   r   r   ra   rF   )r   r5   rI   r
   ro   rp   rq   rr   rs   r6   rt   ru   rv   )rw   r   r1   r2   r3   r4   rx   ry   rz   r{   r|   r}   r   r   r   s                  r   :test_budget_vs_actual_analysis_is_separate_chart_viewmodelr   R   s"
   44D$/$5$5!GT66dGT66:::*4f===F): :: ::::::::::: :::::::::: ::::::::::::::::::::::::::::&>#V#>V##########>V#####>####V###########################/"2l2"l2222222222"l22222"2222l222222222222222222222222222- )E) E)))))))))) E))))) ))))E)))))))))))))))))))))))))))01111111111111111111111111.!!$Z0F4FF04FFFFFFFFFFF04FFFFFF0FFFF4FFFFFFFFFFFFFFFFFFFFFFFFFFFF%&q)'2?i?2i??????????2i?????2????i???????????????????????????%&q)*<=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IIIIIIIIIIIIIIII"#A&z2H6HH26HHHHHHHHHHH26HHHHHH2HHHH6HHHHHHHHHHHHHHHHHHHHHHHHHHHH"#A&';<GG<GGGGGGGGGG<GGGGG<GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG&3v;;&8;&&&&&&&&&&8;&&&&&8&&&&&&&&&&&3&&&&&3&&&&&&&&&&&&&v&&&&&v&&&&&&;&&&&&&&&&&&&&&&&&&&&&&&&&&&&3v;;&8;&&&&&&&&&&8;&&&&&8&&&&&&&&&&&3&&&&&3&&&&&&&&&&&&&v&&&&&v&&&&&&;&&&&&&&&&&&&&&&&&&&&&&&&&&&&3v;;&8;&&&&&&&&&&8;&&&&&8&&&&&&&&&&&3&&&&&3&&&&&&&&&&&&&v&&&&&v&&&&&&;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&r   )
r1   r6   r2   r6   r3   r6   r4   r6   r7   r8   )r7   r8   )
__future__r   builtinsrt   _pytest.assertion.rewrite	assertionrewritero   'jarvis_finance.services.budget_accountsr   )jarvis_finance.services.budget_categoriesr   $jarvis_finance.services.budget_plansr   +jarvis_finance.services.budget_transactionsr   'jarvis_finance.services.budget_overviewr   +jarvis_finance.services.budget_analytics_v2r	   r
   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r5   rI   r   r   r   r   r   r   <module>r      sD   " " " " " "               Q Q Q Q Q Q M M M M M M I I I I I I R R R R R R Q Q Q Q Q Q s s s s s s s s : : : : : : > > > > > >  ) ) )
 
 
 
@ @ @ @*) ) ) )$' ' ' ' ' 'r   