
    ojCJ                    r   d dl mZ d dlZd dlZd dlZd dl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mZ d dlmZ d dlmZ d d	lmZ d
ZdZd7dZd8dZd9dZd7dZd:dZd;dZd<d"Zd=d#Zd>d*Z d?d,Z!d@d-Z"dAd0Z#dBd1Z$e%d2k    r0 e& ej'         e# e$                      d3d4d56                     dS dS )C    )annotationsN)Decimal)Path)Any)record_audit_event)now)parse_budget_csv_textconfigure_source_mapping"OPTION1_ACCOUNTS_AND_MAPPINGS_ONLYzs16-source-truth-v1pathr   returnstrc                    |                                  }dD ])}	 |                    |          c S # t          $ r Y &w xY wt          d          )N)z	utf-8-sigcp1252zunsupported source encoding)
read_bytesdecodeUnicodeDecodeErrorRuntimeError)r   dataencodings      ^/home/agent/.hermes/worktrees/FinanceManager-sprint23/scripts/sprint16_household_onboarding.py	_read_csvr      sl    ??D+  	;;x(((((! 	 	 	D	
4
5
55s   1
>>valuer   r   c                    t          t          | pd                              dd                              dd                              dd                    S )N0u   ’ ',.)r   r   replace)r   s    r   _decimalr"       sN    3u|$$,,UB77??RHHPPQTVYZZ[[[    connsqlite3.Connectionsqlparamstuple[Any, ...]sqlite3.Rowc                    |                      ||                                          }t          |          dk    rt          d          |d         S )N   z*canonical account resolution is not uniquer   )executefetchalllenr   )r$   r&   r'   rowss       r   _oner0   $   sH    <<V$$--//D
4yyA~~GHHH7Nr#   c                r    t          j        |                                                                           S N)hashlibsha256r   	hexdigest)r   s    r   
_db_digestr6   +   s(    >$//++,,66888r#   c           
        t          j                    }d |                     d          D             }|D ]}|                    |                                           |                     d| d          D ]Q}|                    t          j        t          |          t          dd                                                     R|	                                S )Nc                    g | ]
}|d          S )r    .0rows     r   
<listcomp>z#_logical_digest.<locals>.<listcomp>1   s,        	A  r#   z\SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY namezSELECT * FROM "z" ORDER BY rowidF)r   :)defaultensure_ascii
separators)
r3   r4   r,   updateencodejsondumpslistr   r5   )r$   digesttablestabler<   s        r   _logical_digestrJ   /   s    ^F <<j
 
  F  r rellnn%%%<< I% I I IJJ 	r 	rCMM$*T#YY%\fgggnnppqqqq	rr#   dict[str, Any]c           
        |                                  j        dz  rt          d          t          j        |                     d                    }|                    d          t          k    rt          d          |                    d          pi }|                    d          pi }t          |                    d	          d
u |                    d          d
u |                    d          d
u |                    d          d
u |                    d          du |                    d          du f          st          d          |S )N?   z)authorization manifest must be owner-onlyzutf-8)r   contractz(authorization manifest contract mismatch
raiffeisenchain_auditboth_base_blocksTboth_reference_aboth_transitions_correctremoval_breaks_chain!identical_provider_transaction_idFpending_booked_pairz$Raiffeisen chain audit is incomplete)	statst_moder   rD   loads	read_textgetMANIFEST_CONTRACTall)r   manifestrO   chains       r   _load_manifestr`   >   sF   yy{{U" HFGGGz$..'.::;;H||J#444EFFFl++1rJNN=))/REII())T1II())T1II011T9II,--5II9::eCII+,,5	
	 	 
C ABBBOr#   backup_pathNonec                <   |                                                                 }|j                            dd           |                                rt          d          t          j        |t          j        t          j	        z  t          j
        z  d          }t          j        |           t          j        |          }	 |                     |           |                                 n# |                                 w xY w|                    d           t          j        |          }t          j        |_        |                    d                                          d         dk    r#|                                 t          d          t)          j        d	d
d          5 }t-          |j                  }d d d            n# 1 swxY w Y   	 t          j        |          }|                    |           |                                 t          j        |          }t          j        |_        |                    d                                          d         dk    rt          d          t1          |          t1          |          k    rt          d          |                                 |                                 |                    d           d S # |                                 |                    d           w xY w)NT)parentsexist_okzbackup path already existsi  PRAGMA integrity_checkr   okzbackup integrity check failedzs16-restore-probe-z.sqlite3F)prefixsuffixdeletez$restore probe integrity check failedz%restore probe logical digest mismatch)
missing_ok)
expanduserresolveparentmkdirexistsr   osopenO_CREATO_EXCLO_WRONLYclosesqlite3connectbackupchmodRowrow_factoryr,   fetchonetempfileNamedTemporaryFiler   namerJ   unlink)	r$   ra   
descriptordestinationry   handlerestore_pathrestoredprobes	            r   _backup_and_restore_prober   T   s   ((**2244KTD999 97888bj29&<r{&JERRJHZ/+..KK   e_[))F F~~.//88::1=EE:;;;		$,@\a	b	b	b )flFK(() ) ) ) ) ) ) ) ) ) ) ) ) ) )-?<00h--#K==122;;==a@DHHEFFF5!!_V%<%<<<FGGGt,,,,, 	t,,,,s+   	C3 3D	1GGGC%K/ /,Lc                |   d}|                      d|f                                          }d}|r<|d         |d         |d         |d         |d         f}||k    rt          d	          d S t                      }|                      d
|g|d d         d||R            t	          | ddd|ddddd           d S )Nplatform_s16_visa_liabilityz+SELECT * FROM platforms WHERE platform_id=?)VISA KartenverbindlichkeitbankCHCHFr+   r   platform_typecountrydefault_currency	is_activez1existing VISA platform has incompatible semanticszINSERT INTO platforms(
             platform_id,name,platform_type,country,default_currency,is_active,notes,created_at,updated_at)
           VALUES (?,?,?,?,?,1,?,?,?)   zNon-cash card liabilitysprint16_household_onboardingcreateplatformr   r   card_liability)r   r   roleusersourceactionentity_type	entity_id
new_values
created_byr,   r}   r   r   r   )r$   platform_idexistingexpectedactual	timestamps         r   _ensure_platformr   x   s   /K||IK>ZZcceeHEH Vh7)9L'((;*?
 XRSSSILL	) 
Ux|U%>U	U9UU	   4X+%+P`aa	     r#   
account_idr   r   account_typebucketnotesc                  |                      d|f                                          }|||ddddd|f	}|rX|d         |d         |d         |d	         |d
         |d         |d         |d         |d         f	}	|	|k    rt          d          d S t                      }
|                      d||||d||
|
d|f
           t	          | ddd|||ddd|dd           d S )Nz)SELECT * FROM accounts WHERE account_id=?r   r   r+   csv_calculatedr   account_namer   currencyperformance_includedis_health_reserver   balance_modeportfolio_bucketz@existing canonical onboarding account has incompatible semanticsa  INSERT INTO accounts(
             account_id,platform_id,account_name,account_type,currency,performance_included,
             is_health_reserve,is_active,notes,created_at,updated_at,balance_mode,portfolio_bucket)
           VALUES (?,?,?,?,?,0,0,1,?,?,?,?,?)r   r   account)r   r   r   r   r   r   r   r   r   )r$   r   r   r   r   r   r   r   r   r   r   s              r   _ensure_accountr      sE    ||G*WW``bbHT<1aAQSYZH ]#Xn%=x?WZ (+A"BHM`Da[!8N#;XFX=Y

 XabbbILL	1 
[$eUIyZjlrs   4X$(,TY,-?Oekm m     r#   	budget_idc               p   |                      d|f                                          }|||ddf}|r<|d         |d         |d         |d         |d         f}||k    rt          d	          d S t                      }|                      d
||||dd||f           t	          | ddd||||ddd           d S )Nz7SELECT * FROM budget_accounts WHERE budget_account_id=?r   r+   linked_account_idr   r   r   r   z=existing budget onboarding account has incompatible semanticszINSERT INTO budget_accounts(
             budget_account_id,linked_account_id,name,account_type,currency,is_active,notes,created_at,updated_at)
           VALUES (?,?,?,?,?,1,?,?,?)z%Sprint 16 confirmed source onboardingr   r   budget_account)r   r   r   r   r   r   r   )	r$   r   r   r   r   r   r   r   r   s	            r   _ensure_budget_accountr      s    ||UXaWcddmmooHD,q9H ()8F+;Xn=UZ (;"7
 X^___ILL	) 
JlE;bdmoxy	   4X$	)3TS_mrss	     r#   c           
         t          | d|f          }t          |d                   }||k    rd S |                     d|t                      |f           t	          | ddd|d|id|id           d S )	Nz4SELECT account_name FROM accounts WHERE account_id=?r   zBUPDATE accounts SET account_name=?,updated_at=? WHERE account_id=?r   renamer   r   )r   r   r   r   
old_valuesr   r   )r0   r   r,   r   r   )r$   r   r   r   old_names        r   _ensure_account_namer      s    DPS]R_``H8N+,,H4LLUX\^a^c^ceoWpqqq4X"H->4:P]c     r#   argsargparse.Namespacec           	        t           j                            d          st          d          | j        r| j        t          k    rt          d          t          | j                  }|d         |d         }t          t          | j                  d          }i }|d         D ]>}|                    t          |d                   g                               |           ?t          t!          d	                   t!          d
                   g          }|d         dz   t!          d                   k    s/t          d |                                D                       |k    rt          d          t%          fd|                                D                       }t%          fd|                                D                       }|                    t          d                             r(|                    t          d                             st          d          t+          fd||         D                       st          d          ||         d         }	t-          |	                    d                    t/          t          d                             k    sFt-          |	                    d                    t/          t          d                             k    rt          d          t          t          | j                  d          }
i }|
d         D ]k}t          |                    d          p|                    d          pd                                           }|r|                    |d          dz   ||<   lt5          |
d                   t7          |                                          z
  }t5          |
d                   t!          |d!                   k    sdt7          |                                          t!          |d"                   k    s,|t!          |d#                   k    st5          |          dk    rt          d$          t          |          d%gz   }t9          | j                  }t=          j        | j                  t<          j         _!        "                    d&           t!          "                    d'          #                                d                   }|d(k     rt          d)          "                    d*          #                                d         d+k    rt          d,          d- "                    d.          $                                D             }tK          d/| j&        f          }tK          d/| j'        f          }||fD ]k}|d0         d1k    sN|d2         d3k    sBt!          |d4         pd          dk    s't!          |d5         pd          dk    s|d6         d1k    rt          d7          ld8|d9d          z   }d:|d9d          z   }|d;t!          d                   t7          |          t          |d;<          d=d3d1d>d?d3d@d>d?dAtQ          | j                  dB}| j        sB)                                 t9          | j                  |k    rt          dC          d;|dD<   |S | j*        t          dE          tW          | j*                   "                    dF           j,        }	 t[                     t]          t          |dG                   |           t_          dHt          |dI                   |d1d1dJK           t_          dLdMdNdOd@dPK           ta          dQt          |dG                   |dRS           ta          dTdH|dRS           ta          dUdLdNdVS           ta          dWt          |dG                   dXdRS           d|dQfd|dTfdY| j1        dWfgdZ |D             }fd[|D             }d\ "                    d.          $                                D             }||k    rt          d]          "                    d*          #                                d         d+k    rt          d^          j,        |k    }2                                 n## tf          $ r 4                                  w xY w"                    d*          #                                d         d+k    r#)                                 t          d_          )                                 |rd`nda| t7          db |D                       d+d;t5          |          ddc|dd<   |S )eNJARVIS_FINANCE_FINGERPRINT_KEYz*JARVIS_FINANCE_FINGERPRINT_KEY is requiredz/exact onboarding authorization text is requiredrO   visaraiffeisen_bankr/   IBANreference_a_bookingsreference_b_bookingsphysical_row_countr+   physical_lines_including_headerc              3  4   K   | ]}t          |          V  d S r2   )r.   )r;   r/   s     r   	<genexpr>zrun.<locals>.<genexpr>   s(      ::#d))::::::r#   z"Raiffeisen source contract changedc              3  n   K   | ]/\  }}t          |          t          d                    k    +|V  0dS )r   Nr.   intr;   refr/   expected_raiffeisens      r   r   zrun.<locals>.<genexpr>   F      ~~ysDD		SQde{Q|M}M}@}@}s@}@}@}@}~~r#   c              3  n   K   | ]/\  }}t          |          t          d                    k    +|V  0dS )r   Nr   r   s      r   r   zrun.<locals>.<genexpr>   r   r#   reference_a_suffixreference_b_suffixz,Raiffeisen reference suffix contract changedc              3     K   | ]J}t          |                    d                     t          t          d                             k    V  KdS )Balance reference_a_provider_balance_chfN)r"   r[   r   r   )r;   r<   r   s     r   r   zrun.<locals>.<genexpr>   sg         	##$$4GHj4k0l0l(m(mm     r#   z/Raiffeisen reference A provider balance changedr   r    reference_b_provider_balance_chfzCredit/Debit Amountreference_b_interest_chfz.Raiffeisen reference B source contract changedvisa_credit_cardCardIdcardidr   transactionsprovider_reference_rowsfallback_role_rowszVISA source contract changedz	visa-cardzPRAGMA foreign_keys=ONz6SELECT COALESCE(MAX(version),0) FROM schema_migrations/   z&onboarding requires schema 47 or newerrf   rg   z#database integrity preflight failedc                ,    g | ]}t          |          S r9   tupler:   s     r   r=   zrun.<locals>.<listcomp>"  s    gggCU3ZZgggr#   zPRAGMA foreign_key_checkz9SELECT * FROM accounts WHERE account_id=? AND is_active=1r   cashr   r   r   r   r   z;existing bank accounts must be compatible CHF cash accountsu/   Raiffeisen Mitglieder-Privatkonto •••• u-   Raiffeisen Mitglieder-Sparkonto •••• T)reverse)r   logical_bookingsreference_distributionF)r   r   r   	liability)raiffeisen_extrar   )schemasource_contract_verifiedrO   account_rolesconfirm_onboardingz!dry-run changed the database filedatabase_unchangedz+--backup is required for confirm onboardingzBEGIN IMMEDIATEr   acct_s16_raiffeisen_extrar   zCSeparate managed Raiffeisen cash asset; no invented opening balance)r   r   r   r   r   r   acct_s16_visa_liabilityr   r   credit_card_liabilityzCCard liability; excluded from cash assets and portfolio performancebacc_s16_raiffeisen_achecking)r   r   r   r   bacc_s16_raiffeisen_bbacc_s16_visa_liabilitycredit_cardbacc_s16_akb_householdzAKB Haushaltskontoakb_bankc              3      K   | ]	}d |dfV  
dS )r   r   Nr9   )r;   r   s     r   r   zrun.<locals>.<genexpr>c  s+      ffs!3(ABffffffr#   c           
     B    g | ]\  }}}t          |||d d          S )T)source_typesource_referencebudget_account_idconfirmr
   )r;   r   r   r   r$   s       r   r=   zrun.<locals>.<listcomp>e  sX     
 
 
 A-/@ % +AQ&7DJ J 
 
 
r#   c                ,    g | ]}t          |          S r9   r   r:   s     r   r=   zrun.<locals>.<listcomp>m  s    hhhSeCjjhhhr#   z'onboarding changed foreign-key findingsz!pre-commit integrity check failedz"post-commit integrity check failed	confirmed	unchangedc              3  H   K   | ]}|                     d           dk    V  dS )statusr  N)r[   )r;   results     r   r   zrun.<locals>.<genexpr>~  s4      (k(kQWH)=)=)L(k(k(k(k(k(kr#   )r  
idempotentmapping_results_unchanged	integritybackup_restore_verified preexisting_foreign_key_findingsforeign_key_finding_deltar  )5rq   environr[   r   r   authorizationAUTHORIZATIONr`   authorization_manifestr	   r   raiffeisen_csv
setdefaultr   appendsortedr   valuesnextitemsendswithanyr"   r   visa_csvstripr.   sumr6   dbrw   rx   r{   r|   r,   r}   r-   r0   raiffeisen_account_idakb_account_idboolrv   ry   r   total_changesr   r   r   r   akb_source_referencecommit	Exceptionrollback)r   r^   expected_visarO   ref_rowsr<   expected_distributionreference_areference_bb_rowr   	visa_refs	referenceblank_visa_reference_rowsvisa_mapping_referencesbefore_digestr   baseline_foreign_keysraiffeisen_aakbr   masked_primary_namemasked_extra_nameplanchanges_beforemappingsmapping_resultsfinal_foreign_keyschangedr$   r   s                                @@r   runr=     s
   :>>:;; IGHHH N4#5#F#FLMMMd9::H"<0V$M&y1D'E'EGXYYJ02H&! > >CF,,b1188===="	 !78	9	93?RSi?j;k;kl  	'(1,4GHi4j0k0kkk::(9(9:::::>SSS?@@@~~~~HNN,<,<~~~~~K~~~~HNN,<,<~~~~~K$78L$M N NOO KWbWkWk 4566X X K IJJJ    K(     N LMMM[!!$E9%%&&'#6IJl6m2n2n*o*oooEII34455EXYsEtAuAu9v9vvvKLLL 4=!9!9;MNND "IF| C C))DSWWX->->D"EEKKMM	 	C#,==A#>#>#BIi  #DL 1 1C	8H8H8J8J4K4K KDLS~!>????y!!""c-8Q*R&S&SSS$M:N,O(P(PPPy>>Q9:::$Y//;-?tw''M?47##D{DLL)***VWW``bbcdeffF{{CDDD||,--6688;tCC@AAAgg4<<@Z3[3[3d3d3f3fgggY\`\v[xyyL
tPSWSfRh
i
iC #& ^ ^N#v--1D1M1M7127a88A==7./4155::)*f44\]]] 5 LkZ\Z]Z]N^^G+VXVYVYJZZ $(/23FGh3i/j/j #$9 : :&,-BD&Q&Q&Q
 
 .3hm n n!&Kafgg
 
 #4#:;; D " 

dg-//BCCC%)!"{HIIIdDK000LL"###'N,T3|L'A#B#BDWXXX8c,WdJeFfFf"W	
 	
 	
 	

 	6Da-<S\gW	
 	
 	
 	

 	t/FSVWcdpWqSrSr$7j	R 	R 	R 	Rt/FSn$5J	P 	P 	P 	Pt/HUn$@}	^ 	^ 	^ 	^t/GTWX[\hXiTjTj$8z	S 	S 	S 	S -DE-DE24LM
 gfNefff	

 
 
 
 EM
 
 
 ihDLLA[4\4\4e4e4g4ghhh!666HIII<<011::<<Q?4GGBCCC$~5    ||,--6688;tCC

?@@@JJLLL!(9++k!k%((k(k[j(k(k(k%k%k#',/0E,F,F%& DN Ks   F:c? ? dc                 Z   t          j        d          } |                     dt          d           |                     dt                     |                     dt          d           |                     d	t          d           |                     d
t          d           |                     dd           |                     dd           |                     dd           |                     dd           |                     dd           |                                 S )NzESprint 16 account/source onboarding; never confirms real transactions)descriptionz--dbT)typerequiredz--backup)r@  z--authorization-manifestz--raiffeisen-csvz
--visa-csvz--raiffeisen-account-id)rA  z--akb-account-idz--akb-source-referencez--confirm-onboarding
store_true)r   z--authorizationr   )r?   )argparseArgumentParseradd_argumentr   
parse_args)parsers    r   rF  rF    s1   $1xyyyF
TD999

...
2MMM
*EEE
4$???
1DAAA
*T:::
04@@@
.|DDD
)2666r#   __main__F   T)r@   indent	sort_keys)r   r   r   r   )r   r   r   r   )r$   r%   r&   r   r'   r(   r   r)   )r$   r%   r   r   )r   r   r   rK   )r$   r%   ra   r   r   rb   )r$   r%   r   rb   )r$   r%   r   r   r   r   r   r   r   r   r   r   r   r   r   rb   )r$   r%   r   r   r   r   r   r   r   r   r   rb   )r$   r%   r   r   r   r   r   rb   )r   r   r   rK   )r   r   )(
__future__r   rC  r3   rD   rq   rw   r~   decimalr   pathlibr   typingr   jarvis_finance.audit.logr   %jarvis_finance.services.budget_commonr   *jarvis_finance.services.budget_csv_importsr	   (jarvis_finance.services.household_importr   r  r\   r   r"   r0   r6   rJ   r`   r   r   r   r   r   r=  rF  __name__printrE   r9   r#   r   <module>rV     s6   " " " " " "    				                     7 7 7 7 7 7 5 5 5 5 5 5 L L L L L L M M M M M M4) 6 6 6 6\ \ \ \   9 9 9 9      ,!- !- !- !-H   6# # # #L   8
 
 
 
b b b bJ    z	E*$*SS&&U1PT
U
U
UVVVVV r#   