
    UjD                       d dl mZ d dlZd dlmZ d dlmZ d dlZd dlm	Z	m
Z
mZmZmZ d dlmZ d dlmZ d dlmZ d	Zd
 Zd)d*dZd+dZd,dZd Zd-dZd-dZ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S ).    )annotationsN)Decimal)sha256)TrueWealthActivityTrueWealthCashTrueWealthPositionTrueWealthStatementparse_truewealth_text)truewealth_service)connect_memory)apply_migrationsaccount_truewealth_testc                    t                      } t          |            |                     d           |                     dt          f           |                     dt          f           |                                  | S )NzINSERT INTO platforms(platform_id,name,platform_type,country,default_currency,is_active,created_at) VALUES('p','True Wealth','robo','CH','CHF',1,'2026-01-01')zINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,performance_included,is_active,created_at,portfolio_bucket)
           VALUES(?,'p','Manual Portfolio','managed_portfolio','CHF',0,1,'2026-01-01','truewealth')a  INSERT INTO account_value_snapshots(snapshot_id,account_id,valuation_date,total_value_chf,currency,source_type,quality_status,notes,created_at)
           VALUES('legacy_manual',?,'2026-06-30','10000','CHF','manual_total_value','ok','historical','2026-06-30T12:00:00Z'))r   r   executeTEST_ACCOUNT_IDcommit)conns    !tests/test_truewealth_sprint12.py	make_connr      s    DTLL 	i   	LL	g	  
 	LL	A	  
 	KKMMMK    
2026-07-2712000rawbytesdatestrtotalreturnr	   c                R   t          |d|t          |          t          dddt          d          dt          d          t          d                    t          d	d
dt          d          dt          d          t          d                    ft          ddt          d          d t          d                    ft	          |                                           dt          t	          d                                          ddddt          d          d d           f	  	        S )Nz
2026-01-01zposition:CH0000000001zSynthetic ETF ACH0000000001100CHF505000zposition:US0000000002zSynthetic ETF BUS0000000002202004000zcash:CHF3000   s   synthetic-activityz
2026-02-01buy2)source_row_fingerprintoccurred_on
event_typeinstrument_nameisinquantitygross_amount_chftax_amount_chf)	statement_dateperiod_from	period_tosource_total_chf	positionscashfile_sha256
page_count
activities)r	   r   r   r   r   	hexdigestr   )r   r   r   s      r   	statementr?   +   sR     68I>[bch[i[ikpryz~rr  BI  JP  BQ  BQ  R  R68I>[bcg[h[hjoqxy~qq  BI  JP  BQ  BQ  R  R
 ZwvWWY3KK))++'-.C'D'D'N'N'P'P(  1# !%#	 	 	
   r   dict[str, str]c                `    t           dt          j        |                                           dS )Nzofficial.pdf)
account_id	file_namecontent_base64)r   base64	b64encodedecode)r   s    r   import_requestrH   G   s1    %# *3//6688  r   c                    t          |          }t          j        | |          }t          j        | i ||d         |d         dd          S )N
preview_idconfirmation_idTrJ   rK   confirm)rH   servicepreview_truewealth_importconfirm_truewealth_import)r   r   requestpreviews       r   confirm_importrS   O   s\    S!!G/g>>G,x7x',"7GTeLfswxxx  r   c                 *   d} t          | dd          }|j        dk    sJ |j        t          d          k    sJ |j        d         j        dk    sJ |j        d         j        t          d	          k    sJ |j        t          d
          k    sJ d S )Nuy  
True Wealth AG
Periode 01.01.2026 - 27.07.2026
Steuerauszug in CHF 27.07.2026
Total Steuerwert der A, B, DA-1 und USA-Werte am 27.07.2026
12’000 0 0 0
CHF (Synthetic Custodian AG)
27.07.2026 Steuerwert / Ertrag CHF 7’000.00 7’000.00 0.00
0000000 CH0000000001 - Synthetic ETF A, CH
27.07.2026 Bestand / Steuerwert / Ertrag 100.00 CHF 50.00 5’000.00 0.00
True Wealth AG
	synthetic   r;   r<   r   r   r   r    z7000.0012000.00)	r
   r5   r8   r   r9   r1   r:   amount_originalcomponents_total_chftextparseds     r   @test_text_parser_extracts_official_rows_without_inventing_valuesr^   X   s    D #4[QOOOF L0000"gg&6&66666A#~5555;q>)WY-?-?????&'**=*=======r   Nonec                     d} t          | dd          }d |j        D             g dk    sJ |j        d         j        t          d          k    sJ t	          d |j        D                       d	k    sJ d S )
Nu  
True Wealth AG
Periode 01.01.2026 - 26.08.2026
Steuerauszug in CHF 26.08.2026
Total Steuerwert der A, B, DA-1 und USA-Werte am 26.08.2026
12’000 0 0 0
CHF (Synthetic Custodian AG)
26.08.2026 Steuerwert / Ertrag CHF 7’000.00 7’000.00 0.00
0000000 CH0000000001 - Synthetic ETF A, CH
05.01.2026 Kauf + 2.00
06.01.2026 Bardividende 2.00 CHF 1.50 03.01. 3.00
21.04.2026 Aktiensplit Abgang - 2.00
21.04.2026 Aktiensplit Zugang + 20.00
26.08.2026 Bestand / Steuerwert / Ertrag 100.00 CHF 50.00 5’000.00 0.00
True Wealth AG
rU   rV   rW   c                    g | ]	}|j         
S  )r/   .0rows     r   
<listcomp>zatest_text_parser_extracts_internal_activity_without_marking_external_cashflow.<locals>.<listcomp>   s    888sCN888r   )r+   dividend	split_outsplit_inz3.00c                    h | ]	}|j         
S rb   r-   rc   s     r   	<setcomp>z`test_text_parser_extracts_internal_activity_without_marking_external_cashflow.<locals>.<setcomp>   s    HHHs*HHHr      )r
   r=   r3   r   lenr[   s     r   Mtest_text_parser_extracts_internal_activity_without_marking_external_cashflowro   m   s    D" #4[QOOOF88f&7888<h<h<hhhhhQ0GFOOCCCCHHf6GHHHIIQNNNNNNr   c                 "   d} t          | dd          }t          | dd          }t          |j                  dk    sJ |j        d         j        |j        d         j        k    sJ d |j        D             d |j        D             k    sJ d S )	Nu  
True Wealth AG
Periode 01.01.2026 - 26.08.2026
Steuerauszug in CHF 26.08.2026
Total Steuerwert der A, B, DA-1 und USA-Werte am 26.08.2026
12’000 0 0 0
CHF (Synthetic Custodian AG)
26.08.2026 Steuerwert / Ertrag CHF 7’000.00 7’000.00 0.00
0000000 CH0000000001 - Synthetic ETF A, CH
05.01.2026 Kauf + 2.00
05.01.2026 Kauf + 2.00
26.08.2026 Bestand / Steuerwert / Ertrag 100.00 CHF 50.00 5’000.00 0.00
True Wealth AG
rU   rV   rW      r   c                    g | ]	}|j         
S rb   rk   rc   s     r   rf   zZtest_text_parser_keeps_repeated_identical_same_day_activities_distinct.<locals>.<listcomp>   s    CCC3C&CCCr   c                    g | ]	}|j         
S rb   rk   rc   s     r   rf   zZtest_text_parser_keeps_repeated_identical_same_day_activities_distinct.<locals>.<listcomp>   s.     H H H'*"H H Hr   )r
   rn   r=   r-   )r\   firstreplays      r   Ftest_text_parser_keeps_repeated_identical_same_day_activities_distinctrv      s    D "$KANNNE"4[QOOOFu  A%%%%A59I!9L9cccccCC%2BCCC H H.4.?H H H      r   c                     d} t          | dd          }|j        t          d          k    sJ |j        t          d          k    sJ d S )Nu  
True Wealth AG
Periode 01.01.2026 - 26.08.2026
Steuerauszug in CHF 26.08.2026
Total Steuerwert der A, B, DA-1 und USA-Werte am 26.08.2026
12’001 0 0 0
CHF (Synthetic Custodian AG)
26.08.2026 Steuerwert / Ertrag CHF 7’000.10 7’000.10 0.00
Total Bankkonten 7’000.10 0.00 0.00
0000000 CH0000000001 - Synthetic ETF A, CH
26.08.2026 Bestand / Steuerwert / Ertrag 100.00 CHF 50.00 5’000.19 0.00
Total Wertschriften 5’000.19 0.00 0.00
True Wealth AG
rU   rV   rW   z12000.29)r
   r8   r   rZ   r[   s     r   Ktest_text_parser_prefers_exact_component_subtotals_over_rounded_tax_summaryrx      s]    D #4[QOOOF"gj&9&99999&'**=*=======r   c                    t                      } t          j        |           }|d         dk    sJ |d         du sJ d|d                                         v sJ |d         du sJ t          j        | d	dd
dd           t          j        |           }|d         J t          d |d         D                       sJ d S )Ncurrent_source_typemanual_total_valuecurrent_is_manual_provisionalTmanuellcurrent_labelallocation_performance_usableFlegacy_manual
reversibleactivenoterM   current_value_chfc              3  F   K   | ]}|d          dk    o|d         dk    V  dS )snapshot_idr   	is_activer   Nrb   rc   s     r   	<genexpr>zItest_legacy_manual_value_is_never_labelled_as_official.<locals>.<genexpr>   s<      nnSVs=!_4N[9IQ9Nnnnnnnr   history)r   rN   get_truewealth_summarylower"set_manual_truewealth_value_activeany)r   summarydisableds      r   6test_legacy_manual_value_is_never_labelled_as_officialr      s    ;;D,T22G()-AAAAA23t;;;;06688888823u<<<<.t_QV`ly}F~F~-d33H'(000nnZbclZmnnnnnnnnnnr   c                t   t                      }|                    d           |                    d           |                                 d}|                     t          dd            t	          j        |t          |                    }|d         dk    sJ t	          j        |          d         J d S )	Nz<UPDATE platforms SET name='TrueWealth' WHERE platform_id='p'z#DELETE FROM account_value_snapshotss   %PDF-synthetic-bootstrapparse_truewealth_tax_statementc                     t          |           S Nr?   values    r   <lambda>zRtest_platform_spelling_without_space_and_empty_account_bootstrap.<locals>.<lambda>       QZ[`QaQa r   reconciliation_statusmatchedr   )r   r   r   setattrrN   rO   rH   r   )monkeypatchr   r   rR   s       r   @test_platform_spelling_without_space_and_empty_account_bootstrapr      s    ;;DLLOPPPLL6777KKMMM
%C!ACaCabbb/nS6I6IJJG*+y8888)$//0CDLLLLLr   c                   t                      }d}|                     dt          |                     |                     t          dd            t          ||          }t          ||          }t	          j        |          }|d         du sJ |d         du sJ |d         |d         k    sJ |d	         d
k    sJ |d         dk    sJ |d         du sJ t          |d                   dk    sJ |                    d          	                                d         dk    sJ |                    d          	                                d         dk    sJ |                    d          	                                d         dk    sJ |                    dt          f          	                                }t          |          dk    sJ |                    dt          f          	                                d         dk    sJ |dz  dz  dz  t          |                                           dz  }|                                |k    sJ |                                j        dz  dk    sJ d S )Ns   %PDF-1.7 official-aJARVIS_FINANCE_RUNTIME_DIRr   c                     t          |           S r   r   r   s    r   r   zStest_official_confirm_is_idempotent_preserves_legacy_and_archives.<locals>.<lambda>   r   r   
idempotentFTbatch_idr   rX   rz   truewealth_official_importr   r9   rq   zNSELECT COUNT(*) FROM account_value_snapshots WHERE snapshot_id='legacy_manual'r   rV   .SELECT COUNT(*) FROM truewealth_import_batchesz*SELECT COUNT(*) FROM truewealth_activitieszySELECT included,classification_role,decision_version
           FROM performance_scope_classifications WHERE account_id=?)rV    canonical_truewealth_total_valueinvestment_performance_scope_v1znSELECT COUNT(*) FROM audit_log
           WHERE entity_type='performance_scope_classification' AND entity_id=?imports
truewealtharchivez.pdfi  i  )r   setenvr   r   rN   rS   r   rn   r   fetchoner   tupler   r>   
read_bytesstatst_mode)	r   tmp_pathr   r   rt   secondr   classificationarchiveds	            r   Atest_official_confirm_is_idempotent_preserves_legacy_and_archivesr      s   ;;D
 C3S]]CCC!ACaCabbb4%%ED#&&F,T22G%'''',4''''*z!22222&':5555()-IIIII23t;;;;w{#$$))))<<hiirrttuvw{|||||<<HIIRRTTUVW[\\\\\<<DEENNPPQRSWXXXXX\\	H	  hjj	 
   $nnnnn<<	S	  hjj	 	   
 )#l2Y>F3KKDYDYD[D[AaAaAaaH  C''''==??"U*e333333r   c                   t                      }d}|                     dt          |                     |                     t          dd            t          ||           dddd}t	          j        ||          }t	          j        |i ||d	         |d
         dd          t	          j        |          }|d         dk    sJ |d         du sJ |d         dk    sJ |d         du sJ |d         du sJ t          |d                   dk    sJ t	          j
        |d         dddd           t	          j        |          }|d         dk    sJ |d         dk    sJ t          fd|d         D                       sJ t	          j
        |d         dddd           t	          j        |          d         dk    sJ d S ) Ns   %PDF-1.7 official-br   r   c                     t          |           S r   r   r   s    r   r   z]test_newer_manual_value_wins_without_changing_positions_and_can_be_reversed.<locals>.<lambda>   r   r   125002026-07-28T08:00:00Zzportal viewtotal_value_chfvaluation_atr   rJ   rK   TrL   r   12500.00r|   positions_snapshot_dater   mixed_as_ofr   Fr9   rq   r   revertr   rX   rz   r   c              3  T   K   | ]"}|d          d          k    o|d         dk    V  #dS )r   r   r   Nrb   )rd   re   results     r   r   z^test_newer_manual_value_wins_without_changing_positions_and_can_be_reversed.<locals>.<genexpr>  sC      ttY\s=!VM%::Ts;?OST?Tttttttr   r   
reactivate)r   r   r   r   rN   rS   preview_manual_truewealth_valueconfirm_manual_truewealth_valuer   rn   r   r   )	r   r   r   r   payloadrR   r   restoredr   s	           @r   Ktest_newer_manual_value_wins_without_changing_positions_and_can_be_reversedr      sc   ;;D
 C3S]]CCC!ACaCabbb4");Q[hiiG5dGDDG4x7x',"7GTeLfswxxx F ,T22G&':555523t;;;;,-=====!T))))23u<<<<w{#$$)))).tVM5JW\fn{  MA  MA  B  B  B-d33H'(J6666)*.JJJJJtttt`hir`stttttttt.tVM5JW[eq  C  MD  MD  E  E  E)$//0CD
RRRRRRr   c                   t                      }|                     dt          |                     dd}|                     t          dfd           t          |           dddd	}t	          j        ||          }t	          j        |i ||d
         |d         dd           t          ||           t	          j        |          }|d         dk    sJ |d         dk    sJ d S )Nr   s   %PDF-1.7 official-news   %PDF-1.7 official-oldr   c                4    t          | | k    rdnd          S )Nr   z
2026-07-20r   )r   
newest_raws    r   r   zItest_older_official_import_cannot_displace_newer_manual.<locals>.<lambda>  s>    QZ[`rw  |F  sF  sFbnbn  LX  RY  RY r   r   r   znewer manualr   rJ   rK   TrL   r   r   r   r   )	r   r   r   r   rN   rS   r   r   r   )r   r   r   old_rawr   rR   r   r   s          @r   7test_older_official_import_cannot_displace_newer_manualr     sP   ;;D3S]]CCC)J&G!A  DY  DY  DY  DY  Z  Z  Z4$$$");Q[ijjG5dGDDG+D  3cW  3cGT`Lav}  P  wQ  ^b  3c  3c  3c  d  d  d4!!!,T22G&':5555,-======r   c                   t                      }|                     dt          |                     dddd}t          j        ||          }t          j        |i ||d         |d         dd	           d
}|                     t          dd            t          ||           t          j        |          d         dk    sJ d S )Nr   11500z2026-07-27T22:00:00Zzsame dayr   rJ   rK   TrL   s   %PDF-1.7 same-dayr   c                     t          |           S r   r   r   s    r   r   zAtest_same_day_official_has_priority_over_manual.<locals>.<lambda>(  r   r   rz   r   )	r   r   r   rN   r   r   r   rS   r   )r   r   r   r   rR   r   s         r   /test_same_day_official_has_priority_over_manualr   !  s    ;;D3S]]CCC");Q[effG5dGDDG+D  3cW  3cGT`Lav}  P  wQ  ^b  3c  3c  3c  d  d  d
C!ACaCabbb4)$//0EFJfffffffr   c                    t                      }d}|                     t          dd            |j        }t          j        |t          |                     t          j        |           |j        |k    sJ d S )Ns   %PDF-1.7 preview-onlyr   c                     t          |           S r   r   r   s    r   r   z;test_preview_and_get_are_side_effect_free.<locals>.<lambda>0  r   r   )r   r   rN   total_changesrO   rH   r   )r   r   r   befores       r   )test_preview_and_get_are_side_effect_freer   -  s{    ;;D
"C!ACaCabbbF%dN3,?,?@@@"4(((''''''r   c                   t                      }d}|                     dt          |                     |                     t          dd            t          ||          }t          j        t          d          5  |	                    d|d         f           d d d            n# 1 swxY w Y   t          j        t          d	          5  |	                    d
|d         f           d d d            d S # 1 swxY w Y   d S )Ns   %PDF-1.7 immutabler   r   c                     t          |           S r   r   r   s    r   r   zGtest_immutable_source_tables_reject_update_and_delete.<locals>.<lambda>;  r   r   	immutablematchzHUPDATE truewealth_snapshots SET source_total_chf='0' WHERE snapshot_id=?r   cannot be deletedz4DELETE FROM truewealth_snapshots WHERE snapshot_id=?)
r   r   r   r   rN   rS   pytestraises	Exceptionr   )r   r   r   r   r   s        r   5test_immutable_source_tables_reject_update_and_deleter   7  s   ;;D
C3S]]CCC!ACaCabbbD#&&F	y	4	4	4 { {_bhivbwayzzz{ { { { { { { { { { { { { { {	y(;	<	<	< g gKfUbNcMefffg g g g g g g g g g g g g g g g g gs$   <B&&B*-B*C77C;>C;c           	        t                      }|                     dt          |                     d|                     t          dfd           t                    }t	          j        ||          }|                    d           t          j	        t          d          5  t	          j        |i ||d         |d	         d
d           d d d            n# 1 swxY w Y   t          |dz  dz  dz                      d                    rJ |                    d                                          d         dk    sJ d S )Nr   s   %PDF-synthetic-rollbackr   c                "    t                    S r   r   )_rawr   s    r   r   z;test_confirm_rollback_removes_new_archive.<locals>.<lambda>G  s    PYZ]P^P^ r   z{CREATE TRIGGER force_truewealth_failure BEFORE INSERT ON truewealth_import_batches BEGIN SELECT RAISE(ABORT, 'forced'); END
conflictedr   rJ   rK   TrL   r   r   r   z*.pdfr   r   )r   r   r   r   rN   rH   rO   r   r   r   
ValueErrorrP   listglobr   )r   r   r   rQ   rR   r   s        @r   )test_confirm_rollback_removes_new_archiver   C  s   ;;D3S]]CCC
$C!AC^C^C^C^___S!!G/g>>GLL	3   
z	6	6	6 
 
)|w|gl&;PWXiPjw{|||	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 X	)L89DJJ7SSTTTTT<<HIIRRTTUVW[\\\\\\\s   (*CC"%C"c           	     @   t                      }|                     dt          |                     |                     t          dd            t          |d           t          d          }t	          j        ||          }|d         du sJ t          j	        t          d	          5  t	          j        |i ||d
         |d         dd           d d d            n# 1 swxY w Y   |                    d                                          d         dk    sJ d S )Nr   r   c                     t          |           S r   r   r   s    r   r   zEtest_same_date_different_official_source_is_blocked.<locals>.<lambda>Z  r   r   s   %PDF-1.7 source-ones   %PDF-1.7 source-twoconflictTz$different official TrueWealth sourcer   rJ   rK   rL   r   r   rV   )r   r   r   r   rN   rS   rH   rO   r   r   r   rP   r   r   )r   r   r   r   rR   s        r   3test_same_date_different_official_source_is_blockedr   W  sk   ;;D3S]]CCC!ACaCabbb4/000233F/f==G:$&&&&	z)O	P	P	P 
 
){v{W\%:wWhOivz{{{	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 <<HIIRRTTUVW[\\\\\\\s   **C  C$'C$c            	         t                      } dD ]N}t          j        t          d          5  t	          j        | |ddd           d d d            n# 1 swxY w Y   Od S )N)NaNInfinityz	-Infinityzpositive finiter   r    r   )r   r   r   r   rN   r   )r   r   s     r   *test_manual_non_finite_values_are_rejectedr   g  s    ;;D1  ]:->??? 	 	3$);Q[]^^  	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 s   AA	A	c                    t                      } dddd}t          j        | |          }t          j        | i ||d         |d         dd          }t	          j        t          d	
          5  |                     d|d         f           d d d            n# 1 swxY w Y   t	          j        t          d
          5  |                     d|d         f           d d d            d S # 1 swxY w Y   d S )Nr   r   zimmutable valuer   rJ   rK   TrL   zfields are immutabler   zJUPDATE account_value_snapshots SET total_value_chf='1' WHERE snapshot_id=?r   r   z7DELETE FROM account_value_snapshots WHERE snapshot_id=?)r   rN   r   r   r   r   r   r   )r   r   rR   r   s       r   4test_manual_value_is_not_hard_deleted_or_overwrittenr   q  s   ;;D");Q[lmmG5dGDDG4x7x',"7GTeLfswxxx F 
y(>	?	?	? } }adjkxdyc{|||} } } } } } } } } } } } } } }	y(;	<	<	< j jNQWXeQfPhiiij j j j j j j j j j j j j j j j j js$   .BBB>C))C-0C-)r   r   )r   r   r   r   r   r   r   r	   )r   r   r   r@   )r   r   )r   r_   )*
__future__r   rE   decimalr   hashlibr   r   /jarvis_finance.imports.truewealth_tax_statementr   r   r   r	   r
   jarvis_finance.servicesr   rN   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r   r?   rH   rS   r^   ro   rv   rx   r   r   r   r   r   r   r   r   r   r   r   r   rb   r   r   <module>r      sI   " " " " " "                            B A A A A A : : : : : : > > > > > >+  (    8      > > >*O O O O2   4> > > >,
o 
o 
o	M 	M 	M!4 !4 !4HS S S<> > > 	g 	g 	g( ( (	g 	g 	g] ] ](] ] ]   j j j j jr   