o
    0gh5                     @   sp   d dl Z d dlZd dlmZ d dlmZmZ d dlZd dlmZ d dl	m
Z
 e je jdd G dd	 d	eZdS )
    N)datetime)ListOptional)BaseBankStatementParser)Transactionz&%(asctime)s %(levelname)s: %(message)s)levelformatc                   @   s  e Zd ZdZedZd7ddZdede	e
 fdd	Zd
e	e	e  de	e	e  fddZde	e defddZde	e defddZde	e defddZed
e	e	e  de	e	e  fddZdede	e fddZd7ddZededefddZededefdd Zededefd!d"Zededefd#d$Zeded%ed&edefd'd(Zd)ed*ed+ed,ede
f
d-d.Zd/ed*ed0ed1ed2ed3ed4ede
fd5d6ZdS )8PrivatBankPdfParseru  
    Парсер PDF-выписок ПриватБанка.

    Алгоритм
    --------
    1. Читаем все таблицы со всех страниц.
    2. Отбрасываем заголовки, итоговые и балансовые строки.
    3. Склеиваем «ломаные» записи (там, где первая ячейка пуста).
    4. Разбираем каждую строку в `Transaction`.
       Если в назначении найдена комиссия — создаём вторую,
       отрицательную транзакцию.
    5. Удаляем дубли (номер + дата + сумма).
    u]   (?i)(?:ком[\s\.]*бан(?:ку)?|комiсiя)(?:\s+|\s*\.\s*|\s*\:\s*)([\d\.,]+)\s*грнreturnNc                 C   s(   d | _ d | _d | _d | _d | _d | _d S N)our_company_nameour_company_innour_company_accountour_bank_nameour_bank_edrpouZour_bank_branch)self r   2/var/www/html/app/parsers/privatbank_pdf_parser.py__init__0   s   
zPrivatBankPdfParser.__init__	file_pathc                 C   s0  t d|  g }t|}|jr| |jd  dd |jD }| | |}g }|D ]}|dgdt|  7 }|d pAd	 }|d pId	 }	|d pQd
d	d

dd}
| |d pad}td|
rmt|
nd }|d u sy|dkrz|szq/ddd |dd  D }tdd|	 }| |p| jpd}| |}| |||}|| j|| |	|||||d |dkrt| |dD ]\}}|| | d| | |	|| qq/W d    n1 sw   Y  t }|D ]}|j|j|jf}||vr|| || qt dt|  |S )Nu*   Начало парсинга файла: r   c                 S   sH   g | ] }|  p	g D ]}|D ]}td d |D rdd |D qq
qS )c                 s   s    | ]	}|pd   V  qdS ) N)strip.0cr   r   r   	<genexpr>I   s    z7PrivatBankPdfParser.parse.<locals>.<listcomp>.<genexpr>c                 S   s   g | ]}|pd qS )r   r   r   r   r   r   
<listcomp>E   s    z8PrivatBankPdfParser.parse.<locals>.<listcomp>.<listcomp>)Zextract_tablesany)r   pageZtblrowr   r   r   r   D   s    

z-PrivatBankPdfParser.parse.<locals>.<listcomp>r            ,.    z	-?[\d\.]+c                 s   s"    | ]}d  |p	d V  qdS )r%   r   N)join
splitlines)r   cellr   r   r   r   ^   s    
z,PrivatBankPdfParser.parse.<locals>.<genexpr>   \s+1)numberop_dateamountpayment_detailscontragent_namecontragent_inncontragent_accountZ_COMuL   Парсинг завершён, уникальных транзакций: ) loggingdebug
pdfplumberopenpages_extract_our_company_data_merge_continuation_rows_filter_rowslenr   replace_to_single_linere	fullmatchfloatr'   sub	_find_innr   _find_account_clean_nameappend_build_transaction_parse_date	enumerate_extract_commissions_build_commission_transactionsetr-   dater/   add)r   r   transactionspdfZall_rowsrowstmpr   
doc_numberdate_strZ
amount_strdetailsr/   Z
contr_fullZ	contr_innZ	contr_accZ
contr_nameidxZfeeseentxkeyr   r   r   parse;   sv   


@


zPrivatBankPdfParser.parserQ   c                 C   s   g }|D ]9}|dgdt |   }| |s | |s | |r!qddd |D }d|v r8d|v r8d|v r8q|| q|S )	Nr   r    r%   c                 s        | ]}|r|   V  qd S r   r   lowerr   r   r   r   r          z3PrivatBankPdfParser._filter_rows.<locals>.<genexpr>   найменування   рахунокu
   єдрпо)r<   _is_summary_line_looks_like_header_is_balance_liner'   rF   )r   rQ   filteredr   joinedr   r   r   r;      s   
z PrivatBankPdfParser._filter_rowsr   c                 C   s   |d pd  dS )Nr   r   u   За )r   
startswith)r   r   r   r   r   ra      s   z$PrivatBankPdfParser._is_summary_linec                 C   s<   d dd |D }td|rdS d|v od|v od|v S )	u  
        Определяем, является ли строка повторным заголовком таблицы.
        Учитываем как «большой» заголовок («Номер документа …»),
        так и подзаголовок блока «Реквізити контрагента»
        («Найменування / РНОКПП / Рахунок / Банк»).
        r%   c                 s   r[   r   r\   r   r   r   r   r      r^   z9PrivatBankPdfParser._looks_like_header.<locals>.<genexpr>u   (номер\s*документ|дата\s*та\s*час|призначення\s*платежу|реквізити\s*контрагента)Tr_   u   рнокппr`   )r'   r?   searchr   r   txtr   r   r   rb      s   z&PrivatBankPdfParser._looks_like_headerc                 C   s$   d dd |D }d|v pd|v S )Nr%   c                 s   r[   r   r\   r   r   r   r   r      r^   z7PrivatBankPdfParser._is_balance_line.<locals>.<genexpr>u   вхідний залишокu   вихідний залишок)r'   rh   r   r   r   rc      s   z$PrivatBankPdfParser._is_balance_linec                 C   s   g d }}| D ]d}|dgdt |  7 }|d pd r&|r#|| |}q|s+|}q|d p0dd |d p7d |d< |d p@dd |d pGd |d< |d pPdd |d pWd |d< |d p`dd |d pgd |d< q|rs|| |S )	Nr   r    r   r&   
r*         )r<   r   rF   )rQ   mergedcurrentr   r   r   r   r:      s"   

   "
z,PrivatBankPdfParser._merge_continuation_rowsrU   c              	   C   sL   g }| j |D ]}z|t|ddd W q ty#   Y qw |S )Nr!   r#   r$   )RE_COMMISSIONfinditerrF   rA   groupr=   
ValueError)r   rU   valsmr   r   r   rJ      s    z(PrivatBankPdfParser._extract_commissionsc                 C   s   |  pddD ]4}| }td| }r| \| _| _td| }r/| \| _| _	td| }r=|
d| _q	d S )Nr   rj   u0   (АТ\s+КБ\s+"[^"]+"),?\s*ЄДРПОУ\s+(\d+)u,   Клієнт\s+(.+?),\s+ЄДРПОУ\s+(\d+)u*   Поточний рахунок\s+№(\w+)r!   )Zextract_textsplitr   r?   rg   groupsr   r   r   r   rq   r   )r   r   linert   r   r   r   r9      s   z-PrivatBankPdfParser._extract_our_company_datatextc                 C   s   | r	d |  S dS )Nr%   r   )r'   ru   )rx   r   r   r   r>      s   z#PrivatBankPdfParser._to_single_linerT   c              	   C   sV   |  dd } dD ]}z	t| |W   S  ty   Y q
w td|   t S )Nrj   r%   )z%d.%m.%Y %H:%Mz%d.%m.%Yz%d/%m/%Y %H:%Mu3   Не удалось распарсить дату: )r=   r   r   strptimerr   r4   r5   now)rT   fmtr   r   r   rH      s   zPrivatBankPdfParser._parse_datec                 C   s8   t d|  }r|dS t d|  }r|dS dS )Nu   ЄДРПОУ:\s*(\d+)r!   z\b\d{8,10}\br   r   )r?   rg   rq   rx   rt   r   r   r   rC      s
   

zPrivatBankPdfParser._find_innc                 C   s@   t d|  }r|dddS t d|  }r|dS dS )Nu   Рахунок:\s*(UA[\w\d]+)r!   r%   r   z\b(UA\d{2,})\b)r?   rg   rq   r=   r|   r   r   r   rD     s
   
z!PrivatBankPdfParser._find_accountinnaccc                 C   sN   t dd| }|r||d}t dd|}|r||d}t dd| S )Nu   ЄДРПОУ:\s*\d+r   u   Рахунок:\s*UA[\w\d]+r+   r%   )r?   rB   r=   r   )rx   r}   r~   cleanedr   r   r   rE   	  s   zPrivatBankPdfParser._clean_namerS   r.   
comm_valueoriginal_detailsc           
      C   s|   | j pd}| jp	d}| jpd}| jpd}| jpd}	t||r!| nd t| ||||	|dd| dd |r:| dS d dS )NOUR_COMPANYr   u   ПРИВАТБАНКZ14360570u0   Комісія банку (з операції: )r-   rM   r/   	payer_inn
payer_namepayer_accountrecipient_innrecipient_namerecipient_accountr0   date_incomedate_outcome)r   r   r   r   r   r   rM   abs)
r   rS   r.   r   r   our_nameour_innour_accZ	bank_nameZbank_innr   r   r   rK     s*   






z1PrivatBankPdfParser._build_commission_transactionr-   r/   r0   r1   r2   r3   c                 C   s   | j pd| jpd| jpd}}	}
|dkr-|||}}}||	|
}}}| d }}n||	|
}}}|||}}}d | }}t||rL| nd |||||||| ||dS )Nr   r   r   r   )r   r   r   rM   r   r   )r   r-   r.   r/   r0   r1   r2   r3   r   r   r   r   r   Z	payer_accZ
recip_nameZ	recip_innZ	recip_accZdate_incZdate_outr   r   r   rG   1  s2   
z&PrivatBankPdfParser._build_transaction)r
   N)__name__
__module____qualname____doc__r?   compilero   r   strr   r   rZ   r;   boolra   rb   rc   staticmethodr:   rA   rJ   r9   r>   r   rH   rC   rD   rE   rK   rG   r   r   r   r   r	      sj    
"P$


	r	   )r4   r?   r   typingr   r   r6   app.parsers.base_parserr   app.models.transactionr   basicConfigDEBUGr	   r   r   r   r   <module>   s    
