
    Mfj(<                    d   d dl mZ d dlZd dlmc mZ d dlZd dl	m
Z
 d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ d dlmZmZmZmZ d dl m!Z! d dl"m#Z# d7dZ$d8dZ%dddd9dZ&dddddd:d"Z'd;d$Z(d%dd&d<d-Z)d=d.Z*d=d/Z+d=d0Z,d=d1Z-d=d2Z.d=d3Z/d=d4Z0d=d5Z1d=d6Z2dS )>    )annotationsN)
Connection)HTTPException)
TestClient)get_db)
create_appconfirm_create_budget_account)'seed_bank_transfer_candidates_from_rows)list_budget_transactionslist_budget_transfers)confirm_transfer_pairlist_transfer_pairspropose_transfer_pairsreject_transfer_pair)connect_memory)apply_migrationsreturnr   c                 @    t                      } t          |            | S N)r   r   conns    v/home/agent/.hermes/worktrees/FinanceManager-sprint11-portfolio-completeness-ux/tests/unit/test_transfer_pairing_v2.pydbr      s     DTK    r   tuple[str, str, str]c                    t          | dddd          d         }t          | dddd          d         }t          | dddd          d         }|||fS )N
RaiffeisencashCHF)nameaccount_typecurrency	entity_idAKB HaushaltskontoReservekontor	   )r   
raiffeisenakbreserves       r   accountsr*      s    .v5II  J (%v5QQ  C ,UKK  G sG##r   -100.00z
2026-05-12)amountdater,   strr-   c                   t          | |d|ddgdd           t          |                     d                                          d                   S )	Nz!Einkauf TWINT SWISSLOS E-COMMERCEOWN-RAIFFEISENr-   descriptionr,   accountzsynthetic-run-raiffeisenraiffeisen_banksource_file_labelcandidate_source_typezfSELECT transaction_candidate_id FROM budget_transaction_candidates WHERE source_type='raiffeisen_bank'r   r   r.   executefetchone)r   r,   r-   s      r   seed_reference_outflowr;   /   sy    + B +	 	
 5/    t	
 	

(**Q	  r   100.00
2026-05-13u   Eigener Kontoübertragzsynthetic-run-akb)r,   r-   r2   source_labelr2   r>   c                   t          | |||ddg|d           t          |                     d|f                                          d                   S )NOWN-AKBr1   akb_bankr5   z\SELECT transaction_candidate_id FROM budget_transaction_candidates WHERE source_file_label=?r   r8   )r   r,   r-   r2   r>   s        r   seed_reference_inflowrB   D   s     , * $	 	
 '(    jO	
 	
 (**Q	  r   tuple[str, str, dict]c                    t          |            t          |           }t          |           }t          |            t	          d t          |           D                       }|||fS )Nc              3  2   K   | ]}|d          dk    |V  dS statusproposedN .0items     r   	<genexpr>zseed_pair.<locals>.<genexpr>f   s1      [[d8nPZ>Z>Z>Z>Z>Z>Z[[r   )r*   r;   rB   r   nextr   )r   	source_id	target_idpairs       r   	seed_pairrR   a   sg    TNNN&t,,I%d++I4   [[!4T!:!:[[[[[Di%%r   r    )r#   r-   candidate_idsource_typeaccount_sourcesigned_amountr#   Nonec               r   |                      d|d| |||dt          t          t          d                              |                              ||t          j        d|                    d          s|                    d          sdnd	i          |d
| f           |                                  d S )Na[  
        INSERT INTO budget_transaction_candidates(
            transaction_candidate_id, source_file_label, source_row_or_range, source_type,
            transaction_date, value_date, description, amount_original, signed_amount_original,
            currency_original, confidence, requires_review, status, notes, classification,
            review_reason, account_source, raw_fingerprint, created_at, updated_at
        ) VALUES (?, ?, 'R1', ?, ?, ?, ?, ?, ?, ?, '0.50', 1, 'needs_review', ?,
                  'bank_review', 'bank_payment_unclear', ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
        z
synthetic-zSynthetic bookingdecimaltransaction_type+-incomeexpensezfingerprint-)	r9   r.   abs
__import__Decimaljsondumps
startswithcommit)r   rS   rT   rU   rV   r#   r-   s          r   insert_candidaterf   j   s     	LL	 '''Jy))11-@@AABBJ*8P8PQT8U8U  -J]j]u]uvy]z]z  -JHH  AJ  K  L  L)<))	
  2 	KKMMMMMr   c                    t                      } t          |            t          |           }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	         }||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         }||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}||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          }||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          }||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%}||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'         }||v }|slt          j        d!|fd"||f          t          j	        |          t          j	        |          dz  }	dd|	iz  }
t          t          j        |
                    d x}x}}d S )(Nc              3  2   K   | ]}|d          dk    |V  dS rF   rI   rJ   s     r   rM   zbtest_reference_case_matches_across_import_runs_despite_misleading_merchant_text.<locals>.<genexpr>   s0      KKTd8n
.J.JD.J.J.J.JKKr   proposed_count   )>=)z%(py1)s >= %(py4)spy1py4assert %(py6)spy6source_candidate_id==z%(py1)s == %(py3)srO   rm   py3assert %(py5)spy5target_candidate_idrP   source_signed_amountr+   z%(py1)s == %(py4)starget_signed_amountr<   r#   r    source_account_namer   target_account_namer%   budget_effect_chf0u3   Interner Transfer Raiffeisen → AKB Haushaltskontosummaryinz%(py1)s in %(py4)szBudgeteffekt CHF 0confirmation_noticeuY   Als interner Transfer erkannt. Die endgültige Verbuchung erfolgt erst nach Bestätigung.merchant_text_not_decisivereason_codes)r   r*   r;   rB   r   r   rN   
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanation@py_builtinslocals_should_repr_global_name)r   rO   rP   resultpairsrH   @py_assert0@py_assert3@py_assert2@py_format5@py_format7@py_format4@py_format6s                r   Otest_reference_case_matches_across_import_runs_despite_misleading_merchant_textr      s	   44DTNNN&t,,I%d++I#D))F%%EKKUKKKKKH"#(q(#q((((((((((#q(((((#((((q((((((((((((((((((((((((((()*7*i7777777777*i77777*77777777777i77777i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*i7777777777*i77777*77777777777i77777i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*+8y8+y8888888888+y88888+8888y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*+7x7+x7777777777+x77777+7777x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J(5(5((((((((((5(((((((((5((((((((((((((((((((((((((()*:l:*l::::::::::*l:::::*::::l:::::::::::::::::::::::::::)*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BBBBBBBBBBBBBBBBBBBBB'(/C/(C//////////(C/////(////C///////////////////////////@WHYDWW@DWWWWWWWWWWW@DWWWWWW@WWWWDW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68I#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666)* c*c       *c    +    	d                         (C8N+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Cr   c                    t                      } t          |            t          |           }t          |            t	          d t          |           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 }||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         }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	          f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	          d |
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 S )Nc              3  2   K   | ]}|d          dk    |V  dS )rG   	unmatchedNrI   rJ   s     r   rM   zYtest_missing_counterbooking_is_unmatched_then_later_pair_supersedes_it.<locals>.<genexpr>   s1      aad4>U`C`C`TC`C`C`C`aar   rq   rr   rt   rO   ru   rw   rx   ry   isz%(py1)s is %(py4)srl   ro   rp   quality_statusr   r{   (SELECT COUNT(*) FROM budget_transactionsr   c              3  @   K   | ]}|d          d          k    |V  dS )transfer_pair_idNrI   )rK   rL   r   s     r   rM   zYtest_missing_counterbooking_is_unmatched_then_later_pair_supersedes_it.<locals>.<genexpr>   s9      hhd3E.F)TfJg.g.g.g.g.g.ghhr   rG   
supersededc              3  2   K   | ]}|d          dk    |V  dS rF   rI   rJ   s     r   rM   zYtest_missing_counterbooking_is_unmatched_then_later_pair_supersedes_it.<locals>.<genexpr>   s0      OOT$x.J2N2ND2N2N2N2NOOr   rP   )r   r*   r;   r   rN   r   r   r   r   r   r   r   r   r   r9   r:   rB   )r   rO   r   r   r   r   r   r   r   rP   	all_pairsrH   r   s               @r   Ftest_missing_counterbooking_is_unmatched_then_later_pair_supersedes_itr      s   44DTNNN&t,,I4   aa&9$&?&?aaaaaI*+8+y8888888888+y88888+88888888888y88888y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*+3t3+t3333333333+t33333+3333t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%&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5555555555555555<<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%d++I4   #D))Ihhhhhhhhhiqr  C  wC  Cr  wC  C  C  C  C  C  C  C  C  C  Cr  wC  C  C  C  C  Cr  C  C  C  C  w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OOYOOOOOH)*7*i7777777777*i77777*77777777777i77777i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7r   c                 :   t                      } t          |            t          |           t          | d           t	          | ddddd           t          |            t          f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 }||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         }||v }|slt          j	        d|fd||f          t          j
        |          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d S )Nzsynthetic-akb-a)r>   z
cand-akb-brA   r@   r<   r=   )rS   rT   rU   rV   r-   c              3  4   K   | ]}|d          k    |V  dS )rq   NrI   )rK   rL   rO   s     r   rM   zBtest_ambiguous_counterbookings_are_not_selected.<locals>.<genexpr>   s4      ggdCX>Y]f>f>f>f>f>f>fggr   rG   r   rr   r{   rl   ro   rp   r   	ambiguousalternative_count   ry   r   r   ambiguous_counterbookingsr   r   r   )r   r*   r;   rB   rf   r   rN   r   r   r   r   r   r   )r   rQ   r   r   r   r   r   rO   s          @r   /test_ambiguous_counterbookings_are_not_selectedr      s   44DTNNN&t,,I$->????!     4   gggg!4T!:!:gggggD>([(>[((((((((((>[(((((>(((([((((((((((((((((((((((((((( !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000000000000000000#$))$))))))))))$)))))$)))))))))))))))))))))))))))))))%&.$.&$..........&$.....&....$...........................&>$~*>>&*>>>>>>>>>>>&*>>>>>>&>>>>*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>r   c                    t                      } t          |            t          | dddd           t          | dddd           t          | d	ddd
           t          | dddd           t          | dddd
d           t          |            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}||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sourcer4   r0   r+   rS   rT   rU   rV   zsame-directionrA   r@   zsame-accountr<   zother-amountz99.99zother-currencyEUR)rS   rT   rU   rV   r#   c              3  2   K   | ]}|d          dk    |V  dS )rq   r   NrI   rJ   s     r   rM   zWtest_invalid_direction_account_amount_and_currency_are_never_guessed.<locals>.<genexpr>   s3      ffdCX>Y]e>e>e>e>e>e>effr   rG   r   rr   r{   rl   ro   rp   r   r   )r   r*   rf   r   rN   r   r   r   r   r   r   )r   rQ   r   r   r   r   r   s          r   Dtest_invalid_direction_account_amount_and_currency_are_never_guessedr      si   44DTNNN%'    %     #%'    #     %     4   ff!4T!:!:fffffD>([(>[((((((((((>[(((((>(((([(((((((((((((((((((((((((((#$))$))))))))))$)))))$)))))))))))))))))))))))))))))))))r   c            
     v   t                      } t          |           \  }}}t          | |d         d          }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}||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}||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          	                                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||f          
                                }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}}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}t          | |          }t!          |          }d}||k    }|s`t          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        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        |          t          j        |          d$z  }d%d&|iz  }t          t          j        |                    d x}x}x}x}}d}d'}t#          | ||(          }g }||k    }|st          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        |          t          j        |          t          j        |          d+z  }d,d-|iz  }t          t          j        |                    d x}x}x}x}}d}d.}t#          | ||(          }g }||k    }|st          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        |          t          j        |          t          j        |          d+z  }d,d-|iz  }t          t          j        |                    d x}x}x}x}}|                     d/          	                                }d }||u}|st          j        d0|fd1||f          d2t          j                    v st          j        |          rt          j        |          nd2t          j        |          d3z  }d4d5|iz  }t          t          j        |                    d x}}d6}|d7         }||v}|slt          j        d8|fd9||f          t          j        |          t          j        |          dz  }	d	d
|	iz  }
t          t          j        |
                    d x}x}}d:}|d7         }||v}|slt          j        d8|fd9||f          t          j        |          t          j        |          dz  }	d	d
|	iz  }
t          t          j        |
                    d x}x}}d S );Nr   synthetic-userdecision_byrG   	confirmedrr   r{   rl   ro   rp   r   r   r$   
idempotentTr   r   %SELECT COUNT(*) FROM budget_transfersr   rj   zJSELECT COUNT(*) FROM budget_transactions WHERE transaction_type='transfer'r   zWSELECT COUNT(*) FROM budget_transactions WHERE transaction_type IN ('income','expense')zSELECT transaction_candidate_id, status, confirmed_transaction_id FROM budget_transaction_candidates WHERE transaction_candidate_id IN (?, ?)c                    h | ]
}|d          S rG   rI   rK   rows     r   	<setcomp>zWtest_confirm_consumes_both_candidates_once_and_budget_effect_is_zero.<locals>.<setcomp>  s    ...cCM...r   c              3  &   K   | ]}|d          V  dS )confirmed_transaction_idNrI   r   s     r   rM   zWtest_confirm_consumes_both_candidates_once_and_budget_effect_is_zero.<locals>.<genexpr>  s(      CC3s-.CCCCCCr   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allpy0py2rn   2026)year)z]%(py8)s
{%(py8)s = %(py0)s(%(py6)s
{%(py6)s = %(py1)s(%(py2)s, year=%(py4)s)
})
} == %(py11)slenr   r   )r   rm   r   rn   rp   py8py11zassert %(py13)spy13r]   )r   rZ   )zY%(py7)s
{%(py7)s = %(py0)s(%(py1)s, year=%(py3)s, transaction_type=%(py5)s)
} == %(py10)sr   )r   rm   rv   rx   py7py10zassert %(py12)spy12r^   zLSELECT new_values_json FROM audit_log WHERE action='transfer_pair_confirmed')is not)z%(py0)s is not %(py3)saudit)r   rv   rw   rx   OWN-new_values_jsonnot in)z%(py1)s not in %(py4)ssource_file)r   rR   r   r   r   r   r   r   r9   r:   fetchallr   r   r   r   r   r   r   )r   rO   rP   rQ   firstsecondr   r   r   r   r   statuses@py_assert1@py_assert5@py_assert7@py_assert10@py_assert9@py_format12@py_format14@py_assert4@py_assert6@py_assert8@py_format11@py_format13r   r   r   s                              r   Dtest_confirm_consumes_both_candidates_once_and_budget_effect_is_zeror     s   44D!*4Iy$!$-?(@N^___E"4.@)AO_```F?)k)?k))))))))))?k)))))?))))k)))))))))))))))))))))))))))$%,,%,,,,,,,,,,%,,,,,%,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,(*{*{**********{*********{***************************+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'''''''''''''''''''''''''''<<?@@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<<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|| 	X	I  hjj  /.X...?;-?.-??????????.-?????.????-???????????????????????????CC(CCCC3CCCCCCCCCCCCCCCC3CCCCC3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C06=$T777=3788=A=8A==========8A============3=====3=============$=====$=============T=====T==========7====8====A===============================/5WW#DvQQQWUWWQUWWWWWWWWWWWQUW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WDWWWWWDWWWWWWvWWWWWWWWQWWWWUW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/5X	X#Dv	RRRXVXXRVXXXXXXXXXXXRVX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XDXXXXXDXXXXXXvXXXX	XXXXRXXXXVX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LLV hjj 
 5555101161111111111161111116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&7 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88888r   c                    t                      } t          |           \  }}}|                     d|f           |                                  t	          j        t                    5 }t          | |d                    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                                          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         f                                          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 )NzZUPDATE budget_transaction_candidates SET status='ignored' WHERE transaction_candidate_id=?r     rr   zN%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.status_code
} == %(py7)sexcr   r   rn   r   assert %(py9)spy9r   r   r{   rl   ro   rp   r   zASELECT status FROM budget_transfer_pairs WHERE transfer_pair_id=?rH   )r   rR   r9   re   pytestraisesr   r   valuestatus_coder   r   r   r   r   r   r   r   r:   )r   
_source_idrP   rQ   r   r   r   r   r   @py_format8@py_format10r   r   r   r   s                  r   Btest_confirm_revalidates_both_candidates_and_rolls_back_atomicallyr   %  s   44D"+D//J	4LLd	   	KKMMM	}	%	% >dD);$<===> > > > > > > > > > > > > > > 9'9 'C' C'''''''''' C''''''''''''3'''''3''''''9'''' ''''C'''''''''''''''''''''''''''''<<?@@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<<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<<K	 	!#  hjj " ""  "" " " " " "" " " "  "" " " " " " " " "z" " " " " " " " " " " " " " "" " " " " " " " " " " " " "s   &B		BBc                 4	   t                      } t          |           \  }}}t          | |d         dd          }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}||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||f          	                                }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}}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                                          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 )Nr   r   zNot this pair)r   noter   rG   rejectedrr   r{   rl   ro   rp   r   Tr   r   znSELECT status, linked_candidate_id FROM budget_transaction_candidates WHERE transaction_candidate_id IN (?, ?)c                    h | ]
}|d          S r   rI   r   s     r   r   zLtest_reject_does_not_consume_candidates_and_is_idempotent.<locals>.<setcomp>H  s    888cCM888r   needs_reviewc              3  *   K   | ]}|d          du V  dS )linked_candidate_idNrI   r   s     r   rM   zLtest_reject_does_not_consume_candidates_and_is_idempotent.<locals>.<genexpr>I  s-      PPcs()T1PPPPPPr   r   r   r   r   r   zDSELECT COUNT(*) FROM audit_log WHERE action='transfer_pair_rejected'rj   )r   rR   r   r   r   r   r   r   r9   r   r   r   r   r   r:   )r   rO   rP   rQ   r   r   r   r   r   r   r   candidate_statusesr   s                r   9test_reject_does_not_consume_candidates_and_is_idempotentr   :  s~   44D!*4Iy$ t,>'?M]dstttE!$-?(@N^___F?(j(?j((((((((((?j(((((?((((j(((((((((((((((((((((((((((()z)z))))))))))z)))))))))z))))))))))))))))))))))))))),'4'4''''''''''4'''''''''4'''''''''''''''''''''''''''x	I  hjj  98%7888L^<LL8<LLLLLLLLLLL8<LLLLLL8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PP=OPPPP3PPPPPPPPPPPPPPPP3PPPPP3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<<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<<^__hhjjklmrqrrmqrrrrrrrrrrrmqr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rr   c                    t                      } t          |           \  }}}t          | dddd           |                     d|d         f           |                                  t          | |d                    t          j        t                    5 }t          | d           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 )Nzother-targetrA   r@   r<   r   a  
        INSERT INTO budget_transfer_pairs(
            transfer_pair_id, source_candidate_id, target_candidate_id, source_account_id,
            target_account_id, source_signed_amount, target_signed_amount, currency,
            source_booking_date, target_booking_date, status, quality_status,
            evidence_json, reason_codes_json, budget_effect_chf, created_at, updated_at
        )
        SELECT 'pair_competing', source_candidate_id, 'other-target', source_account_id,
               target_account_id, source_signed_amount, '100.00', currency,
               source_booking_date, target_booking_date, 'proposed', 'strong',
               evidence_json, reason_codes_json, '0', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
        FROM budget_transfer_pairs WHERE transfer_pair_id=?
        r   pair_competingr   rr   r   r   r   r   r   r   r   rj   r{   rl   ro   rp   )r   rR   rf   r9   re   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r:   )r   rO   
_target_idrQ   r   r   r   r   r   r   r   r   r   r   r   s                  r   =test_competing_pair_cannot_create_a_second_confirmed_transferr  N  s   44D"+D//Iz4#     	LL	 
 	!#    	KKMMM$%7 8999	}	%	% 6d$45556 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9'9 'C' C'''''''''' C''''''''''''3'''''3''''''9'''' ''''C'''''''''''''''''''''''''''''<<?@@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SSs   B33B7:B7c            
     N   t                      t                    \  } }}fd}t          d          }||j        t          <   t          |          }|                    d                                          d         }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          }|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}}|                                }t          j        |          }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         }|j        }d} ||          }|ssdt          j
        |          t          j
        |          t          j
        |          t          j
        |          dz  }t          t          j        |                    d x}x}x}}|                    d |d!          d"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  }
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.          }||j        t          <   t          |          }|j        }d/}i } |||&          }|j        }d0}||k    }|st          j	        d|fd1||f          d2t          j                    v st          j        |          rt          j
        |          nd2t          j
        |          t          j
        |          t          j
        |          t          j
        |          t          j
        |          t          j
        |          d3z  }d4d5|iz  }t          t          j        |                    d x}x}x}x}x}x}}d S )6Nc               3     K    V  d S r   rI   r   s   r   override_dbz\test_api_contract_redacts_source_data_and_write_security_remains_active.<locals>.override_dbv  s      




r   test)
write_modez/openapi.jsonpathsz/api/budget/transfer-pairsr   )z%(py1)s in %(py3)sopenapiru   rw   rx   z,/api/budget/transfer-pairs/{pair_id}/confirm   rr   )z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sresponse)r   r   rx   zassert %(py7)sr   r   r   )z%(py1)s not in %(py3)s
serializedzsynthetic-runr6   r   r   zAls interner Transfer erkanntzLassert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.startswith
}(%(py5)s)
})rm   rv   rx   r   z/api/budget/transfer-pairs/r   z/confirmTzSynthetic UAT)confirmr   )rb   r   r   r   r{   rl   ro   rp   disabledz /api/budget/transfer-pairs/matchi  )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   rn   rp   r   r   r   zassert %(py15)spy15)r   rR   r   dependency_overridesr   r   getrb   r   r   r   r   r   r   r   r   r   rc   rd   post) r   r  rQ   r  appclientr  r   r   r   r   r  r   r   r   r   bodyr  r   r   r   r   blocked_appr  r   r   r   @py_assert12@py_assert11r   @py_format16r   s                                   @r   Gtest_api_contract_redacts_source_data_and_write_security_remains_activer  r  sw	   44D#,T?? J
D     
'
'
'C'2CV$__Fjj))..009G'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9D9WDDDDDDDDDD9WDDDDD9DDDDDDDDDDDWDDDDDW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zz677H&3&3&&&&&&&&&&3&&&&&&&&&&&&8&&&&&8&&&&&&&&&&3&&&&&&&&&&&&&&&&&&&&&&&&&&&==??DD!!J#6##########6#####6###########################################,?*,,,,,,,,,,?*,,,,,?,,,,,,,,,,,*,,,,,*,,,,,,,,,,,,,,,,,,,,,,,,,,,0j0000000000j0000000000000000j00000j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7()U)4U5TU445TUUUUUUUU)UUUU4UUUU5T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Hd+=&>HHH77   I  'C' C'''''''''' C''''''''''''9'''''9'''''' ''''C'''''''''''''''''''''''''''>>/07C70C77777777770C777770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
333K/:K$V,%%G<W:WW<<:DDDWDPWTWWPTWWWWWWWWWWWPTWWWWWWWWWWWWW7WWWWW7WWWWWW<WWWW:WWWWWWWWDWWWWPWWWWTW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WWWWWr   )r   r   )r   r   r   r   )r   r   r,   r.   r-   r.   r   r.   )r   r   r,   r.   r-   r.   r2   r.   r>   r.   r   r.   )r   r   r   rC   )r   r   rS   r.   rT   r.   rU   r.   rV   r.   r#   r.   r-   r.   r   rW   )r   rW   )3
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   rb   sqlite3r   r   fastapir   fastapi.testclientr   jarvis_finance.api.dependenciesr   jarvis_finance.api.mainr   'jarvis_finance.services.budget_accountsr
   &jarvis_finance.services.budget_importsr   +jarvis_finance.services.budget_transactionsr   r   (jarvis_finance.services.transfer_pairingr   r   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r*   r;   rB   rR   rf   r   r   r   r   r   r   r   r  r  rI   r   r   <module>r.     s   " " " " " "                      ! ! ! ! ! ! ) ) ) ) ) ) 2 2 2 2 2 2 . . . . . . Q Q Q Q Q Q Z Z Z Z Z Z g g g g g g g g            ; : : : : : > > > > > >   $ $ $ $  ?HUa      0 /+     :& & & &  # # # # # #LD D D D68 8 8 8(? ? ? ?0+* +* +* +*\9 9 9 9@" " " "*s s s s(!T !T !T !TH!X !X !X !X !X !Xr   