
    Yaj                       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mZmZmZmZ d dlmZ d d	lmZ d
 Zd Zdddddd dZd!dZej                            dg d          d"d            Zd!dZd!dZd!dZdS )#    )annotationsN)HTTPException)confirm_create_budget_account)confirm_create_category)import_budget_csv_text)batch_mark_candidatesconfirm_duplicate_overrideconfirm_transaction_candidatelist_transaction_candidates preview_batch_confirm_candidates)connect_memory)apply_migrationsc                 @    t                      } t          |            | S )N)r   r   )conns    3tests/unit/test_budget_duplicate_handling_hotfix.pydbr      s     DTK    c                p    t          | dddd          d         }t          | ddd          d         }||fS )	NzBudget KontocashCHF)nameaccount_typecurrency	entity_idzEssen & Haushaltexpense)r   category_type)r   r   )r   accountfoods      r   
setup_baser      sS    +D>[aot2u2uvv  xC  DG"42DW`)a)abbcnoDD=r   pendingz
M Windischmigros_receiptsstatuscategory_iddescriptionsource_typecidstrr#   r$   
str | Noner%   r&   returnNonec               j    |                      d||||||||f           |                                  d S )Nu  
        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,
            proposed_category_id, proposed_category_name, confidence, requires_review, status,
            classification, review_reason, raw_fingerprint, created_at, updated_at
        ) VALUES (?, '2026 Migros Einkäufe.csv', ?, ?, '2026-03-20', ?, 'M Windisch', '0.40', 'CHF', ?,
            CASE WHEN ? IS NULL THEN NULL ELSE 'Essen & Haushalt' END, '0.80', 0, ?, 'migros_receipt_food_household',
            'duplicate_detection_v1', ?, '2026-01-01T00:00:00', '2026-01-01T00:00:00')
        )executecommit)r   r'   r#   r$   r%   r&   s         r   	candidater/       sF    LL		 
c;[+vsS   	KKMMMMMr   c                    t                      } t          |           \  }}t          | dd|           t          | dd|           t          | dd|           t          | dd	|           d
 t          | d          D             }d t          | dd          D             }d t          | dd          D             }|dhk    sJ |dhk    sJ |h dk    sJ d S )Nopen1r    r#   r$   dup1duplicate_candidateblocked1duplicate_blocked	possible1possible_duplicatec                    h | ]
}|d          S transaction_candidate_id .0rs     r   	<setcomp>zetest_normal_review_and_migros_tab_exclude_duplicates_but_duplicates_tab_shows_them.<locals>.<setcomp>8   s    oooA!./ooor   2026)budget_yearc                    h | ]
}|d          S r:   r<   r=   s     r   r@   zetest_normal_review_and_migros_tab_exclude_duplicates_but_duplicates_tab_shows_them.<locals>.<setcomp>9   s    }}}A!./}}}r   migros)tabrB   c                    h | ]
}|d          S r:   r<   r=   s     r   r@   zetest_normal_review_and_migros_tab_exclude_duplicates_but_duplicates_tab_shows_them.<locals>.<setcomp>:   s0      E  E  EqQ12  E  E  Er   
duplicates>   r3   r5   r7   )r   r   r/   r   )r   _accountr   
normal_ids
migros_idsduplicate_idss         r   Rtest_normal_review_and_migros_tab_exclude_duplicates_but_duplicates_tab_shows_themrL   1   sI   44D*T"2"24dGI4@@@@dF#8dKKKKdJ':MMMMdK(<$OOOOoo9TUYgm9n9n9noooJ}}9TUY_gu{9|9|9|}}}J E  E<WX\bn  }C  =D  =D  =D  E  E  EM'""""'""""=========r   )r4   r6   r8   
supersededcovered_by_migrosignoredc           	        t                      }t          |          \  }}t          |d|  | |           t          j        t
                    5 }t          |d|  ||dd           d d d            n# 1 swxY w Y   |j        j        dk    sJ dt          |j        j
                  v sJ |                    d                                          d         dk    sJ d S )	Ncand_r2   rA   
account_idr$   rB   i  z2Kandidat ist als Duplikat/covered/ignored markiert(SELECT COUNT(*) FROM budget_transactionsr   )r   r   r/   pytestraisesr   r
   valuestatus_coder(   detailr-   fetchone)r#   r   r   r   excs        r   ?test_normal_confirm_guard_blocks_duplicate_and_covered_statusesr\   A   sS   44DD!1!1$d$F$$VFFFF	}	%	% C%d,<F,<,<Wei  {A  ?B  ?B  	C  	C  	CC C C C C C C C C C C C C C C 9 C''''?3syGWCXCXXXXX<<BCCLLNNqQUVVVVVVVs   A55A9<A9c            	     8   t                      } t          |           \  }}t          | dd|           t          j        t
                    5 }t          | d||dd           d d d            n# 1 swxY w Y   |j        j        dk    sJ t          | d||ddd          }|d	         d
k    sJ | 	                    d          
                                d         dk    sJ d | 	                    d                                          D             }d|v sJ d S )Nr3   r4   r2   rA   rR   i  z#Bewusst separater Bon trotz Treffer)rS   r$   rB   reasonr#   	confirmedrT   r      c                    h | ]
}|d          S )r   r<   r=   s     r   r@   zVtest_duplicate_override_requires_reason_and_audits_explicit_booking.<locals>.<setcomp>Z   s    [[[aQqT[[[r   zSELECT action FROM audit_log&candidate_duplicate_override_confirmed)r   r   r/   rU   rV   r   r	   rW   rX   r-   rZ   fetchall)r   r   r   r[   resultaudit_actionss         r   Ctest_duplicate_override_requires_reason_and_audits_explicit_bookingrf   N   s   44DD!1!1$dF#8dKKKK	}	%	% v"4X\ms1t1tuuuv v v v v v v v v v v v v v v9 C'''''fW]arx  Ej  7k  7k  l  lF({****<<BCCLLNNqQUVVVVV[[4<<0N#O#O#X#X#Z#Z[[[M3}DDDDDDs   A//A36A3c                    t                      } t          |           \  }}t          | dd|dd           t          | dd|           t          | ddg|d	
          }|d         dk    sJ |d         du sJ |d         dddgk    sJ t	          | ddgd||d         d	          }|d         dk    sJ |d         dk    sJ |d         dddgk    sJ |                     d                                          d         dk    sJ d S )Nok1r    zCoop Einkaufvisa_credit_cardr"   r3   r6   r2   rA   )candidate_idsrS   rB   countr`   can_confirmF	conflictsduplicate_candidate_blocked)candidate_idr^   confirm
preview_id)rj   actionrS   rq   rB   confirmed_countskipped_counterrors)ro   errorzVSELECT status FROM budget_transaction_candidates WHERE transaction_candidate_id='dup1'r   )r   r   r/   r   r   r-   rZ   )r   r   r   previewrd   s        r   Ctest_batch_confirm_skips_duplicates_and_reports_per_candidate_errorrx   ^   s   44DD!1!1$dE)>gyzzzzdF#6DIIII.tE6?_ftz{{{G7q    =!U****;VGd$e$e#fffff"4vyel  zA  BN  zO  ]c  d  d  dF#$))))/"a''''(B_ ` `aaaaa<<pqqzz||}~  DW  W  W  W  W  W  Wr   c                    t                      } t          |           \  }}d}t          | d|dd|          }t          | d|dd|          }|d         dk    sJ |d         d	k    sJ |                     d
                                          d	         dk    sJ |                     d                                          d	         dk    sJ d S )NzDatum;Zeit;Filiale;Kassennummer;Transaktionsnummer;Artikel;Menge;Aktion;Umsatz
02.01.2026;10:00;Migros Test;1;99;Artikel A;1;;1.10
02.01.2026;10:00;Migros Test;1;99;Artikel B;1;;2.20
r!   u   2026 Migros Einkäufe.csvF)source_file_labeldry_rundefault_category_idzsame receipt exported again.csvcandidate_countr`   r   zlSELECT COUNT(*) FROM budget_transaction_candidates WHERE source_type IN ('migros_receipts','migros_receipt')z-SELECT COUNT(*) FROM budget_import_line_items   )r   r   r   r-   rZ   )r   rH   r   csv_textfirstseconds         r   ^test_migros_receipt_key_import_is_idempotent_across_reimports_and_article_rows_are_detail_onlyr   o   sC   44D*T"2"24 LH"4):HXs  ~C  Y]  ^  ^  ^E#D*;XYz  EJ  `d  e  e  eF"#q((((#$))))<<  G  H  H  Q  Q  S  S  TU  V  Z[  [  [  [  [<<GHHQQSSTUVZ[[[[[[[r   )r'   r(   r#   r(   r$   r)   r%   r(   r&   r(   r*   r+   )r*   r+   )r#   r(   r*   r+   )
__future__r   rU   fastapir   'jarvis_finance.services.budget_accountsr   )jarvis_finance.services.budget_categoriesr   *jarvis_finance.services.budget_csv_importsr   &jarvis_finance.services.budget_importsr   r	   r
   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r   r/   rL   markparametrizer\   rf   rx   r   r<   r   r   <module>r      s   " " " " " "  ! ! ! ! ! ! Q Q Q Q Q Q M M M M M M M M M M M M              ; : : : : : > > > > > >     09TXmy  O`      "> > > >    $T  $T  $T  U  U	W 	W 	W U  U	WE E E E W W W W"
\ 
\ 
\ 
\ 
\ 
\r   