U
    hV                     @   s   d Z ddlZddlmZmZ ddlmZmZmZmZ ddl	m
Z
mZmZmZmZmZmZmZ ddlmZ ddlmZmZ ddlmZ dd	lmZ eeZe ZG d
d deZG dd dZ dS )uX   
Модуль для работы с базой данных AI-КАЛОРИЯ бота
    N)datetime	timedelta)ListDictAnyOptional)create_engineColumnIntegerStringFloatDateTimeTextfunc)declarative_base)sessionmakerSession)SQLAlchemyError)Configc                   @   s   e Zd ZdZdZeedddZeedddZee	dddZ
ee	d	ddZeeddZee	d
ddZeeddZeeejdddZeeddZdd ZdS )
FoodRecordu#   Модель записи о едеZfood_recordsT)Zprimary_keyZautoincrementF)nullableindex   )r   i  2   )defaultr   r   c              	   C   s&   d| j  d| j d| j d| j d	S )Nz<FoodRecord(id=z
, user_id=z, food='z', calories=z)>)iduser_id	food_namecaloriesself r!   K/var/www/u0236315/data/www/consultsolution.ru/ai-calories-app/./database.py__repr__$   s    zFoodRecord.__repr__N)__name__
__module____qualname____doc__Z__tablename__r	   r
   r   r   r   usernamer   r   amountunitr   r   r   utcnow
created_atr   raw_textr#   r!   r!   r!   r"   r      s   r   c                
   @   s  e Zd ZdZdd Zdd ZedddZd3ee	e	e
e	e
e	ed
ddZeeee	ef  dddZd4eeeee	ef  dddZeedddZd5eeee	ef dddZd6ee	eeee	ef  dddZeeee	ef  dddZeeee	ef  dddZd7eeeee	ef  dd d!Zeeed"d#d$Zeeeee	ef  d"d%d&Zeee
ed'd(d)Zeeeed*d+d,Zd8eeeee	ef d.d/d0Zd1d2 Z d	S )9DatabaseManageru&   Менеджер базы данныхc                 C   s   d | _ d | _d| _d S )NF)engineSessionLocal_initializedr   r!   r!   r"   __init__*   s    zDatabaseManager.__init__c              
   C   s   z`t  }t|d |d |d |d d| _tdd| jd| _tjj| jd d	| _	t
d
 W n4 tk
r } zt
d|   W 5 d}~X Y nX dS )u0   Инициализация базы данныхurl	pool_sizemax_overflowecho)r4   r5   r6   F)Z
autocommitZ	autoflushbind)r7   TuE   База данных успешно инициализированаuF   Ошибка при инициализации базы данных: N)r   get_database_configr   r/   r   r0   BaseZmetadataZ
create_allr1   loggerinfo	Exceptionerror)r    Z	db_configer!   r!   r"   init_database/   s    zDatabaseManager.init_database)returnc                 C   s   | j std|  S )u5   Получение сессии базы данныхum   База данных не инициализирована. Вызовите init_database() сначала.)r1   RuntimeErrorr0   r   r!   r!   r"   get_sessionH   s    zDatabaseManager.get_sessionN)r   r(   r   r)   r*   r   r-   r@   c              
   C   s   |   }zzTt|||||||d}	||	 |  |	j}
td|
 d| d|  |
W W HS  tk
r } z$|	  t
d| d|   W 5 d}~X Y nX W 5 |  X dS )u+   Добавление записи о еде)r   r(   r   r)   r*   r   r-   u    Добавлена запись !    для пользователя : uV   Ошибка при добавлении записи для пользователя N)rB   closer   addcommitr   r:   r;   r   rollbackr=   )r    r   r(   r   r)   r*   r   r-   sessionrecord	record_idr>   r!   r!   r"   add_food_recordO   s*    


zDatabaseManager.add_food_record)r   r@   c              
   C   s  |   }zzX|ttjtj|k	 }|dkrFW W fdS |t
tjtj|k	 pjd}|ttj|ktj  }t tdd }|t
tjtj|ktj|k	 pd}|dkr|d nd}|tjttjdtj|ktjttj d }	|t|||rN|jdnddd	 |	D d
W W BS  tk
r }
 ztd| d|
   W 5 d}
~
X Y nX W 5 |  X dS )u@   Получение статистики пользователяr   N   )dayscount   z%d.%m.%Y %H:%Mc                 S   s   g | ]}|j |jd qS )r   rO   rQ   ).0foodr!   r!   r"   
<listcomp>   s     z2DatabaseManager.get_user_stats.<locals>.<listcomp>)total_recordstotal_caloriesavg_calories_per_daylast_record_date	top_foodsu\   Ошибка при получении статистики для пользователя rD   )rB   rE   queryr   rO   r   r   filterr   scalarsumr   order_byr,   descfirstr   r+   r   r   labelZgroup_bylimitallfloatstrftimer   r:   r=   )r    r   rI   rU   rV   Zlast_recordZthirty_days_agoZrecent_caloriesrW   rY   r>   r!   r!   r"   get_user_statsm   s^    

zDatabaseManager.get_user_stats
   )r   rb   r@   c              
   C   s   |   }zz@|ttj|ktj 	|
 }dd |D W W @S  tk
r } ztd| d|   W 5 d}~X Y nX W 5 |  X dS )uI   Получение истории записей пользователяc              
   S   s.   g | ]&}|j |j|j|j|j|j|jd qS )r   r   r)   r*   r   r,   r-   rh   rR   rJ   r!   r!   r"   rT      s   
z4DatabaseManager.get_user_history.<locals>.<listcomp>uV   Ошибка при получении истории для пользователя rD   NrB   rE   rZ   r   r[   r   r^   r,   r_   rb   rc   r   r:   r=   r    r   rb   rI   recordsr>   r!   r!   r"   get_user_history   s     

z DatabaseManager.get_user_historyc              
   C   s   |   }zzB|ttj|k }|  t	d| d|  |W W HS  t
k
r } z$|  td| d|   W 5 d}~X Y nX W 5 |  X dS )u6   Очистка истории пользователяu   Удалено u0    записей для пользователя uR   Ошибка при очистке истории для пользователя rD   N)rB   rE   rZ   r   r[   r   deleterG   r:   r;   r   rH   r=   )r    r   rI   Zdeleted_countr>   r!   r!   r"   clear_user_history   s    

z"DatabaseManager.clear_user_history)r   dater@   c           	   
   C   s   |dkrt   }|  }zzt |t j }t |t j }|	t
t
j|kt
j|kt
j|k }tdd |D }|dt||dd |D dW W @S  tk
r } ztd| d	|   W 5 d}~X Y nX W 5 |  X dS )
u5   Получение статистики за деньNc                 s   s   | ]}|j V  qd S )N)r   ri   r!   r!   r"   	<genexpr>   s     z2DatabaseManager.get_daily_stats.<locals>.<genexpr>z%d.%m.%Yc              	   S   s,   g | ]$}|j |j|j|j|jd dqS )z%H:%M)r   r)   r*   r   time)r   r)   r*   r   r,   re   ri   r!   r!   r"   rT      s   
z3DatabaseManager.get_daily_stats.<locals>.<listcomp>)rp   records_countrV   rl   uk   Ошибка при получении дневной статистики для пользователя rD   )r   r+   rp   rB   rE   combineminrr   maxrZ   r   r[   r   r,   rc   r]   re   lenr   r:   r=   )	r    r   rp   rI   
start_dateend_daterl   rV   r>   r!   r!   r"   get_daily_stats   s.    
zDatabaseManager.get_daily_stats)r   rZ   rb   r@   c              
   C   s   |   }zzR|ttj|ktjd| dtj	
 | }dd |D W W @S  tk
r } ztd| d|   W 5 d}~X Y nX W 5 |  X dS )u6   Поиск записей по названию еды%c              	   S   s*   g | ]"}|j |j|j|j|j|jd qS r   r   r)   r*   r   r,   r}   ri   r!   r!   r"   rT     s   	z7DatabaseManager.search_food_records.<locals>.<listcomp>uP   Ошибка при поиске записей для пользователя rD   N)rB   rE   rZ   r   r[   r   r   Ziliker^   r,   r_   rb   rc   r   r:   r=   )r    r   rZ   rb   rI   rl   r>   r!   r!   r"   search_food_records   s"    
	z#DatabaseManager.search_food_recordsc              
   C   s   |   }zzj|ttj|ktj 	 }|s@W W xdS ||j
|j|ttjtj|k dW W @S  tk
r } ztd| d|   W 5 d}~X Y nX W 5 |  X dS )uC   Получение информации о пользователеN)r   r(   Zfirst_record_daterU   uX   Ошибка при получении информации о пользователе rD   )rB   rE   rZ   r   r[   r   r^   r,   Zascr`   r(   r   rO   r   r\   r   r:   r=   )r    r   rI   Zfirst_recordr>   r!   r!   r"   get_user_by_id  s(    

	zDatabaseManager.get_user_by_idc                 C   s   |   }zznt|tj }t|tj }|t	tj
|ktj|ktj|ktj  }dd |D W W PS  tk
r } z,td| d| d|  g  W Y W S d}~X Y nX W 5 |  X dS )uY   Получить записи пользователя за конкретную датуc              	   S   s*   g | ]"}|j |j|j|j|j|jd qS r|   r}   ri   r!   r!   r"   rT   >  s   	z<DatabaseManager.get_user_records_by_date.<locals>.<listcomp>uD   Ошибка при получении записей за дату rC   rD   N)rB   rE   r   rt   ru   rr   rv   rZ   r   r[   r   r,   r^   r_   rc   r   r:   r=   )r    r   target_daterI   rx   ry   rl   r>   r!   r!   r"   get_user_records_by_date0  s$    
	"z(DatabaseManager.get_user_records_by_datec              
   C   s   |   }zz@|ttj|ktj 	|
 }dd |D W W JS  tk
r } z&td| d|  g  W Y W S d}~X Y nX W 5 |  X dS )uI   Получить последние записи пользователяc              	   S   s*   g | ]"}|j |j|j|j|j|jd qS r|   r}   ri   r!   r!   r"   rT   X  s   	z;DatabaseManager.get_user_recent_records.<locals>.<listcomp>ui   Ошибка при получении последних записей для пользователя rD   Nrj   rk   r!   r!   r"   get_user_recent_recordsP  s     
	"z'DatabaseManager.get_user_recent_records)rK   r   r@   c                 C   s   |   }zzx|ttj|ktj|k }|sRt	d| d|  W W dS |
| |  td| d|  W W XdS  tk
r } z2|  td| d| d|  W Y W dS d	}~X Y nX W 5 |  X d	S )
u:   Удалить конкретную запись о еде   Запись 5    не найдена для пользователя Fu0    удалена для пользователя Tu2   Ошибка при удалении записи rC   rD   N)rB   rE   rZ   r   r[   r   r   r`   r:   warningrn   rG   r;   r   rH   r=   r    rK   r   rI   rJ   r>   r!   r!   r"   delete_food_recordj  s$    



 z"DatabaseManager.delete_food_recordc                 C   s   |   }zzT|ttj|ktj|k }|s<W W tdS |j|j|j	|j
|j|jdW W NS  tk
r } z*td| d| d|  W Y W dS d}~X Y nX W 5 |  X dS )u\   Получить запись по ID для конкретного пользователяNr}   u4   Ошибка при получении записи rC   rD   )rB   rE   rZ   r   r[   r   r   r`   r   r)   r*   r   r,   r   r:   r=   r   r!   r!   r"   get_record_by_id  s&    

	 z DatabaseManager.get_record_by_id)rK   r   new_caloriesr@   c                 C   s   |   }zzz|ttj|ktj|k }|sRt	d| d|  W W dS ||_
|  td| d| d|  W W XdS  tk
r } z2|  td| d| d	|  W Y W dS d
}~X Y nX W 5 |  X d
S )u,   Обновить калории записиr   r   Fu   Калории записи u    обновлены на rC   TuE   Ошибка при обновлении калорий записи rD   N)rB   rE   rZ   r   r[   r   r   r`   r:   r   r   rG   r;   r   rH   r=   )r    rK   r   r   rI   rJ   r>   r!   r!   r"   update_record_calories  s$    


 z&DatabaseManager.update_record_calories)rK   r   changesr@   c                 C   s  |   }zz|ttj|ktj|k }|sTt	d| d|  W W dS d|krf|d |_
d|krx|d |_d|kr|d |_|  td| d| d|  W W Zd	S  tk
r } z2|  td
| d| d|  W Y W dS d}~X Y nX W 5 |  X dS )u7   Обновить запись с изменениямиr   r   Fr)   r*   r   u4    обновлена для пользователя rD   Tu6   Ошибка при обновлении записи rC   N)rB   rE   rZ   r   r[   r   r   r`   r:   r   r)   r*   r   rG   r;   r   rH   r=   )r    rK   r   r   rI   rJ   r>   r!   r!   r"   update_record  s.    





 zDatabaseManager.update_record   )r   pageper_pager@   c           
   
   C   s   |   }zz|ttj|k }|d | }|ttj|ktj	 
|| }|| d | }dd |D |||||dk||k ddW W @S  tk
r }	 ztd| d|	   W 5 d}	~	X Y nX W 5 |  X dS )	uR   Получение записей пользователя с пагинациейr   c              	   S   s*   g | ]"}|j |j|j|j|j|jd qS r|   r}   ri   r!   r!   r"   rT     s   	z>DatabaseManager.get_user_records_paginated.<locals>.<listcomp>)current_pagetotal_pagesrU   r   has_prevhas_next)rl   
paginationun   Ошибка при получении записей с пагинацией для пользователя rD   N)rB   rE   rZ   r   r[   r   rO   r^   r,   r_   offsetrb   rc   r   r:   r=   )
r    r   r   r   rI   total_countr   rl   r   r>   r!   r!   r"   get_user_records_paginated  s>    

	z*DatabaseManager.get_user_records_paginatedc                 C   s   | j r| j   td dS )u@   Закрытие соединения с базой данныхu>   Соединение с базой данных закрытоN)r/   Zdisposer:   r;   r   r!   r!   r"   rE     s    
zDatabaseManager.close)N)rg   )N)rg   )rg   )r   rg   )!r$   r%   r&   r'   r2   r?   r   rB   intstrrd   rL   r   r   r   rf   r   rm   ro   r   rz   r~   r   r   r   boolr   r   r   dictr   r   rE   r!   r!   r!   r"   r.   '   s4        7 ("  "0r.   )!r'   loggingr   r   typingr   r   r   r   Z
sqlalchemyr   r	   r
   r   r   r   r   r   Zsqlalchemy.ext.declarativer   Zsqlalchemy.ormr   r   Zsqlalchemy.excr   configr   	getLoggerr$   r:   r9   r   r.   r!   r!   r!   r"   <module>   s   (
