o
    gcIhH                     @   sj  d Z ddlmZmZ ddlmZmZmZ ddlmZmZm	Z	m
Z
mZmZ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 ed
eZededdd Zdd Zejdddgdeddd Zejdddgdeddd Zejddgdeddd Zededdd Z ed edd!d" Z!ed#edd$d% Z"d&S )'u   
Адмін-панель керування користувачами.
Вхід лише для ролі 'admin' (див. @role_required).
    )jsonify	send_file)datedatetime	timedelta)	Blueprintrender_templaterequestflashredirecturl_forcurrent_app)current_user)get_db_connection)role_required)hash_password)StatsServiceadmin_bp/adminc                     s  t jdd } t jjddtd d} d | }t }| T}| r2d|  d}|d|f n|d	 | }| rKd|  d}|d
|f n|d |	 d }| rb|d|||f n|d||f | }W d   n1 sxw   Y  |
  || || rdnd  || dk k  d  d df fdd	d	}	t }| }|d | }
W d   n1 sw   Y  |
  dd |
D }td||| |	t |dS )uL  
    Ділимо всі записи з таблиці users на дві групи:
      • PF-клієнти  (is_pf_client = 1) — без пагінації
      • Зовнішні    (is_pf_client = 0) — з пагінацією
    А також підтримуємо пошук (argument 'search') за username.
    search page   type   %zVSELECT * FROM users WHERE is_pf_client=1 AND username LIKE %s ORDER BY created_at DESCzASELECT * FROM users WHERE is_pf_client=1 ORDER BY created_at DESCzKSELECT COUNT(*) AS cnt FROM users WHERE is_pf_client=0 AND username LIKE %sz6SELECT COUNT(*) AS cnt FROM users WHERE is_pf_client=0cntz
                SELECT *
                  FROM users
                 WHERE is_pf_client=0
                   AND username LIKE %s
                 ORDER BY created_at DESC
                 LIMIT %s OFFSET %s
                z
                SELECT *
                  FROM users
                 WHERE is_pf_client=0
                 ORDER BY created_at DESC
                 LIMIT %s OFFSET %s
                Nr   c                    s   t  | |S )N)_iter_pages)lrr   pages ,/var/www/html/app/blueprints/admin/routes.py<lambda>n   s    zadmin_panel.<locals>.<lambda>)	r   per_pagetotalr#   has_prevhas_nextprev_numnext_num
iter_pagesQSELECT pf_company_id AS id, name, pay_status FROM planfix_companies ORDER BY namec                 S   s   i | ]}|d  |qS )idr$   .0rowr$   r$   r%   
<dictcomp>}   s    zadmin_panel.<locals>.<dictcomp>z
admin.html)
pf_clientsext_clientsr   
paginationtodaypf_map)r	   argsgetstripintr   cursorexecutefetchallfetchonecloser   r   r7   )Zsearch_queryr'   offsetconncurZlike_patternr4   Z	total_extr5   r6   Zpf_rowsr8   r$   r"   r%   admin_panel   s   



5

rE   c                 c   sl    d}t d|d D ])}||ks%| d |  k r| d k s%n ||| kr3|d |kr.dV  |V  |}q
dS )uU   Генерує послідовність сторінок для пагінації.r   r      N)range)Zcurrent_pageleftrightZtotal_pageslastnumr$   r$   r%   r      s   r   z/create_userGETPOST)methodsc                  C   s@  t jdkrt jddk} t jdd }t jdd}t jdd}|r(|s2td	d
 tt jS | rQt jd}|sFtdd
 tt jS dt|d}}}nt jdd }|sftdd
 tt jS d\}}t jdd}d	t j
d}	tjd |}
|
du rdn|
}t }|tdd }|tdd }t|}t }| "}|d||||||||||	||f ttjd| W d   n1 sw   Y  |  |  tdd ttdS t &}| }|d | }W d   n	1 sw   Y  W d   n	1 sw   Y  td tjd! |d"S )#u   
    • Зовнішній клієнт  → place = вільний текст, is_pf_client=0.
    • Клієнт PlanFix    → place пусте,  is_pf_client=1, pf_company_id = id договору.
    rM   is_our_clientonusernamer   passwordroleclientu-   Заповніть логін і парольwarningpf_contract_id%   Оберіть договір PlanFixr   placeu8   Поле «Заклад (place)» обовʼязкове)r   Nsubscription_planstart,available_banksPLAN_LIMITSNi?B    daysaw  
                INSERT INTO users (
                    username, password_hash, role, place,
                    payment_date, created_at,
                    subscription_plan, parse_count, parse_reset_date,
                    available_banks,
                    is_pf_client, pf_company_id
                ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
                create_useru'   Користувача створеноsuccessadmin_bp.admin_panelr.   zcreate_user.html	ALL_BANKS)	all_banks	contracts)r	   methodformr:   r;   r
   r   urlr<   joingetlistr   configr   utcnowr   r   r   r=   r>   r   logr   r/   commitrA   r   r?   r   )is_pfrQ   rR   rS   pf_idis_pf_clientpf_company_idrX   Zplanr\   limitparse_countnowpayment_dateZparse_resetZpw_hashrC   rD   rf   r$   r$   r%   ra      sf   





 ra   z/edit_user/<int:user_id>c                 C   s  t  '}| }|d| f | }W d    n1 sw   Y  W d    n1 s-w   Y  |s?tdd ttdS tjdkrJtj	
ddk}tj	
d|d  }tj	
d	d
}tj	
d|d }|sttdd ttjS |rtj	
d}|stdd ttjS d}	t|}
d
}ntj	
dd
 }|stdd ttjS d}	d }
tj	
d|d }ttj	
d|d }dtj	d}tj	
dd
}|d }|rzt|d}W n ty   tdd Y nw t  @}| +}|d||||||||	|
| f
 |rt|}|d|| f |  W d    n	1 s"w   Y  W d    n	1 s2w   Y  ttjd| tdd ttdS t  &}| }|d | }W d    n	1 sgw   Y  W d    n	1 sww   Y  t|
d }	td!|tjd" ||	d#S )$NzSELECT * FROM users WHERE id=%su,   Користувача не знайденоrU   rc   rM   rO   rP   rQ   Znew_passwordr   rS   u?   Поле «Логін» не може бути порожнімrV   rW   r   rX   ue   Поле «Заклад (place)» обовʼязкове для зовнішнього клієнтаr   rY   ru   r[   r\   rw   z%Y-%m-%dT%H:%Mu@   Невірний формат дати «Оплачено до»a  
                UPDATE users
                   SET username=%s,
                       role=%s,
                       place=%s,
                       subscription_plan=%s,
                       payment_date=%s,
                       parse_count=%s,
                       available_banks=%s,
                       is_pf_client=%s,
                       pf_company_id=%s
                 WHERE id=%s
                z-UPDATE users SET password_hash=%s WHERE id=%s	edit_useru   Зміни збереженоrb   z
            SELECT pf_company_id AS id, name, pay_status
              FROM planfix_companies
             ORDER BY name
        rr   zedit_user.htmlrd   )userre   rf   rO   )r   r=   r>   r@   r
   r   r   r	   rg   rh   r:   r;   ri   r<   rj   rk   r   strptime
ValueErrorr   ro   r   rn   r   r/   r?   boolr   r   rl   )user_idrC   rD   ry   rp   rQ   Znew_passrS   rq   rr   rs   rX   rY   ru   r\   Zpay_date_strZpay_datenew_hashrf   r$   r$   r%   rx      s   
 







  


 	rx   z/delete_user/<int:user_id>c                 C   sb   t  }| }|d| f W d    n1 sw   Y  |  |  tdd ttdS )NzDELETE FROM users WHERE id=%su'   Користувача видаленоinforc   )r   r=   r>   ro   rA   r
   r   r   )r}   rC   rD   r$   r$   r%   delete_user_  s   

r   z
/dashboardc               	   C   s  t  } t d}t d}t  }tjjddtd}d}|d | }t	 }|
 }|d | d }	|d	||f | }
W d    n1 sLw   Y  |  |	| |	| r^dnd
 }|||	||dk||k |d |d d}| ||||
|d}tdi |S )Nr   r^   r   r   r   
   z(SELECT COUNT(*) AS cnt FROM activity_logr   ad  
            SELECT 
              a.created_at AS created_at, 
              u.username    AS username, 
              a.action      AS action, 
              a.obj_info    AS obj_info
            FROM activity_log AS a
            LEFT JOIN users AS u ON u.id = a.user_id
            ORDER BY a.created_at DESC
            LIMIT %s OFFSET %s
            r   )r   r'   r(   r#   r)   r*   r+   r,   )kpi	top_usersdaily_statsplans_breakdownlast_eventsr6   admin_dashboard.html)r   )r   Zkpi_countersr   daily_generationsr   r	   r9   r:   r<   r   r=   r>   r@   r?   rA   r   )r   r   r   r   r   r'   rB   rC   rD   r(   r   r#   r6   ctxr$   r$   r%   admin_dashboardl  sH   




r   z/dashboard/datac                  C   sR   t jjddtd} tdt| d} t| }dd |D dd |D d	}t|S )
u_  
    Возвращает JSON статистики генераций за запрошенный период.

    Query-param:
        days (int) – кол-во дней (7 / 30 / 90). По умолчанию 30.

    Response-schema:
        {
          "labels": ["2025-06-01", "2025-06-02", ...],
          "values": [3, 7, ...]
        }
    r`   r^   r   r   m  c                 S   s   g | ]}|d    qS )day)	isoformatr0   r$   r$   r%   
<listcomp>  s    z(admin_dashboard_data.<locals>.<listcomp>c                 S   s   g | ]}|d  qS )r   r$   r0   r$   r$   r%   r     s    )labelsvalues)	r	   r9   r:   r<   maxminr   r   r   )r`   statspayloadr$   r$   r%   admin_dashboard_data  s   
r   z/dashboard/export_xlsxc                  C   s   t jdd} t| ddddS )u   
    Генерує Excel-файл (xlsx) з даними генерацій за останні 365 днів
    і видає його як завантаження.
    r   r_   zAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetTzgenerations_last365.xlsx)mimetypeas_attachmentdownload_name)r   Zxlsx_daily_generationsr   )Zmemr$   r$   r%   admin_dashboard_xlsx  s   r   N)#__doc__flaskr   r   r   r   r   r   r   r	   r
   r   r   r   flask_loginr   app.databaser   Zapp.security.rbacr   app.security.passwordsr   Zapp.services.stats_servicer   __name__r   routerE   r   ra   rx   r   r   r   r   r$   r$   r$   r%   <module>   s@   $	
lNt=