
    mj(                    
   d dl mZ d dlmZ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mZmZ d d	lmZ d d
lmZ  eddde          Zd Zd'd(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 ))    )annotations)UTCdatetime)Decimal)
TestClient)get_db)
create_appcombined_freshness)_safe_account_labelbuild_reconciliation_snapshotlist_reconciliation_recordslist_snapshot_metadata)connect_memory)apply_migrationsi        )tzinfoc                     t                      } t          |            |                     d           |                     d           |                                  | S )NzINSERT INTO platforms(platform_id, name, platform_type, default_currency, created_at) VALUES ('plat_test', 'Synthetic Bank', 'bank', 'CHF', '2026-01-01')zINSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, is_active, created_at) VALUES ('acct_test', 'plat_test', 'Testkonto', 'cash', 'CHF', 1, '2026-01-01'))r   r   executecommitconns    5tests/unit/test_reconciliation_snapshot_foundation.pydbr      sk    DTLL  m  n  n  nLL  M  N  N  NKKMMMK    CHFsnapshot_typestrdateamountcurrencyreturnNonec           	     x    |                      dd| d| d| |||||f           |                                  d S )NzINSERT INTO cash_account_snapshots(snapshot_id, account_id, snapshot_type, balance_date, amount_original, currency, amount_chf, source, created_at)
           VALUES (?, 'acct_test', ?, ?, ?, ?, ?, 'synthetic', '2026-05-21T10:00:00Z')snap__)r   r   )r   r   r    r!   r"   s        r   add_snapshotr(      s[    LL	Z	2	2	2	2	2	2	2M4QY[ab  
 	KKMMMMMr   c                :    t          | t                    d         S )Nnowr   )r   NOWr   s    r   recordr-   $   s    &t555a88r   c                 p   t                      } t          | ddd           t          | ddd           t          |           }|j        dk    sJ |j        dk    sJ |j        dk    sJ |j        dk    sJ |j        dk    sJ |                     d          	                                d	         d	k    sJ d S )
Ncsv_anchor_balance
2026-05-20100.00manual_balance
reconciledz0.00freshz!SELECT COUNT(*) FROM transactionsr   )
r   r(   r-   status
differenceledger_balancesnapshot_balancefreshness_statusr   fetchoner   items     r   Atest_identical_comparable_balances_are_reconciled_without_a_writer=   (   s    44D+\8DDD'x@@@$<<D;,&&&&?f$$$$(**** H,,,, G++++<<;<<EEGGJaOOOOOOr   c                 *   t                      } t          | ddd           t          | ddd           t          |           }|j        dk    sJ |j        dk    sJ t          |j                  t          d          t          d          z
  k    sJ d S )Nr/   r0   z100.10r2   z99.90r6   z0.20)r   r(   r-   r5   r6   r   r;   s     r   Atest_difference_uses_ledger_minus_snapshot_with_decimal_semanticsr?   7   s    44D+\8DDD'w???$<<D;,&&&&?f$$$$4?##wx'8'877;K;K'KKKKKKKr   c                     t                      } t          | ddd           t          |           }|j        dk    sJ |j        J |j        J d|j        v sJ d S )Nr/   r0   r1   partialcomparison_snapshot_missing)r   r(   r-   r5   r8   r6   reason_codesr;   s     r   3test_missing_comparison_balance_is_partial_not_zerorD   C   su    44D+\8DDD$<<D;)#### (((?"""(D,=======r   c                    t                      } t          | ddd           t          | dddd           t          |           j        dk    sJ t          |           j        J t                      } t          | ddd           t          | ddd           t          |           j        dk    sJ d	t          |           j        v sJ d S )
Nr/   r0   r1   r2   USDr"   not_comparablez
2026-05-19as_of_mismatch)r   r(   r-   r5   r6   rC   r   s    r   3test_currency_or_as_of_mismatch_is_never_subtractedrJ   O   s    44D+\8DDD'x%PPPP$<<"22222$<<"***44D+\8DDD'x@@@$<<"22222vd||8888888r   c                     t                      } t          | ddd           t          | ddd           t          |           }|j        dk    sJ |j        dk    sJ t                      } t          | ddd           t          | ddd           t          |           }|j        d	k    sJ |j        d
k    sJ |j        dk    sJ t                      } t          |           }|j        dk    sJ |j        |j        J d S )Nr/   
2026-01-01r1   r2   r3   stalez100.004z100.000r6   0.004unavailable)r   r(   r-   r5   r9   r6   r7   r8   r;   s     r   =test_stale_freshness_does_not_replace_a_reconciliation_resultrP   ]   s#   44D+\8DDD'x@@@$<<D;,&&&& G++++44D+\9EEE'yAAA$<<D;,&&&&?g%%%% G++++44D$<<D;-''''&4+@+H+HH+H+Hr   c                    t                      } |                     d           |                     d           |                                  t          | t                    }t          d |D                       }t          d |D                       }|j        dk    r|j        dk    sJ |j        dk    sJ |j	        d	k    r|j
        d
k    r|j        dk    sJ t          |j                  t          d          k    sJ d S )Na  INSERT INTO account_value_snapshots(snapshot_id, account_id, valuation_date, total_value_chf, currency, source_type, quality_status, created_at) VALUES ('value_1', 'acct_test', '2026-05-20', '12.34', 'CHF', 'manual_total_value', 'ok', '2026-05-21T10:00:00Z')zINSERT INTO fx_rates(fx_rate_id, base_currency, quote_currency, rate_date, rate, provider, rate_type, quality_status, created_at) VALUES ('fx_1', 'USD', 'CHF', '2026-05-20', '0.91234567', 'synthetic_fx', 'close', 'fresh', '2026-05-21T10:00:00Z')r*   c              3  0   K   | ]}|j         d k    |V  dS )account_valuationNsnapshot_kind.0rows     r   	<genexpr>zVtest_snapshot_and_fx_metadata_keep_actual_as_of_and_decimal_strings.<locals>.<genexpr>{   s0      UUSC,=AT,T,TS,T,T,T,TUUr   c              3  0   K   | ]}|j         d k    |V  dS )fx_rateNrT   rV   s     r   rY   zVtest_snapshot_and_fx_metadata_keep_actual_as_of_and_decimal_strings.<locals>.<genexpr>|   s/      DDcS%6)%C%Cc%C%C%C%CDDr   r0   z2026-05-21T10:00:00Zz12.34rF   r   z
0.91234567)r   r   r   r   r,   nextas_ofreceived_atvaluebase_currencyquote_currencyr   )r   rows	valuationfxs       r   Ctest_snapshot_and_fx_metadata_keep_actual_as_of_and_decimal_stringsre   s   s+   44DLL  V  W  W  WLL  I  J  J  JKKMMM!$C000DUUDUUUUUI	DDTDDD	D	DB?l**y/DH^/^/^/^^?g%%%%u$$):e)C)CT`H`H`H``28 5 5555555r   c                 z   t                      } t          | dddd           t          | dddd           t          |           }|j        dk    sJ |j        J t                      } t          | ddd	d           t          | ddd
d           t          |           }|j        dk    sJ |j        dk    sJ d S )Nr/   r0   r1   rF   rG   r2   r   rH   z1.234z1.230r6   rN   )r   r(   r-   r5   r6   r;   s     r   Ctest_ledger_anchor_currency_and_subunit_difference_are_never_hiddenrg      s    44D+\8eTTTT'x%PPPP$<<D;*****?"""44D+\7USSSS'wOOOO$<<D;,&&&&?g%%%%%%r   c                 4    t          ddg          dk    sJ d S )NrM   rO   rA   r
    r   r   .test_mixed_stale_and_missing_source_is_partialrj      s&    w6779DDDDDDr   c                 P   t                      } dD ]\  }}}|                     d|||f            dD ]\  }}}|                     d|||f            |                                  t          | t                    }t          |          dk    sJ d |D             dd	hk    sJ d S )
N))	old_valuerL   z1.00)	new_valuer0   2.00zINSERT INTO account_value_snapshots(snapshot_id, account_id, valuation_date, total_value_chf, currency, source_type, quality_status, created_at) VALUES (?, 'acct_test', ?, ?, 'CHF', 'manual_total_value', 'ok', '2026-05-21T10:00:00Z')))old_fxrL   z0.90)new_fxr0   0.91zINSERT INTO fx_rates(fx_rate_id, base_currency, quote_currency, rate_date, rate, provider, rate_type, quality_status, created_at) VALUES (?, 'USD', 'CHF', ?, ?, 'synthetic_fx', 'close', 'fresh', '2026-05-21T10:00:00Z')r*      c                6    h | ]}|j         |j        |j        fS ri   )rU   r_   r]   rV   s     r   	<setcomp>zWtest_metadata_uses_only_latest_row_per_logical_series_and_is_bounded.<locals>.<setcomp>   s&    FFF#S	395FFFr   )rS   rn   r0   )r[   rq   r0   )r   r   r   r   r,   len)r   snapshot_idr    r_   rate_idrb   s         r   Dtest_metadata_uses_only_latest_row_per_logical_series_and_is_boundedrx      s5   44D$n ^ ^ T5  A  DO  QU  W\  C]  	^  	^  	^  	^ d K Ku  r  u|  ~B  DI  tJ  	K  	K  	K  	KKKMMM!$C000Dt99>>>>FFFFFKv  yZ  K[  [  [  [  [  [  [r   c                    t                                          d                               d                               d                               d                               d                                            t          d          } fd| j        t
          <   t          |                               d	          }|j        d
k    sJ |j	        }d|vrd|vrd|vsJ d|v rd|v rd|v sJ d S )NzoUPDATE accounts SET account_name='CH9300762011623852957', account_id='acct_secret' WHERE account_id='acct_test'zWUPDATE cash_account_snapshots SET account_id='acct_secret' WHERE account_id='acct_test'a  INSERT INTO cash_account_snapshots(snapshot_id, account_id, snapshot_type, balance_date, amount_original, currency, amount_chf, source, created_at) VALUES ('anchor', 'acct_secret', 'csv_anchor_balance', '2026-05-20', '1.00', 'CHF', '1.00', 'local', '2026-05-20T12:00:00Z')a  INSERT INTO cash_account_snapshots(snapshot_id, account_id, snapshot_type, balance_date, amount_original, currency, amount_chf, source, created_at) VALUES ('manual', 'acct_secret', 'manual_balance', '2026-05-20', '1.00', 'CHF', '1.00', 'local', '2026-05-20T12:00:00Z')a  INSERT INTO account_value_snapshots(snapshot_id, account_id, valuation_date, total_value_chf, currency, source_type, quality_status, created_at) VALUES ('value_sensitive', 'acct_secret', '2026-05-20', '1.00', 'CHF', '/tmp/secret.csv', 'ok', '2026-05-20T12:00:00Z')disabled
write_modec                      S Nri   r   s   r   <lambda>zMtest_api_redacts_adversarial_account_labels_ids_and_sources.<locals>.<lambda>       t r   &/api/portfolio/reconciliation-snapshot   CH9300762011623852957acct_secretz/tmp/secret.csvzaccount-Konto (redigiert)z"source":"local")
r   r   r   r	   dependency_overridesr   r   getstatus_codetext)appresponserenderedr   s      @r   ;test_api_redacts_adversarial_account_labels_ids_and_sourcesr      sU   44DLL  C  D  D  DLLjkkkLL  d  e  e  eLL  `  a  a  aLL  \  ]  ]  ]KKMMM


+
+
+C'3|||CV$#""#KLLH3&&&&}H"(22}H7T7TYjrzYzYzYzz!!&9X&E&EJ\`hJhJhJhhJhJhr   c                     dD ]} t          |           dk    sJ t          d          dk    sJ t          d          dk    sJ d S )N)r   zch93 0076 2011 6238 5295 71234567890123456*0X1234567890ABCDEF1234567890ABCDEF12345678*BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KYGT080"1BoatSLRHtKNngkdXEeobR76b53LETtpyTz/srv/private/finance.sqlite'wallet_abcdefghijklmnopqrstuvwxyz123456r   zAKB Haushaltskonto
Raiffeisen)r   )	sensitives    r   Rtest_redaction_covers_account_wallet_and_path_identifiers_but_keeps_friendly_namesr      sm     m E E	"9--1DDDDDD3448LLLLL|,,<<<<<<r   c                 
   t                      t          d          } fd| j        t          <   t	          |           }|                    d                                          }|d         d         }t          |          dhk    sJ |                    d          }|j        dk    sJ |j	        
                                }d	|vrd
|vrd|vsJ t          t                      t                    d         dk    sJ d S )Nrz   r{   c                      S r~   ri   r   s   r   r   z\test_read_only_api_and_openapi_contract_expose_no_sensitive_account_fields.<locals>.<lambda>   r   r   z/openapi.jsonpathsr   r   r   ibanwallet_addresssource_filenamer*   data_quality_statusrO   )r   r	   r   r   r   r   jsonsetr   r   lowerr   r,   )r   clientschema
operationsr   r   r   s         @r   Jtest_read_only_api_and_openapi_contract_expose_no_sensitive_account_fieldsr      s   44D


+
+
+C'3|||CV$__FZZ((--//F!IJJz??ug%%%%zzBCCH3&&&&}""$$H!!&6h&F&FK\dlKlKlKll(37778MNR_______r   N)r   )
r   r   r    r   r!   r   r"   r   r#   r$   )'
__future__r   r   r   decimalr   fastapi.testclientr   jarvis_finance.api.dependenciesr   jarvis_finance.api.mainr	    jarvis_finance.quality.freshnessr   /jarvis_finance.services.reconciliation_snapshotr   r   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r,   r   r(   r-   r=   r?   rD   rJ   rP   re   rg   rj   rx   r   r   r   ri   r   r   <module>r      s   " " " " " " " " " " " " " "       ) ) ) ) ) ) 2 2 2 2 2 2 . . . . . . ? ? ? ? ? ? d  d  d  d  d  d  d  d  d  d  d  d : : : : : : > > > > > >htQ3'''      9 9 9P P P	L 	L 	L	> 	> 	>9 9 9I I I,6 6 6 & & & E E E
[ [ [i i i&= = =` ` ` ` `r   