
    >j                         d Z ddlZddlmc mZ ddlZddlm	Z	 ddl
mZ dZ ej                  d      d        Z G d	 d
      Z G d d      Z G d d      Zy)u   
Kohl's Rewards Visa (Capital One) statement parser tests — Story 9.8.

Fixture: tests/fixtures/pdfs/kohls_visa_0532.pdf
Source:  Kohl's Visa ending 0532, period Apr 26 – May 26, 2026
    N)Decimal)datez'tests/fixtures/pdfs/kohls_visa_0532.pdfmodule)scopec                  &    ddl m}   | t              S )Nr   parse)app.services.pdf_parsers.kohlsr	   FIXTURE_PATHr   s    @/var/www/html/financials/tests/test_parsers/test_kohls_parser.pyparsedr      s    4    c                   6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestKohlsParserBasicsc                    |\  }}g }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j
                  |      ndt        j
                  |      dz  }t        j                  d|       dz   d|iz  }t        t        j                  |            d x}}y )N==z%(py0)s == %(py3)serrorspy0py3zUnexpected errors: z
>assert %(py5)spy5)	
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanation)selfr   _r   @py_assert2@py_assert1@py_format4@py_format6s           r   test_no_errorsz$TestKohlsParserBasics.test_no_errors   ss    	6;v|;;;v;;;;;;v;;;v;;;;;;26(;;;;;;;r   c                 .   |\  }}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}}y )	N   r   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slentxns)r   py1r   py6assert %(py8)spy8)	r,   r   r   r   r   r   r   r!   r"   )	r#   r   r-   r$   r%   @py_assert5@py_assert4@py_format7@py_format9s	            r   test_transaction_countz,TestKohlsParserBasics.test_transaction_count   s    a4yAyA~yAss44yAr   c                    |\  }}|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}} y )Nkohlsr   )z.%(py2)s
{%(py2)s = %(py0)s.issuer
} == %(py5)str   py2r   assert %(py7)spy7)	issuerr   r   r   r   r   r   r!   r"   )
r#   r   r-   r$   r9   r&   r3   @py_assert3r(   @py_format8s
             r   test_issuer_is_kohlsz*TestKohlsParserBasics.test_issuer_is_kohls   s    a 	'A88&w&8w&&&&8w&&&&&&1&&&1&&&8&&&w&&&&&&&	'r   c                    |\  }}|D ]  }|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}} y )N  r   )zF%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.date
}.year
} == %(py7)sr9   )r   r;   py4r=   zassert %(py9)spy9)
r   yearr   r   r   r   r   r   r!   r"   )r#   r   r-   r$   r9   r&   r?   @py_assert6r2   r@   @py_format10s              r   test_all_dates_are_2026z-TestKohlsParserBasics.test_all_dates_are_2026"   s    a 	'A66&6;;&$&;$&&&&;$&&&&&&1&&&1&&&6&&&;&&&$&&&&&&&	'r   c           	         |\  }}|D ]6  }|j                   }d}t        |      }||kD  }|s
t        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                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}x}}9 y )	N0)>)zK%(py2)s
{%(py2)s = %(py0)s.amount
} > %(py8)s
{%(py8)s = %(py4)s(%(py6)s)
}r9   r   r   r;   rD   r/   r1   assert %(py10)spy10)
amountr   r   r   r   r   r   r   r!   r"   )r#   r   r-   r$   r9   r&   r2   @py_assert7r?   r5   @py_format11s              r   test_all_amounts_positivez/TestKohlsParserBasics.test_all_amounts_positive'   s    a 	+A88*c*gcl*8l****8l******1***1***8******g***g***c***l*******	+r   c           	         |\  }}|D ]E  }|j                   }t        |t              }|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                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d x}}H y )NzQassert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.amount
}, %(py4)s)
}
isinstancer9   r   )r   r.   r   rD   r/   )
rP   rU   r   r   r   r   r   r   r!   r"   )r#   r   r-   r$   r9   r%   r2   r4   s           r   test_all_amounts_are_decimalz2TestKohlsParserBasics.test_all_amounts_are_decimal,   s    a 	1Ahh0:h00000000:000:000000a000a000h0000000000000000000	1r   c           	         |\  }}|D ]  }g }|j                   }|}|r |j                   }t        |      }	d}
|	|
k(  }|}|sddt        j                         v st	        j
                  |      rt	        j                  |      ndt	        j                  |      dz  }|j                  |       |rt	        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                  |
      dz  }d	d
|iz  }|j                  |       t	        j                  |d      i z  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}	x}}
 y )N@   z'%(py4)s
{%(py4)s = %(py2)s.dedup_hash
}r9   )r;   rD   r   )zS%(py11)s
{%(py11)s = %(py6)s(%(py9)s
{%(py9)s = %(py7)s.dedup_hash
})
} == %(py14)sr,   )r/   r=   rE   py11py14z%(py16)spy16r   zassert %(py19)spy19)
dedup_hashr,   r   r   r   r   r   appendr   _format_boolopr!   r"   )r#   r   r-   r$   r9   r&   r?   @py_assert0@py_assert8@py_assert10@py_assert13@py_assert12@py_format5@py_format15@py_format17@py_format18@py_format20s                    r   test_all_have_dedup_hashz.TestKohlsParserBasics.test_all_have_dedup_hash1   s   a 	<A;1<<;<;<;C$5;;$5$;;;;;;;1;;;1;;;<;;;;<;;;$5;;;;;;C;;;C;;;;;;;;;;;;;;;$5;;;;;;;;;;;;;;;;;	<r   N)
__name__
__module____qualname__r)   r6   rA   rI   rS   rV   rj    r   r   r   r      s%    <'
'
+
1
<r   r   c                   0    e Zd Zd Zd Zd Zd Zd Zd Zy)TestKohlsParserTransactionsc           
         |\  }}t        d |D              }|j                  }d}t        |      }||k(  }|s
t        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                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }	dd	|	iz  }
t        t        j                  |
            d x}x}x}}|j                  }d
}d}d}t        |||      }||k(  }|s2t        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                  t              rt        j                  t              nd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}||u }|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}}y )Nc              3   Z   K   | ]#  }d |j                   j                         v s | % ywCHUNKYSNmerchant_rawupper.0r9   s     r   	<genexpr>zLTestKohlsParserTransactions.test_chunky_restaurant_charge.<locals>.<genexpr>:   $     MAann6J6J6L)LaM   !++z80.09r   zL%(py2)s
{%(py2)s = %(py0)s.amount
} == %(py8)s
{%(py8)s = %(py4)s(%(py6)s)
}chunkyr   rM   rN   rO   rC         z_%(py2)s
{%(py2)s = %(py0)s.date
} == %(py12)s
{%(py12)s = %(py4)s(%(py6)s, %(py8)s, %(py10)s)
}r   r   r;   rD   r/   r1   rO   py12assert %(py14)srZ   F)is)z1%(py2)s
{%(py2)s = %(py0)s.is_credit
} is %(py5)sr:   r<   r=   )nextrP   r   r   r   r   r   r   r   r!   r"   r   	is_credit)r#   r   r-   r$   r~   r&   r2   rQ   r?   r5   rR   @py_assert9@py_assert11@py_format13rf   r3   r(   r@   s                     r   test_chunky_restaurant_chargez9TestKohlsParserTransactions.test_chunky_restaurant_charge8   s   aMMM}}00 00} 00000} 0000000v000v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{{/4//B/d4B//{/////{///////v///v///{//////d///d///4//////B////////////(5(5((((5((((((v(((v((((((5(((((((r   c                 N   |\  }}t        d |D              }d}|j                  }||v}|st        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        t        j                  |	            d x}x}}d	}|j                  }||v}|st        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        t        j                  |	            d x}x}}y )
Nc              3   Z   K   | ]#  }d |j                   j                         v s | % ywrs   ru   rx   s     r   rz   zJTestKohlsParserTransactions.test_chunky_normalized_name.<locals>.<genexpr>A   r{   r|   
Manchester)not in)z?%(py1)s not in %(py5)s
{%(py5)s = %(py3)s.merchant_normalized
}r~   )r.   r   r   r<   r=   NH)
r   merchant_normalizedr   r   r   r   r   r   r!   r"   )
r#   r   r-   r$   r~   r`   r3   r%   r(   r@   s
             r   test_chunky_normalized_namez7TestKohlsParserTransactions.test_chunky_normalized_name?   s    aMMM=6#=#==|#=====|#====|======6===6===#========56555t55555t5555t5555556555655555555555r   c           
         |\  }}t        d |D              }|j                  }d}t        |      }||k(  }|s
t        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                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }	dd	|	iz  }
t        t        j                  |
            d x}x}x}}|j                  }d
}d}d}t        |||      }||k(  }|s2t        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                  t              rt        j                  t              nd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}||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}}y )Nc              3   Z   K   | ]#  }d |j                   j                         v s | % yw)	WALGREENSNru   rx   s     r   rz   zDTestKohlsParserTransactions.test_walgreens_charge.<locals>.<genexpr>H   s$     K[ANN4H4H4J%J!Kr|   z30.00r   r}   wgr   rM   rN   rO   rC         r   r   r   r   rZ   	Walgreensz;%(py2)s
{%(py2)s = %(py0)s.merchant_normalized
} == %(py5)sr:   r<   r=   r   rP   r   r   r   r   r   r   r   r!   r"   r   r   )r#   r   r-   r$   r   r&   r2   rQ   r?   r5   rR   r   r   r   rf   r3   r(   r@   s                     r   test_walgreens_chargez1TestKohlsParserTransactions.test_walgreens_chargeF   s   aKTKKyy,G,GG,,y,,,,,y,,,,,,,r,,,r,,,y,,,,,,G,,,G,,,G,,,,,,,,,,,ww*t*Q**$tQ**w*****w*******r***r***w******$***$***t***Q***************%%44%4444%444444r444r444%4444444444r   c           
         |\  }}t        d |D              }|j                  }d}t        |      }||k(  }|s
t        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                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }	dd	|	iz  }
t        t        j                  |
            d x}x}x}}|j                  }d
}d}d}t        |||      }||k(  }|s2t        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                  t              rt        j                  t              nd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}||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}}y )Nc              3   Z   K   | ]#  }d |j                   j                         v s | % yw)KOHLSNru   rx   s     r   rz   z@TestKohlsParserTransactions.test_kohls_charge.<locals>.<genexpr>O   s$     J11>>3G3G3I(IQJr|   z29.63r   r}   r8   r   rM   rN   rO   rC   r      r   r   r   r   rZ   zKohl'sr   r:   r<   r=   r   )r#   r   r-   r$   r8   r&   r2   rQ   r?   r5   rR   r   r   r   rf   r3   r(   r@   s                     r   test_kohls_chargez-TestKohlsParserTransactions.test_kohls_chargeM   s   aJJJ||/w/ww//|/////|///////u///u///|//////w///w///w///////////zz-$--1-T$1--z-----z-------u---u---z------T---T---$------1------------((4H4(H4444(H444444u444u444(444H4444444r   c                    |\  }}|D cg c]  }|j                   s| }}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}}yc c}w )u7   Statement has $0 payments — no credits should appear.r   r   creditsr   assert %(py5)sr   N)	r   r   r   r   r   r   r   r!   r"   )
r#   r   r-   r$   r9   r   r%   r&   r'   r(   s
             r   test_no_payments_extractedz6TestKohlsParserTransactions.test_no_payments_extractedT   s    a"2akk122w"}w"ww" 3s
   C	C	c                 R   |\  }}t        d |D              }d}t        |      }||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                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }dd	|iz  }	t        t        j                  |	            d
x}x}}y
)z&Statement shows Transactions: $139.72.c              3   N   K   | ]  }|j                   r|j                    y w)N)r   rP   rx   s     r   rz   zKTestKohlsParserTransactions.test_total_matches_statement.<locals>.<genexpr>]   s     >!++AHH>s   %%z139.72r   )z0%(py0)s == %(py6)s
{%(py6)s = %(py2)s(%(py4)s)
}totalr   )r   r;   rD   r/   r0   r1   N)
sumr   r   r   r   r   r   r   r!   r"   )
r#   r   r-   r$   r   r?   r2   r&   r4   r5   s
             r   test_total_matches_statementz8TestKohlsParserTransactions.test_total_matches_statementZ   s    a>d>> ()))u)))))u)))))))u)))u)))))))))))))))))))))))r   N)	rk   rl   rm   r   r   r   r   r   r   rn   r   r   rp   rp   7   s     )655*r   rp   c                       e Zd Zd Zy)TestKohlsIssuerDetectionc                 ^   dd l }ddlm} |j                  t              5 }|j
                  d   j                         xs d}d 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}}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}}y # 1 sw Y   bxY w)Nr   )detect_issuer r8   r   r   r>   r   r   r   gffffff?)>=)z%(py0)s >= %(py3)sconf)
pdfplumber!app.services.pdf_parsers.detectorr   openr   pagesextract_textr   r   r   r   r   r   r!   r"   )r#   r   r   pdftextr>   r   r%   r&   r'   r(   s              r   test_detects_kohls_from_pdfz4TestKohlsIssuerDetection.test_detects_kohls_from_pdfb   s   C__\* 	5c99Q<,,.4"D	5$T*  v    v      v   v          tt|ttttt		5 	5s   "F""F,N)rk   rl   rm   r   rn   r   r   r   r   a   s    r   r   )__doc__builtinsr   _pytest.assertion.rewrite	assertionrewriter   pytestdecimalr   datetimer   r   fixturer   r   rp   r   rn   r   r   <module>r      s]       8 h  
 <  <F'* '*T r   