
    mjO                   j   d dl mZ d dlZd dlmc mZ d dlZd dl	Z	d dl
mZ d dlmZ d dlZd dlmZ d dlmZ d dlmc mZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ d dl m!Z!m"Z"m#Z# d dl$m%Z% d dlm&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- d dl.m/Z/ d dl0m1Z1m2Z2 dLdZ3dMdNdZ4dOdNdZ5dPdZ6dQd"Z7dRd%Z8dSd'Z9dSd(Z:dSd)Z;dSd*Z<dSd+Z=dSd,Z>dSd-Z?dSd.Z@dSd/ZAdSd0ZBdSd1ZCdSd2ZDdSd3ZEdSd4ZFdSd5ZGdSd6ZHdSd7ZIdSd8ZJdSd9ZKdSd:ZLdSd;ZMdSd<ZNdSd=ZOdSd>ZPdSd?ZQdSd@ZRdSdAZSdSdBZTdTdEZUdSdFZVdSdGZWdSdHZXdSdIZYdSdJZZdSdKZ[dS )U    )annotationsNDecimal)
Connection)HTTPException)
TestClient)get_db)
create_app)confirm_create_category)get_budget_charts_2026get_monthly_summary)confirm_budget_transactionconfirm_transfer!create_budget_transaction_preview)get_household_financial_summary)configure_source_mappingconfirm_household_importconfirm_household_review_actionget_household_overviewget_household_reviewlist_household_transactionspreview_household_importpreview_household_review_action)connect_memory)apply_migrationsget_schema_versionreturnr   c            
        t                      } t          |            |                     d           dD ]U\  }}|dk    rdnd}|                     dd| d|||dk    rd	ndf           |                     d
d| d| ||f           V|                                  t	          | ddddd           t	          | ddddd           t	          | ddddd           | S )NzqINSERT INTO platforms(platform_id,name,platform_type,created_at) VALUES ('p_syn','Synthetic','bank','2026-01-01')))raiHousehold A)akbHousehold B)visaCard Ar#   credit_cardcashzINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,portfolio_bucket,created_at)
               VALUES (?,?,?,?, 'CHF',?,'2026-01-01')acct_p_syn	liabilityzINSERT INTO budget_accounts(budget_account_id,linked_account_id,name,account_type,currency,created_at)
               VALUES (?,?,?,?, 'CHF','2026-01-01')bacc_Traiffeisen_bankSYN-RAI-001bacc_rai)confirmsource_typesource_referencebudget_account_idakb_bankSYN-AKB-001bacc_akbvisa_credit_cardzSYN-CARD-001	bacc_visa)r   r   executecommitr   )connkeylabelaccount_types       V/home/agent/.hermes/repos/FinanceManager/tests/unit/test_household_import_v1_golden.pydatabaser>   %   s   DTLL  E  F  F  FZ m m
U(+v}}69;H3=='SXZfwz  E  xE  xEhshs  KQ  ;R	S 	S 	S 	79FPSW\^j8k	m 	m 	m 	m 	KKMMMTtDUkx  PZ  $[  $[  \  \  \TtJdq  IS  $T  $T  U  U  UTtDVlz  R]  $^  $^  _  _  _K    -100.00SWISSLOS E-COMMERCE
2026-01-26amountstrtexttx_datec           	          d| d| d|  d| d	S )Nz@IBAN;Booked At;Text;Credit/Debit Amount;Valuta Date
SYN-RAI-001;;
 rC   rE   rF   s      r=   raiffeisen_csvrL   8   s.    twttY]tt`fttipttttr?   100.00Own account transferc           	          d| d| d| d|  d	S )Nz1Buchung;Valuta;Buchungstext;Belastung;Gutschrift
rH   z;;rI   rJ   rK   s      r=   akb_csvrP   <   s-    fff'ffTXff\bffffr?   dictc                 L    ddt                      dddt                      dgiS )Nfilesr+   profilecsv_textr2   r3   rU   r0   rV   )rL   rP   rJ   r?   r=   transfer_payloadrX   @   s6    %>3C3CDDMwyyYY  r?   sourcepreviewc                ,    | d|d         |d         dz  S )NTpreview_fingerprintbaseline_fingerprint)r.   r\   r]   rJ   )rY   rZ   s     r=   confirm_payloadr^   G   s0    WEZ=[-45K-LN N N Nr?   r9   tuple[dict, dict]c                   t          | |          }d |d         D             fd|d         D             }|d|iz  }t          | |          }|d         }d}||u }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }	dd|	iz  }
t	          t          j        |
                    d x}x}}||fS )Nc                    i | ]O}|                     d           dv t          |                     d                     t          |d                   PS )category_type>   incomeexpensecategory_id)getrD   ).0categorys     r=   
<dictcomp>z*business_ready_preview.<locals>.<dictcomp>N   s]       <<((,AAA 	HLL))**C0G,H,HAAAr?   
categoriesc                    i | ]T}|d          dk    rFt          |d                   v %t          |d                   t          |d                            US )
user_stateproposal_readytransaction_semantics	row_token)rD   )rg   itemby_types     r=   ri   z*business_ready_preview.<locals>.<dictcomp>S   sq       !111,-..'99 	DD1H,I(J(J K :99r?   itemscategory_overridesbusiness_ready_for_confirmTisz%(py1)s is %(py4)spy1py4assert %(py6)spy6)r   
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanation)r9   rY   initial	overridesresolvedrZ   @py_assert0@py_assert3@py_assert2@py_format5@py_format7rq   s              @r=   business_ready_previewr   L   s8   &tV44G -  G
   G$  I -y99H&tX66G/08D80D88888888880D8888808888D888888888888888888888888888Wr?   Nonec                    t                      } t          |           }d}||k    }|st          j        d|fd||f          dt	          j                    v st          j        t                    rt          j        t                    nddt	          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}d	 | 
                    d
          D             }h d}|j        } ||          }|sdt          j        |          t          j        |          dt	          j                    v st          j        |          rt          j        |          ndt          j        |          dz  }t          t          j	        |                    d x}x}}d | 
                    d          D             }ddh}|j        } ||          }|sdt          j        |          t          j        |          dt	          j                    v st          j        |          rt          j        |          ndt          j        |          dz  }t          t          j	        |                    d x}x}}d S )N1   ==z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   r9   py0ry   py3r|   assert %(py8)spy8c                    h | ]
}|d          S r   rJ   rg   rows     r=   	<setcomp>zPtest_schema_48_has_household_contract_and_three_unique_layers.<locals>.<setcomp>b   s    bbbc!fbbbr?   z1SELECT name FROM sqlite_master WHERE type='table'>   household_import_fileshousehold_import_itemshousehold_migros_linkshousehold_import_batches!household_account_source_mappingsJassert %(py6)s
{%(py6)s = %(py3)s
{%(py3)s = %(py1)s.issubset
}(%(py4)s)
}tablesry   r   rz   r|   c                    h | ]
}|d          S r   rJ   r   s     r=   r   zPtest_schema_48_has_household_contract_and_three_unique_layers.<locals>.<setcomp>e   s    ccc#s1vcccr?   z1SELECT name FROM sqlite_master WHERE type='index')ux_budget_candidates_household_source_row&ux_budget_candidates_household_logicalindexes)r>   r   r}   r~   @py_builtinslocals_should_repr_global_namer   r   r   r7   issubset)	r9   r   @py_assert5@py_assert4r   @py_format9r   r   r   s	            r=   =test_schema_48_has_household_contract_and_three_unique_layersr   _   s   ::Dd##)r)#r))))))))))#r))))))))))))))))))))))))))))))d)))))d))))))#))))r)))))))))))))))))))))))))))bb-` a abbbF@ @ @ Q @@HQ I IIOQ Q Q Q Q Q QGP@ Q Q QGPI Q Q Q QJPQ Q Q Q Q8PQ Q Q QGPQ Q Q Q QGPQ Q Q Q Q Q Q Q Q=PQ Q Q Q Q Q Q Q Q Q Q Qcc.a!b!bcccG79abtbktkklsttttttttbttttktttttttttttlstttttlsttttttttttttttttttttttttttttttr?   c            
     (   t                      } t                      }|                                  | j        }d                    |                                           }t          | |          }t          | |          }d |                                D             }d |                                D             }||k    }|st          j	        d|fd||f          dt          j                    v st          j        |          rt          j        |          nddt          j                    v st          j        |          rt          j        |          nddz  }	d	d
|	iz  }
t          t          j        |
                    d }|d         }|d         }||k    }|slt          j	        d|fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}}|d         d         }d}||k    }|slt          j	        d|fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}}|d         d         }t!          |          }d}||k    }|st          j	        d|fd||f          dt          j                    v st          j        t                     rt          j        t                     ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}x}}| j        }||k    }|st          j	        d|fd||f          dt          j                    v st          j        |           rt          j        |           ndt          j        |          dt          j                    v st          j        |          rt          j        |          nddz  }
dd|
iz  }t          t          j        |                    d x}}d}|j        }| j        } |            } ||          }||k    }|s!t          j	        d|fd ||f          t          j        |          t          j        |          dt          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          t          j        |          d!t          j                    v st          j        |          rt          j        |          nd!d"z  }d#d$|iz  }t          t          j        |                    d x}x}x}x}x}}|d%         }d&}||u }|slt          j	        d'|fd(||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}}|d)         d*         }d+}||k    }|slt          j	        d|fd||f          t          j        |          t          j        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}}t#          j        |          }g }d,}||v}|}|rd-}||v}|}|sXt          j	        d.|fd/||f          t          j        |          d0t          j                    v st          j        |          rt          j        |          nd0d1z  }d2d3|iz  }|                    |           |rt          j	        d.|fd4||f          t          j        |          d0t          j                    v st          j        |          rt          j        |          nd0d5z  }d6d$|iz  }|                    |           t          j        |d          i z  }d7d8|iz  }t          t          j        |                    d x}x}x}x}x}}d9}||v}|st          j	        d.|fd:||f          t          j        |          d0t          j                    v st          j        |          rt          j        |          nd0d;z  }d<d=|iz  }t          t          j        |                    d x}}d S )>NrI   c                &    i | ]\  }}|d k    ||S performancerJ   rg   r:   values      r=   ri   zQtest_preview_is_strictly_read_only_deterministic_and_redacted.<locals>.<dictcomp>q   s(    WWW:3#BVBVCBVBVBVr?   c                &    i | ]\  }}|d k    ||S r   rJ   r   s      r=   ri   zQtest_preview_is_strictly_read_only_deterministic_and_redacted.<locals>.<dictcomp>r   s(    YYYJCC=DXDXS%DXDXDXr?   r   )z%(py0)s == %(py2)sfirst_stablesecond_stabler   py2assert %(py4)srz   r\   z%(py1)s == %(py4)srx   r{   r|   r   api_total_secondsr   )>=)z%(py1)s >= %(py4)sparsing_by_file   z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)slenr   r   rz   py7assert %(py9)spy9z5%(py2)s
{%(py2)s = %(py0)s.total_changes
} == %(py4)sr9   before_changesr   r   rz   )z%(py10)s
{%(py10)s = %(py3)s
{%(py3)s = %(py1)s.join
}(%(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.iterdump
}()
})
} == %(py12)sbefore_dump)ry   r   rz   r|   r   py10py12assert %(py14)spy14confirmableTru   rw   countssafe_transfer_pairs   r,   r3   not inz%(py3)s not in %(py5)s
serializedr   py5%(py7)sr   z%(py10)s not in %(py12)sr   r   %(py14)sassert %(py17)spy17r0   z%(py1)s not in %(py3)sry   r   assert %(py5)sr   )r>   rX   r8   total_changesjoiniterdumpr   rr   r}   r~   r   r   r   r   r   r   r   jsondumpsappend_format_boolop)r9   payloadr   r   firstsecondr   r   @py_assert1@py_format3r   r   r   r   r   @py_assert6r   @py_format8@py_format10@py_assert7@py_assert9@py_assert11@py_format13@py_format15r   r   @py_format6@py_format16@py_format18@py_format4s                                 r=   =test_preview_is_strictly_read_only_deterministic_and_redactedr   i   su
   ::D  GKKMMM'N))DMMOO,,K$T733E%dG44FWWWWWLYY&,,..YYYM=((((((((((<=((((((((((((<(((((<(((((((((((((=(((((=(((((((((((((((((((((((((&'H62G+HH'+HHHHHHHHHHH'+HHHHHH'HHHH+HHHHHHHHHHHHHHHHHHHHHHHHHHHH 34994999999999949999949999999999999999999999999999999]#$56<3677<1<71<<<<<<<<<<71<<<<<<<<<<<<3<<<<<3<<<<<<6<<<<7<<<<1<<<<<<<<<<<<<<<<<<<<<<<<<<<<<///////////////////////4/////4/////////////////////////////////////////////////4494T]4]]__499_%%4%4444444444%4444444444944444444444T44444T444444]4444_4444%444444444444444444444444444444444444444444444444444'4'4''''''''''4'''''''''4'''''''''''''''''''''''''''?016Q61Q66666666661Q6666616666Q666666666666666666666666666E""JNN=N=
*NNNNN}N}J/NNNNNNNNNNNN=
NNNNN=NNNNNNNNNNN
NNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNN}JNNNNN}NNNNNNNNNNNJNNNNNJNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN/Z//////////Z////////////////Z/////Z/////////////////////////////r?   c                 L   t                      } d                    d t          d          D                       }ddd|z   dgi}g }|                     |j                   t          | |           |                     d            d |D             }t          |          }d	}||k    }|st          j        d
|fd||f          dt          j
                    v st          j        t                    rt          j        t                    nddt          j
                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d S )N c           
   3  V   K   | ]$}d |dz  dz   dd| d|dz    d|dz  dz   dd	V  %dS )	zSYN-RAI-001;2026-01-   r   02dz
;Merchant z;-z.00;2026-01-rI   NrJ   rg   indexs     r=   	<genexpr>zStest_preview_bulk_loads_repeated_source_mapping_once_per_binding.<locals>.<genexpr>   s{         	x
a/wwwuwwPQ	ww`ehj`jno_owwww     r?   (   rS   r+   z4IBAN;Booked At;Text;Credit/Debit Amount;Valuta Date
rT   c                    g | ]A}|                                                                                     d           rd|v ?|BS )zSELECT M.MAPPING_IDr   )lstripupper
startswith)rg   	statements     r=   
<listcomp>zTtest_preview_bulk_loads_repeated_source_mapping_once_per_binding.<locals>.<listcomp>   s`       ##%%001FGG 09<< 	 =<<r?   r   r   r   r   mapping_selectsr   r   r   )r>   r   rangeset_trace_callbackr   r   r   r}   r~   r   r   r   r   r   r   )
r9   rowsr   
statementsr	  r   r   r   r   r   s
             r=   @test_preview_bulk_loads_repeated_source_mapping_once_per_bindingr     s   ::D77  2YY    D
 	(ORVV
 
 G JJ-...T7+++D!!! #  O $1$1$$$$$$$$$$1$$$$$$$$$$$$3$$$$$3$$$$$$$$$$$$$$$$$$$$$$$$$$$$1$$$$$$$$$$$$$$$$$$$$$$$$$$$$$r?   c                 4   t                      } t                      }t          | |          }|d         d         }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd	|iz  }t          t          j        |                    d x}x}}g }	|d
         }d}
||
k    }|}|r|d         }d}||k    }|}|st          j        d|fd||
f          t          j        |          t          j        |
          dz  }dd|iz  }|	                    |           |r`t          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }|	                    |           t          j	        |	d          i z  }dd|iz  }t          t          j        |                    d x}x}	x}x}x}
x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd	|iz  }t          t          j        |                    d x}x}}t          | t          ||                    }t          | t          ||                    }d|v r|d         n|d         d         dk    }|s:ddt          j        |          iz  }t          t          j        |                    d }g }	|d         }d }
||
u }|}|r|d!         }|d!         }||k    }|}|st          j        d"|fd#||
f          t          j        |          t          j        |
          dz  }dd|iz  }|	                    |           |r`t          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }|	                    |           t          j	        |	d          i z  }dd|iz  }t          t          j        |                    d x}x}	x}x}x}
x}x}}|                     d$                                          d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd	|iz  }t          t          j        |                    d x}x}}|                     d%                                          d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd	|iz  }t          t          j        |                    d x}x}}|                     d&                                          d         }d'}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd	|iz  }t          t          j        |                    d x}x}}|                     d(                                          d         }g }	d)}||v}|}|rd*}||v}|}|rd+}||v}|}|st          j        d,|fd-||f          t          j        |          d.t          j                    v st          j        |          rt          j        |          nd.d/z  }d0d1|iz  }|	                    |           |rt          j        d,|fd2||f          t          j        |          d.t          j                    v st          j        |          rt          j        |          nd.d3z  }d4d5|iz  }|	                    |           |rt          j        d,|fd6||f          t          j        |          d.t          j                    v st          j        |          rt          j        |          nd.d7z  }d8d9|iz  }|	                    |           t          j	        |	d          i z  } d:d;| iz  }!t          t          j        |!                    d x}x}	x}x}x}x}x}}d S )<Ntransfer_pairsr   pairing_classsafer   r   rx   r{   r|   rC   rM   currencyCHFz%(py3)s == %(py6)sr   r|   %(py8)sr   z%(py11)s == %(py14)spy11r   %(py16)spy16assert %(py19)spy19pairing_versiontransfer_pairing_v3transfer_pair_countr   r   zassert %(py1)sry   
idempotentTbatch_idru   z%(py3)s is %(py6)sz]SELECT COUNT(*) FROM budget_transfer_pairs WHERE status='confirmed' AND quality_status='safe'z%SELECT COUNT(*) FROM budget_transferszJSELECT COUNT(*) FROM budget_transactions WHERE transaction_type='transfer'r   zOSELECT new_values_json FROM audit_log WHERE action='household_import_confirmed'SYN-SWISSLOSrV   r   r   auditr   r   r   r   r   r   r   )z%(py17)s not in %(py19)s)r   r  z%(py21)spy21zassert %(py24)spy24)r>   rX   r   r}   r~   r   r   r   r   r   r   r^   r7   fetchoner   r   r   )"r9   r   rZ   pairr   r   r   r   r   r   r   r   @py_assert10@py_assert13@py_assert12r   r   @py_format17r   @py_format20r   r   @py_format2r'  r   r   @py_assert16@py_assert18r   r   r   @py_format22@py_format23@py_format25s"                                     r=   _test_golden_raiffeisen_2026_01_26_swisslos_chf100_is_safe_v3_transfer_and_confirm_is_noop_twicer7     sz   ::D  G&tW55G#$Q'D *F* F********** F***** ****F***************************CC4>CXC>X%CCCCC$z*:CeC*:e*CCCCCCCCCCCC>XCCCCC>CCCCXCCCCCCCCCCCCCCCCCCCCCCCCCCC*:eCCCCC*:CCCCeCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC$%>)>>%)>>>>>>>>>>>%)>>>>>>%>>>>)>>>>>>>>>>>>>>>>>>>>>>>>>>>>$T?7G+L+LMME%dOGW,M,MNNF+@E+I+I5&''uU]_tOuyzOzzzzzzzzzzzzzzzzzzzzzzzzzSS6,S4S4'SSSSSF:,>S%
BSS,>BS,SSSSSSSSSSSS4SSSSSSSSS4SSSSSSSSSSSSSSSSSSSSSSSSSSS,>BSSSSSS,>SSSSBSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS<<wxx  B  B  D  D  EF  G  L  KL  L  G  KL  L  L  L  L  L  L  L  L  L  L  G  KL  L  L  L  L  L  G  L  L  L  L  KL  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L  L<<?@@IIKKANSRSSNRSSSSSSSSSSSNRSSSSSSNSSSSRSSSSSSSSSSSSSSSSSSSSSSSSSSSS<<deennppqrsxwxxswxxxxxxxxxxxswxxxxxxsxxxxwxxxxxxxxxxxxxxxxxxxxxxxxxxxxLLjkkttvvwxyEVV6V6VVVVV:V:U#:VVVVVzVzQV?VVVVVVVVVVVV6VVVVV6VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV:UVVVVV:VVVVVVVVVVVUVVVVVUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVzQVVVVVVzVVVVVVVVVVVQVVVVVVQVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVr?   c                     t                      } ddt          dd          dddt          dd	          d
gi}t          | |          }|d         d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}d |d         D             }t          |          }|sddt          j                    v st	          j        t                    rt	          j        t                    ndt	          j        |          t	          j        |          dz  }t          t	          j        |                    d x}}d S )NrS   r+   -10.00zPayment CoffeerT   r2   r3   10.00zSalary correctionrW   r   r   r   r   r   rx   r{   r|   c              3  .   K   | ]}|d          dk    V  dS )dispositiontransfer_confirmedNrJ   r   s     r=   r  z\test_generic_payment_text_cannot_turn_unrelated_rows_into_a_safe_transfer.<locals>.<genexpr>   s-      UUcs=!%99UUUUUUr?   r  ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr   )r>   rL   rP   r   r}   r~   r   r   r   r?  r   r   r   )	r9   r   rZ   r   r   r   r   r   r   s	            r=   Itest_generic_payment_text_cannot_turn_unrelated_rows_into_a_safe_transferr@     s   ::D%>(L\3]3]^^MwW^`sOtOtuu G 'tW55G8238q83q88888888883q8888838888q888888888888888888888888888UUWV_UUUU3UUUUUUUUUUUUUUUU3UUUUU3UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUr?   c                 Z   t                      } t                      }t          | |          }|                     d           |                                  t          j        t                    5 }t          | t          ||                     d d d            n# 1 swxY w Y   |j
        }|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }	t%          t          j        |	                    d x}x}x}}|                     d	                                          d
         }
d
}|
|k    }|slt          j        d|fd|
|f          t          j        |
          t          j        |          dz  }dd|iz  }t%          t          j        |                    d x}
x}}d S )NzaUPDATE household_account_source_mappings SET updated_at='2026-02-01' WHERE source_type='akb_bank'  r   zN%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.status_code
} == %(py7)sexcr   r   r   -SELECT COUNT(*) FROM household_import_batchesr   r   rx   r{   r|   )r>   rX   r   r7   r8   pytestraisesr   r   r^   r   status_coder}   r~   r   r   r   r   r   r   r*  )r9   r   rZ   rD  r   r   r   r   r   r   r   r   r   r   s                 r=   2test_stale_confirm_rejected_before_any_batch_writerI     s   ::D  G&tW55GLLtuuuKKMMM	}	%	% J w'H'HIIIJ J J J J J J J J J J J J J J9'9 'C' C'''''''''' C''''''''''''3'''''3''''''9'''' ''''C'''''''''''''''''''''''''''''<<GHHQQSSTUV[Z[[VZ[[[[[[[[[[[VZ[[[[[[V[[[[Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[s   /BB!Bc                    t                      } d}dd|dgi}t          | |          \  }}t          | t          ||                     t	          | |          }|d         d         d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}dd|
                    dd          dgi}
t	          | |
          }|d         d         d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}|d         d         d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}dd|dz   dgi}t	          | |          d         d         d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}d S )NzoTransactionId,CardId,Date,Amount,Currency,MerchantName
T-001,SYN-CARD-001,2026-02-01,-12.50,CHF,Synthetic Shop
rS   r5   rT   r  r   r<  duplicate_filer   r   rx   r{   r|   zT-001zT-002reviewclassificationpossible_logical_duplicaterI   duplicate_source_row)r>   r   r   r^   r   r}   r~   r   r   r   replace)r9   r#   r   rZ   	same_filer   r   r   r   r   overlaplogicalsource_overlaps                r=   =test_file_source_row_and_logical_duplicates_are_distinguishedrU     s   ::D~D%7TJJKLG-dG<<GWT?7G#D#DEEE(w77IVQ.B2BB.2BBBBBBBBBBB.2BBBBBB.BBBB2BBBBBBBBBBBBBBBBBBBBBBBBBBBB%7T\\RY[bEcEcddefG&tW55G6?1m,88,8888888888,88888,88888888888888888888888888888886?1./O3OO/3OOOOOOOOOOO/3OOOOOO/OOOO3OOOOOOOOOOOOOOOOOOOOOOOOOOOO,>DSWK X XYZN#D.99&A!D]SmWmmSWmmmmmmmmmmmSWmmmmmmSmmmmWmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmr?   c                    t                      } |                     d           |                     d           |                                  t          | ddddgi          }|d         d         }|d	         }d
}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}|d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}|d         }d}||u }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}|d         d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}d S )Na  INSERT INTO budget_transaction_candidates(
             transaction_candidate_id,source_file_label,source_row_or_range,source_type,
             transaction_date,description,merchant,amount_original,currency_original,
             confidence,requires_review,status,created_at,updated_at)
           VALUES ('legacy-apple','legacy-visa.csv','R1122','credit_card_csv',
                   '2026-05-12','Apple','Apple','20.00','CHF','1',0,'confirmed',
                   '2026-05-18','2026-05-18')a  INSERT INTO budget_transactions(
             budget_transaction_id,account_id,transaction_type,transaction_date,description,payee,
             amount_original,currency_original,amount_chf,fx_status,status,source_type,
             source_candidate_id,created_at,updated_at)
           VALUES ('legacy-apple-tx','bacc_rai','expense','2026-05-12','Apple','Apple',
                   '20.00','CHF','20.00','not_needed','confirmed','import_candidate',
                   'legacy-apple','2026-05-18','2026-05-18')rS   r5   z~TransactionId,CardId,Date,Amount,Currency,MerchantName,OriginalAmount
new-apple,SYN-CARD-001,2026-05-12,20.00,CHF,Apple,20.00
rT   r  r   rM  possible_legacy_duplicater   r   rx   r{   r|   r<  rL  requires_reviewTru   rw   expected_budget_effectexpense_chf0.00)	r>   r7   r8   r   r}   r~   r   r   r   )r9   rZ   r   r   r   r   r   r   s           r=   Utest_canonical_visa_row_overlapping_legacy_positive_household_booking_requires_reviewr\     sK   ::DLL	1   	LL	@   	KKMMM&-P  	
 G &/!
C ?$?? $??????????? $?????? ????$????????????????????????????})))))))))))))))))))))))))))))))))))))))))))))))) !)T)!T))))))))))!T)))))!))))T)))))))))))))))))))))))))))+,];EvE;vEEEEEEEEEE;vEEEEE;EEEEvEEEEEEEEEEEEEEEEEEEEEEEEEEEEEr?   c            	     ^   t                      } d}t          | dd|dgi          }d |d         D             }d |d         D             }g }d}||v }|}|rd	}	|	|v }
|
}|sXt          j        d
|fd||f          t          j        |          dt          j                    v st          j        |          rt          j        |          nddz  }dd|iz  }|                    |           |rt          j        d
|
fd|	|f          t          j        |	          dt          j                    v st          j        |          rt          j        |          nddz  }dd|iz  }|                    |           t          j	        |d          i z  }dd|iz  }t          t          j        |                    d x}x}x}x}x}	}
d}||v }|st          j        d
|fd||f          t          j        |          dt          j                    v st          j        |          rt          j        |          nddz  }dd|iz  }t          t          j        |                    d x}}t          | ddt          dd          dgi          }|d         d         d          }d!}||k    }|slt          j        d"|fd#||f          t          j        |          t          j        |          d$z  }d%d&|iz  }t          t          j        |                    d x}x}}|d'         d         d(         }d)}||k    }|slt          j        d"|fd#||f          t          j        |          t          j        |          d$z  }d%d&|iz  }t          t          j        |                    d x}x}}d S )*NzTransactionId,CardId,Date,Amount,Currency,MerchantName,Status
T-P,SYN-CARD-001,2026-02-02,-20.00,CHF,Synthetic Market,pending
T-P,SYN-CARD-001,2026-02-02,-20.00,CHF,Synthetic Market,booked
T-R,SYN-CARD-001,2026-02-03,5.00,CHF,Synthetic Refund,booked
rS   r5   rT   c                    g | ]
}|d          S r<  rJ   r   s     r=   r  zRtest_credit_card_pending_final_refund_and_payment_are_explicit.<locals>.<listcomp>      BBB3C&BBBr?   r  c                    g | ]
}|d          S )rM  rJ   r   s     r=   r  zRtest_credit_card_pending_final_refund_and_payment_are_explicit.<locals>.<listcomp>  s    @@@s#$@@@r?   superseded_pending	candidatein)z%(py3)s in %(py5)sdispositionsr   r   r   )z%(py10)s in %(py12)sr   r   r   r   r   r   credit_card_refund)z%(py1)s in %(py3)sclassesr   r   r   r+   z-55.00zVISA CARD PAYMENTrM  credit_card_paymentr   r   rx   r{   r|   r  r  	unmatched)r>   r   r}   r~   r   r   r   r   r   r   r   r   rL   )r9   rV   rZ   rf  rh  r   r   r   r   r   r   r   r   r   r   r   r   r   bank_paymentr   r   r   s                         r=   >test_credit_card_pending_final_refund_and_payment_are_explicitrl     s   ::DPH 'tgDVdl8m8m7n-oppGBB'&/BBBL@@@@@GOOO</OOOOOKOK<4OOOOOOOOOOOO<OOOOOOOOOOOOOOOO<OOOOO<OOOOOOOOOOOOOOOOOOOOOOOOOOOOOK<OOOOOKOOOOOOOOOOO<OOOOO<OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO*7**********7****************7*****7***************************+D7IZhvw  BU  iV  iV  >W  >W  =X  3Y  Z  ZL"#34M8MM48MMMMMMMMMMM48MMMMMM4MMMM8MMMMMMMMMMMMMMMMMMMMMMMMMMMM()!,_=LL=LLLLLLLLLL=LLLLL=LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLr?   c                 	   t                      } d}d}dd|dd|dgi}t          | |          }|d         d         d	         }d
}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}t          | t          ||                    }
|
d         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}| 	                    d          
                                d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}| 	                    d          
                                d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}| 	                    d          
                                d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}t                      }|d|d         d         d|                    dd          dgiz  }t          ||          }|d         d         d	         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         d         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d S )NzoTransactionId,CardId,Date,Amount,Currency,MerchantName
M-1,SYN-CARD-001,2026-03-01,-60.00,CHF,Migros Synthetic
zDatum;Zeit;Filiale;Kassennummer;Transaktionsnummer;Artikel;Umsatz
2026-03-01;12:00;Synthetic Store;1;99;Item A;24.00
2026-03-01;12:00;Synthetic Store;1;99;Item B;36.00
rS   r5   rT   migros_receiptsreceipt_linksr   statuslinkedr   r   rx   r{   r|   r   receipt_link_countr   -SELECT COUNT(*) FROM budget_import_line_itemsr   (SELECT COUNT(*) FROM budget_transactionsASELECT COUNT(*) FROM household_migros_links WHERE status='linked'z36.00z36.02rL  
differencez0.02)r>   r   r}   r~   r   r   r   r   r^   r7   r*  rP  )r9   r#   receiptr   rZ   r   r   r   r   r   resultconn2mismatchrL  s                 r=   Qtest_migros_links_detail_without_double_counting_and_difference_over_cent_reviewsr{    s   ::D~DEG %7TJJ%6GLLN OG&tW55G?#A&x0<H<0H<<<<<<<<<<0H<<<<<0<<<<H<<<<<<<<<<<<<<<<<<<<<<<<<<<%dOGW,M,MNNF(016Q61Q66666666661Q6666616666Q666666666666666666666666666<<GHHQQSSTUV[Z[[VZ[[[[[[[[[[[VZ[[[[[[V[[[[Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[<<BCCLLNNqQVUVVQUVVVVVVVVVVVQUVVVVVVQVVVVUVVVVVVVVVVVVVVVVVVVVVVVVVVVV<<[\\eegghijonoojnooooooooooojnoooooojoooonooooooooooooooooooooooooooooJJE'GG$4Q$7EVdkdsdst{  ~E  eF  eF  :G  :G  $H  I  IH%eX66F/"1%h/;8;/8;;;;;;;;;;/8;;;;;/;;;;8;;;;;;;;;;;;;;;;;;;;;;;;;;;/"1%l3=v=3v==========3v=====3====v=============================r?   c            
     f   t                      fd} t          d          }| |j        t          <   t	          |          }|                    d                                          d         }dD ]}||v }|st          j        d|fd||f          d	t          j
                    v st          j        |          rt          j        |          nd	dt          j
                    v st          j        |          rt          j        |          ndd
z  }dd|iz  }t          t          j        |                    d }͉j        }|j        }d}	 ||	          }
|
j        }d}||k    }|st          j        d|fd||f          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          t          j        |	          t          j        |
          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}	x}
x}x}}|j        }d}	 ||	          }
|
j        }d}||k    }|st          j        d|fd||f          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          t          j        |	          t          j        |
          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}	x}
x}x}}j        }||k    }	|	st          j        d|	fd||f          dt          j
                    v st          j                  rt          j                  ndt          j        |          dt          j
                    v st          j        |          rt          j        |          nddz  }dd|iz  }t          t          j        |                    d x}}	t          d          }| |j        t          <   t	          |          }|j        }d}	i }
 ||	|
          }|j        }d}||k    }|st          j        d|fd ||f          d!t          j
                    v st          j        |          rt          j        |          nd!t          j        |          t          j        |	          t          j        |
          t          j        |          t          j        |          t          j        |          d"z  }d#d$|iz  }t          t          j        |                    d x}x}	x}
x}x}x}}d S )%Nc               3     K    V  d S NrJ   r9   s   r=   override_dbz\test_api_contract_gets_are_side_effect_free_and_write_gate_is_preserved.<locals>.override_db&        




r?   test
write_mode/openapi.jsonpaths)%/api/budget/household/source-mappingsz$/api/budget/household/import/preview$/api/budget/household/import/confirm$/api/budget/household/import/batchesrd  )z%(py0)s in %(py2)spathr   r   rz   r     r   )zk%(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
}.status_code
} == %(py11)sclient)r   r   rz   r|   r   r  zassert %(py13)spy13r  r   r9   beforer   r{   r|   disabledr  r     )z|%(py10)s
{%(py10)s = %(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s.post
}(%(py4)s, json=%(py6)s)
}.status_code
} == %(py13)sblocked)r   r   rz   r|   r   r   r  assert %(py15)spy15)r>   r
   dependency_overridesr	   r   rf   r   r}   r~   r   r   r   r   r   r   r   rH  post)r  appr  r  r  r   r   r   r  r   r   r   r,  r   @py_format12@py_format14r   blocked_appr  r.  r   r   r9   s                         @r=   Gtest_api_contract_gets_are_side_effect_free_and_write_gate_is_preservedr  $  sy   ::D    

'
'
'C'2CV$__FJJ'',,..w7Ea  u}tuttuuF:Q=Q::=>>Q>JQcQJcQQQQQQQQQQJcQQQQQQQQQQQQ6QQQQQ6QQQQQQ:QQQQ=QQQQ>QQQQJQQQQcQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ:P<P::<==P=IPSPISPPPPPPPPPPISPPPPPPPPPPPP6PPPPP6PPPPPP:PPPP<PPPP=PPPPIPPPPSPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP'''''''''''''''''''''''4'''''4'''''''''''''''''''''''''''''''''''''''''''''''''
333K/:K$V,%%G<[>[R[<<>RHHH[HT[X[[TX[[[[[[[[[[[TX[[[[[[[[[[[[[7[[[[[7[[[[[[<[[[[>[[[[R[[[[H[[[[T[[[[X[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[r?   c            	        t                      } t                      }t          | |          }t          | t	          ||                     t                      }t          d          |d         d         d<   t          j        t                    5 }t          | t	          ||                     d d d            n# 1 swxY w Y   |j	        }|j
        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          t          j        |          d	z  }	d
d|	iz  }
t#          t          j        |
                    d x}x}x}}d}|j	        }|j        }t)          |          }||v}|st          j        d|fd||f          t          j        |          dt          j                    v st          j        t(                    rt          j        t(                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }t#          t          j        |                    d x}x}x}x}}d S )Nz-101.00rS   r   rV   rB  r   rC  rD  r   r   r   r%  r   zm%(py1)s not in %(py10)s
{%(py10)s = %(py3)s(%(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.value
}.detail
})
}rD   ry   r   rz   r|   r   r   assert %(py12)sr   )r>   rX   r   r   r^   rL   rF  rG  r   r   rH  r}   r~   r   r   r   r   r   r   detailrD   )r9   r   rZ   stolenrD  r   r   r   r   r   r   r   r   r   r   @py_format11r   s                    r=   =test_idempotent_confirm_recomputes_input_identity_before_noopr  9  sL   ::D  G&tW55GT?7G#D#DEEEF%3I%>%>F7OAz"	}	%	% I vw'G'GHHHI I I I I I I I I I I I I I I9'9 'C' C'''''''''' C''''''''''''3'''''3''''''9'''' ''''C'''''''''''''''''''''''''''''.SY.Y-.-...6...........6......6.............................S.....S......Y....-......................................s   B;;B?B?c                    t                      } ddt          d          dgi}d |                     d          D             }|d         |d         d         d	<   t          | |          }|d
         }d}||u }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}|d         d         d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}|d         |d         d         d	<   t          | |          \  }}	|	d
         }d}||u }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}t          | t          ||	                     |d         |d         d         d	<   t          j        t                    5 }
t          | t          ||	                     d d d            n# 1 swxY w Y   |
j        }|j        }d}||k    }|st	          j        d|fd||f          dt#          j                    v st	          j        |
          rt	          j        |
          ndt	          j        |          t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}x}}d S )NrS   r+   r9  rT   c                ,    i | ]}|d          |d         S )r/   
mapping_idrJ   r   s     r=   ri   zLtest_selected_mapping_is_bound_and_mismatch_fails_closed.<locals>.<dictcomp>I  s4        	MC-  r?   zDSELECT mapping_id,source_type FROM household_account_source_mappingsr5   r   r  r   Fru   rw   rx   r{   r|   errorscode*account_source_mapping_missing_or_mismatchr   r   TrB  rC  rD  r   r   r   )r>   rL   r7   r   r}   r~   r   r   r   r   r   r^   rF  rG  r   r   rH  r   r   r   )r9   r   mapping_idsrz  r   r   r   r   r   matchedrD  r   r   r   r   r   s                   r=   8test_selected_mapping_is_bound_and_mismatch_fails_closedr  F  sy   ::D%6NS[D\D\]]^_G << fgg  K )44F(GGGQ%'g66HM"+e+"e++++++++++"e+++++"++++e+++++++++++++++++++++++++++Ha (X,XX(,XXXXXXXXXXX(,XXXXXX(XXXX,XXXXXXXXXXXXXXXXXXXXXXXXXXXX(34E(FGGQ%-dG<<GW=!)T)!T))))))))))!T)))))!))))T)))))))))))))))))))))))))))T?7G#D#DEEE(34F(GGGQ%	}	%	% J w'H'HIIIJ J J J J J J J J J J J J J J9'9 'C' C'''''''''' C''''''''''''3'''''3''''''9'''' ''''C'''''''''''''''''''''''''''''''s   6J!!J%(J%c            	        d} | D ]}t                      }t                      }t          ||          }|                    |           |                                 t          j        t                    5 }t          |t          ||                     d d d            n# 1 swxY w Y   |j
        }|j        }d}||k    }	|	st          j        d|	fd||f          dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          t          j        |          dz  }
dd|
iz  }t%          t          j        |                    d x}x}x}	}d S )	N)zFUPDATE accounts SET account_name='Changed' WHERE account_id='acct_rai'zRUPDATE budget_accounts SET updated_at='changed' WHERE budget_account_id='bacc_rai'a>  INSERT INTO budget_transactions(budget_transaction_id,account_id,transaction_type,transaction_date,description,amount_original,currency_original,amount_chf,fx_status,status,source_type,created_at,updated_at) VALUES ('drift','bacc_rai','expense','2026-01-01','x','1','CHF','1','not_needed','confirmed','manual','x','x')rB  r   rC  rD  r   r   r   )r>   rX   r   r7   r8   rF  rG  r   r   r^   r   rH  r}   r~   r   r   r   r   r   r   )	mutationssqlr9   r   rZ   rD  r   r   r   r   r   r   s               r=   Ltest_baseline_covers_accounts_transactions_transfers_and_household_relationsr  [  s   I
  , ,zz"$$*499S]=)) 	NS$T?7G+L+LMMM	N 	N 	N 	N 	N 	N 	N 	N 	N 	N 	N 	N 	N 	N 	Ny+y$++$++++++++++$++++++++++++s+++++s++++++y++++$++++++++++++++++++++++++++++++++++, ,s   6B!!B%	(B%	c            
     D   t                      } dg iddddgiddddgiddddgidddd	z  dgif}|D ]i}t          j        t                    5 }t	          | |           d d d            n# 1 swxY w Y   |j        }|j        }d
dh}||v }|st          j        d|fd||f          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}x}}d}
|j        }|j        }t!          |          }|
|v}|st          j        d|fd|
|f          t          j        |
          dt          j
                    v st          j        t                     rt          j        t                     nddt          j
                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}
x}x}x}}kd S )NrS   r5   r   rT   unknownzsecret-account-referenceautoxi P i    rd  )zN%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.status_code
} in %(py7)srD  r   r   r   r   r  rD   r  r  r   )r>   rF  rG  r   r   r   rH  r}   r~   r   r   r   r   r   r   r  rD   )r9   bad_payloadsr   rD  r   r   r   r   r   r   r   r   r   r   r  r   s                   r=   Ftest_limits_empty_unsupported_and_errors_fail_closed_without_raw_leaksr  l  s_   ::D	"	1rBBCD	y6PQQRS	v3MNNOP	1sFY?Z[[\]L   G G]=)) 	4S$T7333	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4y2y$2c
2$
2222222222$
222222222222s22222s222222y2222$2222
22222222222222222222222222222)FSYFY5EF5E1F1FF)1FFFFFFFFFFF)1FFFFFF)FFFFFFFFFFFFFFFFFFFFFFFFFFFFFSFFFFFSFFFFFFYFFFF5EFFFF1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF	G Gs   A..A2	5A2	c                    t                      } t                      }t          | |          }t          |          }g }|d         }|}|r
|d         }|}|sddt	          j        |          iz  }|                    |           |r.ddt	          j        |          iz  }	|                    |	           t	          j        |d          i z  }
dd	|
iz  }t          t	          j	        |                    d x}x}x}}d
}||v}|st	          j
        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j	        |                    d x}}d}||v}|st	          j
        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j	        |                    d x}}d}||v}|st	          j
        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j	        |                    d x}}d}||v}|st	          j
        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j	        |                    d x}}d}||v}|st	          j
        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j	        |                    d x}}d}||v}|st	          j
        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j	        |                    d x}}d |d         D             }t          |          }|sddt          j                    v st	          j        t                    rt	          j        t                    ndt	          j        |          t	          j        |          dz  }t          t	          j	        |                    d x}}d S )Nr\   r]   z%(py3)sr   z%(py6)sr|   r   r   r   input_fingerprintr   r   rZ   r   r   r   file_fingerprintencodedsource_row_fingerprintlogical_fingerprintmoney_candidate_idr%  c              3  f   K   | ],}t          |d                                        d          V  -dS )ro   row_N)rD   r  r   s     r=   r  zctest_public_preview_exposes_protocol_bindings_but_no_internal_file_or_row_hashes.<locals>.<genexpr>  s=      SSCs3{#$$//77SSSSSSr?   r  r>  r?  r   )r>   rX   r   rD   r}   r   r   r   r   r   r~   r   r   r   r?  )r9   r   rZ   r  r   r   r   r   r   r   r   r   r   r   r   s                  r=   Ptest_public_preview_exposes_protocol_bindings_but_no_internal_file_or_row_hashesr  |  s   ::D  G&tW55G'llGMM7()M)M)Mg6L.MM.MMMMMMMM)MMMMMMMMMMMM)MMMMM.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-g----------g----------------g-----g---------------------------,W,,,,,,,,,,W,,,,,,,,,,,,,,,,W,,,,,W,,,,,,,,,,,,,,,,,,,,,,,,,,,#2#72222222222#722222#222222222227222227222222222222222222222222222 / ////////// ///// ///////////////////////////////////////////.w..........w................w.....w........................... 6          6     6                                           SS76?SSSS3SSSSSSSSSSSSSSSS3SSSSS3SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSr?   c                    t                      } d}dd|dgi}t          | |          \  }}|d         d         }d}||k    }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}d |d         D             }|j        }d}	 ||	          }
d}|
|k    }|st          j        d|fd|
|f          t          j        |          t          j        |          t          j        |	          t          j        |
          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}x}	x}
x}}t          | t          ||                    }|d         d         }d}||k    }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}| 
                    d                                          d         }d}||k    }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}t                      }d}dd|dgi}t          ||          \  }}d |d         D             }ddg}||k    }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}t          |t          ||                     |
                    d                                          d         }d}||k    }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}d S )NzTransactionId,CardId,Date,Amount,Currency,MerchantName,Status
P-1,SYN-CARD-001,2026-02-02,-20.00,CHF,Synthetic,pending
P-1,SYN-CARD-001,2026-02-02,-20.00,CHF,Synthetic,booked
P-1,SYN-CARD-001,2026-02-02,-20.00,CHF,Synthetic,booked
rS   r5   rT   r   
duplicatesr   r   r   rx   r{   r|   c                    g | ]
}|d          S r_  rJ   r   s     r=   r  zYtest_same_request_duplicate_and_pending_final_have_one_writable_final.<locals>.<listcomp>  s    :::3C:::r?   r  rc  r   )zL%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.count
}(%(py5)s)
} == %(py10)s)ry   r   r   r   r   r  r   candidate_countWSELECT COUNT(*) FROM budget_transaction_candidates WHERE household_batch_id IS NOT NULLr   zTransactionId,CardId,Date,Amount,Currency,MerchantName
D-1,SYN-CARD-001,2026-02-03,-5.00,CHF,Synthetic
D-1,SYN-CARD-001,2026-02-03,-5.00,CHF,Synthetic
c                    g | ]
}|d          S r_  rJ   r   s     r=   r  zYtest_same_request_duplicate_and_pending_final_have_one_writable_final.<locals>.<listcomp>  s    DDD3CDDDr?   rO  )r>   r   r}   r~   r   r   r   countr   r^   r7   r*  )r9   r  r   rZ   r   r   r   r   r   r   r   r   @py_assert8r  r   rx  ry  duplicate_rowsduplicate_payloadduplicate_previews                       r=   Etest_same_request_duplicate_and_pending_final_have_one_writable_finalr    s   ::DGD %7TJJKLG-dG<<GW8\*/a/*a//////////*a/////*////a///////////////////////////::'&/:::R:@RR@@MMRQRRMQRRRRRRRRRRRMQRRRRRR:RRRR@RRRRRRRRMRRRRQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR%dOGW,M,MNNF(-.3!3.!3333333333.!33333.3333!333333333333333333333333333<<qrr{{}}~  A  F  EF  F  A  EF  F  F  F  F  F  F  F  F  F  F  A  EF  F  F  F  F  F  A  F  F  F  F  EF  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  FJJEIN !/A~#^#^"_`+A%IZ+[+[((DD*;F*CDDDmVlHmmDHmmmmmmmmmmmDHmmmmmmDmmmmHmmmmmmmmmmmmmmmmmmmmmmmmmmmmUO4EGX$Y$YZZZ==rss||~~  @A  B  G  FG  G  B  FG  G  G  G  G  G  G  G  G  G  G  B  FG  G  G  G  G  G  B  G  G  G  G  FG  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  Gr?   c                 |   t                      } d}dd|dgi}t          | |          \  }}d |d         D             }ddg}||k    }|st          j        d	|fd
||f          dt	          j                    v st          j        |          rt          j        |          ndt          j        |          dz  }dd|iz  }t          t          j	        |                    d x}}|d         d         d         }	d}
|	|
k    }|slt          j        d	|fd|	|
f          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}	x}}
t          | t          ||                     |                     d                                          d         }	d}
|	|
k    }|slt          j        d	|fd|	|
f          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}	x}}
d S )NzTransactionId,CardId,Date,Amount,Currency,MerchantName
REAL-1,SYN-CARD-001,2026-02-03,-5.00,CHF,Synthetic Coffee
REAL-2,SYN-CARD-001,2026-02-03,-5.00,CHF,Synthetic Coffee
rS   r5   rT   c                    g | ]
}|d          S r_  rJ   r   s     r=   r  zmtest_distinct_provider_transactions_with_same_business_fields_are_not_silently_suppressed.<locals>.<listcomp>  r`  r?   r  rc  rL  r   z%(py0)s == %(py3)srf  r   r   r   r   r   rM  rN  r   rx   r{   r|   r  r   r   )r>   r   r}   r~   r   r   r   r   r   r   r   r^   r7   r*  )r9   rV   r   rZ   rf  r   r   r   r   r   r   r   r   s                r=   Ytest_distinct_provider_transactions_with_same_business_fields_are_not_silently_suppressedr    s!   ::DMH %7XNNOPG-dG<<GWBB'&/BBBL'22<22222222222<2222222222222<22222<222222222222222222222222222222226?1./O3OO/3OOOOOOOOOOO/3OOOOOO/OOOO3OOOOOOOOOOOOOOOOOOOOOOOOOOOOT?7G#D#DEEE<<a hjj                q                          r?   c                    t                      } |                     d                                          d         }|                     d|f           |                                  ddt	          dd          dgi}t          | |          \  }}|d	         d         d
         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}}|d	         d         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}}t          | t          ||                     |                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}}t          d t          |           d         D                       }	d}|	d         }||v }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}}|	d         dd}
t          | |
          }t!          | i |
|ddi           |                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}}d S ) NzcSELECT budget_account_id FROM household_account_source_mappings WHERE source_type='raiffeisen_bank'r   a  INSERT INTO budget_transactions(
             budget_transaction_id,account_id,transaction_type,transaction_date,booking_date,
             description,amount_original,currency_original,fx_rate_to_chf,amount_chf,fx_status,
             status,source_type,created_at,updated_at)
           VALUES ('legacy-overlap',?,'expense','2026-01-26','2026-01-26',
                   'Synthetic Grocery','-25.50','CHF','1','-25.50','not_needed',
                   'confirmed','manual','2026-01-15T00:00:00Z','2026-01-15T00:00:00Z')rS   r+   z-25.50zSynthetic GroceryrT   r  rM  rW  r   r   rx   r{   r|   r<  rL  rt  r   c              3  2   K   | ]}|d          dk    |V  dS )titlezPossible Legacy DuplicateNrJ   )rg   gs     r=   r  zOtest_legacy_productive_overlap_is_reviewed_not_counted_again.<locals>.<genexpr>  s1      nnqAgJRmDmDmDmDmDmDmnnr?   groups	duplicatesupported_actionsrd  z%(py1)s in %(py4)s	group_keyr  actionr.   TzKSELECT COUNT(*) FROM budget_transaction_candidates WHERE status='duplicate')r>   r7   r*  r8   rL   r   r}   r~   r   r   r   r   r^   nextr   r   r   )r9   
account_idr   rZ   r   r   r   r   r   groupr  action_previews               r=   <test_legacy_productive_overlap_is_reviewed_not_counted_againr    s/   ::Dm hjjJ 	LL	Z 
	 	 	 	KKMMM%6NS[]pDqDqrrstG-dG<<GW6?1./N3NN/3NNNNNNNNNNN/3NNNNNN/NNNN3NNNNNNNNNNNNNNNNNNNNNNNNNNNN6?1m,88,8888888888,88888,8888888888888888888888888888888T?7G#D#DEEE<<BCCLLNNqQVUVVQUVVVVVVVVVVVQUVVVVVVQVVVVUVVVVVVVVVVVVVVVVVVVVVVVVVVVVnn066x@nnnnnE4% 344;44444444444;444444;44444444444444444444444444444444 -EEF4T6BBN#D*WV*W~*WyRV*W*WXXX<<U hjj                q                          r?   c                 .   t                      } t                      }t          | |          }|                     d           t	          | t          ||                    }g }|d         }d}||u }|}|r	| j        }	|	}|st          j        d|fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }|
                    |           |rld	d
t          j                    v st          j        |           rt          j	        |           nd
t          j	        |	          dz  }|
                    |           t          j        |d          i z  }dd|iz  }t          t          j        |                    d x}x}x}x}x}}	|                                  |                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}|                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}t                      } t          | |          }|                     d           |                     d           t'          j        t*                    5  t	          | t          ||                     d d d            n# 1 swxY w Y   | j        }|sxdd
t          j                    v st          j        |           rt          j	        |           nd
t          j	        |          dz  }t          t          j        |                    d }|                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}|                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}|                     d                                          d         }d}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }
t          t          j        |
                    d x}x}}d S )NzfINSERT INTO platforms(platform_id,name,platform_type,created_at) VALUES ('caller','Caller','bank','x')r"  Fru   r$  r  r  r   z.%(py12)s
{%(py12)s = %(py10)s.in_transaction
}r9   r   r   r  r  rE  r   r   rx   r{   r|   z9SELECT COUNT(*) FROM platforms WHERE platform_id='caller'zCREATE TEMP TRIGGER fail_household_candidate BEFORE INSERT ON budget_transaction_candidates BEGIN SELECT RAISE(ABORT,'synthetic failure'); ENDz2assert %(py2)s
{%(py2)s = %(py0)s.in_transaction
}r   r   zHSELECT COUNT(*) FROM audit_log WHERE action='household_import_confirmed')r>   rX   r   r7   r   r^   in_transactionr}   r~   r   r   r   r   r   r   r   r   rollbackr*  rF  rG  	Exception)r9   r   rZ   rx  r   r   r   r   r   r   r   r   r   r  r   r   r   r   s                     r=   Ttest_household_confirm_preserves_outer_transaction_and_rolls_back_only_its_savepointr    s8   ::D  G&tW55GLLyzzz%dOGW,M,MNNF@@6,@5@5(@@@@@T-@@-@@@@@@@@@@5@@@@@@@@@5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@T@@@@@T@@@@@@-@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@MMOOO<<GHHQQSSTUV[Z[[VZ[[[[[[[[[[[VZ[[[[[[V[[[[Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[<<STT]]__`abgfggbfgggggggggggbfggggggbggggfgggggggggggggggggggggggggggg::D&tW55GLLyzzzLL  b  c  c  c	y	!	! J J w'H'HIIIJ J J J J J J J J J J J J J J44<<STT]]__`abgfggbfgggggggggggbfggggggbggggfgggggggggggggggggggggggggggg<<GHHQQSSTUV[Z[[VZ[[[[[[[[[[[VZ[[[[[[V[[[[Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[<<bccllnnopqvuvvquvvvvvvvvvvvquvvvvvvqvvvvuvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvs   !NNNc                    t                      } t          dd          }d}t          | dd|dd|dgi          }|d         d	         }d
}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d S )Nr9  zOrdinary purchasezmTransactionId,CardId,Date,Amount,Currency,MerchantName
R-1,SYN-CARD-001,2026-01-26,10.00,CHF,Ordinary refund
rS   r+   rT   r5   r   r   r   r   r   rx   r{   r|   )r>   rL   r   r}   r~   r   r   r   )	r9   bankcardrZ   r   r   r   r   r   s	            r=   4test_transfer_false_positive_card_refund_is_not_safer    s
   ::D($788D|D&tg%488&D998 .  G 8238q83q88888888883q8888838888q88888888888888888888888888888r?   c                 b   t                      } d}dd|dgi}t          | |          }|d         d         d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|                     d                                          d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | t          ||                     |                     d                                          }	t          |	          }d}
||
k    }|st          j        d	|fd||
f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |	          rt          j        |	          ndt          j        |          t          j        |
          dz  }dd|iz  }t          t          j        |                    d x}x}}
t          | d          }g }|d         }d}
||
k    }|}|r|d         }d}||k    }|}|st          j        d	|fd||
f          t          j        |          t          j        |
          dz  }dd|iz  }|                    |           |r`t          j        d	|fd||f          t          j        |          t          j        |          d z  }d!d"|iz  }|                    |           t          j        |d          i z  }d#d$|iz  }t          t          j        |                    d x}x}x}x}x}
x}x}}|d%         }d&}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t                      }|                    d'd(                              d)d*          }dd|dgi}t          ||          }|d         d         d+         }d,}||u }|slt          j        d-|fd.||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          |t          ||                     |                    d                                          d         }d}||k    }|slt          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d S )/NzoTransactionId,CardId,Date,Amount,Currency,MerchantName
RF-1,SYN-CARD-001,2026-02-10,12.50,CHF,Synthetic refund
rS   r5   rT   r  r   rM  rg  r   r   rx   r{   r|   rt  zSSELECT transaction_type,amount_original,status,source_type FROM budget_transactions)refundz12.50	confirmedimport_candidater   tupletxr   r   r   2026-02month
income_chfr[  rZ  r  r  r  r  r  r  r  r  r  unlinked_refund_countr   z,CHF,z,EUR,zRF-1zRF-2rX  Tru   rw   )r>   r   r}   r~   r   r   r   r7   r*  r   r^   r  r   r   r   r   r   r   rP  )r9   rV   r   rZ   r   r   r   r   r   r  r   r   r   overviewr   r,  r-  r.  r   r/  r   r0  ry  eur_csveur_payloadeur_previews                             r=   Gtest_clear_chf_card_refund_becomes_productive_refund_only_after_confirmr    sl   ::D CH%7XNNOPG&tW55G6?1./G3GG/3GGGGGGGGGGG/3GGGGGG/GGGG3GGGGGGGGGGGGGGGGGGGGGGGGGGGG<<BCCLLNNqQVUVVQUVVVVVVVVVVVQUVVVVVVQVVVVUVVVVVVVVVVVVVVVVVVVVVVVVVVVVT?7G#D#DEEE	]
 
hjj  99LLL9LLLLLLLLLLL9LLLLLLLLLLLLL5LLLLL5LLLLLLLLLLLLLLLLLLLLLLLL9LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL%d)<<<HQQ8L!QVQ!V+QQQQQ0GQ6Q0G60QQQQQQQQQQQQ!VQQQQQ!QQQQVQQQQQQQQQQQQQQQQQQQQQQQQQQQ0G6QQQQQ0GQQQQ6QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ+,11,1111111111,11111,1111111111111111111111111111111JJEw0088HHG);QQRSK*5+>>Kvq!"34<<4<<<<<<<<<<4<<<<<4<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<UOK$M$MNNN==CDDMMOOPQRWVWWRVWWWWWWWWWWWRVWWWWWWRWWWWVWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWr?   c            	        t                      } ddddgi}t          | |          \  }}t          | t          ||                     |                     d                                          d         }ddddgi}t          | |          }|d         d         }|d	         }d
}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}|d         }d}||u }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}d}||v}	|	st          j        d|	fd||f          t          j	        |          dt          j                    v st          j        |          rt          j	        |          nddz  }dd|iz  }t          t          j        |                    d x}}	t          | t          ||                     |                     d                                          }|d         }d}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}|d         }t          |          }d}t          |          }||k    }|s"t          j        d|fd ||f          d!t          j                    v st          j        t                    rt          j	        t                    nd!t          j	        |          t          j	        |          d!t          j                    v st          j        t                    rt          j	        t                    nd!t          j	        |          t          j	        |          d"z  }d#d$|iz  }t          t          j        |                    d x}x}x}x}}|d         }||k    }	|	st          j        d|	fd%||f          t          j	        |          d&t          j                    v st          j        |          rt          j	        |          nd&dz  }dd|iz  }t          t          j        |                    d x}}	t!          j        |d'                   d         }||k    }	|	st          j        d|	fd%||f          t          j	        |          d&t          j                    v st          j        |          rt          j	        |          nd&dz  }dd|iz  }t          t          j        |                    d x}}	|                     d(                                          d         }d}	||	k    }|st          j        d|fd)||	f          d*t          j                    v st          j        |          rt          j	        |          nd*t          j	        |	          d+z  }dd|iz  }t          t          j        |                    d x}}	t%          | d,-          }|d.         }d/}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}|d0         }d/}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}|d1         }d}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}t          | |          }|d         d         d2         }d3}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}dd|d         d         d4                             d5d6          dgi}t          | |          }|d         d         d	         }d7}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}|d         d         d2         }d8}||k    }	|	slt          j        d|	fd||f          t          j	        |          t          j	        |          dz  }
dd|
iz  }t          t          j        |                    d x}x}	}d S )9NrS   r5   zDate,Amount,Currency,MerchantName,TransactionId,CardId
2026-02-01,-8.25,CHF,Synthetic reverse purchase,rev-purchase,SYN-CARD-001
rT   zdSELECT budget_transaction_id FROM budget_transactions WHERE description='Synthetic reverse purchase'r   zDate,Amount,Currency,MerchantName,TransactionId,CardId
2026-02-03,8.25,CHF,Storno Synthetic reverse purchase,rev-refund,SYN-CARD-001
r  rM  credit_card_reversalr   r   rx   r{   r|   rX  Fru   rw   reversal_of_transaction_idr   r   r   r   r   r   zSELECT transaction_type,amount_original,reversal_of_transaction_id,notes
           FROM budget_transactions WHERE description LIKE 'Storno %'transaction_typer  amount_original8.25zP%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py10)s
{%(py10)s = %(py6)s(%(py8)s)
}r   r   r   rz   r|   r   r   r  r   )z%(py1)s == %(py3)soriginal_idnoteszhSELECT SUM(CAST(amount_chf AS REAL)) FROM budget_transactions WHERE description LIKE '%reverse purchase'r  totalr  r  periodrZ  r[  net_chfr  r<  rK  rV   z
rev-refundzrev-refund-new-idrN  rL  )r>   r   r   r^   r7   r*  r   r}   r~   r   r   r   r   r   r   r   r   loadsr   rP  )r9   purchasepurchase_previewr  reversalreversal_previewr   r   r   r   r   r   r   r   rx  r   r   r   r   r  r   r  
financialsrQ  same_business_new_provider_idlogical_overlaps                             r=   Ctest_unique_reversal_deterministically_offsets_original_transactionr    sY   ::D) ^
 
 H "8h!G!GHT?8=M#N#NOOO,,n hjjK
 	) b
 
 H 0h??
6
"1
%C :$:: $::::::::::: $:::::: ::::$:::::::::::::::::::::::::::: !*U*!U**********!U*****!****U***************************'2's2222222222's22222'22222222222s22222s222222222222222222222222222T?8=M#N#NOOO\\	I  hjj  $%11%1111111111%11111%1111111111111111111111111111111+,@7,--@@@-@@@@@@@@@@-@@@@@@@@@@@@7@@@@@7@@@@@@,@@@@-@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@./>/;>>>>>>>>>>/;>>>>>/>>>>>>>>>>>;>>>>>;>>>>>>>>>>>>>>>>>>>>>>>>>>>:fWo&&'CDSDSSSSSSSSSSDSSSSSDSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSLLr hjjE 5A:5A55A0iHHHJm$..$..........$.....$...............................i *F* F********** F***** ****F***************************-.3!3.!3333333333.!33333.3333!333333333333333333333333333(x88IVQ.B2BB.2BBBBBBBBBBB.2BBBBBB.BBBB2BBBBBBBBBBBBBBBBBBBBBBBBBBBB) )!,Z8@@Obcc
 
 %! /t5RSSO6"1%&67W;WW7;WWWWWWWWWWW7;WWWWWW7WWWW;WWWWWWWWWWWWWWWWWWWWWWWWWWWW6"1%m4@@4@@@@@@@@@@4@@@@@4@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r?   c                    t                      } ddddgi}t          | |          \  }}t          | t          ||                     ddddgi}t	          | |          }|d         d         d         }d	}||k    }|slt          j        d
|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}|d         d         d         }d}||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}|d         }d}||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}t          | t          ||                     | 
                    d                                          d         }d}||k    }|slt          j        d
|fd||f          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}}d S )NrS   r5   zDate,Amount,Currency,MerchantName,TransactionId,CardId
2026-02-01,-8.25,CHF,Repeated purchase,amb-1,SYN-CARD-001
2026-02-02,-8.25,CHF,Repeated purchase,amb-2,SYN-CARD-001
rT   zwDate,Amount,Currency,MerchantName,TransactionId,CardId
2026-02-03,8.25,CHF,Storno Repeated purchase,amb-r,SYN-CARD-001
r  r   rM  credit_card_reversal_unmatchedr   r   rx   r{   r|   rX  Tru   rw   rt   zJSELECT COUNT(*) FROM budget_transactions WHERE description LIKE 'Storno %')r>   r   r   r^   r   r}   r~   r   r   r   r7   r*  )
r9   	purchasesr  r  r  r   r   r   r   r   s
             r=   Dtest_ambiguous_reversal_remains_review_and_never_posts_automaticallyr  F  s   ::D)N
 
 	I #9y"I"IIT?9>N#O#OPPP 	) T
 
 H 0h??F#A&'78\<\\8<\\\\\\\\\\\8<\\\\\\8\\\\<\\\\\\\\\\\\\\\\\\\\\\\\\\\\F#A&'89ATA9TAAAAAAAAAA9TAAAAA9AAAATAAAAAAAAAAAAAAAAAAAAAAAAAAA89ATA9TAAAAAAAAAA9TAAAAA9AAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAT?8=M#N#NOOO<<deennppqrsxwxxswxxxxxxxxxxxswxxxxxxsxxxxwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxr?   c                    t                      } d}d                    d t          d          D                       }||z   dz   }dd|dgi}t          | |          }t	          | t          ||                     t          |           }t          d	 |d
         D                       }g }d}	|d         }
|	|
v }|}|r|d         }d}||u }|}|st          j	        d|fd|	|
f          t          j
        |	          t          j
        |
          dz  }dd|iz  }|                    |           |r`t          j	        d|fd||f          t          j
        |          t          j
        |          dz  }dd|iz  }|                    |           t          j        |d          i z  }dd|iz  }t          t          j        |                    d x}x}x}	x}x}
x}x}}| j        }t!          | |d         dd          }| j        }||k    }|st          j	        d|fd||f          d t#          j                    v st          j        |           rt          j
        |           nd t          j
        |          d!t#          j                    v st          j        |          rt          j
        |          nd!d"z  }d#d$|iz  }t          t          j        |                    d x}}|d         d|d%         |d&         d'}t)          | |          }g }|d(         }	d)}
|	|
k    }|}|r|d*         }d+}||u }|}|st          j	        d|fd,|	|
f          t          j
        |	          t          j
        |
          dz  }dd|iz  }|                    |           |r`t          j	        d|fd||f          t          j
        |          t          j
        |          dz  }dd|iz  }|                    |           t          j        |d          i z  }dd|iz  }t          t          j        |                    d x}x}x}	x}x}
x}x}}|                     d-                                          }t/          |          }	d.}
|	|
k    }|st          j	        d|fd/|	|
f          d0t#          j                    v st          j        t.                    rt          j
        t.                    nd0d1t#          j                    v st          j        |          rt          j
        |          nd1t          j
        |	          t          j
        |
          d2z  }d3d|iz  }t          t          j        |                    d x}	x}}
t1          | d4d5d6d7d89          }|d:         }d)}||k    }	|	slt          j	        d|	fd;||f          t          j
        |          t          j
        |          d<z  }d#d$|iz  }t          t          j        |                    d x}x}	}|d=         d         d>         }d8}||k    }	|	slt          j	        d|	fd;||f          t          j
        |          t          j
        |          d<z  }d#d$|iz  }t          t          j        |                    d x}x}	}|d=         d         d?         }d6}||k    }	|	slt          j	        d|	fd;||f          t          j
        |          t          j
        |          d<z  }d#d$|iz  }t          t          j        |                    d x}x}	}t1          | d@A          d:         }d}||k    }	|	slt          j	        d|	fd;||f          t          j
        |          t          j
        |          d<z  }d#d$|iz  }t          t          j        |                    d x}x}	}t)          | |          d*         }d}||u }	|	slt          j	        d|	fdB||f          t          j
        |          t          j
        |          d<z  }d#d$|iz  }t          t          j        |                    d x}x}	}d S )CN7TransactionId,CardId,Date,Amount,Currency,MerchantName
r   c              3  \   K   | ]'}d | d|dk     rdnd d|dk     r|dz   n|dz
  dd	V  (d
S )zSAFE-z,SYN-CARD-001,2026-   0102-r      r   ,-3.00,CHF,Migros
NrJ   r   s     r=   r  zUtest_review_expense_preview_confirm_is_bound_atomic_and_idempotent.<locals>.<genexpr>f  s         	J  	J  	J%"**$$$  	J  	JV[^`V`V`QRfknpfp  	J  	J  	J  	J     r?   !   z@RV-1,SYN-CARD-001,2026-02-28,-8.25,CHF,Synthetic review expense
rS   r5   rT   c              3  2   K   | ]}|d          dk    |V  dS )r  zExpense CandidateNrJ   rg   rp   s     r=   r  zUtest_review_expense_preview_confirm_is_bound_atomic_and_idempotent.<locals>.<genexpr>q  s1      [[$d7mGZ6Z6Z6Z6Z6Z6Z[[r?   r  rd   r  can_confirmTrd  )z%(py3)s in %(py6)sr  r  r   ru   )z%(py11)s is %(py14)sr  r  r  r   r  r  r  r  r   r   r9   r  r   r{   r|   r\   r]   )r  r  r\   r]   confirmed_countr   r"  Fr  ztSELECT transaction_type,amount_original,status FROM budget_transactions WHERE description='Synthetic review expense')rd   z-8.25r  r   r  r  r   r   r  r$   ImportzSynthetic review expensereviewed)r  accountrY   merchantrL  r  r   rx   rr   review_statussource_labelignored)rL  rw   )r>   r   r
  r   r   r^   r   r  r}   r~   r   r   r   r   r   r   r   r   r   r   r   r7   r*  r  r   )r9   headerknownrV   r   import_previewrL  r  r   r   r   r   r   r,  r-  r.  r   r   r   r/  r   r0  r  r  r   r   requestrx  r  filtereds                                 r=   Btest_review_expense_preview_confirm_is_bound_atomic_and_idempotentr1  c  sy
   ::DGFGG  2YY    E ~KH %7XNNOPG-dG<<NT?7N#K#KLLL!$''F[[&"2[[[[[ESS9S12S922SSSSSu]7KStS7Kt7SSSSSSSSSSSS92SSSSS9SSSS2SSSSSSSSSSSSSSSSSSSSSSSSSSS7KtSSSSS7KSSSStSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSF4E+.)DD N '''''''''''''''''''''''4'''''4''''''''''''''''''''''''''''''''''''''''''''''''';'-.CD ./E F	 G -T7;;FKK6#$KK$)KKKKKf\.BKeK.Be.KKKKKKKKKKKK$KKKKK$KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK.BeKKKKK.BKKKKeKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK		7
 
 hjj  99999999999999999999999999999995999995999999999999999999999999999999999999999999999999999999999*Y+J  H G!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!GQ0>J>0J>>>>>>>>>>0J>>>>>0>>>>J>>>>>>>>>>>>>>>>>>>>>>>>>>>GQ/;8;/8;;;;;;;;;;/8;;;;;/;;;;8;;;;;;;;;;;;;;;;;;;;;;;;;;;&tI>>>wGL1LG1LLLLLLLLLLG1LLLLLGLLLL1LLLLLLLLLLLLLLLLLLLLLLLLLLL*499,GO4OG4OOOOOOOOOOG4OOOOOGOOOO4OOOOOOOOOOOOOOOOOOOOOOOOOOOOOr?   c                    t                      } d}dd|dgi}t          | |          }t          | t          ||                     |                     d                                          d         }d}dd|dgi}t          | |          }|d	         d         d
         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	t          | t          ||                     |                     d                                          }t          |          }
d |df}|
|k    }|st          j        d|fd|
|f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |
          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}
x}}|                     d                                          d         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	|                     d                                          d         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	|                    dd          }dd|dgi}t          | |          }|d	         d         d
         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	t          | t          ||                     |                     d                                          d         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	|                     d                                           }d }
||
u }|st          j        d!|fd"||
f          d#t          j                    v st          j        |          rt          j        |          nd#t          j        |
          d$z  }d%d&|iz  }t          t          j
        |                    d x}}
|                     d'                                          d         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	d S )(NzpTransactionId,CardId,Date,Amount,Currency,MerchantName
MX-1,SYN-CARD-001,2026-03-01,-10.00,CHF,Migros Synthetic
rS   r5   rT   5SELECT budget_transaction_id FROM budget_transactionsr   zDatum;Zeit;Filiale;Kassennummer;Transaktionsnummer;Artikel;Umsatz
2026-03-01;12:00;Synthetic Store;1;100;A;4.00
2026-03-01;12:00;Synthetic Store;1;100;B;6.00
rn  ro  rp  rq  r   r   rx   r{   r|   QSELECT money_candidate_id,money_transaction_id,status FROM household_migros_linksr   r  linkr   r   r   rs  r   zISELECT COUNT(*) FROM budget_transactions WHERE transaction_type='expense'r   z;100;z;102;rj  ru  zjSELECT money_candidate_id,money_transaction_id,status FROM household_migros_links WHERE status='unmatched'ru   )z%(py0)s is %(py3)ssecond_linkr  r   r   z+SELECT COUNT(*) FROM household_migros_linksr>   r   r   r^   r7   r*  r}   r~   r   r   r   r  r   r   r   rP  )r9   r#   money_payloadmoney_previewtransaction_idrw  receipt_payloadreceipt_previewr   r   r   r   r   r5  r   r   r   second_receiptsecond_payloadsecond_previewr6  r   r   r   s                           r=   Ctest_migros_receipt_links_to_existing_money_movement_across_batchesr@    s$   ::DD+=4PPQRM,T=AAMT?=-#P#PQQQ\\"YZZcceefghN@G ->G!T!T UVO.t_EEO?+A.x8DHD8HDDDDDDDDDD8HDDDDD8DDDDHDDDDDDDDDDDDDDDDDDDDDDDDDDDT??O#T#TUUU<<klluuwwD;;:4::;:::::::::::;:::::::::::::5:::::5::::::::::::::::::::::::;::::::::::::::::::::::::::::::::<<GHHQQSSTUV[Z[[VZ[[[[[[[[[[[VZ[[[[[[V[[[[Z[[[[[[[[[[[[[[[[[[[[[[[[[[[[<<cddmmoopqrwvwwrvwwwwwwwwwwwrvwwwwwwrwwwwvwwwwwwwwwwwwwwwwwwwwwwwwwwww__Wg66N,=> Z Z[\N-dNCCN/*1-h7F;F7;FFFFFFFFFF7;FFFFF7FFFF;FFFFFFFFFFFFFFFFFFFFFFFFFFFT?>>#R#RSSS<<K hjj                q                         ,,	#  hjj  ;$;$;;$<<EFFOOQQRSTYXYYTXYYYYYYYYYYYTXYYYYYYTYYYYXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYr?   c                    t                      } d}dd|dgi}t          | |          }t          | t          ||                     |                     d                                          d         }d}dd|dgi}t          | |          }|d	         d         d
         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	t          | t          ||                     |                     d                                          }t          |          }
d |df}|
|k    }|st          j        d|fd|
|f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |
          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}
x}}dd|                    dd          dgi}t          | |          }|d	         d         d
         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	t          | t          ||                     |                     d                                          d         }d}	||	k    }
|
slt          j        d|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }t          t          j
        |                    d x}x}
}	d S )NzqTransactionId,CardId,Date,Amount,Currency,MerchantName
MX-2,SYN-CARD-001,2026-03-02,-10.00,CHF,Migros Productive
rS   r5   rT   r3  r   zDatum;Zeit;Filiale;Kassennummer;Transaktionsnummer;Artikel;Umsatz
2026-03-02;12:00;Synthetic Store;1;101;A;4.00
2026-03-02;12:00;Synthetic Store;1;101;B;6.00
rn  ro  rp  rq  r   r   rx   r{   r|   r4  r   r  r5  r   r   r   z;101;z;103;rj  ru  r   r7  )r9   r#   r8  r9  r:  rw  r;  r<  r   r   r   r   r   r5  r   r   r   r>  r?  s                      r=   Jtest_migros_receipt_links_to_productive_transaction_not_consumed_candidaterB    s   ::D AD+=4PPQRM,T=AAMT?=-#P#PQQQ\\"YZZcceefghN	: 
 ->G!T!T UVO.t_EEO?+A.x8DHD8HDDDDDDDDDD8HDDDDD8DDDDHDDDDDDDDDDDDDDDDDDDDDDDDDDDT??O#T#TUUU<<klluuwwD;;:4::;:::::::::::;:::::::::::::5:::::5::::::::::::::::::::::::;:::::::::::::::::::::::::::::::: 	/W__WV]=^=^__`N .dNCCN/*1-h7F;F7;FFFFFFFFFF7;FFFFF7FFFF;FFFFFFFFFFFFFFFFFFFFFFFFFFFT?>>#R#RSSS<<K hjj                q                          r?   c                   ' t                      ''fd} t          d          }| |j        t          <   t	          |          }|                    d                                          d         }d}t          |          }|j        } ||          }|s$ddt          j
                    v st          j        t                    rt          j        t                    ndd	t          j
                    v st          j        |          rt          j        |          nd	t          j        |          t          j        |          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          d
z  }t          t          j        |                    d x}x}}'j        }	|dd         D ]}
|                    |
          }|j        }d}||k    }|st          j        d|fd||f          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }t          j        |j                  dz   d|iz  }t          t          j        |                    d x}x}}g }d}|j        }||v}|}|rd}|j        }||v}|}|s~t          j        d|fd||f          t          j        |          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          dz  }dd|iz  }|                    |           |rt          j        d|fd||f          t          j        |          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          dz  }dd|iz  }|                    |           t          j        |d          i z  }d d!|iz  }t          t          j        |                    d x}x}x}x}x}x}x}}'j        }||	k    }|st          j        d|fd"||	f          d#t          j
                    v st          j        '          rt          j        '          nd#t          j        |          d$t          j
                    v st          j        |	          rt          j        |	          nd$d%z  }d&d'|iz  }t          t          j        |                    d x}}|                    d(                                          }h d)}|j        } ||          }|sd*t          j        |          t          j        |          d+t          j
                    v st          j        |          rt          j        |          nd+t          j        |          d,z  }t          t          j        |                    d x}x}}|                    d-                                          }h d.}|j        } ||          }|sd*t          j        |          t          j        |          d/t          j
                    v st          j        |          rt          j        |          nd/t          j        |          d,z  }t          t          j        |                    d x}x}}|                    d0                                          }g }|d1         }d2}||u }|}|rd3} | |v }!|!}|s-t          j        d4|fd5||f          t          j        |          t          j        |          d6z  }d7d8|iz  }|                    |           |rt          j        d9|!fd:| |f          t          j        |           d;t          j
                    v st          j        |          rt          j        |          nd;d<z  }"d=d>|"iz  }#|                    |#           t          j        |d          i z  }d?d|iz  }t          t          j        |                    d x}x}x}x}x}x} }!|d@d          D ]X}
|j        }i } ||
|A          }|j        }$h dB}|$|v } | s!t          j        d9| fdC|$|f          dDt          j
                    v st          j        |          rt          j        |          ndDt          j        |          dEt          j
                    v st          j        |
          rt          j        |
          ndEt          j        |          t          j        |          t          j        |$          t          j        |          dFz  }%dGdH|%iz  }&t          t          j        |&                    d x}x}x}x}$x} }Zd S )INc               3     K    V  d S r~  rJ   r  s   r=   r  zItest_plural_api_and_read_models_are_side_effect_free.<locals>.override_db  r  r?   r  r  r  r  )
%/api/budget/household/imports/preview%/api/budget/household/imports/confirmz%/api/budget/household/imports/optionsz%/api/budget/household/imports/historyz/api/budget/household/importsz/api/budget/household/overviewz"/api/budget/household/transactions/api/budget/household/reviewz$/api/budget/household/review/previewz$/api/budget/household/review/confirmzhassert %(py8)s
{%(py8)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.issubset
}(%(py6)s)
}setrequired)r   ry   r   r   r|   r   r      r  r   z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sresponser   r   r   
>assert %(py7)sr   r%  rV   r   )z0%(py3)s not in %(py7)s
{%(py7)s = %(py5)s.text
})r   r   r   z%(py9)sr   )z4%(py12)s not in %(py16)s
{%(py16)s = %(py14)s.text
})r   r   r  z%(py18)spy18r   zassert %(py21)sr(  r   r9   r  r   r{   r|   z,/api/budget/household/overview?month=2026-01>   r  r  balance_chfdata_statusrZ  review_countr   r  r   z1/api/budget/household/transactions?period=2026-01>   rr   r  has_more	total_all
page_countnext_cursorfiltered_totaltransactionsrG  unsafe_groups_can_confirmFr  ru   r$  r  r  r   rd  )z%(py11)s in %(py13)srL  )r  r  z%(py15)sr  zassert %(py18)sr  >     rB  r  )zz%(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py2)s
{%(py2)s = %(py0)s.post
}(%(py3)s, json=%(py5)s)
}.status_code
} in %(py12)sr  r  )r   r   r   r   r   r   r   r   r   )r>   r
   r  r	   r   rf   r   rH  r   r   r   r}   r   r   r   r   r   rH  r~   _format_assertmsgrE   r   r   r  )(r  r  r  r  rI  r   r   r   r   r  r  rL  r   r   r   r   r   r   r   @py_assert15r-  r   r/  @py_format19r0  r4  r   r   r  r   rX  rL  r,  r.  r  r   r  r   r   r9   s(                                          @r=   4test_plural_api_and_read_models_are_side_effect_freer_    si   ::D    

'
'
'C'2CV$__FJJ'',,..w7E8H x==(=!(!!%(((((((((((((((3(((((3(((((((((((((x(((((x((((((=((((!(((((((((((%(((((%((((((((((((((((((((((((((((F1 O O::d###9s9#s*999999999#s999999999999x99999x999999#9999s99999999HM999999999999999999999999NNvNX]Nv]*NNNNNzNNz/NNNNNNNNNNNNv]NNNNNvNNNNNNNNNNNXNNNNNXNNNNNN]NNNNNNNNNNNNNNNNNNNNNNNNNNNzNNNNNzNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN'''''''''''''''''''''''4'''''4'''''''''''''''''''''''''''''''''''''''''''''''''zzHIINNPPH___r_hrhhiqrrrrrrrr_rrrrhrrrrrrrrrrriqrrrrriqrrrrrrrrrrrrrrrrrrrrrrrrrrrr::QRRWWYYLeee|en|nno{||||||||e||||n|||||||||||o{|||||o{||||||||||||||||||||||||||||ZZ677<<>>FNN6-.N%N.%7NNNNNHNH<NNNNNNNNNNNN.%NNNNN.NNNN%NNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN I I{HbH{{4b)))H)5HH5HHHHHHHHHH5HHHHHHHHHHHHvHHHHHvHHHHHH{HHHHHHHHHHH4HHHHH4HHHHHHbHHHH)HHHH5HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHI Ir?   monkeypatchpytest.MonkeyPatchc           	       !" |                      dd           t                      ""fd}t          d          }||j        t          <   t          |          }d}dd|d	gi}|                    d
|          }|j        }d}||k    }	|	st          j	        d|	fd||f          dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }
t          j        |j                  dz   d|
iz  }t!          t          j        |                    d x}x}	}|                                d         d         }d|d|d         |d         d}|                    dddi|          }|j        }d}||k    }	|	st          j	        d|	fd||f          dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }
d d|
iz  }t!          t          j        |                    d x}x}	}|                    dddi|d!|d         d d"         iz            }|j        }d#}||k    }	|	st          j	        d|	fd||f          d$t          j                    v st          j        |          rt          j        |          nd$t          j        |          t          j        |          dz  }
d d|
iz  }t!          t          j        |                    d x}x}	}|                    dddi|          !!j        }d}||k    }	|	st          j	        d|	fd||f          d%t          j                    v st          j        !          rt          j        !          nd%t          j        |          t          j        |          dz  }
t          j        !j                  dz   d|
iz  }t!          t          j        |                    d x}x}	}!                                }d&|d'         |d         t'          |d!                   |d(         |d)         |d*         |d+         d,}t)          j        t%          j        |d-d.d/                                                                                    |d0<   |                    d
i |d1|gi          }|j        }d#}||k    }	|	st          j	        d|	fd||f          d2t          j                    v st          j        |          rt          j        |          nd2t          j        |          t          j        |          dz  }
d d|
iz  }t!          t          j        |                    d x}x}	}i |d1!                                gi}|                    d
|          }|j        }d}||k    }	|	st          j	        d|	fd||f          d3t          j                    v st          j        |          rt          j        |          nd3t          j        |          t          j        |          dz  }
t          j        |j                  dz   d|
iz  }t!          t          j        |                    d x}x}	}|                                }|d4         }d}	||	u }|slt          j	        d5|fd6||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	d: |d;         D             }d<h}	||	k    }|slt          j	        d|fd=||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	t3          ||          }|                    d>|          }|j        }d}||k    }	|	st          j	        d|	fd||f          d?t          j                    v st          j        |          rt          j        |          nd?t          j        |          t          j        |          dz  }
t          j        |j                  dz   d|
iz  }t!          t          j        |                    d x}x}	}|                    d>|          }|j        }d}||k    }	|	st          j	        d|	fd||f          d@t          j                    v st          j        |          rt          j        |          nd@t          j        |          t          j        |          dz  }
d d|
iz  }t!          t          j        |                    d x}x}	}|                                dA         }d}	||	u }|slt          j	        d5|fd6||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	|                     t6          j        dB!fdC           |                    d>|          }|j        }dD}||k    }	|	st          j	        d|	fd||f          dEt          j                    v st          j        |          rt          j        |          ndEt          j        |          t          j        |          dz  }
d d|
iz  }t!          t          j        |                    d x}x}	}|                    dF                                          }|dG         }dH}	||	k    }|slt          j	        d|fd=||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	|dI         }dH}	||	k    }|slt          j	        d|fd=||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	"                    dJ                                          }t%          j         |dK                   } | dL         }d"}	||	k    }|slt          j	        d|fd=||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	| dM         }d}	||	k    }|slt          j	        d|fd=||	f          t          j        |          t          j        |	          d7z  }d8d9|iz  }t!          t          j        |                    d x}x}}	d S )NN$JARVIS_FINANCE_OPERATOR_APPROVAL_KEYzsynthetic-operator-keyc               3     K    V  d S r~  rJ   r  s   r=   r  zotest_authenticated_owner_attestation_api_binds_exact_cluster_and_confirms_neutral_transfer.<locals>.override_db  r  r?   r  r  zIBAN;Booked At;Text;Credit/Debit Amount;Valuta Date
SYN-RAI-001;2026-07-01;Synthetic Household Counterparty;-20.00;2026-07-01
SYN-RAI-001;2026-07-02;Synthetic Household Counterparty;-30.00;2026-07-02
rS   r+   rT   rE  r  r  r   rK  baserM  rN  r   merchant_clustersr   T.owner_attested_known_household_counterparty_v1cluster_token
row_tokens)confirm_owner_attestationpreview_requestapproval_evidencerh  approved_row_tokensz</api/budget/household/imports/owner-neutral-cluster-approvalzX-Jarvis-Operator-Approvalwrong)headersr   r  deniedzassert %(py7)srm  r   r  subsetapproved-owner_confirmed_neutral_household_transfer_v2rl  approval_baseline_fingerprintapproval_issued_atapproval_expires_atapproval_nonce)scoperl  rh  ri  r]   	issued_at
expires_atnonceF),:)ensure_ascii
separators	sort_keysapproval_tokencluster_decisionsforged_previewpreview_responsert   ru   rw   rx   r{   r|   c                    h | ]
}|d          S )rn   rJ   r"  s     r=   r   zmtest_authenticated_owner_attestation_api_binds_exact_cluster_and_confirms_neutral_transfer.<locals>.<setcomp>6  s    GGGdD()GGGr?   rr   !user_confirmed_unmatched_transferr   rF  r  immediate_replayr"  timec                 X    t                                           d                   dz   S )Nrv  r   )intr   )rr  s   r=   <lambda>zltest_authenticated_owner_attestation_api_binds_exact_cluster_and_confirms_neutral_transfer.<locals>.<lambda>H  s"    HMMOO$9:;;a? r?   rB  expired_replayz,/api/budget/household/overview?month=2026-07r  r[  rZ  zkSELECT new_values_json FROM audit_log WHERE action='household_import_confirmed' ORDER BY rowid DESC LIMIT 1new_values_json$owner_attested_neutral_cluster_count"owner_attestation_evidence_version)!setenvr>   r
   r  r	   r   r  rH  r}   r~   r   r   r   r   r\  rE   r   r   r   sortedhashlibsha256r   encode	hexdigestr^   setattrhousehold_import_servicer  rf   r7   r*  r
  )#r`  r  r  r  rV   r   re  r   r   r   r   r   clusterapproval_bodyrp  rq  forged_decisionpublic_materialr  signed_payloadr  rZ   r   r   r   r   confirm_requestr  r  r  r  r'  audit_valuesrr  r9   s#                                    @@r=   Ztest_authenticated_owner_attestation_api_binds_exact_cluster_and_confirms_neutral_transferr    s\    =?WXXX::D     
'
'
'C'2CV$__F	V 
 %6HMMNOG;;>W;MMD-s-s"---------s------------4-----4----------s--------DI------------------------iikk-.q1G%)"M 1&|4 M [[F-w7   F
 $$$$$$$$$$$$$$$$$$$$$$$$6$$$$$6$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$[[F-/GH3W\5J2A25NOO   F
 $$$$$$$$$$$$$$$$$$$$$$$$6$$$$$6$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$${{F-/GH   H
 5353&555555555355555555555585555585555555555355555555555555555555555555555555mmooO@,-@A(9_-BCDD /0O P$%9:%&;< !12	 	O )0
?:Y]^^^eegg) )ikk $% [[/@@,.?@@ !  N %,,%,,,,,,,,,,%,,,,,,,,,,,,>,,,,,>,,,,,,%,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,HH!4x}}6GHHN{{#JQ_{``'E3E'3.EEEEEEEEE'3EEEEEEEEEEEEEEEEEEEEEEE'EEEE3EEEEEEEE0@0EEEEEEEEEEEEEEEEEEEEEEEEE##%%G/08D80D88888888880D8888808888D888888888888888888888888888GGgg6FGGG +L G L        G L     H   L                          &ng>>O/   I  7C7 C'777777777 C7777777777779777779777777 7777C77777777777777777777777777777777{{/ #   '.3.'3..........'3.......................'....3...........................  ""<08D80D88888888880D8888808888D888888888888888888888888888 %????  
 [[/ !  N %,,%,,,,,,,,,,%,,,,,,,,,,,,>,,,,,>,,,,,,%,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,zzHIINNPPHL!+V+!V++++++++++!V+++++!++++V+++++++++++++++++++++++++++M",f,"f,,,,,,,,,,"f,,,,,",,,,f,,,,,,,,,,,,,,,,,,,,,,,,,,,LLu hjj 
 :e$5677L>?D1D?1DDDDDDDDDD?1DDDDD?DDDD1DDDDDDDDDDDDDDDDDDDDDDDDDDD<= 8=8       =8    >    	9                          r?   c                 4   ,- t                      ,d} d                    d t          d          D                       }dd| |z   dz   dgi}t          ,|          }t	          ,t          ||                     t          ,                    d	                                                    -,                    d
                                          },                    d                                          }d dd ddw,-fd} |ddd|d            |ddd|d            |ddd|             |d!dd"|             |d#d$d%d&'           ,                    d(           ,                    d)           ,                    d*|d+         f           ,	                                 t          ,d,-          }|d.         |d/         |d0         |d1         f}d2}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	g }|d8         }
|d.         }|
|k    }|}|r|d9         }d:}||k    }|}|st          j        d3|fd;|
|f          t          j        |
          t          j        |          d<z  }d=d>|iz  }|                    |           |r`t          j        d3|fd?||f          t          j        |          t          j        |          d@z  }dAdB|iz  }|                    |           t          j        |d+          i z  }dCdD|iz  }t          t          j        |                    d x}x}x}
x}x}x}x}}dE |dF         D             }ddh}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	g }|dG         }	t%          |	          }d,}||k    }|}|r|dH         }dI}||u }|}|r
|dJ         }|}|st          j        d3|fdK||f          dLt'          j                    v st          j        t$                    rt          j        t$                    ndLt          j        |	          t          j        |          t          j        |          dMz  }dNdO|iz  }|                    |           |rt          j        dP|fdQ||f          t          j        |          t          j        |          dRz  }dSdD|iz  }|                    |           |r.dTdUt          j        |          iz  }|                    |           t          j        |d+          i z  } dVdW| iz  }!t          t          j        |!                    d x}x}x}	x}x}x}x}x}x}}t          ,d,|dJ         X          }"|"dY         }|dY         }	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	|"dG         d+         dZ         }|dG         d+         dZ         }	||	k    }
|
slt          j        d[|
fd\||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	,                    d]           ,	                                 t-          j        t0                    5 }#t          ,d,|dJ         X           d d d            n# 1 swxY w Y   |#j        }|j        }	d^}$|	|$k    }|st          j        d3|fd_|	|$f          d`t'          j                    v st          j        |#          rt          j        |#          nd`t          j        |          t          j        |	          t          j        |$          daz  }%dbdc|%iz  }t          t          j        |                    d x}x}	x}}$t          ,d,-          }&,                    dd|d+         f           ,	                                 t-          j        t0                    5 }'t          ,d,|&dJ         X           d d d            n# 1 swxY w Y   |'j        }|j        }	d^}$|	|$k    }|st          j        d3|fd_|	|$f          det'          j                    v st          j        |'          rt          j        |'          ndet          j        |          t          j        |	          t          j        |$          daz  }%dbdc|%iz  }t          t          j        |                    d x}x}	x}}$t          ,dfdIg          }(g }|(d.         }
d:}|
|k    }|}|r|(d9         }d,}||k    }|}|st          j        d3|fd;|
|f          t          j        |
          t          j        |          d<z  }d=d>|iz  }|                    |           |r`t          j        d3|fd?||f          t          j        |          t          j        |          d@z  }dAdB|iz  }|                    |           t          j        |d+          i z  }dCdD|iz  }t          t          j        |                    d x}x}x}
x}x}x}x}}|(dG         d+         dh         }di}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	|(dG         d+         dj         }dk}	||	u }
|
slt          j        dP|
fdl||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	t          ,dfdmn          })|)d9         }do}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	dp |)dG         D             }t7          |          }	|	sdqdrt'          j                    v st          j        t6                    rt          j        t6                    ndrt          j        |          t          j        |	          dsz  }t          t          j        |                    d x}}	t          ,dfd/n          }*|*d9         }d,}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	dt |*dG         D             }d/h}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	t          ,dfd0n          }+|+d9         }du}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	dv |+dG         D             }d0h}	||	k    }
|
slt          j        d3|
fd4||	f          t          j        |          t          j        |	          d5z  }d6d7|iz  }t          t          j        |                    d x}x}
}	d S )xNr  r   c              3  0   K   | ]}d | d|dz   ddV  dS )zSAFE-R-z,SYN-CARD-001,2026-03-r   r   r  NrJ   r   s     r=   r  zQtest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.<genexpr>_  sQ         	R%QQuqyQQQQ     r?      rS   r5   zBOPEN-1,SYN-CARD-001,2026-03-25,-8.25,CHF,Synthetic review expense
rT   zXSELECT * FROM budget_transaction_candidates WHERE description='Synthetic review expense'zdSELECT category_id,name FROM budget_categories WHERE is_active=1 AND category_type='expense' LIMIT 1zcSELECT category_id,name FROM budget_categories WHERE is_active=1 AND category_type='income' LIMIT 1)proposedr/   signed_amountcandidate_idrD   rp  rM  r  
str | Noner   r   c               v   	| |||| | d|  d|  |r|d         nd |r|d         nd |p	d         |p	d         dt          |            dd	z  t                    }                    d
d                    |           dd                    d |D                        dfd|D                        d S )Nzrow-zlogical-r   r   r   signed_amount_originalz2026-03-25T00:00:0Z)transaction_candidate_idr/   rp  rM  descriptionr(  r  r  proposed_category_idproposed_category_namer   r  
updated_atz*INSERT INTO budget_transaction_candidates(r|  z
) VALUES (c              3     K   | ]}d V  dS )?NrJ   )rg   _s     r=   r  z`test_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.clone.<locals>.<genexpr>  s$      [n[nde\_[n[n[n[n[n[nr?   )c                     g | ]
}|         S rJ   rJ   )rg   r:   r   s     r=   r  zatest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.clone.<locals>.<listcomp>  s    &&&#SX&&&r?   )r   listr7   r   )
r  rp  rM  r  r/   r  keysr   r9   originals
          @r=   clonezMtest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.clonep  s    (4&,'$&;\&;&;#<l#<#<3;$EHQKK5=&Ghqkk4,K9J0K&3&Yx@X7YCs</@/@CCC
 
 
 Cyyq$qqSVS[S[[n[nim[n[n[nSnSnqqq&&&&&&&	
 	
 	
 	
 	
r?   proposalneeds_reviewincome_candidater  )rp  rM  r  r  zwrong-proposalrd   r+   )rp  rM  r  r/   zinactive-proposal)rp  rM  r  specialrN  coveredcovered_by_sourcemigros_receipt_detailrn  )rp  rM  r/   zdUPDATE budget_transaction_candidates SET requires_review=0 WHERE transaction_candidate_id='proposal'zUPDATE budget_transaction_candidates
           SET status='pending',requires_review=1,classification='possible_logical_duplicate'
           WHERE transaction_candidate_id='covered'z<UPDATE budget_categories SET is_active=0 WHERE category_id=?r   r   )limit
total_openrm   decision_neededspecial_cases)   r      r   r   r   rx   r{   r|   rR  rW  r  r  r  r  r   r  r  r  r  r  r  c                    h | ]
}|d          S )r   rJ   r"  s     r=   r   zQtest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.<setcomp>  s    >>>dDM>>>r?   source_optionsrr   rS  TrV  )z0%(py6)s
{%(py6)s = %(py2)s(%(py4)s)
} == %(py9)sr   )r   rz   r|   r   %(py11)sr  ru   )z%(py14)s is %(py17)s)r   r   z%(py19)sz%(py22)spy22zassert %(py25)spy25)r  cursordata_version
item_token)!=)z%(py1)s != %(py4)szqUPDATE budget_transaction_candidates SET amount_original='999.00' WHERE transaction_candidate_id='wrong-proposal'rB  rC  stale_reviewr   r   r   a1  INSERT INTO budget_review_rules(
             rule_id,merchant_contains,source_type,category_id,target_status,is_active,
             priority,confidence,created_at,updated_at)
           VALUES ('review-rule-mutation','wrong-proposal','raiffeisen_bank',?,'review',1,
                   100,'1.0','x','x')stale_classifier   )r  special_onlyrl   special_caser#  Frw   needs_decision)r  state   c              3  .   K   | ]}|d          dk    V  dS )rl   rm   NrJ   r"  s     r=   r  zQtest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.<genexpr>  s-      ZZ$tL!%55ZZZZZZr?   r>  r?  r   c                    h | ]
}|d          S rl   rJ   r"  s     r=   r   zQtest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.<setcomp>      >>>4D>>>r?   r  c                    h | ]
}|d          S r  rJ   r"  s     r=   r   zQtest_review_summary_is_canonical_filtered_and_cursor_paginated.<locals>.<setcomp>  r  r?   )
r  rD   rp  rD   rM  rD   r  r  r   r   )r>   r   r
  r   r   r^   rQ   r7   r*  r8   r   r}   r~   r   r   r   r   r   r   r   r   r   rF  rG  r   r   rH  r?  ).r,  r-  r   rZ   expense_categoryincome_categoryr  r   r   r   r   r   r   r   r   r   r,  r-  r.  r   r   r/  r   r0  r  r   r2  r]  @py_assert21r   r  r5  @py_format24@py_format26r   r  r   r   freshr  r  r  	proposals	decisionsr9   r  s.                                               @@r=   >test_review_summary_is_canonical_filtered_and_cursor_paginatedr  \  s   ::DGFGG  2YY    E %7Ve^  W\  F\  ]  ]  ^  _G&tW55GT?7G#D#DEEEDLLb hjj H ||n hjj  llm hjj  &$(
 
 
 
 
 
 
 
 
< 
E)     
E  %    
E
nYYijjjj	E)N;Wbrssss	E)/@Wevwwww 	LLwxxxLL	7  
 	LLORbcdReQghhhKKMMM Q///E,'7!8%@Q:RTYZiTjk{o{{ko{{{{{{{{{{{ko{{{{{{k{{{{o{{{{{{{{{{{{{{{{{{{{{{{{{{{{XX5 XE,$7X $77XXXXXEBR<SXWXX<SWX<XXXXXXXXXXXX $7XXXXX XXXX$7XXXXXXXXXXXXXXXXXXXXXXXXXXX<SWXXXXXX<SXXXXWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX>>e,<&=>>>iCUWhBii>Biiiiiiiiiii>Biiiiii>iiiiBiiiiiiiiiiiiiiiiiiiiiiiiiiiiZZuW~Z3~Z!Z!#ZZZZZj(9ZTZ(9T(AZZZZZeMFZZFZZZZZZZZZZ!ZZZZZZZZZZZZ3ZZZZZ3ZZZZZZ~ZZZZZZZZ!ZZZZZZZZZZZZZZZZZZZZZZZZZZZ(9TZZZZZ(9ZZZZTZZZZZZZZZZZZZZZZZZZZZZZZZFZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ!$am8LMMMF.!:U>%::!%:::::::::::!%::::::!::::%::::::::::::::::::::::::::::'?1l+NuW~a/@/NN+/NNNNNNNNNNN+/NNNNNN+NNNN/NNNNNNNNNNNNNNNNNNNNNNNNNNNNLL{   	KKMMM	}	%	% IT53GHHHHI I I I I I I I I I I I I I I0)0S0)S0000000000)S000000000000<00000<0000000000)0000S00000000000000000000000000000 Q///ELL	)
 
!	   	KKMMM	}	%	% I)9T53GHHHHI I I I I I I I I I I I I I I!4!-44-4444444444-44444444444444444444444!4444-444444444444444444444444444444444"4rEEEGHH7< HAH A%HHHHH'2B*CHqH*Cq*HHHHHHHHHHHH AHHHHH HHHHAHHHHHHHHHHHHHHHHHHHHHHHHHHH*CqHHHHH*CHHHHqHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7A|,>>,>>>>>>>>>>,>>>>>,>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>7A}-66-6666666666-66666-6666666666666666666666666666666)$b@PQQQN*+0q0+q0000000000+q00000+0000q000000000000000000000000000ZZ.QXBYZZZZ3ZZZZZZZZZZZZZZZZ3ZZZZZ3ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ$T;KLLLI%&+!+&!++++++++++&!+++++&++++!+++++++++++++++++++++++++++>>9W+=>>>TCSBTT>BTTTTTTTTTTT>BTTTTTT>TTTTBTTTTTTTTTTTTTTTTTTTTTTTTTTTT$T;LMMMI%&+!+&!++++++++++&!+++++&++++!+++++++++++++++++++++++++++>>9W+=>>>UCTBUU>BUUUUUUUUUUU>BUUUUUU>UUUUBUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUs$   ^??__d''d+.d+c            	       & t                      &&                    d                                          d         } &                    d| f                                          d         }&                    d                                          d         }dkdl&fd} |ddd|             |ddd|            |dddd d           &                    dt          j        ddi          f            |ddd            |ddd            |ddd           &                                 t          &d          }|d         }d}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d$         }d%}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d&         }d'}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d(         }d)}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d*         }d+}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d,         }d-}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}d. |d/         D             }
t          |
          }d%}t          |          }||k    }|s"t          j        d|fd0||f          d1t          j                    v st          j        t                    rt          j	        t                    nd1t          j	        |
          t          j	        |          d2t          j                    v st          j        t                    rt          j	        t                    nd2t          j	        |          t          j	        |          d3z  }d4d5|iz  }t          t          j        |                    d x}
x}x}x}}d6 |d/         D             }
t          |
          }d}t          |          }||k    }|s"t          j        d|fd0||f          d1t          j                    v st          j        t                    rt          j	        t                    nd1t          j	        |
          t          j	        |          d2t          j                    v st          j        t                    rt          j	        t                    nd2t          j	        |          t          j	        |          d3z  }d4d5|iz  }t          t          j        |                    d x}
x}x}x}}t#          &d7          }|d         |d$         |d8         f}d9}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d:         }d;}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}|d*         d<         }d+}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}d=}|d*         d>         }||v }|slt          j        d?|fd@||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}&                    dA           &                                 t%          &dd-B          }g }
|dC         }dD}||k    }|}|r&|dE         }dD}||k    }|}|r|dF         }d-}||k    }|}|sdt          j        d|fdG||f          t          j	        |          t          j	        |          dHz  }	dIdJ|	iz  }|
                    |           |rt          j        d|fdK||f          t          j	        |          t          j	        |          dLz  }dMdN|iz  }|
                    |           |r`t          j        d|fdO||f          t          j	        |          t          j	        |          dPz  }dQdR|iz  }|
                    |           t          j        |
d          i z  }dSdT|iz  }t          t          j        |                    d x}x}
x}x}x}x}x}x}x}x}}g }
|dU         }dV}||u }|}|r
|dW         }|}|st          j        dX|fdY||f          t          j	        |          t          j	        |          dHz  }	dIdJ|	iz  }|
                    |           |r.dZd[t          j	        |          iz  } |
                    |            t          j        |
d          i z  }d\d]|iz  }t          t          j        |                    d x}x}
x}x}x}}&                    d^           &                                 t+          j        t.                    5 }!t%          &dd-|dW         _           d d d            n# 1 swxY w Y   |!j        }
|
j        }d`}"||"k    }|st          j        d|fda||"f          dbt          j                    v st          j        |!          rt          j	        |!          ndbt          j	        |
          t          j	        |          t          j	        |"          dcz  }#ddde|#iz  }$t          t          j        |$                    d x}
x}x}}"t%          &d|dfg          }%|%dE         }d-}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}dh |%di         D             }ddh}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}dj |%di         D             }|h}||k    }|slt          j        d|fd ||f          t          j	        |          t          j	        |          d!z  }d"d#|iz  }	t          t          j        |	                    d x}x}}d S )mNz_SELECT category_id FROM budget_categories WHERE is_active=1 AND category_type='expense' LIMIT 1r   z6SELECT name FROM budget_categories WHERE category_id=?z^SELECT category_id FROM budget_categories WHERE is_active=1 AND category_type='income' LIMIT 1tx_idrD   tx_typerC   r   r   c                D                         d| d|| ||||f           d S )Na  INSERT INTO budget_transactions(
                 budget_transaction_id,account_id,transaction_type,transaction_date,description,
                 amount_original,currency_original,amount_chf,fx_status,category_id,status,source_type,
                 reversal_of_transaction_id,created_at,updated_at)
               VALUES (?,?,?,'2026-04-15',?,?,'CHF',?,'not_needed',?,'confirmed','manual',?,'2026-04-15T00:00:00Z','2026-04-15T00:00:00Z')r-   r7   r  r  rC   re   r  r9   s        r=   transactionz\test_financial_semantics_reconcile_refunds_transfers_categories_and_net.<locals>.transaction  s?    N
 JXV	
 	
 	
 	
 	
r?   rd   r@   rc   200.00zlinked-refundr  20.00zrUPDATE budget_transactions SET reversal_of_transaction_id=NULL,notes=? WHERE budget_transaction_id='linked-refund'r  zunlinked-refundz5.00ztransfer-outtransferz-50.00zcard-settlement50.00z2026-04r  r  r   r   rx   r{   r|   rZ  80.00r	  120.00r  r   rQ  partialneutral_transfer_countr   c              3  @   K   | ]}t          |d                    V  dS )rZ  Nr   r   s     r=   r  zZtest_financial_semantics_reconcile_refunds_transfers_categories_and_net.<locals>.<genexpr>  s/      LLsws=)**LLLLLLr?   rj   r  sumr   r  r  r   c              3  @   K   | ]}t          |d                    V  dS )r  Nr   r   s     r=   r  zZtest_financial_semantics_reconcile_refunds_transfers_categories_and_net.<locals>.<genexpr>   s/      KKcws<())KKKKKKr?   r  rP  )r  r  r  neutral_transfers_chfr[  rp  u!   nicht verknüpfte Rückerstattungmessagerd  r  zeUPDATE budget_transactions SET updated_at='2026-04-17T00:00:00Z' WHERE budget_transaction_id='income')r  r  rT     rW  rU  r  r  r  r   r  r  r  r  )z%(py19)s == %(py22)s)r  r  z%(py24)sr)  zassert %(py27)spy27rS  TrV  ru   r$  r  r  r   r   zXUPDATE budget_transactions SET amount_chf='999.00' WHERE budget_transaction_id='expense')r  r  r  rB  rC  staler   r   r   
   r  rh   r  c                    h | ]
}|d          S )r  rJ   r"  s     r=   r   zZtest_financial_semantics_reconcile_refunds_transfers_categories_and_net.<locals>.<setcomp>  s    HHHD#$HHHr?   rr   c                    h | ]
}|d          S )category_namerJ   r"  s     r=   r   zZtest_financial_semantics_reconcile_refunds_transfers_categories_and_net.<locals>.<setcomp>  s    EEEdD!EEEr?   )NN)r  rD   r  rD   rC   rD   r   r   )r>   r7   r*  r   r   r8   r   r}   r~   r   r   r   r  r   r   r   r   r   r   r   r   rF  rG  r   r   rH  )'r  expense_category_namer  r  summaryr   r   r   r   r   r   r   r   r   r  r   r  pager   r,  r-  r.  r3  r  @py_assert20r   r   r/  r5  r6  r  @py_format28r  r  r   r   r   category_pager9   s'                                         @r=   Gtest_financial_semantics_reconcile_refunds_transfers_categories_and_netr    s3   ::D||i hjj !LL@	  hjj llh hjjO
 
 
 
 
 
 
 K	9i1ABBBK(Ho>>>K7D)DDDLL|	19=	>	>@   K!8V444K
H555K!:w777KKMMM-d9EEEG< ,H, H,,,,,,,,,, H,,,,, ,,,,H,,,,,,,,,,,,,,,,,,,,,,,,,,,=!,W,!W,,,,,,,,,,!W,,,,,!,,,,W,,,,,,,,,,,,,,,,,,,,,,,,,,,9))))))))))))))))))))))))))))))))))))))))))))))))*+0q0+q0000000000+q00000+0000q000000000000000000000000000=!.Y.!Y..........!Y.....!....Y...........................+,11,1111111111,11111,1111111111111111111111111111111LLgl6KLLL`3LLL`X_`PWX_P`P``LP```````````LP`````````````3`````3``````L````L```````````PW`````PW``````X_````P````````````````````````````````KKW\5JKKK`3KKK`W_`wW_O`O``KO```````````KO`````````````3`````3``````K````K```````````w`````w``````W_````O````````````````````````````````%d)<<<H\"H]$;Xm=TUvYvvUYvvvvvvvvvvvUYvvvvvvUvvvvYvvvvvvvvvvvvvvvvvvvvvvvvvvvv+,66,6666666666,66666,6666666666666666666666666666666M"8,9	9,	9999999999,	99999,9999	999999999999999999999999999.T(=2I)2TT.2TTTTTTTTTTT.2TTTTTT.TTTT2TTTTTTTTTTTTTTTTTTTTTTTTTTTTLLo   	KKMMM&tIQGGGD]]4]]!]]]]]d+;&<]]&<&A]]]]]d<FX]\]]FX\]F]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]&<]]]]]&<]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]FX\]]]]]]FX]]]]\]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]];;4
;t;t#;;;;;](;;(;;;;;;;;;;t;;;;;;;;;t;;;;;;;;;;;;;;;;;;;;;;;;;(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;LLklllKKMMM	}	%	% a#D!DQ^L_````a a a a a a a a a a a a a a a;);")c)"c))))))))))"c))))))))))))5)))))5))))));))))"))))c)))))))))))))))))))))))))))))/&	  M )*/a/*a//////////*a/////*////a///////////////////////////HHw1GHHHaYX`LaaHLaaaaaaaaaaaHLaaaaaaHaaaaLaaaaaaaaaaaaaaaaaaaaaaaaaaaaEEmG.DEEE`J_I``EI```````````EI``````E````I``````````````````````````````s   r::r>r>c                    t                      } |                     d                                          d         }|                     d|f           |                                  t	          | d          }g }|d         }d}||k    }|}|r|d         }d}	||	k    }
|
}|st          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }|                    |           |r`t          j        d	|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }|                    |           t          j	        |d          i z  }dd|iz  }t          t          j        |                    d x}x}x}x}x}x}x}
}	g }|d         }d}||k    }|}|r|d         }d}	||	k    }
|
}|st          j        d	|fd
||f          t          j        |          t          j        |          dz  }dd|iz  }|                    |           |r`t          j        d	|
fd||	f          t          j        |          t          j        |	          dz  }dd|iz  }|                    |           t          j	        |d          i z  }dd|iz  }t          t          j        |                    d x}x}x}x}x}x}x}
}	t          | d          }|d         }d}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         d         }d}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d          }|d         }d}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d          }|d         d         d         }d }||u }|slt          j        d |fd!||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         d         d"         }d#}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         d         d$         }d%}||k    }|slt          j        d	|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d S )&N_SELECT category_id FROM budget_categories WHERE category_type='expense' AND is_active=1 LIMIT 1r   a  INSERT INTO budget_transactions(
             budget_transaction_id,account_id,transaction_type,transaction_date,description,
             amount_original,currency_original,amount_chf,fx_status,category_id,status,source_type,
             created_at,updated_at)
           VALUES ('foreign-missing','bacc_rai','expense','2026-05-01','Synthetic foreign',
                   '100.00','EUR',NULL,'missing',?,'confirmed','manual','x','x')z2026-05r  rZ  r[  r	  r   r  r  r  r   r  r  r  r  r  r  unavailable_chf_countr   rQ  r  r  r   rx   r{   r|   rp  rr   
amount_chfru   rw   r   rM   r  EUR)r>   r7   r*  r8   r   r}   r~   r   r   r   r   r   r   r   r   )r9   re   r  r   r   r   r   r   r,  r-  r.  r   r   r   r/  r   r0  r  r   r   monthlyr  s                         r=   Ftest_unconverted_foreign_currency_is_partial_and_never_invented_as_chfr    s	   ::D,,i hjjK 	LL	T 
   	KKMMM-d9EEEGLL7=!LVL!V+LLLLL	0BLfL0Bf0LLLLLLLLLLLL!VLLLLL!LLLLVLLLLLLLLLLLLLLLLLLLLLLLLLLL0BfLLLLL0BLLLLfLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLXX7*+XqX+q0XXXXXW]5KXyX5Ky5XXXXXXXXXXXX+qXXXXX+XXXXqXXXXXXXXXXXXXXXXXXXXXXXXXXX5KyXXXXX5KXXXXyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX%d)<<<HM",f,"f,,,,,,,,,,"f,,,,,",,,,f,,,,,,,,,,,,,,,,,,,,,,,,,,,+,11,1111111111,11111,1111111111111111111111111111111M"8,9	9,	9999999999,	99999,9999	999999999999999999999999999!$i888G*+0q0+q0000000000+q00000+0000q000000000000000000000000000=!.Y.!Y..........!Y.....!....Y...........................&tI>>>D=L)1T1)T1111111111)T11111)1111T111111111111111111111111111=-.:(:.(::::::::::.(:::::.::::(:::::::::::::::::::::::::::=J'050'50000000000'500000'0000500000000000000000000000000000r?   c            	        t                                          d                                          d         }                     d                                          }|d         }dMdNfd} |ddd|             |ddd|            |ddd| d            |ddd| d            |ddd| d                                            t	          d          }|d         |d         |d         f}d}||k    }|slt          j        d |fd!||f          t          j        |          t          j        |          d"z  }d#d$|iz  }	t          t          j	        |	                    d x}x}}g }
|d%         }d&}||k    }|}|r|d'         }d(}||k    }|}|st          j        d |fd)||f          t          j        |          t          j        |          d*z  }	d+d,|	iz  }|

                    |           |r`t          j        d |fd-||f          t          j        |          t          j        |          d.z  }d/d0|iz  }|

                    |           t          j        |
d          i z  }d1d2|iz  }t          t          j	        |                    d x}x}
x}x}x}x}x}}t          dt          |d3                   d45          }|d6         }d7}||k    }|slt          j        d |fd!||f          t          j        |          t          j        |          d"z  }d#d$|iz  }	t          t          j	        |	                    d x}x}}|d8         d         d9         }d}||k    }|slt          j        d |fd!||f          t          j        |          t          j        |          d"z  }d#d$|iz  }	t          t          j	        |	                    d x}x}}t          d:;          }t          d< |d=         D                       }|d'         }d(}||k    }|slt          j        d |fd!||f          t          j        |          t          j        |          d"z  }d#d$|iz  }	t          t          j	        |	                    d x}x}}d>dd?d@dAdB| ddC}t!          j        t$                    5 }t'          |           d d d            n# 1 swxY w Y   |j        }
|
j        }dD}||k    }|st          j        d |fdE||f          dFt-          j                    v st          j        |          rt          j        |          ndFt          j        |
          t          j        |          t          j        |          dGz  }dHdI|iz  }t          t          j	        |                    d x}
x}x}}t!          j        t$                    5 }t3          |dJddKz             d d d            n# 1 swxY w Y   |j        }
|
j        }dD}||k    }|st          j        d |fdE||f          dLt-          j                    v st          j        |          rt          j        |          ndLt          j        |
          t          j        |          t          j        |          dGz  }dHdI|iz  }t          t          j	        |                    d x}
x}x}}d S )ONr  r   zcSELECT category_id,name FROM budget_categories WHERE category_type='income' AND is_active=1 LIMIT 1re   r  rD   r  rC   r  r  r   r   c                F                         d| || ||||| | f	           d S )Na  INSERT INTO budget_transactions(
                 budget_transaction_id,account_id,transaction_type,transaction_date,description,
                 amount_original,currency_original,amount_chf,fx_status,category_id,status,source_type,
                 reversal_of_transaction_id,created_at,updated_at)
               VALUES (?, 'bacc_rai', ?, '2026-06-01', ?, ?, 'CHF', ?, 'not_needed', ?,
                       'confirmed','manual',? ,?,?)r  r  s        r=   r  zPtest_refund_links_are_eligible_bounded_and_writer_validated.<locals>.transactionG  sA    7 GUFFK5RWX	
 	
 	
 	
 	
r?   zexpense-originrd   rM   zincome-originrc   zrefund-validr  z60.00zrefund-excessr  zrefund-incomer  2026-06r  r  rZ  r	  )rM   r  r  r   r   rx   r{   r|   r  r   rQ  r  r  r  r  r   r  r  r  r  r  r  namer  r  rW  r   rr   r  2026yearc              3  2   K   | ]}|d          dk    |V  dS r  r  NrJ   r   s     r=   r  zNtest_refund_links_are_eligible_bounded_and_writer_validated.<locals>.<genexpr>i  0      XXc'li>W>W>W>W>W>WXXr?   cashflow_by_monthr-   
2026-06-02zSynthetic invalid refundr:  r  )r  r  transaction_dater  r   currency_originalre   r  r  rC  invalid_originr   r   r   zSynthetic excessive refund)r  r  	excessiver~  )r  rD   r  rD   rC   rD   re   rD   r  r  r   r   )r>   r7   r*  r8   r   r}   r~   r   r   r   r   r   r   rD   r   r  rF  rG  r   r   r   rH  r   r   r   r   )r  income_category_rowr  r  r  r   r   r   r   r   r   r   r   r,  r-  r.  r   r   r/  r   r0  income_pagechartsjuneinvalid_income_linkr  r   r   r   r  r9   s                                 @r=   ;test_refund_links_are_eligible_bounded_and_writer_validatedr#  =  s	   ::D||i hjj ,,m hjj  *-8O	
 	
 	
 	
 	
 	
 	
 K )X7GHHHK8_EEEK'3CEUVVVK74DFVWWWK74DoVVVKKMMM-d9EEEGL!7=#979;MN  S N S     	   N S    	 O   	S              	           
 YX7*+XqX+q0XXXXXW]5KXyX5Ky5XXXXXXXXXXXX+qXXXXX+XXXXqXXXXXXXXXXXXXXXXXXXXXXXXXXX5KyXXXXX5KXXXXyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-(011	  K '(-A-(A----------(A-----(----A---------------------------w"#56B(B6(BBBBBBBBBB6(BBBBB6BBBB(BBBBBBBBBBBBBBBBBBBBBBBBBBB#Dv666FXXv&9:XXXXXD+)+)++++++++++)+++++++++)+++++++++++++++++++++++++++ !$(1""'&5	 	 
}	%	% E)$0CDDDE E E E E E E E E E E E E E E2+2s2+s2222222222+s222222222222>22222>2222222222+2222s22222222222222222222222222222	}	%	% 
";.># # 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 ?-?&-#-&#----------&#------------9-----9------?----&----#-------------------------------s$   S  S$'S$!XXXc                 ,   t                      } |                     d           |                                  t          | d          }|d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }d	d
|iz  }t          t	          j        |                    d x}x}}|d         }d }||u }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }d	d
|iz  }t          t	          j        |                    d x}x}}|d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }d	d
|iz  }t          t	          j        |                    d x}x}}g }|d         }d}||k    }	|	}|	r|d         }
d}|
|k    }|}|st	          j        d|	fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }|	                    |           |	r`t	          j        d|fd|
|f          t	          j        |
          t	          j        |          dz  }dd|iz  }|	                    |           t	          j
        |d          i z  }dd|iz  }t          t	          j        |                    d x}x}x}x}	x}x}
x}}t          | d          }|d         }d }||u }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }d	d
|iz  }t          t	          j        |                    d x}x}}g }|d         }d}||k    }	|	}|	r|d         }
d}|
|k    }|}|st	          j        d|	fd||f          t	          j        |          t	          j        |          dz  }dd|iz  }|	                    |           |	r`t	          j        d|fd|
|f          t	          j        |
          t	          j        |          dz  }dd|iz  }|	                    |           t	          j
        |d          i z  }dd|iz  }t          t	          j        |                    d x}x}x}x}	x}x}
x}}t          | d          }t          d  |d!         D                       }|d         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }d	d
|iz  }t          t	          j        |                    d x}x}}d S )"Na  INSERT INTO budget_transactions(
             budget_transaction_id,account_id,transaction_type,transaction_date,description,
             amount_original,currency_original,amount_chf,fx_status,status,source_type,created_at,updated_at)
           VALUES ('foreign-transfer','bacc_rai','transfer','2026-06-01','Synthetic FX transfer',
                   '100.00','EUR',NULL,'missing','confirmed','manual','x','x')r  r  r  r   r   r   rx   r{   r|   neutral_transfer_volume_chfru   rw   unavailable_transfer_countr	  rQ  r  r  r  r  r   r  r  r  r  r   r  r  r  r  r  c              3  2   K   | ]}|d          dk    |V  dS r  rJ   r   s     r=   r  zJtest_missing_fx_transfer_volume_is_unavailable_not_zero.<locals>.<genexpr>  r  r?   r  )r>   r7   r8   r   r}   r~   r   r   r   r   r   r   r   r  )r9   r  r   r   r   r   r   r   r   r   r,  r-  r.  r   r   r/  r   r0  r  r   r!  s                        r=   7test_missing_fx_transfer_volume_is_unavailable_not_zeror(    sK   ::DLL	R   	KKMMM-d9EEEG+,11,1111111111,11111,1111111111111111111111111111111019T91T99999999991T9999919999T999999999999999999999999999/05A50A55555555550A5555505555A555555555555555555555555555XX7*+XqX+q0XXXXXW]5KXyX5Ky5XXXXXXXXXXXX+qXXXXX+XXXXqXXXXXXXXXXXXXXXXXXXXXXXXXXX5KyXXXXX5KXXXXyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!$i888G019T91T99999999991T9999919999T999999999999999999999999999]]7/0]A]0A5]]]]]'-:P]T]]:PT]:]]]]]]]]]]]]0A]]]]]0]]]]A]]]]]]]]]]]]]]]]]]]]]]]]]]]:PT]]]]]]:P]]]]T]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]#Dv666FXXv&9:XXXXXD+)+)++++++++++)+++++++++)+++++++++++++++++++++++++++++r?   c                 $   t                      } t          | ddddddd           t          | d	          }|d
         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d          }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}dD ]}t          | d|          }	|	d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}| 	                    d           t          | d	          }
|
d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|
d
         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|
d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|
d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|
d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|
d         }d }||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d! |
d"         D             }d#g}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d          }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d }||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d$%          }t          d& |d'         D                       }|d         }d }||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}| 	                    d(           t          | d)d*d+          d,         t          | dd*dd-d.dd/           t          | ddd0ddd1d           | 	                    d2                                          }| 	                    d3                                          d         }| 	                    d4           t!          |d5          D ]5\  }}| 	                    d6d7| ||ddt#          |d8z            df           6t          | d	          }|d         }d9}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d
         }d:}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d;         }d.}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}fd<|d=         D             }t          |          }d.}||k    }|st          j        d|fd>||f          d?t%          j                    v st          j        t                    rt          j        t                    nd?t          j        |          t          j        |          t          j        |          d@z  }dAdB|iz  }t          t          j        |                    d x}x}x}}|d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d5}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d5}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | d          }|d         dC         }d }||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d5}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}| 	                    dD           | 	                    dE           t          | ddFdGdHdIddJ           t          | d	          }|d
         }dK}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }dL}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          | ddd.dMdNdOd           t          | dP	          }|d
         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d5}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d S )QNr-   r4   z900.00r  r  zSynthetic internal transfer)from_account_idto_account_idr   r  r  r  r  r  r  r   r   r   rx   r{   r|   r%  r&  r   r  r  r[  )r    r"   )r  r'  a  INSERT INTO budget_transfers(
             transfer_id,from_transaction_id,to_transaction_id,from_account_id,to_account_id,
             amount_original,currency_original,fx_rate_to_chf,created_at,transfer_type)
           SELECT 'duplicate-membership',from_transaction_id,to_transaction_id,from_account_id,to_account_id,
                  amount_original,currency_original,fx_rate_to_chf,'x',transfer_type
           FROM budget_transfers LIMIT 1confirmed_transaction_countru   rw   r	  "transfer_membership_conflict_countrQ  r  c                    g | ]
}|d          S )r  rJ   r"  s     r=   r  zRtest_paired_transfer_volume_is_counted_once_and_unmatched_once.<locals>.<listcomp>  s    :::TDL:::r?   warningstransfer_membership_conflictr  r  c              3  2   K   | ]}|d          dk    |V  dS r  rJ   r   s     r=   r  zQtest_paired_transfer_volume_is_counted_once_and_unmatched_once.<locals>.<genexpr>  s4      jjPST[P\`iPiPiPiPiPiPijjr?   r  zEDELETE FROM budget_transfers WHERE transfer_id='duplicate-membership'zMalformed membership categoryrd   )r  rb   	entity_idzMalformed membership expenser  )r  re   r  r  r  r   r  z30.00z Malformed membership counterpartz`SELECT from_transaction_id,to_transaction_id FROM budget_transfers WHERE amount_original='30.00'zfSELECT budget_transaction_id FROM budget_transactions WHERE description='Malformed membership expense'z:DELETE FROM budget_transfers WHERE amount_original='30.00'r   a   INSERT INTO budget_transfers(
                 transfer_id,from_transaction_id,to_transaction_id,from_account_id,to_account_id,
                 amount_original,currency_original,created_at,transfer_type)
               VALUES(?,?,?,?,?,?,?,'x','internal')z
malformed-r  r  r  rZ  c              3  @   K   | ]}|d          k    |d         V  dS )re   rZ  NrJ   )rg   r   malformed_categorys     r=   r  zQtest_paired_transfer_volume_is_counted_once_and_unmatched_once.<locals>.<genexpr>  sE        }!333 	M3333 r?   rj   r   r  r   r   r   rp  zADELETE FROM budget_transfers WHERE transfer_id LIKE 'malformed-%'zNDELETE FROM budget_transactions WHERE description LIKE 'Malformed membership%'r  z
2026-06-03zSynthetic unmatched transferrM   )r  r  r  r  r   r  r  z1000.00r  z
2026-07-02zSynthetic unconverted pairz2026-07)r>   r   r   r}   r~   r   r   r   r   r7   r   r   r  r   r   r*  	enumeraterD   r   r   r   )r9   r  r   r   r   r   r   r  account_namescopedconflictconflict_monthconflict_chartsconflict_junemalformed_pair
expense_idr   counterpart_id	malformedr   r   r   r   r   malformed_overviewwith_unmatchedunavailable_pairr4  s                              @r=   >test_paired_transfer_volume_is_counted_once_and_unmatched_oncerC    sl   ::DT%##"(4     .d9EEEG+,11,1111111111,11111,111111111111111111111111111111101=X=1X==========1X=====1====X===========================/05A50A55555555550A5555505555A555555555555555555555555555%d)<<<H+,66,6666666666,66666,666666666666666666666666666666612>h>2h>>>>>>>>>>2h>>>>>2>>>>h>>>>>>>>>>>>>>>>>>>>>>>>>>>6 A A0iQ]^^^34@@4@@@@@@@@@@4@@@@@4@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@LL	,   /tIFFFH127a72a77777777772a7777727777a777777777777777777777777777,-22-2222222222-22222-222222222222222222222222222222212:d:2d::::::::::2d:::::2::::d:::::::::::::::::::::::::::+,11,1111111111,11111,111111111111111111111111111111189>Q>9Q>>>>>>>>>>9Q>>>>>9>>>>Q>>>>>>>>>>>>>>>>>>>>>>>>>>>M"/i/"i//////////"i/////"////i///////////////////////////::Xj%9:::^?]>^^:>^^^^^^^^^^^:>^^^^^^:^^^^>^^^^^^^^^^^^^^^^^^^^^^^^^^^^(Y???N>?D1D?1DDDDDDDDDD?1DDDDD?DDDD1DDDDDDDDDDDDDDDDDDDDDDDDDDD-(5I5(I5555555555(I55555(5555I555555555555555555555555555,T???Ojj8K(LjjjjjM'494'94444444444'944444'44449444444444444444444444444444LLXYYY06SS  t 1CYb(9W"& &   
 T%
W^"9    
 \\j hjj  p hjjJ 	LLMNNN!*>1!=!= 
 
~7 "%!!:~z:WZ[`ce[eWfWfhmn	
 	
 	
 	
 0YGGGI238q83q88888888883q8888838888q888888888888888888888888888-.3!3.!3333333333.!33333.3333!333333333333333333333333333]#.w.#w..........#w.....#....w...........................   \*   4     
	  
	    	     
	     	    	      	       	    	    	             	             
 23;t;3t;;;;;;;;;;3t;;;;;3;;;;t;;;;;;;;;;;;;;;;;;;;;;;;;;;127a72a77777777772a7777727777a7777777777777777777777777779:?a?:a??????????:a?????:????a???????????????????????????/IFFFm,X6C)C6)CCCCCCCCCC6)CCCCC6CCCC)CCCCCCCCCCCCCCCCCCCCCCCCCCCBCHqHCqHHHHHHHHHHCqHHHHHCHHHHqHHHHHHHHHHHHHHHHHHHHHHHHHHHLLTUUULLabbbt &(5#"& &    5T)LLLN238q83q88888888883q8888838888q88888888888888888888888888878EIE8IEEEEEEEEEE8IEEEEE8EEEEIEEEEEEEEEEEEEEEEEEEEEEEEEEET%#""(3     7tINNN45::5::::::::::5:::::5:::::::::::::::::::::::::::::::9:BdB:dBBBBBBBBBB:dBBBBB:BBBBdBBBBBBBBBBBBBBBBBBBBBBBBBBB89>Q>9Q>>>>>>>>>>9Q>>>>>9>>>>Q>>>>>>>>>>>>>>>>>>>>>>>>>>>>>r?   )r   r   )r@   rA   rB   )rC   rD   rE   rD   rF   rD   r   rD   )rM   rN   rB   )r   rQ   )rY   rQ   rZ   rQ   r   rQ   )r9   r   rY   rQ   r   r_   )r   r   )r`  ra  r   r   )\
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter}   r  r   decimalr   sqlite3r   rF  fastapir   fastapi.testclientr   (jarvis_finance.services.household_importserviceshousehold_importr  jarvis_finance.api.dependenciesr	   jarvis_finance.api.mainr
   )jarvis_finance.services.budget_categoriesr   'jarvis_finance.services.budget_overviewr   r   +jarvis_finance.services.budget_transactionsr   r   r   ,jarvis_finance.services.household_financialsr   r   r   r   r   r   r   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r>   rL   rP   rX   r^   r   r   r   r  r7  r@  rI  rU  r\  rl  r{  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r1  r@  rB  r_  r  r  r  r  r#  r(  rC  rJ   r?   r=   <module>rX     s   " " " " " "                             ! ! ! ! ! ! ) ) ) ) ) ) K K K K K K K K K 2 2 2 2 2 2 . . . . . . M M M M M M _ _ _ _ _ _ _ _         
 Y X X X X X	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ; : : : : : R R R R R R R R   &u u u u ug g g g g   N N N N
   &u u u u0 0 0 0.% % % %2W W W W&V V V V	\ 	\ 	\ 	\n n n n &F &F &F &FRM M M M > > > >0\ \ \ \*
/ 
/ 
/ 
/( ( ( (*, , , ,"G G G G T T T TG G G G2       @w w w w.9 9 9 9X X X X24A 4A 4A 4Any y y y:*P *P *P *PZ Z  Z  Z  ZF   <I I I I>i i i iXvV vV vV vVrEa Ea Ea EaP1 1 1 1@D. D. D. D.N, , , ,.r? r? r? r? r? r?r?   