
    (\je                        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 d dlmZ d d	lm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dZddZddZddZy)    )annotations)IteratorN)Decimal)
Connection)
TestClient)get_db)
create_app)apply_migrationsc                     t        j                  dd      } t         j                  | _        | j	                  d       | S )Nz:memory:F)check_same_threadzPRAGMA foreign_keys = ON)sqlite3connectRowrow_factoryexecuteconns    /tests/unit/test_vue_dashboard_v12_acceptance.py_connectr      s0    ??:?D{{DLL+,K    c                `     t               }d fd}||j                  t        <   t        |      S )Nc               3     K     y wN r   s   r   override_dbz_client.<locals>.override_db   s     
s   	)returnzIterator[Connection])r	   dependency_overridesr   r   )r   appr   s   `  r   _clientr      s+    
,C (3CV$c?r   c                   d}| j                  d|f       | j                  d|f       | j                  d|f       | j                  d|f       | j                  d|f       | j                  d|f       | j                  d|f       | j                  d	|f       | j                  d
|f       | j                  d|f       | j                  d|f       | j                  d|f       | j                  d|f       | j                          y )N2026-05-16T12:00:00ZzINSERT INTO platforms(platform_id, name, platform_type, country, default_currency, created_at) VALUES ('p1', 'Raiffeisen', 'bank', 'CH', 'CHF', ?)zINSERT INTO platforms(platform_id, name, platform_type, country, default_currency, created_at) VALUES ('p2', 'PostFinance', 'broker', 'CH', 'CHF', ?)zINSERT INTO platforms(platform_id, name, platform_type, country, default_currency, created_at) VALUES ('p3', 'True Wealth', 'broker', 'CH', 'CHF', ?)zINSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, created_at) VALUES ('cash1', 'p1', 'Privatkonto', 'cash', 'CHF', ?)zINSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, created_at) VALUES ('broker1', 'p2', 'Depot', 'brokerage', 'CHF', ?)zINSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, created_at) VALUES ('tw1', 'p3', 'Gesamtwert', 'managed_portfolio', 'CHF', ?)zINSERT INTO instruments(instrument_id, asset_class, name, ticker, isin, currency, created_at) VALUES ('usd1', 'etf', 'Vanguard Total Stock Market ETF', 'VTI', 'US9229087690', 'USD', ?)zINSERT INTO instruments(instrument_id, asset_class, name, ticker, isin, currency, created_at) VALUES ('chf1', 'stock', 'Swiss Demo', 'SWD', 'CH0000000000', 'CHF', ?)zINSERT INTO fx_rates(fx_rate_id, base_currency, quote_currency, rate_date, rate, provider, rate_type, quality_status, created_at) VALUES ('fx_usd', 'USD', 'CHF', '2026-05-16', '0.91', 'frankfurter', 'close', 'fresh', ?)zINSERT INTO fx_rates(fx_rate_id, base_currency, quote_currency, rate_date, rate, provider, rate_type, quality_status, created_at) VALUES ('fx_eur', 'EUR', 'CHF', '2026-05-16', '0.98', 'frankfurter', 'close', 'fresh', ?)zwINSERT INTO crypto_wallets(wallet_id, wallet_name, wallet_type, created_at) VALUES ('w1', 'Cold Wallet', 'hardware', ?)zINSERT INTO crypto_assets(asset_id, symbol, coin_name, coingecko_id, created_at) VALUES ('btc', 'BTC', 'Bitcoin', 'bitcoin', ?)zINSERT INTO crypto_holdings(crypto_holding_id, wallet_id, asset_id, quantity, verification_status, created_at) VALUES ('h1', 'w1', 'btc', '0.25', 'ok', ?))r   commit)r   nows     r   _seedr$       s   
 CLL  f  il  hn  oLL  i  lo  kq  rLL  i  lo  kq  rLL  k  nq  ms  tLL  l  or  nt  uLL  u  x{  w}  ~LL  L  OR  NT  ULL  y  |  {A  BLL  o  ru  qw  xLL  o  ru  qw  xLL  K  NQ  MS  TLL  S  VY  U[  \LL  n  qt  pv  wKKMr   c            
        t               } t        |        t        |        t        |       }ddddddddd	d
	}|j	                  d|      j                         }|d   dk(  sJ |d   dk(  sJ |j	                  di ||d   dd      j                         }| j                  d|d   f      j                         }|d   dk(  sJ |d   dk(  sJ |d   dk(  sJ |j                  d      j                         }|d   dk(  sJ |d   dk7  sJ ddddd ddd!d"d
	}|j	                  d|      j                         }|d   d#k(  sJ |j	                  di ||d   dd      j                         }	| j                  d$|	d   f      j                         }
|
d   dk(  sJ |
d   d#k(  sJ |j                  d%      j                         }|d   d#k(  sJ y )&Netfbroker1usd12USD
2026-05-16initial_snapshot100z
manual usd	asset_class
account_idinstrument_idquantitycurrency
trade_datetransaction_typecost_basis_originalnote/api/positions/previewjson	fx_statusok
amount_chfz91.00/api/positions/confirm
preview_idTr?   confirmzkSELECT fx_rate_to_chf, fx_status, gross_amount_chf, net_amount_chf FROM transactions WHERE transaction_id=?	entity_idfx_rate_to_chfz0.91gross_amount_chfz%/api/portfolio/positions/broker1:usd1statuszFX fehltstockchf11CHF10z
manual chf
not_neededzISELECT fx_rate_to_chf, fx_status FROM transactions WHERE transaction_id=?z%/api/portfolio/positions/broker1:chf1)	r   r
   r$   r   postr:   r   fetchoneget)r   clientreqpreview	confirmedtxdetailchfpreview_chfconfirmed_chftx_chf
detail_chfs               r   ;test_position_confirm_resolves_cached_fx_and_chf_not_neededrZ   2   s   :D'-uT{T]Fy6_bpu  FR  hz  SX  bn  oCkk2k=BBDG;4'''< G+++4;xc;xQXYeQfsw;xy~~  AI	  D  GP  Q\  G]  F_  
`  
i  
i  
kB6)))k?d""" !W,,,ZZ?@EEGF+$&&&(z)))!Vadrw  HT  j|  UY  co  pC++6S+AFFHK{#|333KK 8  @A#  @AU`amUn{  @AK  B  G  G  IM\\ehu  wB  iC  hE  F  O  O  QF"#s***+,...CDIIKJk"l222r   c            
        t               } t        |        t        |        t        |       }|j	                  d      j                         }t        d |D              }|d   dk(  sJ |d   dk(  sJ |d   du sJ d	|d
   dddddddd	}|j                  d|      }|j                  dk(  sJ d|j                  j                         v sd|j                  j                         v sJ |j                  d|d
    ddddd      j                         }|d   dk(  sJ |j                  d|d
    dddd|d    d!d"      j                         }|d#   d$k(  sJ | j                  d%|d
   f      j                         d&   d'k(  sJ | j                  d(|d
   f      j                         d&   d'k(  sJ |j	                  d)      j                         }|d*   dk(  sJ d+|v sJ y ),Nz/api/reference/accountsc              3  0   K   | ]  }d |d   v s|  yw)zTrue WealthlabelNr   ).0as     r   	<genexpr>zStest_truewealth_is_managed_total_value_account_not_equity_target.<locals>.<genexpr>U   s     AA]aj%@aAs   valuation_modemanual_total_valueportfolio_bucket
truewealthallow_position_addsFr&   r0   r(   rH   r*   r+   r,   rJ   zmust be blockedr.   r8   r9   i  
gesamtwertzmanual total/api/accounts/z/value/previewz12345.67zmanual TW value)valuation_datetotal_value_chfr7   r;   rK   z/value/confirmr?   T)rh   ri   r7   r?   rA   rE   rR   z?SELECT COUNT(*) FROM account_value_snapshots WHERE account_id=?r      zSSELECT COUNT(*) FROM audit_log WHERE action='account_value_confirm' AND entity_id=?/api/overviewtruewealth_value_chfpostfinance_equity_value_chf)r   r
   r$   r   rN   r:   nextrL   status_codetextlowerr   rM   )	r   rO   accountstwblocked_reqblockedrQ   rR   overviews	            r   @test_truewealth_is_managed_total_value_account_not_equity_targetrw   P   s   :D'-uT{T]Fzz3499;H	AA	AB#7777 !\111#$---"'r,7GZ`nq  @E  Ua  wI  bf  pA  BKkk2kEG#%%%7<<--//>W\\EWEWEY3YYYkkN2l+;*<NKeq  GQ  [l  Smk  n  s  s  uG;<///nR-=,>nMgs  IS  ]n  ~E  FR  ~S  `d  Ue  f  k  k  mIX+---<<Y\^_k\l[noxxz{|}  BC  C  C  C<<mprs  qA  pC  D  M  M  O  PQ  R  VW  W  W  Wzz/*//1H*+z999)X555r   c                   t               }t        |       t        |       ddi G fdd      dd lmc m} | j                  |dfd       t        |      }|j                  d       d   dk(  sJ |j                  dd	d
dd      j                         }d   dk(  sJ |d   d   d   d
k(  sJ |d   du sJ dt        |      j                         vsJ y )Ncountr   c                  $    e Zd ZdZddd fdZy)etest_provider_search_endpoint_returns_candidates_and_no_provider_call_on_render.<locals>.FakeProviderfake_providerNr/   c               X    dxx   dz  cc<   ddl m}  |d |xs ddddd	d
ddd
      gS )Nry   rj   r   CatalogSearchResultr&   zVanguard Total StockUS9229087690VTINYSEARCAr*   r|   highfake)isintickerexchangetrading_currencyprovider
confidencesource"jarvis_finance.market_data.catalogr   )selfqueryr/   r   calleds       r   searchzltest_provider_search_endpoint_returns_candidates_and_no_provider_call_on_render.<locals>.FakeProvider.searchq   s^    7Oq ON'k.BUDZaox}  IS  fk  vE  RX  ag  h  i  ir   r   strr/   z
str | None__name__
__module____qualname__namer   )r   s   r   FakeProviderr{   o   s    BF 	i 	ir   r   _provider_search_providersc                              gS r   r   )r   s   r   <lambda>zatest_provider_search_endpoint_returns_candidates_and_no_provider_call_on_render.<locals>.<lambda>w   s    LNCS r   rk    /api/instruments/provider-searchr&   r   r*   r/   r   r3   r9   rj   
candidatesr   selection_requiredTapi_key)r   r
   r$   ,jarvis_finance.services.manual_entry_serviceservicesmanual_entry_servicesetattrr   rN   rL   r:   r   rq   )monkeypatchr   svcrO   payloadr   r   s        @@r   Otest_provider_search_endpoint_returns_candidates_and_no_provider_call_on_renderr   k   s    :D'-uT{q\Fi i ?>9;STT]F
JJ'?akk<SXchv{C|k}  C  C  EG'?a< #H-666'(D000CL..0000r   c                    t               } t        |        t        |        d}| j                  d|f       | j                  d|f       | j                  d|f       | j	                          t        |       }|j                  di       j                         }|d   dk(  sJ |d	   dk(  sJ |d
   dk(  sJ | j                  d      j                         d   dk(  sJ |j                  dddd      j                         }|d   dk(  sJ | j                  d      j                         d   dk(  sJ | j                  d      j                         d   dk(  sJ | j                  d      j                         d   dk(  sJ y )Nr!   zINSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, created_at) VALUES ('review_acc', 'p2', 'True Wealth Review Brokerage', 'brokerage', 'CHF', ?)a  INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, gross_amount_original, net_amount_original, currency_original, source_type, is_confirmed, quality_status, notes, created_at) VALUES ('review_tx', 'initial_position_snapshot', 'review_acc', 'usd1', '2026-05-16', '1', '1', '1', 'USD', 'broker_import_reviewed_snapshot', 1, 'ok', 'review artifact', ?)a  INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, gross_amount_original, net_amount_original, currency_original, source_type, is_confirmed, quality_status, notes, created_at) VALUES ('manual_tx', 'initial_position_snapshot', 'broker1', 'chf1', '2026-05-16', '1', '1', '1', 'CHF', 'vue_manual_position', 1, 'ok', 'real manual', ?)z%/api/cleanup/review-artifacts/previewr9   rr   rj   transactionsmanual_positions_preservedz<SELECT is_active FROM accounts WHERE account_id='review_acc'r   z%/api/cleanup/review-artifacts/confirmTzacceptance cleanuprA   r7   rE   rR   zCSELECT is_voided FROM transactions WHERE transaction_id='review_tx'zCSELECT is_voided FROM transactions WHERE transaction_id='manual_tx')	r   r
   r$   r   r"   r   rL   r:   rM   )r   r#   rO   rQ   rR   s        r   Vtest_cleanup_preview_and_confirm_archives_review_artifacts_preserving_manual_positionsr      s   :D'-uT{
 CLL  F  IL  HN  OLL  j  mp  lr  sLL  W  Z]  Y_  `KKMT]FkkAkKPPRG:!###>"a'''/0A555<<VW``bcdeijjjjCVZdxJyz  BIX+---<<VW``bcdeijjjj<<]^ggijklpqqqq<<]^ggijklpqqqqr   c            
     6   t               } t        |        t        |        t        |       }ddddddddd	d
	}|j	                  d|      j                         }|j	                  di ||d   dd       |j	                  di       j                         }|d   du sJ |j	                  ddddd      j                         }|d   dk(  sJ | j                  d      j                         d   dk(  sJ | j                  d      j                         d   dk(  sJ | j                  d       | j                          |j	                  di       j                         }|d   du sJ |j	                  dddd d      j                         }|d   dk(  sJ | j                  d!       | j                          |j	                  di       j                         }|d   du sJ |j	                  dddd"d      j                         }	|	d   dk(  sJ |j	                  d|      j                         }
|j	                  di ||
d   dd       | j                  d#       | j                          |j	                  di       j                         }|d   d$u sJ y )%NrF   r'   rG   rH   rI   r+   r,   rJ   z	bad inputr.   r8   r9   r>   r?   Tr@   z*/api/positions/broker1:chf1/remove/previewsafe_to_removez*/api/positions/broker1:chf1/remove/confirm	ENTFERNENzwrong position)rA   confirmation_textr7   rE   rR   zLSELECT COUNT(*) FROM transactions WHERE is_voided=1 AND instrument_id='chf1'r   rj   zESELECT COUNT(*) FROM audit_log WHERE action='position_remove_confirm'a  INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, gross_amount_original, net_amount_original, currency_original, fx_rate_to_chf, fx_status, source_type, is_confirmed, quality_status, notes, created_at) VALUES ('legacy_snapshot', 'initial_snapshot', 'broker1', 'usd1', '2026-05-16', '1', '10', '10', 'USD', '0.91', 'ok', 'manual_initial_snapshot', 1, 'ok', 'legacy manual snapshot', '2026-05-16T12:00:00Z')z*/api/positions/broker1:usd1/remove/previewz*/api/positions/broker1:usd1/remove/confirmzlegacy cleanupa  INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, gross_amount_original, net_amount_original, currency_original, fx_rate_to_chf, fx_status, source_type, is_confirmed, quality_status, notes, created_at) VALUES ('manual_adjustment_snapshot', 'manual_adjustment', 'broker1', 'usd1', '2026-05-16', '1', '10', '10', 'USD', '0.91', 'ok', 'manual_dashboard', 1, 'ok', 'manual adjustment snapshot', '2026-05-16T12:00:00Z')zmanual adjustment cleanupa~  INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, gross_amount_original, net_amount_original, currency_original, source_type, is_confirmed, quality_status, notes, created_at) VALUES ('hist_tx', 'buy', 'broker1', 'chf1', '2026-05-17', '1', '10', '10', 'CHF', 'vue_manual_position', 1, 'ok', 'history', '2026-05-17T12:00:00Z')F)	r   r
   r$   r   rL   r:   r   rM   r"   )r   rO   rP   rQ   remove_previewdonelegacy_previewlegacy_doneadjustment_previewadjustment_donepreview2ru   s               r   Dtest_remove_position_voids_single_manual_snapshot_but_blocks_historyr      sO   :D'-uT{T]F!Vadrw  HT  j|  UY  cn  oCkk2k=BBDG
KK(/l#/lW\EZgk/lKm[[!MTV[W\\^N*+t333;;CVZq|  GW  KX;  Y  ^  ^  `D>[(((<<fgpprstuyzzzz<<_`iiklmnrssss 	LL  c  dKKM[[!MTV[W\\^N*+t333++J]a  yD  N^  R_+  `  e  e  gKx K/// 	LL  l  mKKM%QXZ[``b./4777kk"Nae  }H  Rm  Vnk  o  t  t  vO8$333 {{3#{>CCEHv{{Sk  squx  sq  IQ  R^  I_  lp  sq{  HrLL  R  SKKMkkFRkPUUWG#$---r   c                    t               } t        |        t        |        t        |       }|j	                  ddddd      j                         }|j	                  dddd|d   d	d
      j                         }|d   }|j	                  d| dd	dd      j                         }|d   j                         j                  d      sJ |j	                  dd	dd      j                         }d|d   j                         v sJ | j                  d      j                         d   dk(  sJ |j	                  ddddddd      j                         }|j	                  dddddd|d   d	d      j                         }|d   }	|j	                  d|	 d d	d!d      j                         }
|
d"   d#k(  sJ | j                  d$      j                         d   d%k\  sJ y )&Nz/api/wallets/previewzEmpty Walletr   new)r   wallet_typer7   r9   z/api/wallets/confirmr?   T)r   r   r7   r?   rA   rB   z/api/wallets/z/delete/confirmemptyr   messageu   wallet gelöschtz/api/wallets/w1/delete/confirmarchivedeaktiviertz9SELECT is_active FROM crypto_wallets WHERE wallet_id='w1'r   z/api/accounts/previewzAnderes KontozManual Broker	brokeragerI   )platform_nameaccount_nameaccount_typer3   r7   z/api/accounts/confirm)r   r   r   r3   r7   r?   rA   rg   z/deactivate/confirmz
not neededrE   rR   zSELECT COUNT(*) FROM audit_log WHERE action IN ('wallet_create_confirm','wallet_delete_confirm','wallet_deactivate_confirm','account_create_confirm','account_deactivate_confirm')   )
r   r
   r$   r   rL   r:   rq   
startswithr   rM   )r   rO   wallet_previewwalletwiddeletednonemptyaccount_previewaccountaiddeactivateds              r   Btest_wallet_and_account_create_deactivate_delete_rules_are_auditedr      s   :D'-uT{T]F[[!7~fpz  ?A[  B  G  G  IN[[/~^hrw  HV  Wc  Hd  qu  7v[  w  |  |  ~F

CkkM#o>QU_fEgkhmmoG9##%001CDDD{{;d\eBf{gllnHHY/557777<<ST]]_`abfggggkk"9Ra  tC  U`  ns  }B  ACk  D  I  I  KOkk1/kz  MX  fk  uz  JY  Zf  Jg  tx  9yk  z      AG
+
C++se3FGZ^htNu+v{{}Kx K///<<  M  N  W  W  Y  Z[  \  `a  a  a  ar   c                d   t               }t        |       t        |        G d d       G d d      dd lmc m} | j                  |dfd       t        |      }|j                  dd	d
dddddd      j                         }t        |d         dk(  sJ |d   d   }|d   d
k(  sJ |d   dk(  sJ |d   dk(  sJ |d   sJ |d   dk(  sJ |d   dk(  sJ |d   dk(  sJ |d   dk(  sJ |d   sJ |d   dk(  sJ |d    d!k(  sJ |d"   d#k(  sJ d$|d%   v rd&|d%   v sJ |d'   d(v sJ y ))Nc                      e Zd ZdZddddZy)Xtest_provider_search_deduplicates_enriches_filters_and_ranks_goog.<locals>.FakeProviderAopenfigiNr}   c                   ddl m}  |di 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ddddd d!d" |d d#d$d%dd&d'dd(d&d)ddd*d*+      gS ),Nr   r   )NrF   zALPHABET INC-CL Cr   US02079K1079r   GOOGr   NASDAQr   r*   r   r   provider_symbolBBG009S3NB30provider_marketcountryUSr   mediumr   evidence_notezprimary listing
last_price175.12price_currency
price_dater+   security_typeCommon Stockexchange_namezNasdaq Global SelectmicXNASrF   zALPHABET INC - CDRCA02079K3055NEOCADBBGCDRCACDR)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r/   r   s       r   r   z_test_provider_search_deduplicates_enriches_filters_and_ranks_goog.<locals>.FakeProviderA.search   s?   N#  Q^  Qdj  Qu}  Q  QV  Q  ak  Q  }K  Q  ]e  Q  os  Q  @H  Q  Q[  Q  k|  Q  IQ  Q  bg  Q  t@  Q  P^  Q  nD  Q  JP  Q#D'3Gnekv{  OT  _i  {C  UZ  dh  u}  FP  `e  uz  { r   r   r   r   r   r   FakeProviderAr      s    BF 	r   r   c                      e Zd ZdZddddZy)Xtest_provider_search_deduplicates_enriches_filters_and_ranks_goog.<locals>.FakeProviderBfinnhubNr}   c                   ddl m}  |di 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dddddd d! |d d"d#d$d%d&dd'd(dd)*      gS )+Nr   r   )NrF   Alphabet Inc Class Cr   r   r   r   r   r   r   r*   r   r   r   r   r   r   r   r   r   r   zsymbol lookupr   z175.10r   r   r+   r   r   r   Nasdaqr   r   rF   zGoogol Technology Co Ltd8118HKEXHKDHKlowzweak name match)r   r   r   r   r   r   r   r   r   r   s       r   r   z_test_provider_search_deduplicates_enriches_filters_and_ranks_goog.<locals>.FakeProviderB.search   s-   N#  zP^  zgm  z  yA  z  TY  z  dm  z  E  z  W_  z  im  z  zB  z  KT  z  ds  z  @H  z  Y^  z  kw  z  GU  z  em  z  sy  z#D'3MV\gm  AF  QZ  dh  uz  CL  \m  n r   r   r   r   r   r   FakeProviderBr      s    BF 	r   r   r   r   c                                       gS r   r   )r   r   s   r   r   zStest_provider_search_deduplicates_enriches_filters_and_ranks_goog.<locals>.<lambda>   s    MOUbUdCe r   r   rF   r   r*   r   r   T)r/   r   r3   r   r   main_listing_onlyhide_cdr_adr_derivativesr9   r   rj   r   r   r   r   r   r   r   r3   r   r   r   r   r   r   r+   r   r   r   r   r   confidence_label>   	EindeutigWahrscheinlich)r   r
   r$   r   r   r   r   r   rL   r:   len)r   r   r   rO   r   googr   r   s         @@r   Atest_provider_search_deduplicates_enriches_filters_and_ranks_googr     s   :D'-uT{   ?>9;efT]Fkk<SZeky~  MU  bf  }A  _c  Ddk  e  j  j  lGw|$%***< #D>V###<>)))
x'''   ;&   
u$$$	?d""" N222 !U***---!"n444j))i4
;K.KKK"#'FFFFr   c                p   t               }t        |       t        |        G d d       G d d      dd lmc m} | j                  |dfd       t        |      }|j                  dd	d
dd      j                         }|d   sJ |d   dgk(  sJ dt        |      vsJ dt        |      vsJ y )Nc                      e Zd ZdZddddZy)btest_provider_search_suppresses_raw_provider_errors_when_candidate_exists.<locals>.WorkingProviderr   Nr}   c               @    ddl m}  |d |xs ddddddd	dd
dd	      gS )Nr   r   rF   r   r   r   r   r*   r   r   r   )	r   r   r   r   r   r   r   r   r   r   r   s       r   r   zitest_provider_search_suppresses_raw_provider_errors_when_candidate_exists.<locals>.WorkingProvider.search  sa    N'k.DWF\cq  {A  LT  gl  wA  SY  cg  tz  CM  N  O  Or   r   r   r   r   r   WorkingProviderr
    s    BF 	Or   r  c                      e Zd ZdZddddZy)atest_provider_search_suppresses_raw_provider_errors_when_candidate_exists.<locals>.BrokenProviderbroken_providerNr}   c                   t        d      )Nz1upstream HTTP 500 secret-ish raw provider failure)RuntimeErrorr   r   r/   s      r   r   zhtest_provider_search_suppresses_raw_provider_errors_when_candidate_exists.<locals>.BrokenProvider.search  s    RSSr   r   r   r   r   r   BrokenProviderr    s     BF 	Tr   r  r   r   c                                       gS r   r   )r  r  s   r   r   z[test_provider_search_suppresses_raw_provider_errors_when_candidate_exists.<locals>.<lambda>  s    ODUWeWgCh r   r   rF   r   r*   r   r9   r   warningsue   Datenquelle teilweise eingeschränkt: Ein Provider lieferte keine Daten; Treffer stammt aus openfigi.zHTTP 500zraw provider failure)r   r
   r$   r   r   r   r   r   rL   r:   r   )r   r   r   rO   r   r  r  s        @@r   Itest_provider_search_suppresses_raw_provider_errors_when_candidate_existsr    s    :D'-uT{O OT T
 ?>9;hiT]Fkk<SZeky~Ck  A  F  F  HG<   :  $K  #L  L  L  LS\)))!W555r   c                    t               }t        |       t        |        G d d      dd lmc m} | j                  |dfd       t        |      }|j                  dddd	
      j                         }|d   g k(  sJ |d   dgk(  sJ y )Nc                      e Zd ZdZddddZy)Ptest_provider_search_no_candidates_has_clear_user_warning.<locals>.EmptyProviderempty_providerNr}   c                   g S r   r   r  s      r   r   zWtest_provider_search_no_candidates_has_clear_user_warning.<locals>.EmptyProvider.search"  s    Ir   r   r   r   r   r   EmptyProviderr     s    BF 	r   r  r   r   c                              gS r   r   )r  s   r   r   zKtest_provider_search_no_candidates_has_clear_user_warning.<locals>.<lambda>&  s    MOCT r   r   rF   DOESNOTEXIST)r/   r   r9   r   r  u,   Keine verlässlichen Providerdaten gefunden.)
r   r
   r$   r   r   r   r   r   rL   r:   )r   r   r   rO   r   r  s        @r   9test_provider_search_no_candidates_has_clear_user_warningr    s    :D'-uT{ 
 ?>9;TUT]Fkk<SZesCtkuzz|G< B&&&:#Q"RRRRr   c            
     P   t               } t        |        t        |        d}| j                  d||f       | j	                          t        |       }ddddddd	d
dd	}| j                  d      j                         d   }|j                  d|      j                         }|d   j                  d      sJ | j                  d      j                         d   |k(  sJ |j                  di ||d   dd      j                         }| j                  d|d   f      j                         }|d   dk(  sJ | j                  d|d   f      j                         }t        |      dddddd d!k(  sJ | j                  d"|d   f      j                         }	|	d#   d$k(  sJ |	d%   dk(  sJ |	d&   d k(  sJ |j                  d'      j                         }
t        d( |
D              }|d%   dk(  sJ |d)   d*k(  sJ |d+   J | j                  d,      j                         d   d-k(  sJ y ).Nr!   a  
        INSERT INTO instrument_catalog_entries(catalog_entry_id, asset_class, name, normalized_name, isin, ticker, exchange, trading_currency, instrument_currency, provider, provider_symbol, provider_market, country, source, source_confidence, last_price, price_currency, price_date, created_at, updated_at)
        VALUES ('cat_goog', 'stock', 'ALPHABET INC-CL C', 'alphabet inc cl c', 'US02079K1079', 'GOOG', 'NASDAQ', 'USD', 'USD', 'openfigi', 'BBG009S3NB30', 'NASDAQ', 'US', 'openfigi', 'high', '175.12', 'USD', '2026-05-16', ?, ?)
    rF   r'   cat_googr)   r*   r+   r,   r-   zprovider candidate)	r/   r0   candidate_idr2   r3   r4   r5   r6   r7   z:SELECT COUNT(*) FROM instruments WHERE isin='US02079K1079'r   r8   r9   summaryALPHABETr>   r?   Tr@   zPSELECT instrument_id, currency_original FROM transactions WHERE transaction_id=?rB   currency_originalzvSELECT ticker, isin, exchange, currency, provider_symbol, data_provider_primary FROM instruments WHERE instrument_id=?r1   r   r   r   r   r   )r   r   r   r3   r   data_provider_primaryzISELECT close, currency, provider FROM market_prices WHERE instrument_id=?closer   r3   r   z/api/equity/positionsc              3  2   K   | ]  }|d    dk(  s|  yw)r   r   Nr   )r^   rows     r   r`   z\test_provider_candidate_preview_confirm_materializes_instrument_and_audit.<locals>.<genexpr>I  s     ECS]f-DCEs   rE   Bewertetmarket_value_chfz>SELECT COUNT(*) FROM audit_log WHERE action='position_confirm'rj   )r   r
   r$   r   r"   r   rM   rL   r:   r   dictrN   rn   )r   r#   rO   rP   beforerQ   rR   rS   instpriceequitygoog_rows               r   Itest_provider_candidate_preview_confirm_materializes_instrument_and_auditr2  /  s   :D'-uT{
 CLL  s 	KKMT]F!Jdguz  KW  m  X]  g{  |C\\VW``bcdeFkk2k=BBDG9((444<<TU^^`abcgmmmm4;xc;xQXYeQfsw;xy~~  AI	hkt  vA  lB  kD  
E  
N  
N  
PB!"e+++<<  Q  TV  Wf  Tg  Si  j  s  s  uD:FNPXfk  AO  jt  u  u  u  uLLdgijygzf|}  G  G  IE>X%%%%%%
***ZZ/0557FE6EEHJ5(((H+++&'333<<XYbbdefgkllllr   c                 ^   t               } t        |        t        |        | j                  dd       | j                  d       | j	                          t        |       }|j                  d      j                         }|d   d   dk(  sJ |d   d   d	k(  sJ |d
   j                  d      sJ y )N5UPDATE crypto_assets SET notes=? WHERE asset_id='btc')z{"coingecko": {"market_cap_rank": 1, "market_cap": "2000000000000", "volume_24h": "50000000000", "change_24h_pct": "2.50", "change_7d_pct": "5.00", "homepage": "https://bitcoin.org", "image_url": "https://example.test/btc.png"}}zINSERT INTO crypto_prices(crypto_price_id, asset_id, coingecko_id, price_currency, price, provider, fetched_at, quality_status) VALUES ('cp1', 'btc', 'bitcoin', 'CHF', '80000', 'coingecko_cache', '2026-05-16T12:00:00Z', 'fresh')/api/crypto/positions/btccoingecko_infomarket_cap_rankrj   homepagezhttps://bitcoin.orgread_only_notezLive-Modus optional)	r   r
   r$   r   r"   r   rN   r:   r   r   rO   rT   s      r   Ftest_crypto_detail_exposes_cached_coingecko_info_without_provider_callr;  P  s    :D'-uT{LLH  Kt  uLL  x  yKKMT]FZZ3499;F"#$56!;;;"#J/3HHHH"#../DEEEr   c                    t               } t        |        t        |        | j                  dd       | j	                          t        |       }|j                  d      j                         }|d   d   J |d   d   J y )Nr4  )zZ{"coingecko": {"homepage": "javascript:alert(1)", "image_url": "data:image/svg+xml,evil"}}r5  r6  r8  	image_url)r   r
   r$   r   r"   r   rN   r:   r:  s      r   2test_crypto_detail_sanitizes_cached_coingecko_urlsr>  _  s    :D'-uT{LLH  Kj  kKKMT]FZZ3499;F"#J/777"#K0888r   )r   r   )r   r   r   r   )r   r   r   None)r   r?  )
__future__r   collections.abcr   r   decimalr   r   fastapi.testclientr   jarvis_finance.api.dependenciesr   jarvis_finance.api.mainr	   !jarvis_finance.storage.migrationsr
   r   r   r$   rZ   rw   r   r   r   r   r  r  r  r2  r;  r>  r   r   r   <module>rG     st    " $    ) 2 . >$3<6610r,#.La.*GZ64S$mBF	9r   