
    wohjÕ                    T   d dl mZ d dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dl
Z
d dlmZmZ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mZ d d
lmZ d dlm Z m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z) d dl*m+Z+ dZ,dZ-d Z.d Z/	 d&d'dZ0d&d(dZ1d Z2d Z3d  Z4d! Z5d" Z6d# Z7d$ Z8d% Z9dS ))    )annotationsN)replace)Decimal)sha256)get_cash_overviewget_command_center_summaryget_positions)PFBundle
PFDocumentPFEvent
PFSnapshotPFSnapshotCashPFSnapshotPosition_reconcile_cash_components)postfinance_service)get_cash_position_detailget_cash_summary)get_equity_summary) latest_official_postfinance_cash%latest_official_postfinance_positions)confirmed_canonical_positions)build_portfolio_reconciliation)get_overview)connect_memory)apply_migrationsaccount_pf_depot_testaccount_pf_trading_cash_testc                    t          t          dt          d          t          d          t          d                    t          dt          d          t          d          t          d                    gt          d                    } d | D             t          d          t          d	          gk    sJ t          d
 | D             t          d                    t          d          k    sJ d S )NEURz-1001USD20z-80.01c                    g | ]	}|j         
S  source_value_chf.0items     "tests/test_postfinance_sprint13.py
<listcomp>zRtest_cash_component_reconciliation_preserves_negative_balances.<locals>.<listcomp>2   s    999dD!999    z-100.01z20.00c              3  $   K   | ]}|j         V  d S Nr%   r'   s     r*   	<genexpr>zQtest_cash_component_reconciliation_preserves_negative_balances.<locals>.<genexpr>6   s%      ==$%======r,   0)r   r   r   sum)
reconcileds    r*   >test_cash_component_reconciliation_preserves_negative_balancesr3   *   s    +5'&//73<<QQ5'$--wt}}MM	
 	 J :9j999	>     ==*===ws||LLPWQ Q      r,   c                    t                      } t          |            |                     d           |                     dt          f           |                     dt          f           t          d          D ]s}d|d}d|dz   d}|                     d	||d
|dd|d|dk     rdndddf           |                     dd| dt          d|ddddddd|dk     rdndddf           t|                                  | S )NzINSERT INTO platforms(platform_id,name,platform_type,country,default_currency,is_active,created_at) VALUES('pf','PostFinance','bank','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(?,'pf','PostFinance E-Trading','brokerage','CHF',0,1,'2026-01-01','postfinance')zINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,performance_included,is_active,created_at,portfolio_bucket) VALUES(?,'pf','PostFinance Cash-Konto','cash','CHF',0,1,'2026-01-01','cash')   instrument_pf_02dSynthetic Asset    zyINSERT INTO instruments(instrument_id,name,ticker,isin,asset_class,currency,is_active,created_at) VALUES(?,?,?,?,?,?,1,?)SCH010d   equityetfCHFz
2026-01-01a;  INSERT INTO positions_snapshot(position_snapshot_id,snapshot_date,account_id,platform_id,instrument_id,quantity,average_cost_original,cost_basis_original,market_price_original,market_value_original,market_fx_rate_to_chf,market_value_chf,category,data_quality_status,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)	baseline_z
2026-06-30pfr    5090completez2026-06-30T00:00:00Z)r   r   executeDEPOTCASHrangecommit)connindex
instrumentlabels       r*   	make_connrO   ;   s   DTLL 	j   	LL 	m	   	LL 	b	   r "
 "
1e111
2519222 HE!U!!!!BJJE	
 	
 	
 	 J#E##!BJJE&	
 	
 	
 	
( 	KKMMMKr,      synthetic-zip   %PDF-synthetic-overviewzip_rawbytesoverview_rawreturnr
   c                   t          |                                           }t          |                                          }d}t          t          |                                          t          d                                          ddt          d                                          dt          d                                          dd	|d
          }t          t          d                                          |j        |j        dddddddt          d          t          d          t          d          t          d          t          d          t          d          dt          d          d dd          }t          t          d                                          |j        ddddddd d d d t          d          t          d          t          d          t          d          dt          d          ddd           }t          t          d!                                          |j        dddddd"d d d d t          d          t          d          t          d          t          d          dt          d          ddd           }t          d# t          d$          D                       }	t          |d%d&|	t          d't          d(          t          d          t          d(                    t          d)t          d(          t          d          t          d(                    ft          d*          t          d+          t          d,          t          d-          t          d-          d.          }
t          ||t          ||z                                                                             |f|||f|
d/d          S )0Ns   %PDF-synthetic-trades	   trade.pdftrade_confirmationzsynthetic-references   semanticz
2026-07-01s   accountetrading_cashr9   	synthetics   eventbuyz
2026-07-03outzSynthetic Asset 01CH0000000000r    rC   r0   51r@   rE   r$   s   transfer-outztransfer-referenceinternal_transferefinancez
2026-07-0210synthetic-transfer-grouppartial)'internal_transfer_not_income_or_expenses   transfer-ininc              3    K   | ]}t          t          d |                                                                           dd         d|dz   dd|dz   d|dk     rdnd	t	          d
          t	          d          t	          d          t	          d          dt	          d          t	          d                    V  dS )zrow-N    r8   r9   r7   zsynthetic asset r=   stockr?   r    rC   100r@   z4.17)r   r   encode	hexdigestr   )r(   rL   s     r*   r/   zbundle.<locals>.<genexpr>   s          	>%>>((**++5577<.uqy....uqy...rzzGGuCLLDMMDMMENNENNFOO	
 	
     r,   r5      2026-07-27T09:14:30+02:00r   rh   r!   220020024001100r   )ra   )r   rj   r   r   document_hashsemantic_referencer   tuplerI   r   r   r
   ri   )rR   rT   zip_hashoverview_hashdoc_rawdocumenteventtransfer_outtransfer_in	positionssnapshots              r*   bundler}   p   s~    g((**H<((2244M%Gw!!##|&&(({%%''z$$&&	 H x""$$#
+ E. ))++"4+ L. ~((**"4+ K.    2YY    I  	#5'%..'#,,OO5'%..'#,,OO	
 		 H  =(002233==??		k*%
	 	 	r,   c                    ddt          j        |                                           t          j        |                                          dS )Nzdocuments.zipzoverview.pdf)zip_file_nameoverview_file_namezip_content_base64overview_content_base64)base64	b64encodedecoderR   rT   s     r*   requestr      sK    (,$.w77>>@@#)#3L#A#A#H#H#J#J	  r,   c                   t                      }g |                     dt          |                     |                     t          dfd           t                      }|j        }t	          j        ||          }|j        |k    sJ |d         dk    sJ t	          j        |i ||d         |d         dd	          }t	          j        ||          }t	          j        |i ||d         |d         dd	          }t                    d
k    sJ |d         du r
|d         du sJ t	          j
        |          }	t          |	          }
d|
vrd|
vsJ d|	d         vsJ d|	d         d         vsJ d|	d         d         vsJ |                    d                                          d         dk    sJ |                    d                                          d         dk    sJ |                    d                                          d         dk    sJ |                    d                                          d         dk    sJ t          |                    d                    }|d         t          k    sJ |d         t          k    sJ |d         t          t          hvsJ t          t!          |                                                    dk    sJ d  |                    d!          D             }|t                   d"k    sJ |t                   d#k    sJ ||d                  d$k    sJ |                    d%                                          d         dk    sJ |                    d&|d         f                                          d         d'k    sJ |                    d(                                          }d) |D             |d         t          hk    sJ d* |D             d+hk    sJ |                    d,                                          d         d-k    sJ t          t'          |dz  d.z  d/z                      d0                              dk    sJ d S )1NJARVIS_FINANCE_RUNTIME_DIRparse_postfinance_bundlec                R                         | |f          pt          | |          S r.   )appendr}   )rR   rT   callss     r*   <lambda>z`test_preview_confirm_and_reparse_are_atomic_idempotent_and_keep_roles_separate.<locals>.<lambda>  s+    LL'<011RVG\5R5R r,   mapped_position_countr5   
preview_idconfirmation_idTr   r   confirm   
idempotentFaccount_pf_r\   snapshot_idlatest_snapshotinstrument_idr{   r   batch_idimports/SELECT COUNT(*) FROM postfinance_import_batchesr9   z*SELECT COUNT(*) FROM postfinance_snapshotsz3SELECT COUNT(*) FROM postfinance_snapshot_positionsz.SELECT COUNT(*) FROM postfinance_account_roles   z5SELECT role,account_id FROM postfinance_account_rolesetrading_depotrX   r_   c                <    i | ]}|d          |d         |d         fS )
account_idincludedclassification_roler$   r(   rows     r*   
<dictcomp>zbtest_preview_confirm_and_reparse_are_atomic_idempotent_and_keep_roles_separate.<locals>.<dictcomp>3  s>        	LC
OS1F-GH  r,   zUSELECT account_id,included,classification_role FROM performance_scope_classifications)r9   postfinance_etrading_depot)r9   postfinance_etrading_cash)r   postfinance_efinance_controlzSSELECT COUNT(*) FROM audit_log WHERE entity_type='performance_scope_classification'z4SELECT account_name FROM accounts WHERE account_id=?zPostFinance E-FinancezSELECT account_id,activity_kind FROM transactions WHERE internal_transfer_group_id='synthetic-transfer-group' ORDER BY account_idc                    h | ]
}|d          S r   r$   r   s     r*   	<setcomp>zatest_preview_confirm_and_reparse_are_atomic_idempotent_and_keep_roles_separate.<locals>.<setcomp>H  s    777#C777r,   c                    h | ]
}|d          S )activity_kindr$   r   s     r*   r   zatest_preview_confirm_and_reparse_are_atomic_idempotent_and_keep_roles_separate.<locals>.<setcomp>I  s    :::SC :::r,   r^   zVSELECT activity_kind FROM transactions WHERE source_type='postfinance_official_import'tradepostfinancearchive*)rO   setenvstrsetattrservicer   total_changespreview_postfinance_importconfirm_postfinance_importlenget_postfinance_summaryrF   fetchonedictrG   rH   setvaluesfetchalllistglob)monkeypatchtmp_pathrK   payloadbeforepreviewfirstagain_previewsecondsafe_summary
serializedrolesclassificationstransfer_rowsr   s                 @r*   Ntest_preview_confirm_and_reparse_are_atomic_idempotent_and_keep_roles_separater      sU    ;;DE3S]]CCC"	
 	
 	
 	
   iiGF0w??G''''*+r1111.	
	
!,/&'89		
 	
 	
 E 6tWEEM/	
	
'5,->?		
 	
 	
 F u::????%''F<,@D,H,H,HH2488L\""J
**~Z/O/O/OO-> ?????,{";A">>>>>\)4Q77777<<IJJSSUUVWX\]]]]]<<DEENNPPQRSWXXXXX<<MNNWWYYZ[\`bbbbb<<HIIRRTTUVW[\\\\\UVVWWE!"e++++!T))))UDM1111s5<<>>""##q(((( <<c
 
  O 5!%FFFFF4 $DDDDD5,-1TTTTT<<] hjj    	BU:EVDX	
 	

(**Q	 #	# 	# 	# 	#
 LL 	L hjj  87777E*<Mt;TTTTT::M:::?R>SSSSSd	
 	

(**Q	 	 	 	 	
 tX	)M9IEKKCPPQQRRVWWWWWWWr,   c                :   t                      }|                     dt          |                     |                     t          dd            t                      }t	          j        ||          }t	          j        |i ||d         |d         dd           |                    d          	                                }|d	         d
k    r|d         dk    r|d         dk    sJ |                    d          	                                d	         dk    sJ d S )Nr   r   c                "    t          | |          S r.   r}   r   s     r*   r   zDtest_provider_and_computed_cost_basis_are_separate.<locals>.<lambda>Y      fWl&C&C r,   r   r   Tr   zSELECT provider_cost_total_original,computed_cost_basis_original,computed_cost_basis_status FROM postfinance_snapshot_positions WHERE computed_cost_basis_original IS NOT NULLr   rC   r9   r]      rE   z0SELECT COUNT(*) FROM postfinance_cost_basis_lots)
rO   r   r   r   r   r   r   r   rF   r   )r   r   rK   r   r   r   s         r*   2test_provider_and_computed_cost_basis_are_separater   S  sB   ;;D3S]]CCC"CC  
 iiG0w??G&	
	
!,/&'89		
 	
 	
   LL 	y hjj 
 8taD 0 0U1X5K5K5KK<<JKKTTVVWXY]^^^^^^^r,   c                  
 t                      }|                     dt          |                     t                      }t	          |j        d         t          d          t          d          t          d                    }t	          |t          d                                          dd	d
t          d          t          d          t          d          t          d          t          d          
  
        }t	          |||g|j        dd          R           
| 	                    t          d
fd           t                      }t          j        ||          }t          j        |i ||d         |d         dd           |                    d                                          }t!          |          dk    sJ |                    d                                          }	t!          |	          dk    sJ d S )Nr   r   2rh   101)quantitygross_originalnet_originals
   sell-eventsellz
2026-07-10rd   r    6059)	event_fingerprint
event_typeoccurred_on	directionr   price_originalr   fee_originalr   r9   )eventsr   c                    S r.   r$   )_zip	_overviewfifo_bundles     r*   r   zVtest_sell_consumes_documented_fifo_lot_before_cost_basis_persistence.<locals>.<lambda>  s    U` r,   r   r   Tr   zLSELECT quantity_acquired,quantity_remaining FROM postfinance_cost_basis_lots)r   r    zSELECT computed_cost_basis_original,computed_cost_basis_status FROM postfinance_snapshot_positions WHERE computed_cost_basis_original IS NOT NULL)z50.5rE   )rO   r   r   r}   r   r   r   r   rj   r   r   r   r   r   rF   r   rs   )r   r   rK   originalrZ   r   r   r   lotcomputedr   s             @r*   Dtest_sell_consumes_documented_fifo_lot_before_cost_basis_persistencer   m  s   ;;D3S]]CCCxxH
u~~U^^	  C  //99;; t}}t}}S\\T]]  D (C+L8K+L+LMMMK!;=`=`=`=`aaaiiG0w??G&	
	
!,/&'89		
 	
 	
   ,,V hjj  ::####|| 	\ hjj  ??2222222r,   c           	        t                      }|                     dt          |                     |                     t          dd            t                      }t	          j        ||          }t	          j        |i ||d         |d         dd           t          d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   zNtest_same_snapshot_with_different_original_source_is_blocked.<locals>.<lambda>  r   r,   r   r   Tr   s   synthetic-zip-revisions    %PDF-synthetic-overview-revisionconflictmatchr   r   r9   )rO   r   r   r   r   r   r   r   pytestraises
ValueErrorrF   r   )r   r   rK   r   r   	alternater   s          r*   <test_same_snapshot_with_different_original_source_is_blockedr     s   ;;D3S]]CCC"CC  
 iiG0w??G&	
	
!,/&'89		
 	
 	
   13VWWI1$	BBHJ4''''	z	4	4	4 	
 	
*&|4#+,=#>	  	
 	
 	
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 <<IJJSSUUVWX\]]]]]]]s   '*DD!$D!c                2   t                      }|                    dt          f           |                                 |                     t
          dd            t          j        |t                                }|d         du sJ |d         dk    sJ d S )Na  INSERT INTO positions_snapshot(position_snapshot_id,snapshot_date,account_id,platform_id,
               instrument_id,quantity,market_value_chf,data_quality_status,created_at)
           VALUES('same-day','2026-07-27',?,'pf','instrument_pf_00','1','100','complete','2026-07-27')r   c                    t                      S r.   r   r   r   s     r*   r   zWtest_existing_same_day_canonical_projection_is_blocked_during_preview.<locals>.<lambda>      U[U]U] r,   r   Tconflicting_batch_id"canonical_projection_date_conflict)rO   rF   rG   rJ   r   r   r   r   )r   rK   r   s      r*   Etest_existing_same_day_canonical_projection_is_blocked_during_previewr     s    ;;DLL	j 
	   	KKMMM!;=]=]^^^0wyyAAG:$&&&&)*.RRRRRRRr,   c                f   t                      }|                     dt          |                     |                     t          dd            t                      }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            n# 1 swxY w Y   ddddd}|                                D ]\  }}t          j	        t          d	          5  |                    d| d|            d d d            n# 1 swxY w Y   t          j	        t          d	          5  |                    d|            d d d            n# 1 swxY w Y   dddd}	|	                                D ]\  }}
t          j	        t          d	          5  |                    d| d|
            d d d            n# 1 swxY w Y   t          j	        t          d	          5  |                    d| d|
            d d d            n# 1 swxY w Y   d S )Nr   r   c                "    t          | |          S r.   r   r   s     r*   r   zEtest_immutable_postfinance_source_and_snapshot_rows.<locals>.<lambda>  r   r,   r   r   Tr   	immutabler   zBUPDATE postfinance_snapshots SET total_chf='0' WHERE snapshot_id=?r   zcannot be deletedz5DELETE FROM postfinance_snapshots WHERE snapshot_id=?zdocument_hash=document_hashzcreated_at=created_at)postfinance_batch_documentspostfinance_snapshot_positionspostfinance_snapshot_cashpostfinance_event_componentszUPDATE z SET zDELETE FROM z)source_type='postfinance_official_import')positions_snapshotcash_balancestransactionsz! SET created_at=created_at WHERE z WHERE )rO   r   r   r   r   r   r   r   r   r   	ExceptionrF   items)r   r   rK   r   r   resultimmutable_columnstable
assignmentcanonical_tables	predicates              r*   3test_immutable_postfinance_source_and_snapshot_rowsr    s   ;;D3S]]CCC"CC  
 iiG0w??G/	
	
!,/&'89		
 	
 	
 F 
y	4	4	4 
 
PM"$	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
y(;	<	<	< 
 
Cf]F[E]	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 (E*A%<(?	  /4466 1 1z]9K888 	= 	=LL;5;;z;;<<<	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	=]9,?@@@ 	1 	1LL///000	1 	1 	1 	1 	1 	1 	1 	1 	1 	1 	1 	1 	1 	1 	1 JDC 
 -2244 C Cy]9K888 	X 	XLLV5VV9VVWWW	X 	X 	X 	X 	X 	X 	X 	X 	X 	X 	X 	X 	X 	X 	X]9,?@@@ 	C 	CLLAAAiAABBB	C 	C 	C 	C 	C 	C 	C 	C 	C 	C 	C 	C 	C 	C 	CC Csl   6C  C$'C$D00D47D46FF"	%F"	G))G-	0G-	/II	I	=J%%J)	,J)	c                   t                      }|                     dt          |                     t                      }t	          d          }t	          d          }dJd} ||           ||          z   }t          d	 t          |j        j        |d
          D                       }t          |t          |j        |t          dt	          d          t	          d          t	          d                    t          dt	          d          t	          d          t	          d                    ft	          d          t	          d          t	          d          ||                    |                     t          dfd           |                    dt          f           |                    d           |                    d           |                    d           |                                 t!                      }	t          j        ||	          }
t          j        |i |	|
d         |
d          d
d!           |j        }t)          |          }t+          |          }t-          |          }t/          |          }t1          |d"#          }t3          |          }|j        |k    sJ |j        dk    sJ t7          d$ |j        D                       t	          d          k    sJ t9          d% |j        D                       }t;          ||j                  j        dk    sJ |j         dk    sJ |j!        d&k    sJ t7          d' |D                       t	          d          k    sJ d( |D             rJ t	          |j                  t	          |j                   z   t	          d          k    sJ |j"        d)k    sJ |d*         dk    sJ t9          d+ |d,         D                       }|d-         dk    sJ |d.         d/k    sJ |                    d0          #                                d1         dk    sJ |                    d2          #                                d1         d3k    sJ g }t          d4 |D              |t	          d5                     |t	          d6                    z   d
          D ]G\  }}|$                    tJ          |d7         d8t          |          t          |          d9d:d;           H|                    d<           |                    d=tM          j'        d>|i          f           |                                 t+          |          }|j         d?k    sJ |j!        d@k    sJ t)          |          j        dk    sJ t          j(        |          dA         dB         dk    sJ t          j        ||	          }t          j        |i |	|d         |d          d
d!          }|dC         d
u r
|dD         dEu sJ |dF         d
u sJ |                    dG          #                                d1         dHk    sJ dIS )KzLReproduce the production placeholder/exposure/settlement-position collision.r   z	255791.97z37673.19totalr   rU   list[Decimal]c           
           fdt          d          D             }|dxx          t          |t          d                    z
  z  cc<   |S )Nc                t    g | ]4}t          d           z                      t          d                    5S )11z0.01)r   quantize)r(   _r  s     r*   r+   zktest_global_read_model_counts_official_postfinance_components_once.<locals>.split_total.<locals>.<listcomp>  s8    WWW574==(2276??CCWWWr,   r=   r0   )rI   r1   r   )r  r   s   ` r*   split_totalzWtest_global_read_model_counts_official_postfinance_components_once.<locals>.split_total  sS    WWWWUSUYYWWWr


ec&'#,,7777


r,   c              3  \   K   | ]'\  }}t          |t          d           ||          V  (dS )r    )r   market_price_originalmarket_value_chfN)r   r   )r(   r)   values      r*   r/   zUtest_global_read_model_counts_official_postfinance_components_once.<locals>.<genexpr>  sR        D% 	ws||5[`aaa     r,   T)strictr   z21693.27z0.9293z71623.09r!   z9235.55z0.8146z	249526.14z	293465.16z27684.07	321149.23)r{   cashsecurities_total_chfcash_total_chftotal_value_chfstock_total_chfetf_total_chf)r|   r   c                    S r.   r$   )r   r   	realistics     r*   r   zTtest_global_read_model_counts_official_postfinance_components_once.<locals>.<lambda>!  s    U^ r,   a  INSERT INTO cash_account_snapshots(snapshot_id,account_id,snapshot_type,balance_date,
               amount_original,currency,amount_chf,source,note,created_at,created_by)
           VALUES('legacy-total',?,'manual_balance','2026-07-26','321149.23','CHF',
                  '321149.23','manual','historical depot total placeholder',
                  '2026-07-26T00:00:00Z','synthetic')zINSERT INTO platforms(platform_id,name,platform_type,country,default_currency,is_active,created_at) VALUES('tw','True Wealth','wealth','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('account_tw','tw','True Wealth','brokerage','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,created_at,is_active)
           VALUES('tw-value','account_tw','2026-07-27','152845.00','CHF',
                  'synthetic_truewealth','complete','2026-07-27T00:00:00Z',1)r   r   r   
2026-07-27as_ofc              3  ^   K   | ](}|j         t          k    t          |j                  V  )d S r.   r   rH   r   used_value_chfr'   s     r*   r/   zUtest_global_read_model_counts_official_postfinance_components_once.<locals>.<genexpr>K  s:      bb$/]aJaJawt*++JaJaJaJabbr,   c              3  P   K   | ]!}|j         t          k    |j        d k    |V  "dS r!   N)r   rH   currencyr'   s     r*   r/   zUtest_global_read_model_counts_official_postfinance_components_once.<locals>.<genexpr>L  s=      nn4?d;R;RW[WdhmWmWmWmWmWmWmnnr,   rl   c              3  b   K   | ]*}|d          t           k    t          |d                   V  +dS )r   r  N)rG   r   r   s     r*   r/   zUtest_global_read_model_counts_official_postfinance_components_once.<locals>.<genexpr>P  s@      ^^C3|CTX]C]C]ws-.//C]C]C]C]^^r,   c                H    g | ]}|d          t           k    |d         dv | S )r   asset_class>   r?   rg   r>   )rH   r   s     r*   r+   zVtest_global_read_model_counts_official_postfinance_components_once.<locals>.<listcomp>Q  s7    vvvs<'8D'@'@SEW[uEuEuEuEuEur,   z	152845.00r$  c              3  2   K   | ]}|d          dk    |V  dS )reported_totalr!  Nr$   r'   s     r*   r/   zUtest_global_read_model_counts_official_postfinance_components_once.<locals>.<genexpr>U  s?         ![00 	0000 r,   account_totalsderived_totalstatusmatchedzNSELECT amount_chf FROM cash_account_snapshots WHERE snapshot_id='legacy-total'r   zNSELECT COUNT(*) FROM transactions WHERE internal_transfer_group_id IS NOT NULLr   c                4    g | ]}|d          t           k    |S r   )rG   r   s     r*   r+   zVtest_global_read_model_counts_official_postfinance_components_once.<locals>.<listcomp>`  s'    ;;;L 1U : : : : :r,   160000140000r   freshr@   zsynthetic-market)r   r   quality_status	value_chfcloser2  providera  INSERT INTO market_data_runs(run_id,source_key,as_of,input_fingerprint,status,
               started_at,completed_at,price_total,price_stored,fx_total,fx_stored,
               benchmark_total,benchmark_stored,valuation_stored,missing_instruments_json,
               reason_codes_json)
           VALUES('newer-run','synthetic','2026-07-28','fp','complete','2026-07-28T00:00:00Z',
                  '2026-07-28T00:01:00Z',22,22,0,0,0,0,22,'[]','[]')a  INSERT INTO portfolio_analysis_snapshots(analysis_snapshot_id,run_id,as_of,
               base_currency,total_value_chf,price_coverage_pct,fx_coverage_pct,
               benchmark_coverage_pct,quality_status,reason_codes_json,summary_json,created_at)
           VALUES('newer-analysis','newer-run','2026-07-28','CHF','300000','100','100','0',
                  'complete','[]',?,'2026-07-28T00:01:00Z')r{   z	300000.00z
2026-07-28r   	total_chf	duplicater   Fr   r   r9   N)r  r   rU   r  ))rO   r   r   r}   r   rs   zipr|   r{   r   r   r   r   rF   rH   rJ   r   r   r   r   r   r   r   r   r   r	   cash_chfr1   nextr   idr2  equity_value_chfr,  truewealth_value_chfr   r   rG   jsondumpsr   )r   r   rK   r   stock_total	etf_totalr  source_valuesr{   r   r   before_getsr"  r>   overviewcommandreconciliationrowsusd_positionpf_reconciliationmarket_positionsr   r  newerrE  r   r)  s                             @r*   Btest_global_read_model_counts_official_postfinance_components_oncerZ    s   ;;D3S]]CCCxxH+&&K
##I   
  K,,{{9/E/EEM  x0:MRVWWW    I ugj&9&978;L;LgV`NaNabbugi&8&8'(:K:KWU`MaMabb ")!5!5":..#K00'#
 
 
  I  !;=^=^=^=^___LL	9
 
   	LL 	l   	LL	f  
 	LL	Q   	KKMMMiiG0w??G&	I7 	I',"7#$564	I 	I 	I  
 $KD!!D%%FD!!H(..G3DMMMND,,,,=J&&&&bbbbbbbfmnxfyfyyyyynnnnnnnL#D,/::CuLLLL"k1111<66666^^4^^^^^bijubvbvvvvvvvtvvvvvv4=!!GF,C$D$DDP[H\H\\\\\(K7777#$
2222  '(89     _-<<<<X&)3333<<hiirrttuvw  |G  G  G  G  G<<hiirrttuvw{|||||;;;;;GH%%&&WX5F5F)G)GG   	 	
U
 	#o2F%CJJU+=!
 !
 	 	 	 	
 	LL	H   	LL	?
 
["23	4	46   	KKMMMt$$E![0000;,&&&&D!!*j8888*4001BCKPT_____24AAI/	K7 	K)L"9%&78T	K 	K 	K F
 [!T))i
.Cu.L.L.LL,4''''<<IJJSSUUVWX\]]]]]]]r,   c                   t                      }|                     dt          |                     |                     t          dd            t                      }t	          j        ||          }t	          j        |i ||d         |d         dd           t          d t          |          D             t          d	                    }t          d
 t          |                                          D             t          d	                    }|                    dt          f           t          d t          |          j        D             t          d	                    |k    sJ |                    dt          f                                          d         }|                    d|f           |                    d           |                    d           |                    d           d t%          |          D             }d |D             h dk    sJ t'          d |D                       }	t'          d |D                       }
t'          d |D                       }|	d         dk    sJ |	d         dk    sJ |
d         dk    sJ |
d         dk    sJ |d         dk    sJ |d         d k    sJ |                    d!           |                    d"           |                    d#           d$ t%          |          D             }d% |D             d&gk    sJ t)          |                    d'                                                                        d(t-          d)                                          d*d+,           t1                    }|                    d-d.                    |           d/d.                    d0 |D                        d1fd2|D                        t)          |                    d3                                                                        d4d(d5d6d7d8dd9d6d:d+;           t1                    }|                    d<d.                    |           d/d.                    d= |D                        d1fd>|D                        |                    d?           |                    d@           |                                 t          dA t          |          D             t          d	                    t          d8          k    sJ t          |dBC          }t          dD |D             t          d	                    |k    sJ t          |dEC          }t          dF |D             t          d	                    |k    sJ t          |dGdHI          }t          dJ |D             t          d	                    |k    sJ t          |dBC          }t          dK |                                D             t          d	                    |k    sJ dL |                                D             dMhk    sJ t          |dEC          }t          dN |                                D             t          d	                    |k    sJ t          |          }t          dO |                                D             t          d	                    t          d7          k    sJ dP |                                D             d5hk    sJ t'          t7          |                                                    j        }|                    dQt          j        t-          dR                                          f           |                    dSt          f           |                    dTt          j        f           |                    dUt          f           |                                 dV t          |          j        D             }t          dW |D             t          d	                    t          dX          k    sJ t'          dY |D                       j        dZk    sJ t'          d[ |D                       j        d\k    sJ t'          fd]t?          |          D                       }t          |d^                   |t          d_          z   k    sJ t'          fd`tA          |daC          D                       }|j        |t          d_          z   k    sJ d S )bNr   r   c                    t                      S r.   r   r   s     r*   r   zTtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<lambda>  r   r,   r   r   Tr   c              3  $   K   | ]}|j         V  d S r.   
amount_chfr'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  s$      LLTLLLLLLr,   r0   c              3  $   K   | ]}|j         V  d S r.   r  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  s9       	
 	
 !	
 	
 	
 	
 	
 	
r,   z>UPDATE accounts SET account_type='checking' WHERE account_id=?c              3  ^   K   | ](}|j         t          k    t          |j                  V  )d S r.   r.  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  sF       	
 	
$&& D'((&&&&	
 	
r,   z3SELECT platform_id FROM accounts WHERE account_id=?platform_ida4  INSERT INTO accounts(
               account_id,platform_id,account_name,account_type,currency,balance_mode,
               portfolio_bucket,is_active,created_at)
           VALUES('generic-usd-cash',?,'Generic Multi-Currency','cash','CHF','csv_calculated',
                  'cash',1,'2026-07-27T10:00:00Z')a  INSERT INTO transactions(
               transaction_id,transaction_type,account_id,trade_date,gross_amount_original,
               net_amount_original,currency_original,fx_rate_to_chf,fx_status,source_type,
               source_id,is_confirmed,quality_status,created_at)
           VALUES('generic-usd-deposit','cash_deposit','generic-usd-cash','2026-07-27',
                  '100','100','USD','0.9','ok','csv_import','generic-usd-deposit',1,
                  'ok','2026-07-27T10:00:00Z')a  INSERT INTO transactions(
               transaction_id,transaction_type,account_id,trade_date,gross_amount_original,
               net_amount_original,currency_original,fx_rate_to_chf,fx_status,source_type,
               source_id,is_confirmed,quality_status,created_at)
           VALUES('generic-eur-deposit','cash_deposit','generic-usd-cash','2026-07-27',
                  '50','50','EUR','1.1','ok','csv_import','generic-eur-deposit',1,
                  'ok','2026-07-27T10:00:01Z')a`  INSERT INTO cash_balances(
               cash_balance_id,account_id,balance_date,currency,amount_original,
               fx_rate_to_chf,amount_chf,source_type,quality_status,created_at)
           VALUES('generic-gbp-dividend','generic-usd-cash','2026-07-27','GBP','10',
                  '1.1','11','vue_equity_dividend','ok','2026-07-27T10:00:02Z')c                *    g | ]}|d          dk    |S r   zgeneric-usd-cashr$   r   s     r*   r+   zVtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<listcomp>  s/       #l2CGY2Y2Y2Y2Y2Yr,   c                    h | ]
}|d          S r2  r$   r   s     r*   r   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<setcomp>  s    444C
O444r,   >   r   GBPr!   c              3  2   K   | ]}|d          dk    |V  dS )r2  r!   Nr$   r   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  0      OOsc*o6N6Ns6N6N6N6NOOr,   c              3  2   K   | ]}|d          dk    |V  dS )r2  r   Nr$   r   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  rj  r,   c              3  2   K   | ]}|d          dk    |V  dS )r2  rh  Nr$   r   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  rj  r,   amount_originalz100.00r_  z90.00z50.00z55.00z10.00z11.00zMUPDATE accounts SET balance_mode='manual' WHERE account_id='generic-usd-cash'a_  INSERT INTO cash_account_snapshots(
               snapshot_id,account_id,snapshot_type,balance_date,amount_original,currency,
               amount_chf,source,created_at,created_by)
           VALUES('generic-manual-total','generic-usd-cash','manual_balance','2026-07-27',
                  '1000','CHF','1000','manual','2026-07-27T10:01:00Z','user')a_  INSERT INTO cash_balances(
               cash_balance_id,account_id,balance_date,currency,amount_original,
               fx_rate_to_chf,amount_chf,source_type,quality_status,created_at)
           VALUES('generic-missing-fx','generic-usd-cash','2026-07-27','GBP','10',
                  NULL,NULL,'manual_import','missing_fx','2026-07-27T10:01:01Z')c                *    g | ]}|d          dk    |S re  r$   r   s     r*   r+   zVtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<listcomp>  s/       #l2CGY2Y2Y2Y2Y2Yr,   c                .    g | ]}|d          |d         fS )r2  r_  r$   r   s     r*   r+   zVtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<listcomp>  s&    LLLSS_c,/0LLLr,   )r@   z1000.00z0SELECT * FROM postfinance_import_batches LIMIT 1zfuture-batchs   future-bundlez2026-08-01T09:14:30+02:00z2026-08-01T10:00:00Z)r   bundle_sha256snapshot_atconfirmed_atz'INSERT INTO postfinance_import_batches(,z	) VALUES(c              3     K   | ]}d V  dS ?Nr$   r(   r  s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  s$      VlVl_`WZVlVlVlVlVlVlr,   )c                     g | ]
}|         S r$   r$   )r(   columnbatchs     r*   r+   zVtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<listcomp>  s    ---6v---r,   z+SELECT * FROM postfinance_snapshots LIMIT 1zfuture-snapshotz2026-08-01T00:30:00+02:00z1299.00z300.00z999.00z200.00z0.00)r   r   rq  rD  securities_chfrG  
stocks_chfetfs_chfcomponent_total_chfdifference_chf
created_atz"INSERT INTO postfinance_snapshots(c              3     K   | ]}d V  dS ru  r$   rw  s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>  s$      QgQgZ[RUQgQgQgQgQgQgr,   c                     g | ]
}|         S r$   r$   )r(   rz  source_snapshots     r*   r+   zVtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<listcomp>  s    777V	 777r,   aq  INSERT INTO postfinance_snapshot_positions(
               snapshot_position_id,snapshot_id,source_row_reference,instrument_id,asset_class,
               quantity,provider_average_cost_original,provider_cost_total_original,
               price_original,price_currency,value_chf,weight_pct,computed_cost_basis_original,
               computed_cost_basis_status,provenance_json,created_at)
           SELECT 'future-'||snapshot_position_id,'future-snapshot',source_row_reference,
                  instrument_id,asset_class,quantity,provider_average_cost_original,
                  provider_cost_total_original,price_original,price_currency,value_chf,weight_pct,
                  computed_cost_basis_original,computed_cost_basis_status,provenance_json,
                  '2026-08-01T10:00:00Z'
           FROM postfinance_snapshot_positions WHERE snapshot_id<> 'future-snapshot'a|  INSERT INTO postfinance_snapshot_cash(
               snapshot_cash_id,snapshot_id,currency,amount_original,fx_rate_to_chf,value_chf,created_at)
           SELECT 'future-'||snapshot_cash_id,'future-snapshot',currency,amount_original,
                  fx_rate_to_chf,value_chf,'2026-08-01T10:00:00Z'
           FROM postfinance_snapshot_cash WHERE snapshot_id<> 'future-snapshot'c              3  $   K   | ]}|j         V  d S r.   r^  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>'  s$      SSDSSSSSSr,   r*  r+  c              3  $   K   | ]}|j         V  d S r.   r^  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>)  s$      <<D<<<<<<r,   z
2026-07-31c              3  $   K   | ]}|j         V  d S r.   r^  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>,  s$      ::T::::::r,   z
2026-08-01z2026-07-31T23:59:59Z)r,  data_cutoffc              3  $   K   | ]}|j         V  d S r.   r^  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>3  s$      88D888888r,   c              3  $   K   | ]}|j         V  d S r.   ra  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>6  s%      II4	IIIIIIr,   c                    h | ]	}|j         
S r$   valuation_atr'   s     r*   r   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<setcomp>8  s    HHH$DHHHr,   rl   c              3  $   K   | ]}|j         V  d S r.   ra  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>=  s%      NN4	NNNNNNr,   c              3  $   K   | ]}|j         V  d S r.   ra  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>A  s%      MM$%MMMMMMr,   c                    h | ]	}|j         
S r$   r  r'   s     r*   r   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<setcomp>B  s    EEE$DEEEr,   a1  INSERT INTO transactions(
               transaction_id,transaction_type,account_id,instrument_id,trade_date,
               settlement_date,quantity,currency_original,source_type,source_id,
               external_transaction_id,row_hash,is_confirmed,quality_status,created_at,
               updated_at,is_voided)
           VALUES('post-snapshot-buy','buy',?,?, '2026-08-02','2026-08-02','2',
                  'CHF','manual_confirmed_trade','post-snapshot-buy','post-snapshot-buy',?,
                  1,'ok','2026-08-02T10:00:00Z','2026-08-02T10:00:00Z',0)s   post-snapshot-buya  INSERT INTO transactions(
               transaction_id,transaction_type,account_id,trade_date,gross_amount_original,
               net_amount_original,currency_original,fx_rate_to_chf,fx_status,source_type,
               source_id,is_confirmed,quality_status,created_at,is_voided)
           VALUES('post-snapshot-cash','cash_deposit',?,'2026-08-02','10','10','USD',
                  '0.8','ok','manual_confirmed_cash','post-snapshot-cash',1,'ok',
                  '2026-08-02T10:01:00Z',0)a3  INSERT INTO transactions(
               transaction_id,transaction_type,account_id,instrument_id,trade_date,
               settlement_date,quantity,gross_amount_original,net_amount_original,
               currency_original,fx_rate_to_chf,fx_status,source_type,source_id,
               is_confirmed,quality_status,created_at,is_voided)
           VALUES('post-snapshot-sell','sell',?,?, '2026-08-02','2026-08-02','1',
                  '20','20','USD','0.8','ok','manual_confirmed_trade',
                  'post-snapshot-sell',1,'ok','2026-08-02T10:02:00Z',0)aR  INSERT INTO cash_balances(
               cash_balance_id,account_id,balance_date,currency,amount_original,
               fx_rate_to_chf,amount_chf,source_type,quality_status,created_at)
           VALUES('post-snapshot-dividend-cash',?,'2026-08-02','EUR','5','1','5',
                  'vue_equity_dividend','ok','2026-08-02T10:03:00Z')c                2    g | ]}|j         t          k    |S r$   )r   rH   r'   s     r*   r+   zVtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<listcomp>o  s,       T_PT=T=T=T=T=Tr,   c              3  >   K   | ]}t          |j                  V  d S r.   )r   r/  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>s  s-      EE$$	%	%EEEEEEr,   z1028.00c              3  0   K   | ]}|j         d k    |V  dS r1  rg  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>u  .      NNt}7M7M7M7M7M7MNNr,   z130.00c              3  0   K   | ]}|j         d k    |V  dS )r   Nrg  r'   s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>v  r  r,   z105.00c              3  `   K   | ](}|d          t           k    |d         j        k    $|V  )dS )r   r   N)rG   r   )r(   r   selecteds     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>w  sQ        |%%#o*>(BX*X*X 	*X*X*X*X r,   r   r    c              3  \   K   | ]&}|j         t          k    |j        j        k    "|V  'd S r.   )r   rG   r   )r(   r)   r  s     r*   r/   zUtest_official_snapshot_resolvers_honor_historical_as_of_and_cutoff.<locals>.<genexpr>}  sL        ?e##(:h>T(T(T 	(T(T(T(T r,   z
2026-08-02)!rO   r   r   r   r   r   r   r   r1   r   r   r   r   rF   rH   r   r{   r   r   rH  r   updater   rj   r   joinrJ   iterr   r   amountr	   r   )r   r   rK   r   r   original_cash_totaloriginal_position_totalrc  generic_rowsgeneric_usdgeneric_eurgeneric_gbpcontrolled_rowscolumnshistorical_cashprior_local_day_cashcutoff_cashhistorical_positionsprior_local_day_positionscurrent_positionsbaseline_quantitypost_snapshot_cashdashboard_positioncanonical_positionr{  r  r  s                           @@@r*   Btest_official_snapshot_resolvers_honor_historical_as_of_and_cutoffr    sh   ;;D3S]]CCC!;=]=]^^^iiG0w??G&	I7 	I',"7#$564	I 	I 	I  
 LL%Ed%K%KLLLgVYll  "	
 	
=dCCJJLL	
 	
 	
 	  	LLQTXSZ[[[	
 	
(..8	
 	
 	

 	  
    ,,=w hjj K 	LL	6
 
   	LL	2   	LL	2   	LL	S   (..  L 54|4448M8M8MMMMMOOlOOOOOKOOlOOOOOKOOlOOOOOK()X5555|$////()W4444|$////()W4444|$////LLW   	LL	Q   	LL	T   (..  O MLOLLLQ     PQQZZ\\]]E	LL-..88::/+	     5kkGLLo#((72C2CoochhVlVldkVlVlVlNlNlooo----W---   4<<(UVV__aabbO%/%)     ?##GLLjSXXg->->jjQgQg_fQgQgQgIgIgjjj7777w777   	LL
	X   	LL	S   	KKMMMSS,LT,R,RSSSU\]`UaUabbfmnvfwfwwwww6t<PPPO<<O<<<gcllKKObbbbb;DUUU::%9:::GCLL 	    3*  K
 88K888'#,,GGK^^^^^@\ZZZII+?+F+F+H+HIII7SV<< 	 ! ! ! ! IH*>*E*E*G*GHHHMhLiiiii EL! ! ! NN+D+K+K+M+MNNN  
!! ! ! ! >dCCMM2C2J2J2L2LMMMwWZ||\\`ghp`q`qqqqqEE*;*B*B*D*DEEEJeIfffffD*11334455H )LL	M 
x%v.B'C'C'M'M'O'OP
 
 
 	LL	/ 
	 	 	 	LL	K 
x%&
 
 
 	LL	H
 
   	KKMMM )$//9   EE2DEEEws|| 			    NN!3NNNNNUYaaaaaNN!3NNNNNUYaaaaa     &&    
 %j1226G'RU,,6VVVVV    1$lKKK    
 &*;gcll*JJJJJJJr,   )rP   rQ   )rR   rS   rT   rS   rU   r
   )rR   rS   rT   rS   ):
__future__r   r   rL  dataclassesr   decimalr   hashlibr   r   jarvis_finance.dashboard.datar   r   r	   ,jarvis_finance.imports.postfinance_documentsr
   r   r   r   r   r   r   jarvis_finance.servicesr   r   $jarvis_finance.services.cash_servicer   r   &jarvis_finance.services.equity_servicer   -jarvis_finance.services.portfolio_aggregationr   r   +jarvis_finance.services.portfolio_analyticsr   &jarvis_finance.services.portfolio_datar   )jarvis_finance.services.portfolio_servicer   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   rG   rH   r3   rO   r}   r   r   r   r   r   r   r  rZ  r  r$   r,   r*   <module>r     s   " " " " " "                              
                  C B B B B B [ [ [ [ [ [ [ [ E E E E E E        V U U U U U Q Q Q Q Q Q B B B B B B : : : : : : > > > > > >%  "2 2 2l >XA A A A AH    SX SX SXl_ _ _4*3 *3 *3Z ^  ^  ^FS S S0C 0C 0CfI^ I^ I^XwK wK wK wK wKr,   