
    @&j%                       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mZmZmZmZmZmZ d dlmZ d dlmZ  G d	 d
          Z G d d          Z G d 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S )    )annotationsN)Path)data)page_13_equity_manage)ProviderCandidateexport_mapping_decision_packgenerate_mapping_candidatesrank_candidaterecalculate_candidate_rankingsreject_mapping_candidateselect_mapping_candidate)connect_memory)apply_migrationsc                       e Zd ZdZddZd ZdS )StaticLookupProviderstaticNc                    |pi | _         d S N)candidates_by_isin)selfr   s     ^/home/agent/.hermes/repos/FinanceManager/tests/unit/test_true_wealth_mapping_candidates_c3d.py__init__zStaticLookupProvider.__init__   s    "4":    c               R    t          | j                            |g                     S r   )listr   get)r   isinnametickerexchangecurrencys         r   lookupzStaticLookupProvider.lookup   s#    D+//b99:::r   r   )__name__
__module____qualname__r   r   r"    r   r   r   r      s<        D; ; ; ;; ; ; ; ;r   r   c                      e Zd Zd Zd ZdS )FakeTabc                    | S r   r&   )r   s    r   	__enter__zFakeTab.__enter__   s    r   c                    dS NFr&   )r   argss     r   __exit__zFakeTab.__exit__"   s    ur   N)r#   r$   r%   r*   r.   r&   r   r   r(   r(      s2              r   r(   c                      e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd ZdS )FakeStc                    d S r   r&   r   r-   kwargss      r   titlezFakeSt.title'         r   c                    d S r   r&   r2   s      r   captionzFakeSt.caption(   r5   r   c                    d S r   r&   r2   s      r   warningzFakeSt.warning)   r5   r   c                    d S r   r&   r2   s      r   	subheaderzFakeSt.subheader*   r5   r   c                    d S r   r&   r2   s      r   writezFakeSt.write+   r5   r   c                    d S r   r&   r2   s      r   successzFakeSt.success,   r5   r   c                    d S r   r&   r2   s      r   errorzFakeSt.error-   r5   r   c                    d S r   r&   r2   s      r   infozFakeSt.info.   r5   r   c                    d S r   r&   r2   s      r   dividerzFakeSt.divider/   r5   r   c                    d S r   r&   r2   s      r   	dataframezFakeSt.dataframe0   r5   r   c                    d S r   r&   r2   s      r   tablezFakeSt.table1   r5   r   c                    d |D             S )Nc                *    g | ]}t                      S r&   r(   ).0_s     r   
<listcomp>zFakeSt.tabs.<locals>.<listcomp>2   s    #>#>#>!GII#>#>#>r   r&   )r   labelss     r   tabszFakeSt.tabs2   s    #>#>v#>#>#>>r   c                    |r|d         nd S )Nr   r&   )r   labeloptionsr3   s       r   	selectboxzFakeSt.selectbox3   s    :Y'!**UY3Yr   c                .    |                     dd          S )Nvalue )r   r2   s      r   
text_inputzFakeSt.text_input4   s    &**Wb2I2I+Ir   c                    dS )NrX   r&   r2   s      r   	text_areazFakeSt.text_area5   s    r   c                    dS )Nz
2025-12-31r&   r2   s      r   
date_inputzFakeSt.date_input6   s    ,,r   c                    dS r,   r&   r2   s      r   checkboxzFakeSt.checkbox7   s    r   c                    t                      S r   rL   r2   s      r   expanderzFakeSt.expander8   s    		)9r   c                    dS r,   r&   r2   s      r   buttonzFakeSt.button9   s    eer   N)r#   r$   r%   r4   r7   r9   r;   r=   r?   rA   rC   rE   rG   rI   rQ   rU   rY   r[   r]   r_   ra   rc   r&   r   r   r0   r0   &   s        ***,,,,,,...***,,,***))),,,...***>>>YYYIII333>>>55599933333r   r0   c                     t                      } t          |            |                     d           |                     d           |                     d           |                     d           | S )NzINSERT INTO platforms(platform_id,name,platform_type,default_currency,created_at) VALUES('p1','True Wealth','broker','CHF','now')zINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,created_at) VALUES('a1','p1','TW','brokerage','CHF','now')zINSERT INTO instruments(instrument_id,asset_class,name,ticker,isin,exchange,currency,created_at) VALUES('inst1','ETF','Global Equity ETF','GETF','CH0000000001',NULL,'USD','now')aA  INSERT INTO transactions(transaction_id,transaction_type,account_id,instrument_id,trade_date,quantity,currency_original,fx_status,source_type,is_confirmed,quality_status,created_at) VALUES('tx1','initial_position_snapshot','a1','inst1','2025-12-31','1','USD','missing','broker_import_reviewed_snapshot',1,'warning','now'))r   r   execute)conns    r   
setup_connrg   <   s    DTLL  U  V  V  VLL  ]  ^  ^  ^LL  E  F  F  FLL  U  V  V  VKr   returnNonec                 B   dddddddd} t          dd	ddddd
dd	  	        }t          dddddddd          }t          | |d          }t          | |d          }|j        }|j        }||k    }|st          j        d|fd||f          dt          j                    v st          j        |          rt          j        |          ndt          j        |          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}
|j        }|
|v }|st          j        d|fd|
|f          t          j        |
          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#}
|j        }|
|v }|st          j        d|fd|
|f          t          j        |
          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$}
|j        }|
|v }|st          j        d|fd%|
|f          t          j        |
          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CH0000000001ETFGlobal Equity ETFGETFSWXCHF)r   asset_classr   r   r    r!   trading_currencyopenfigiGETF.SWetfactiveopenfigi_isin_mapping	providerprovider_symbolr    r!   r   r   rq   instrument_statusevidence_sourceyahooNYSEUSDstockyahoo_finance_search)ry   rz   r    r!   r   r   rq   r|      )candidate_count)>)zW%(py2)s
{%(py2)s = %(py0)s.ranking_score
} > %(py6)s
{%(py6)s = %(py4)s.ranking_score
}	good_rankbad_rank)py0py2py4py6zassert %(py8)spy8z
ISIN passtin)z6%(py1)s in %(py5)s
{%(py5)s = %(py3)s.ranking_reason
})py1py3py5zassert %(py7)spy7u   Währung passtcurrency_mismatch)z2%(py1)s in %(py5)s
{%(py5)s = %(py3)s.risk_flags
})r   r
   ranking_score
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationranking_reason
risk_flags)instgoodbadr   r   @py_assert1@py_assert5@py_assert3@py_format7@py_format9@py_assert0@py_assert4@py_assert2@py_format6@py_format8s                  r   9test_candidate_ranking_prioritizes_isin_currency_exchanger   F   s   "5BUaguz  IN  di  j  jDj)V[fk  sF  M[  in  BJ  \s  t  t  tD
Wfv`el  GU  cj  |R  S  S  SCtT1===IdC;;;H";X%;;"%;;;;;;;;;;;"%;;;;;;;;;;;;;9;;;;;9;;;;;;";;;;;;;;;;;X;;;;;X;;;;;;%;;;;;;;;;;;;;;;;;;;;;;;;;;;;3933<33333333333<333333<33333333333933333933333333333333333333333333333333337y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7y77777y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5("55"55555555555"55555555555555555(55555(555555"555555555555555555555555555555r   c                    t                      } |                     d           t          dt          dddddddd	d
	  	        t          dddddddd	d
	  	        gi          }t	          | |           t          |           }t          j        |           }|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h}||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         }	t          |	          }|d         d         }
t          |
          }||k    }|s"t          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z  }dd |iz  }t          t          j        |                    d x}	x}x}x}
}|d         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 )%NzYUPDATE instruments SET currency='CHF', trading_currency='CHF' WHERE instrument_id='inst1'rk   rs   zGETF.USr~   r   rm   ru   rv   rw   rx   rt   ro   rp   ry   multiple_listings_same_isin   ==z%(py1)s == %(py4)sr   r   assert %(py6)sr   c                    h | ]
}|d          S )review_statusr&   )rM   rs     r   	<setcomp>zUtest_same_isin_multiple_listings_remain_review_required_and_sorted.<locals>.<setcomp>]   s    ---1Ao---r   needs_manual_reviewr   r   )>=)zP%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} >= %(py10)s
{%(py10)s = %(py6)s(%(py8)s)
}int)r   r   r   r   r   py10zassert %(py12)spy12r   zassert %(py1)sr   candidate_provider_symbol)rg   re   r   r   r	   r   r   !get_instrument_mapping_candidatesr   r   r   r   r   r   r   r   r   )rf   ry   summaryrowsr   r   r   @py_format5r   r   @py_assert7@py_assert9r   @py_format11@py_format13@py_format2s                   r   Btest_same_isin_multiple_listings_remain_review_required_and_sortedr   R   s   <<DLLlmmm#^:ySYdi  qD  KY  gl  @H  Zq  	r  	r  	r:ySXch  pC  JX  fk  G  Yp  	q  	q  	q6 %  H  x8888,T22G1$77D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-----H2G1HH-1HHHHHHHHHHH-1HHHHHH-HHHH1H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Aw'I3'((IQ0HIC0H,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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ICIIIIICIIIIII0H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7#$$$$$$$$$$$$$$$$$$$$$$$$$7./<9</9<<<<<<<<<</9<<<<</<<<<9<<<<<<<<<<<<<<<<<<<<<<<<<<<<<r   c                   t                      }t          dt          ddddddddd	
	  	        gi          }t          ||           t	          |           | dz  dz  }t          ||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}||u }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d}|v }|st          j        d|fd |f          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}}g d%}f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}x}}d S )*Nrk   rs   rt   ro   rp   rm   ru   rv   rw   rx   r   runtime_exportszdecision_pack.md   )output_pathtop_nutf-8encodinginstrument_countr   r   r   r   r   r   candidate_rowstop_candidates_presentT)is)z%(py1)s is %(py4)szRanking Reasonr   z%(py1)s in %(py3)stextr   r   assert %(py5)sr   )quantityamountmarket_value
kontostandportfolioanteilzprice:c              3  h   K   | ],}|                                                                  v V  -d S r   )lower)rM   tokenr   s     r   	<genexpr>zLtest_decision_pack_runtime_only_contains_no_amount_fields.<locals>.<genexpr>r   s8      HHU5;;==DJJLL0HHHHHHr   z0assert not %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr   r   r   )rg   r   r   r	   r   r   	read_textr   r   r   r   r   r   r   r   r   )tmp_pathrf   ry   outr   r   r   r   r   r   @py_format4r   	forbiddenr   r   r   s                  @r   9test_decision_pack_runtime_only_contains_no_amount_fieldsr   c   sc   <<D#^:ySXch  pC  JX  fk  G  Yp  	q  	q  	q6 %  H  x8888"4(((
&
&);
;C*4SJJJG=='=**D%&+!+&!++++++++++&!+++++&++++!+++++++++++++++++++++++++++#$))$))))))))))$)))))$)))))))))))))))))))))))))))))))+,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#t##########t################t#####t###########################aaaIHHHHiHHHHsHHHHHHHHHHHHHHHHHHHsHHHHHs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HHHHHHHHr   c                    t                      } dD ]!}|                     d|dddd||ddf	           "t          d	t          d
ddddd	ddd	  	        gi          }t	          | |           |                     d                                          d         }t          | |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 }||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)missing_provider_symbolambiguous_provider_mappingcandidate_review_requiredzINSERT INTO alerts(alert_id,priority,category,entity_type,entity_id,rule_id,message,status,created_at) VALUES(?,?,?,?,?,?,?,?,?)warnungmarket_data
instrumentinst1rv   nowrk   rs   rt   ro   rp   rm   ru   rw   rx   r   <SELECT candidate_id FROM instrument_price_mapping_candidatescandidate_idzmanual dashboard confirmationr   notezKSELECT COUNT(*) AS c FROM audit_log WHERE action='select_mapping_candidate'cr   r   r   r   r   r   zSELECT COUNT(*) AS c FROM alerts WHERE status='active' AND rule_id IN ('missing_provider_symbol','ambiguous_provider_mapping','candidate_review_required')r   zmSELECT provider_symbol, exchange, trading_currency FROM instrument_price_mappings WHERE instrument_id='inst1'rz   zTSELECT COUNT(*) AS c FROM instrument_catalog_entries WHERE provider_symbol='GETF.SW')rg   re   r   r   r	   fetchoner   r   r   r   r   r   )	rf   rulery   r   r   r   r   r   r   s	            r   Ftest_candidate_confirmation_resolves_mapping_alerts_and_writes_catalogr   u   s   <<Df o o  X  [_  aj  ly  {G  IP  RV  X\  ^f  hm  Zn  	o  	o  	o  	o#^6GQ[mv  BG  RW  ^q  xF  TY  mu  G^  7_  7_  7_  6`  %a  b  bHx8888<< ^__hhjjkyzLTCbcccc<<effooqqruv{z{{vz{{{{{{{{{{{vz{{{{{{v{{{{z{{{{{{{{{{{{{{{{{{{{{{{{{{{{<<  u  v  v      A  A  BE  F  K  JK  K  F  JK  K  K  K  K  K  K  K  K  K  K  F  JK  K  K  K  K  K  F  K  K  K  K  JK  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K  K<<  H  I  I  R  R  T  T  Uf  g  t  kt  t  g  kt  t  t  t  t  t  t  t  t  t  t  g  kt  t  t  t  t  t  g  t  t  t  t  kt  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t  t<<nooxxzz{~  E  DE  E  DE  E  E  E  E  E  E  E  E  E  E  DE  E  E  E  E  E  E  E  E  E  D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r   c            
        t                      } t          dt          ddddd          gi          }t          | |           |                     d                                          d	         }t          | |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|f                                          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 )Nrk   rs   rt   ro   rp   ry   rz   r    r!   r   r   r   r   zwrong listingr   zKSELECT COUNT(*) AS c FROM audit_log WHERE action='reject_mapping_candidate'r   r   r   r   r   r   r   zRSELECT review_status FROM instrument_price_mapping_candidates WHERE candidate_id=?r   rejected)rg   r   r   r	   re   r   r   r   r   r   r   r   )rf   ry   r   r   r   r   r   r   s           r   %test_candidate_rejection_writes_auditr      s   <<D#^6GQ[mv  BG  RW  ^l  7m  7m  7m  6n  %o  p  pHx8888<< ^__hhjjkyzLT?SSSS<<effooqqruv{z{{vz{{{{{{{{{{{vz{{{{{{v{{{{z{{{{{{{{{{{{{{{{{{{{{{{{{{{{<<lo{n}~~  H  H  J  J  KZ  [  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  i  i  i  i  i  ir   c            
         t                      } t          dt          ddddd          gi          }t          | |           t	          |            t          j        t                      |            d S )Nrk   rs   rt   ro   rp   r   r   )rg   r   r   r	   r   r   renderr0   )rf   ry   s     r   Ctest_dashboard_review_ui_renders_ranked_candidates_without_live_apir     s    <<D#^6GQ[mv  BG  RW  ^l  7m  7m  7m  6n  %o  p  pHx8888"4((( 400000r   c                    t          d          } | j        } |            }|sddt          j                    v st	          j        |           rt	          j        |           ndt	          j        |          t	          j        |          dz  }t          t	          j        |                    d x}}| 	                    d          }d}||v }|st	          j
        d|fd	||f          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}}d}||v }|st	          j
        d|fd	||f          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}}d}t          |          }|j        }	 |	            }
|
 }|sddt          j                    v st	          j        t                     rt	          j        t                     ndt	          j        |          t	          j        |          t	          j        |	          t	          j        |
          dz  }t          t	          j        |                    d x}x}x}	x}
}d S )Nz3docs/personal-finance-cashflow-budgeting-backlog.mdzAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}docr   r   r   zBacklog onlyr   r   r   r   r   r   zDo not implementz#src/jarvis_finance/personal_financezcassert not %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}.exists
}()
}r   )r   r   r   r   r   )r   existsr   r   r   r   r   r   r   r   r   )r  r   r   r   r   r   r   r   r   r   r   r   @py_format10s                r   Dtest_personal_finance_backlog_document_exists_without_implementationr     sM   
D
E
EC:::<<<33:<=='=**D!>T!!!!!!!!!!>T!!!!!>!!!!!!!!!!!T!!!!!T!!!!!!!!!!!!!!!!!!!!!!!!!!!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%9Ct9::C:ACAACCCCCCCCCCCCCCCCCCtCCCCCtCCCCCC9CCCC:CCCCA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CCr   )rh   ri   )%
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   pathlibr   jarvis_finance.dashboardr   jarvis_finance.dashboard.pagesr   %jarvis_finance.market_data.candidatesr   r   r	   r
   r   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r(   r0   rg   r   r   r   r   r   r  r  r&   r   r   <module>r     s   " " " " " "                     ) ) ) ) ) ) @ @ @ @ @ @                  ; : : : : : > > > > > >; ; ; ; ; ; ; ;       4 4 4 4 4 4 4 4,  	6 	6 	6 	6= = = ="I I I I$E E E Ei i i i1 1 1 1D D D D D Dr   