
    C^i                       d dl 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mZmZmZ d dlmZ d dlmZmZ d dlZd dlZd dlmZ d d	lmZmZmZmZ d d
lmZ d dlm Z  d dl!m"Z"m#Z# dede$fdZ% eddg      Z& G d de      Z' G d de      Z( G d de      Z) G d de      Z* G d de      Z+e&jY                  dee*          ee       ee      ddfded ed!ee$   d"ee-   fd#       Z.e&j_                  de*d$%       ee       ee      fd&e(ded efd'       Z0e&jY                  d(e*       ee       ee      fd)e1ded efd*       Z2e&jg                  d(e*       ee       ee      fd)e1d&e)ded efd+       Z4e&jk                  d(       ee       ee      fd)e1ded efd,       Z6e&j_                  d-       ee       ee      fd)e1d.eded efd/       Z7e&j_                  d0       ee       ee      d1fd)e1d.eded ed2e$f
d3       Z8e&jY                  d4       ee       ee      fd)e1ded efd5       Z9e&jY                  d6ee+          ee       ee      d7d fd)e1ded ed8e1d9e1f
d:       Z: G d; d<e      Z; G d= d>e      Z< G d? d@e      Z= G dA dBe      Z>e&jY                  dCee;         dD        Z?e&j_                  dE       ee       ee      fdFe>ded efdG       Z@e&j_                  dH       ee       ee      fd)e1ded efdI       ZAe&j_                  dJ       ee       ee      fd)e1ded efdK       ZBe&j_                  dL       ee       ee      fdMe$dNe$d)e1ded ef
dO       ZC	 ddPe$dQe$dRe$dNe$dSe$dz  deDfdTZE	 ddPe$dQe$dRe$dNe$dSe$dz  deDfdUZFe&jY                  dV      dMe$fdW       ZGe&j_                  dXe=d$%       ee       ee      fd&e<ded efdY       ZHe&jY                  dZe=       ee       ee      fd)e1ded efd[       ZIe&j_                  d\      d ee       ee      fd)e1d]eDded efd^       ZJdPe$d_e$d`e$dae$deDdz  f
dbZKdPe$d_e$d`e$dae$deDdz  f
dcZLe&j_                  dd       ee       ee      fd)e1ded efde       ZM G df dge      ZNe&j_                  dh       ee       ee      fdFeNded efdi       ZOe&jY                  dj       ee       ee      fded efdk       ZPd edle1dmee1   de1fdnZQe&jY                  do       ee       ee      fd)e1ded efdp       ZRdqe$dre$dee$ef   fdsZSdte$deee$e$f      fduZTdte$dee$   fdvZUd edwe1dre$dxe'dee   f
dyZVd edwe1dre$dxe'de$f
dzZWe&jY                  d{       ed|d}~       ed|d~       ed       ed       ee       ee      fdNe$de1dee$   dee$   ded efd       ZXe&j_                  d       ee      fd)e1dFed efd       ZYy)    )	APIRouterDependsHTTPExceptionBackgroundTasksQueryRequest)Session)and_)ListOptionalDictAnydatetime)	BaseModel
ConfigDictN)get_db)UserIntegrationIntegrationSyncLogCRMFieldMapping)get_current_userget_settings)encrypt_tokendecrypt_tokenintegrationreturnc                    | j                   xs i }| j                  dk(  ry| j                  dk(  rg d}|D ]  }|j                  |      r y n-| j                  dk(  rg d}|D ]  }|j                  |      r y |j                  d      sy| j                  r>| j                  r2d	d
lm} t        j                         | j                  z
   |d      k  ryy)u  
    Валидирует статус интеграции на основе её конфигурации
    
    Args:
        integration: объект интеграции
        
    Returns:
        str: корректный статус интеграции
    api	connectedbitrix24)	client_idclient_secretapi_url
incompleteamocrmaccess_tokenpendingr   )	timedelta   )minuteserror)configtypeget
last_errorerror_timestampr   r*   utcnow)r   r.   required_fieldsfieldr*   s        ./var/www/notifications/app/api/integrations.py_validate_integration_statusr7      s     %2F 5  :%C$ 	$E::e$#	$
 
		X	%C$ 	$E::e$#	$
 ::n% +"="=&??{:::Yq=QQ     z/integrationsintegrations)prefixtagsc                      e Zd ZU dZdZee   ed<   dZee   ed<   dZ	ee   ed<   dZ
ee   ed<   dZee   ed<   dZee   ed<   dZee   ed	<   dZee   ed
<   dZee   ed<   dZeeeef      ed<   dZeee      ed<    ed      Zy)IntegrationConfigu;   Конфигурация для разных типов CRMNr%   r#   r$   r(   refresh_tokenapi_keyusernamepasswordredirect_uricustom_fieldschannelsallow)extra)__name__
__module____qualname____doc__r%   r   str__annotations__r#   r$   r(   r>   r?   r@   rA   rB   rC   r   r   rD   r   r   model_config r8   r6   r=   r=   A   s    E!GXc]!#Ix}##'M8C='"&L(3-&#'M8C='!GXc]!"Hhsm""Hhsm""&L(3-&.2M8DcN+2$(HhtCy!(G,Lr8   r=   c                   ,    e Zd ZU eed<   eed<   eed<   y)IntegrationCreater/   namer.   N)rG   rH   rI   rK   rL   r=   rN   r8   r6   rP   rP   R   s    
I
Ir8   rP   c                   J    e Zd ZU dZee   ed<   dZee   ed<   dZ	ee
   ed<   y)IntegrationUpdateNrQ   r.   	is_active)rG   rH   rI   rQ   r   rK   rL   r.   r=   rT   boolrN   r8   r6   rS   rS   X   s.    D(3-*.FH&'. $Ix~$r8   rS   c                       e Zd ZU eed<   eed<   eed<   eed<   eed<   ee   ed<   ee   ed<   ee   ed<   ee   ed	<   eee	f   ed
<   eee	f   ed<   e
ed<   eed<   eed<    G d d      Zy)IntegrationOutid	tenant_idr/   rQ   statuslast_sync_atr1   
error_typer2   
sync_statsr.   rT   
created_at
updated_atc                       e Zd ZdZy)IntegrationOut.ConfigTNrG   rH   rI   from_attributesrN   r8   r6   Configra   n       r8   rd   N)rG   rH   rI   intrL   rK   r   r   r   r   rU   rd   rN   r8   r6   rW   rW   ^   s|    GN
I
IK8$$h''S#XcNO r8   rW   c                       e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed<   ee   ed	<   eed
<   ee   ed<   eee	f   ed<    G d d      Z
y)
SyncLogOutrX   integration_id	sync_typerZ   records_processedrecords_createdrecords_updatedrecords_failederror_message
started_atcompleted_atsync_metadatac                       e Zd ZdZy)SyncLogOut.ConfigTNrb   rN   r8   r6   rd   rt      re   r8   rd   N)rG   rH   rI   rf   rL   rK   r   r   r   r   rd   rN   r8   r6   rh   rh   r   sb    GNKC= 8$$S>! r8   rh    )response_modelcurrent_userdbr/   rT   c                    |j                  t              j                  t        j                  | j                  k(        }|r"|j                  t        j                  |k(        }|"|j                  t        j
                  |k(        }|j                  t        j                  j                               j                         }|D ]E  }t        |      }|j                  |k7  s||_        |j                          |j                  |       G |S )u;   Получить список всех интеграций)queryr   filterrY   r/   rT   order_byr^   descallr7   rZ   commitrefresh)rw   rx   r/   rT   rz   r9   r   validated_statuss           r6   list_integrationsr      s     HH[!(()>)>,BXBX)XYE[--56[22i?@>>+"8"8"="="?@DDFL $ $7D!11!1KIIKJJ{#$ r8      )rv   status_codedatac                    g d}| j                   |vrt        dddj                  |             | j                   dv r|j                  t              j                  t        t        j                  |j                  k(  t        j                   | j                   k(              j                         }|r*t        dt        |       d| j                    d	       	 |D ]  }|j                  t              j                  t        j                  |j                  k(        j                          |j                  t              j                  t        j                  |j                  k(        j                          |j                  |        |j!                          t        d
t        |       d| j                           nt)        ||j                  | j                   | j*                        }|rt        d| j                    d       	 |j                  t              j                  t        j                  |j                  k(        j                          |j                  t              j                  t        j                  |j                  k(        j                          |j                  |       |j!                          t        d|j                   d       | j,                  r| j,                  j/                         dk(  r1t1        ||j                  | j                   | j*                        | _        | j                   dk(  rdnd}t	        |j                  | j                   | j,                  | j*                  j3                  d      |i       }|j5                  |       |j!                          |j7                  |       |S # t"        $ r<}|j%                          t        d|        t        ddt'        |             d}~ww xY w# t"        $ r<}|j%                          t        d|        t        ddt'        |             d}~ww xY w)u.   Создать новую интеграцию)r'   r"   1ccustomr      uU   Неверный тип интеграции. Допустимые значения: , r   detail)r    r   r   u   Найдено u8    существующих интеграций типа u   , удаляем ихu   Удалено u6    дублирующих интеграций типа uR   Ошибка при удалении дублирующих интеграций:   Nu;   Найдена дублирующая интеграция u:   , удаляем старую и создаем новуюu,   Дублирующая интеграция u    удаленаuR   Ошибка при удалении дублирующей интеграции: ru   r    r!   r)   Texclude_none)rY   r/   rQ   r.   rZ   r]   )r/   r   joinrz   r   r{   r
   rY   r~   printlenr   ri   rX   deleter   r   	ExceptionrollbackrK   _check_for_duplicatesr.   rQ   strip_generate_unique_name
model_dumpaddr   )	r   rw   rx   valid_typesexisting_integrationsexisting_integrationeinitial_statusr   s	            r6   create_integrationr      s    @Kyy#jkoktkt  vA  lB  kC  D
 	
 yy++ " 5 < <%%)?)??  DII-!

 #% 	 !OC(=$>#??wx|  yB  yB  xC  CX  Y  Z,A 4(HH_-44'66:N:Q:QQfhHH/077*99=Q=T=TTfh II234 		,A(B'CCyz~  {D  {D  zE  F  G  5R9O9OQUQZQZ\`\g\ghOPTPYPY{  [U  V  W)00#226J6M6MM&(+,33&559M9P9PP&( 		./		DEYE\E\D]]lmn 99		)R/)"l.D.DdiiQUQ\Q\]	 %)II$6[IN((YYYY{{%%4%8K FF;IIKJJ{q  jkljmno# #opstupvowx 6  jkljmno# #opstupvowx s2   C&O
 CP 
	P7P

P	Q7QQz/{integration_id}ri   c                     |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |S )u-   Получить интеграцию по ID  (   Интеграция не найденаr   )rz   r   r{   r
   rX   rY   firstr   )ri   rw   rx   r   s       r6   get_integrationr     sj     ((;'..NNn,!!\%;%;;	

 eg  4^__r8   c                 b   |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  |j                  |_        |j                  7|j                  xs i }|j                  j                  d      }i |||_	        |j                  |j                  |_        t        j                         |_        |j                          |j!                  |       |S )u%   Обновить интеграциюr   r   r   Tr   )rz   r   r{   r
   rX   rY   r   r   rQ   r.   r   rT   r   r3   r_   r   r   )ri   r   rw   rx   r   current_config
new_configs          r6   update_integrationr     s     ((;'..NNn,!!\%;%;;	

 eg  4^__ yy99{{$++1r[[+++>
==*=~~! $%__.KIIKJJ{r8   c           	         t        d|  d|j                          |j                  t              j	                  t        t        j                  | k(  t        j                  |j                  k(              j                         }|st        d|  d       t        dd      t        d|j                   d	|j                   d
       	 ddlm}m} |j                  |      j	                  t        |j                  | k(  |j                  |j                  k(              j                         }|D ]  }|j!                  |        |j                  |      j	                  t        |j                  | k(  |j                  |j                  k(              j                         }|D ]  }	|j!                  |	        |j!                  |       |j#                          t        d|  d       ddiS # t$        $ rH}
t        d|  dt'        |
              |j)                          t        ddt'        |
             d}
~
ww xY w)#   Удалить интеграциюu5   Попытка удаления интеграции u!    для пользователя u   Интеграция u    не найденаr   r   r   u%   Найдена интеграция: u
    (тип: )r   )r   r   uA    и связанные записи успешно удаленыmessageu2   Интеграция успешно удаленаu:   Ошибка при удалении интеграции : r   u4   Ошибка удаления интеграции: N)r   rX   rz   r   r{   r
   rY   r   r   rQ   r/   app.db.modelsr   r   ri   r~   r   r   r   rK   r   )ri   rw   rx   r   r   r   	sync_logslogfield_mappingsmappingr   s              r6   delete_integrationr   ?  sE    
A.AQQrs  tC  tC  sD  E  F((;'..NNn,!!\%;%;;	

 eg  %n%55IJK4^__	1+2B2B1C:kN^N^M__`
ab uE HH/077"11^C",,0F0FF

 #% 	  	CIIcN	 /299...@))\-C-CC

 #% 	 & 	GIIg	 			+
		%n%55vwxOPP uJ>JZZ\]`ab]c\def
6jknopkqjr4sttus   	D#G- -	H>6AH99H>z/{integration_id}/testbackground_tasksc                 @   |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      ddlm	} |j                  |       }dd|j                  dd	S )
u4   Тестировать подключение к CRMr   r   r   r   )test_crm_connectionTu@   Тестирование подключения запущеноtesting)successr   task_idrZ   )rz   r   r{   r
   rX   rY   r   r   app.workers.crm_syncr   delay)ri   r   rw   rx   r   r   tasks          r6   test_integrationr   x  s     ((;'..NNn,!!\%;%;;	

 eg  4^__ 9$$^4D U77	 r8   z/{integration_id}/sync	customersrj   c                    |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  dk(  rt        dd      |j                  st        dd      |j                  dk(  rt        dd	      t        |j                  |d
t        j                               }|j                  |       |j                          |j!                  |       	 |j"                  xs i }|j%                  dd      j'                  d      }|j%                  d      }	t)        d|         t)        d|        t)        |	r	d|	dd  dnd       ddl}
ddl}|r|	st/        d      |j                  dk(  r-ddl}|	j3                  d      rt/        d      d|	 dd}dd i}t)        d!| d"       dd#lm}  || d"||d$%      }t)        d&|j8                          |j8                  d'k(  r(|j:                  }t)        d(|        t/        d)|       |j8                  d*k7  r%t/        d+|j8                   d,|j:                         |j=                         }|j%                  d-i       j%                  d.g       }t)        d/t?        |               || d0||d$%      }|j8                  d*k(  r3|j=                         }|j%                  d-i       j%                  d1g       }ng }t)        d2t?        |              d}d}d}d}|D ]  }	 |d3z  }|j%                  d4d      }d}d}|j%                  d5g       }|D ]M  } | j%                  d6      }!| j%                  d7g       }"|"s)|"d   j%                  d8d      }#|!d9k(  r|#}F|!d:k(  sL|#}O dd;l m!}$ |j                  |$      j                  t        |$j
                  |j
                  k(  |$jD                  |k(              j                         }%|%rc|xs |%jF                  |%_#        i |%jH                  |j%                  d<      |t        j                         jK                         d=|%_$        |d3z  }nc |$|j
                  ||dd>g|j%                  d<      |dt        j                         jK                         d?@      }&|j                  |&       |d3z  } dC|_
        ||_&        ||_'        ||_(        ||_)        t        j                         |_*        ||j                  t?        |      t?        |      |dD|_+        t        j                         |_,        t        j                         jK                         ||z   t?        |      t?        |      dE|_-        |j                          dF| dG| dH| |j                  dC||||dIS t/        dJ|j                   dK      # t.        $ r0}'|d3z  }t)        dA|j%                  d<       dB|'        Y d}'~'d}'~'ww xY w# t.        $ r}'t]        |'      rt]        |'      ndL}(t)        dM|(        dN|_
        |(|_/        t        j                         |_*        |(|_0        t        j                         |_1        |j                          t        dOdM|(       d}'~'ww xY w)Pu4   Запустить синхронизацию с CRMr   r   r   r    r   u   API интеграция не требует синхронизации. Используйте API endpoints для отправки уведомлений.u'   Интеграция неактивнаpending_authu   Интеграция ожидает авторизации. Сначала завершите процесс авторизации.in_progress)ri   rj   rZ   rp   r%   ru   /r(   uH   Начинаем синхронизацию для интеграции z	API URL: zAccess token: N   z...Noner   u3   Не настроены api_url или access_tokenr'   test_token_for_demou   Для синхронизации с amoCRM нужен реальный OAuth токен. Выполните OAuth авторизацию в amoCRM.Bearer application/jsonAuthorizationzContent-Typelimit   u-   Запрашиваем контакты из z/api/v4/contacts)http_get   )headersparamstimeoutu   Ответ контактов: i  u,   Ошибка авторизации amoCRM: u2   Ошибка авторизации amoCRM (401):    u   Ошибка API amoCRM: u   . Ответ: 	_embeddedcontactsu#   Найдено контактов: z/api/v4/leadsleadsu   Найдено лидов:    rQ   custom_fields_values
field_codevaluesvaluePHONEEMAILCustomerrX   )	amocrm_idamocrm_name	last_syncimported)r   r   sourcer   rY   phoneemailr;   metau1   Ошибка обработки контакта r   	completed)rj   integration_typecontacts_foundleads_foundr%   )r   total_customerscontacts_syncedleads_synceduE   Синхронизация завершена. Обработано: u   , создано: u   , обновлено: )r   sync_log_idrZ   rk   rl   rm   rn   u+   Синхронизация для типа u    не реализованаu>   Неизвестная ошибка синхронизацииu)   Ошибка синхронизации: failedr   )2rz   r   r{   r
   rX   rY   r   r   r/   rT   rZ   r   r   r3   r   r   r   r.   r0   rstripr   httpxasyncior   requests
startswithapp.utils.httpr   r   textjsonr   r   r   r   r   r   	isoformatrk   rl   rm   rn   rq   rr   r[   r]   rK   ro   r1   r2   ))ri   r   rw   rx   rj   r   sync_logr.   r%   r(   r   r   r   r   auth_paramsr   contacts_responseerror_detailcontacts_datar   leads_response
leads_datar   rk   rl   rm   rn   contactrQ   r   r   rC   r5   r   r   r   r   existing_customernew_customerr   	error_msgs)                                            r6   sync_integrationr    si    ((;'..NNn,!!\%;%;;	

 eg  4^__ 5   5T  U  	U  4]^^^+  5{  |  	| ""~~??$	H FF8IIKJJxO
##)r**Y+2237zz.1XYgXhij	'#$|CR0156RlQRR x' &&'<=  !w  x  x $+<.!9 2G K A'JZ[\ 0 ()+,"	! 34E4Q4Q3RST ,,3055D\NST"TUaTb cdd"..#5";<M<Y<Y;ZZhizii  iA  !B  C  C-224M$((b9==j"MH7HGH &)=)"	N ))S0+002
"{B7;;GRH/E
|<= !"OON# <h;h%*% #;;vr2D E E %,KK0F$KM!. .%*YY|%<
!&8R!8!$*1IMM'2$>E)W4(-!+w!6(-. 7(*(:(A(A$..,2H2HH$NNe3)
 eg & )272R;L;R;R)/2/442)0T):+/)1):)D)D)F	2). (1, (0&2&<&<"'"'"*J!7-4[[->/3*2-5__->-H-H-J	"( |,'1,q<h~ *HO):H&'6H$'6H$&4H#$,OO$5H!&$/$4$4"%h-"5z"&H" (0'8K$%__.88:#2_#D#&x= #E
	&K" IIK cctbu  vH  IX  HY  Yo  p  o@  A'{{%%6#2#2"0  I+JZJZI[[wxyyS ! h"a'NMgkkZ^N_M``bcdbefgghV  
!!fCF*j	9)EF"!* ( 1!*&.oo&7#
		>ykJ
 	

sY   'H/Y AX/"XD.X C.Y /Y 	Y%X<6Y <YY 	[B[[z/{integration_id}/statusc                 4   |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  t              j                  t        j                  | k(        j                  t        j                  j                               j                         }|j                  |j                  |j                  |j                  |j                   |j"                  |j$                  xs i |r]|j                  |j                  |j&                  |j(                  |j*                  |j,                  |j                  |j.                  ddS ddS )u2   Получить статус интеграцииr   r   r   )rX   rZ   rk   rl   rm   rn   rp   rq   N)ri   rQ   r/   rZ   rT   r[   r]   last_sync_log)rz   r   r{   r
   rX   rY   r   r   r   ri   r|   rp   r}   rQ   r/   rZ   rT   r[   r]   rk   rl   rm   rn   rq   )ri   rw   rx   r   r  s        r6   get_integration_statusr    sb    ((;'..NNn,!!\%;%;;	

 eg  4^__ HH/077))^;h!,,1134UUW 
 &..    $$ **#00!,,2   ""#**!.!@!@,<<,<<+::'22)66	
 " !%# r8   z/{integration_id}/logs2   r   offsetc                    |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  t              j                  t        j                  | k(        j                  t        j                  j                               j                  |      j                  |      j                         }|S )u8   Получить журнал синхронизацийr   r   r   )rz   r   r{   r
   rX   rY   r   r   r   ri   r|   rp   r}   r
  r   r~   )ri   rw   rx   r   r
  r   logss          r6   get_sync_logsr    s     ((;'..NNn,!!\%;%;;	

 eg  4^__ 88&'..))^;h%%**,fVnUU5\##%	 	 Kr8   c                   X    e Zd ZU dZeed<   eed<   eed<   dZee   ed<   eed<   eed<   y)	CRMProvideru)   Доступный провайдер CRMrX   rQ   descriptionNlogo_urlconnection_type
setup_time)rG   rH   rI   rJ   rK   rL   r  r   rN   r8   r6   r  r    s.    3G
I"Hhsm"Or8   r  c                   ^    e Zd ZU dZeed<   eeef   ed<   ee   ed<   dZ	e
eeef      ed<   y)FieldMappingCreateu6   Создание сопоставления полейri   r   webhook_eventsNautomation_rules)rG   rH   rI   rJ   rf   rL   r   rK   r   r  r   r   rN   r8   r6   r  r    s;    @cN"I15htCH~.5r8   r  c                       e Zd ZU eed<   eed<   eeef   ed<   ee   ed<   eeef   ed<   e	ed<   e	ed<    G d d	      Z
y
)FieldMappingOutrX   ri   r   r  r  r^   r_   c                       e Zd ZdZy)FieldMappingOut.ConfigTNrb   rN   r8   r6   rd   r    re   r8   rd   N)rG   rH   rI   rf   rL   r   rK   r   r   r   rd   rN   r8   r6   r  r    sI    GcN"I38n$ r8   r  c                   0    e Zd ZU dZeed<   dZee   ed<   y)OAuthInitRequestu    Инициализация OAuthproviderNdomain)rG   rH   rI   rJ   rK   rL   r  r   rN   r8   r6   r  r    s    *M FHSM r8   r  z
/providersc            
      J    ddddddddd	d
ddddddddddddddddddg} | S )u   Получить список доступных CRM-провайдеров (Шаг 1 мастера) - публичный эндпоинтr"   Bitrix24uc   Bitrix24 подключается в один клик через единое приложениеoauthu   1 минутаz/logos/bitrix24.png)rX   rQ   r  r  r  r  r'   amoCRMu;   amoCRM - простая интеграция через APIu   2 минутыz/logos/amocrm.pngr   u   1Сu;   1С облачная или локальная версияr?   u   5 минутz/logos/1c.pngr   u   Другая системаu=   Подключите любую CRM через вебхукиwebhooku   3 минутыz/logos/custom.pngrN   )	providerss    r6   get_crm_providersr&    sy    
  A&*-	
 X&*+	
 X(('	
 1Z(*+	
3!IF r8   z/oauth/initrequestc           
         t        | j                  | j                  dk(  rd| j                   nd| j                   d      }t        ||j                  | j                  |      }|r	 |j                  t              j                  t        j                  |j                  k(        j                          |j                  t              j                  t        j                  |j                  k(        j                          |j                  |       |j                          t        d| j                   d| j                   d|j                   d       ddddddddd}| j                  |vrt#        dd      || j                     }d| j                   }| j                  dk(  rA| j                  st#        dd      |d   j%                  | j                        }	|	d| z  }	nP| j                  dk(  rA| j                  st#        dd      |d   j%                  | j                        }	|	d| dz  }	t'        ||j                  | j                  |      }
t)        |j                  | j                  |
| j                  dk(  rd| j                   nd| j                   d| j                  |ddd !      }|j+                  |       |j                          |j-                  |       |d
u}	|j                  | j                  d"||rd#d$S d
d$S # t        $ r2}|j                          t        d	t!        |              Y d
}~d
}~ww xY w)%uG   Инициировать OAuth авторизацию (Bitrix24/amoCRM)r"   https://z
.amocrm.ru)r  r%   u&   Заменена интеграция u    для домена z (ID: r   uT   Ошибка при удалении существующей интеграции: Nz!https://{domain}/oauth/authorize/zhttps://{domain}/oauth/token/zcrm contact deal entity)auth_url	token_urlscopez https://{domain}.amocrm.ru/oauthz.https://{domain}.amocrm.ru/oauth2/access_tokencrmr"   r'   r   u3   Неподдерживаемый провайдерr   z2http://localhost:3000/integrations/oauth/callback/u"   Укажите домен Bitrix24r*  )r  z!?response_type=code&redirect_uri=r'   u    Укажите домен amoCRMz&mode=popupoauth_pending)r%   r  rB   rZ   r)   )rY   r/   rQ   r.   rZ   u_   Перенаправьте пользователя на auth_url для авторизацииum   Существующая интеграция была автоматически заменена новой)r*  ri   r  r   replaced_integrationreplacement_message)r=   r  r  r   rY   rz   r   r{   ri   rX   r   r   r   r   r   r   rK   r   formatr   r   r   r   )r'  rw   rx   temp_configr   r   oauth_configsr.   rB   r*  unique_namer   was_replaceds                r6   
init_oauthr7  +  s    $~~/6/?/?:/M(7>>*+U]^e^l^l]mmwSxK
 1\5K5KWM]M]_jk	sHH_%,,..2F2I2IIfhHH'(//"115I5L5LLfh II*+IIK :7;K;K:LLabibpbpaqqw  yM  yP  yP  xQ  QR  S  T <8.
 ;I
M },4ijj7++,F HHXHXGYZL :%~~C8\]]*%,,GNN,C7~FF			X	%~~C8Z[[*%,,GNN,C7~[QQ (L,B,BGDTDTVabK ((6=6F6F*6T'..!12\delesesdtt~Znn(%	
 K FF;IIKJJ{ (t3L %..$$t , S_   O  ei E  	sKKMhilmniohpqrr	ss   )C.L 	M 'MMz/{integration_id}/direct-authc                   K   |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  xs i }|j                  dk(  r&ddl
m}  |       }|j                  d      xs |j                  }|j                  d      xs |j                  }|j                  d	d
      j                  d      }	|r|r|	st        dd      t!        |      }
d| |
d<   d|
d<   d|
d<   t#        j$                         j'                         |
d<   d|
d<   |
|_        d|_        d|_        t#        j$                         |_        |j/                          |j1                  |       dd|j                  ddS t        dd|j                         w)uc   Прямая авторизация интеграции (для amoCRM с client_id/client_secret)r   r   r   r'   r   r   r#   r$   r%   ru   r   r   u   Не заполнены client_id (в конфигурации или AMOCRM_CLIENT_ID), client_secret (в конфигурации или AMOCRM_CLIENT_SECRET) или api_url в конфигурацииdemo_token_r(   Bearer
token_type  
expires_inconnected_atcredentialsauth_methodr!   NTu>   amoCRM успешно подключен (демо режим))r   r   ri   rZ   uV   Прямая авторизация не поддерживается для типа )rz   r   r{   r
   rX   rY   r   r   r.   r/   app.core.configr   r0   AMOCRM_CLIENT_IDAMOCRM_CLIENT_SECRETr   dictr   r3   r   rZ   r1   r_   r   r   )ri   rw   rx   r   r.   r   settingsr#   r$   r%   r   s              r6   direct_auth_integrationrF    s     ((;'..NNn,!!\%;%;;	

 eg  4^__%2F8#0> JJ{+Hx/H/H	

?3Tx7T7T**Y+2237W e  &\
'29+%>
>"#+
< #'
< %-__%6%@%@%B
>"$1
=! ((!%!)!2
		


; W)nn!	
 	
 klwl|l|k}~
 	
s   GGz!/{integration_id}/oauth/authorizec                    |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  xs i }|j                  dk(  rddl
m}  |       j                  st        dd      dd	ldd	ldd	ldd	ld
t"        dt$        ffd} ||j
                        }dj                   dj&                   d| }||ddS |j                  dk(  rddl
m}  |       |j)                  d      xs j*                  }	|j)                  dd      j-                  d      }
|j)                  d      }|	r|
st        dd      |sdj.                   d}|
 d|	 d| d|  d}|| d|dS t        dd|j                         ) uM   Получить URL для OAuth авторизации интеграцииr   r   r   r"   r   r   r   u:   BITRIX_CLIENT_ID не настроен на сервереNrY   r   c                 <   j                  d      }|  d| }j                  j                  j                         |j                         j                        j                         } j                  | d| j                               j                         S )N    :)token_urlsafenew
SECRET_KEYencodesha256	hexdigesturlsafe_b64encodedecode)	rY   noncer   	signaturebase64hashlibhmacsecretsrE  s	       r6   _generate_secure_statez5authorize_integration.<locals>._generate_secure_state  s    ))"-E[%)D##**, ik	 
 ,6++tfAi[,A,H,H,JKRRTTr8   z4https://oauth.bitrix.info/oauth/authorize?client_id=z!&response_type=code&redirect_uri=&state=)r*  stater  r'   r#   r%   ru   r   rB   r   u   Не заполнены client_id (в конфигурации или AMOCRM_CLIENT_ID) или api_url в конфигурацииr)  */api/v1/integrations/amocrm/oauth/callbackz/oauth?client_id=z&redirect_uri=z&response_type=code&mode=popup)r*  r[  r  rB   8   OAuth не поддерживается для типа )rz   r   r{   r
   rX   rY   r   r   r.   r/   rA  r   BITRIX_CLIENT_IDrW  rV  rX  rU  rf   rK   BITRIX_REDIRECT_URIr0   rB  r   
APP_DOMAIN)ri   rw   rx   r   r.   r   rY  r[  r*  r#   r%   rB   rU  rV  rW  rX  rE  s               @@@@@r6   authorize_integrationra    s+    ((;'..NNn,!!\%;%;;	

 eg  4^__%2F:%0>((S  		Uc 	Uc 	U 	U '|'='=>"334%99:eW	 	 !"
 	
 
		X	%0> JJ{+Hx/H/H	**Y+2237zz.1 \  %h&9&9%::deL i #\Nn%	 	 !# (	
 	
 MkN^N^M_`
 	
r8   z/oauth/callback/{provider}r  codec           
        K   |j                  t              j                  t        t        j                  |k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  xs i }ddl	m
}  |       }| dk(  r?|j                  d      xs |j                  }	|j                  d      xs |j                  }
nf| d	k(  r?|j                  d      xs |j                  }	|j                  d      xs |j                  }
n"|j                  d      }	|j                  d      }
|j                  d
      xs |j                  d      }|	r|
s0t        dd| j!                          d| j!                          d      	 |j                  d      }| dk(  rt#        ||	|
||       d{   }n.| d	k(  rt%        ||	|
||       d{   }nt        dd|        |j                  d      rt'        |d         |j                  d<   |j                  d      rt'        |d         |j                  d<   |j                  d      r5t)        j*                         j-                         |d   z   |j                  d<   ||j                  d<   d|j                  d<   d|_        t)        j*                         |_        |j3                          |j5                  |       d|j                  | j!                          dd d!S 7 S7 8# t6        j8                  $ rg}d"|_        d#|  d$t;        |       |_        t)        j*                         |_        |j3                          t        d%d#|  d$t;        |             d}~wt@        $ ra}d"|_        d&t;        |       |_        t)        j*                         |_        |j3                          t        d%d&t;        |             d}~ww xY ww)'u!   Обработка OAuth callbackr   r   r   r   r   r"   r#   r$   r'   r%   r  r   u   Не заполнены client_id или client_secret в конфигурации или переменных окружения (z_CLIENT_ID, z_CLIENT_SECRET)rB   )r%   r#   r$   rb  rB   Nr]  r(   access_token_encr>   refresh_token_encr=  token_expires_atauthorization_code
authorizedrZ   r!   Tu"    успешно подключенfield_mapping)r   ri   r   	next_stepr-   u'   Ошибка подключения к r   r   u(   Ошибка обмена токена: )!rz   r   r{   r
   rX   rY   r   r   r.   rA  r   r0   r^  BITRIX_CLIENT_SECRETrB  rC  upperexchange_bitrix24_tokenexchange_amocrm_tokenr   r   r3   	timestamprZ   r_   r   r   r   	HTTPErrorrK   r1   r2   r   )r  rb  ri   rw   rx   r   r.   r   rE  r#   r$   r%   rB   
token_datar   s                  r6   oauth_callbackrr  K  s     ((;'..NNn,!!\%;%;;	

 eg  4^__ %2F,~H :JJ{+Hx/H/H	

?3Tx7T7T	X	JJ{+Hx/H/H	

?3Tx7T7TJJ{+	

?3jj#;vzz(';GM Y  Zb  Zh  Zh  Zj  Yk  kw  x@  xF  xF  xH  wI  IX  Y
 	

F
zz.1z!6#+)  J !4#+)  J  QRZQ[\  >>.)5B:nC]5^K12>>/*6CJD_6`K23>>,'!++-
<0HH 12 48/0'38$(!)!2
		


; )nn"..*++MN(	
 	
QL ?? 
$#J8*TVWZ[\W]V^!_&.oo&7#
		<XJbQQ
 	
  
$#KCPQF8!T&.oo&7#
		=c!fXF
 	

s]   FP)L LL !L"D3L PL L O>/A"NO>AO99O>>Pr%   r#   r$   rB   c                   K   |s(t               }|j                  xs d|j                   d}| j                  d       d| j                  d       dg}d}|D ][  }	 t	        j
                         4 d{   }	|	j                  |d||||dd	
       d{   }
|
j                  dk(  r|
j                         }d|v r/t        dd|j                  d|j                  d                   |j                  d      |j                  d      |j                  dd      dcddd      d{    c S |
j                  j                  dd      j                  d      r|
j                         ni }|j                  d      xs |j                  d      xs |
j                  }ddd      d{    ^ t        dd|xs d       7 V7 77 7 ## 1 d{  7  sw Y   3xY w# t        $ r}t        |      }Y d}~d}~ww xY ww)u?   Обмен authorization_code на access_token для Bitrix24r)  z,/api/v1/integrations/bitrix24/oauth/callbackr   z/oauth/token/z/oauth/tokenNrg  )
grant_typer#   r$   rb  rB         >@)r   r   r   r-   r   u   Ошибка Bitrix24: error_descriptionr   r(   r>   r=  r<  r(   r>   r=  content-typeru   r   r   u   Ошибка Bitrix24 API: u;   Не удалось обменять код на токен)r   r_  r`  r   r   AsyncClientpostr   r   r   r0   r   r   r   r   rK   )r%   r#   r$   rb  rB   rE  
token_urlsr1   r+  clientresponser   
error_datar   s                 r6   rm  rm    sH     >33  D(BUBUAV  WC  8D
 >>#
}->>#
|,J
 J "	!	((* q qf!'&:%.)6 $(4 ! "- 
" 
 ''3.#==?D$+(+%<TXXFY[_[c[cdk[l=m<n#o  )-(@)-/)B&*hh|T&B-q q q8 5=4D4D4H4HY[4\4g4ghz4{  BDJ!+0C!D!p
W^H_!pckcpcpJ;q q"J ,Z-x;x,yz Gq
q q q q q<  	QJ	s   AHG+6G7G+:GGB	G"G+.G/G+3H6A/G%G+0G1G+5HG+GG+G+G(	GG(	$G++	H
4H?HH

Hc                   K   |st               }d|j                   d}|  d}| d| }t        j                  |j	                               j                         }t        j                         4 d{   }	|	j                  |d||dd| d	d
d       d{   }
|
j                  dk7  r|
j                  j                  dd      j                  d	      r|
j                         ni }|j                  d      xs |j                  d      xs |
j                  }t        |
j                  d|       |
j                         }d|v sd|v rD|j                  d      dk7  r0t        dd|j                  d|j                  dd                   |j                  d      |j                  d      |j                  dd      dcddd      d{    S 7 e7 A7 # 1 d{  7  sw Y   yxY ww) u=   Обмен authorization_code на access_token для amoCRMr)  r\  z/oauth2/access_tokenrJ  Nrg  )rt  rb  rB   zBasic r   r   ru  r   r   r   r   rx  ru   r   hintu   Ошибка amoCRM API: r   r-   rZ   r   r   u   Ошибка amoCRM: titlezUnknown errorr(   r>   r=  iQ rw  )r   r`  rU  	b64encoderN  rR  r   ry  rz  r   r   r0   r   r   r   r   )r%   r#   r$   rb  rB   rE  r+  r?  encoded_credentialsr|  r}  r~  r  r   s                 r6   rn  rn    s      >!("5"5!66`a)/0I Kq0K **;+=+=+?@GGI  " #
 #
f2 , $**=)>!? 2  % 
 
 3&,4,<,<,@,@QS,T,_,_`r,sy{J"x0[JNN64J[hmmI$0029+> 
 }}d?h$.488H3E3R.txx$((7TcBd/e.fg  !HH^4!XXo6((<7
?#
 #
 #

#
 #
 #
 #
s[   A2G64G5G68#G!GD+G!G6GG6G!G6!G3'G*(G3/G6z/available-fields/{provider}c           
         ddddddddddd	dd
dddgddddddddddddddddddddgdddddddd	dddddgddddddddd d!ddgd"d#d	dd	dddddd$d%ddd&d'ddgid(}| |vrt        d)d*+      ||    S ),ub   Получить доступные поля CRM для маппинга (Шаг 2 мастера)zcontact.NAMEu   Имя контактаstring)rX   labelr/   zcontact.LAST_NAMEu   Фамилияzcontact.PHONEu   Телефонr   zcontact.EMAILEmailr   z
deal.TITLEu   Название сделкиzdeal.STAGE_IDu   Стадия сделкиzdeal.UF_DATEu   Дата визитаr   zdeal.UF_ADDRESSu
   Адресzdeal.UF_SERVICEu   Услуга)r   dealszcontact.namez#contact.custom_fields_values[phone]z#contact.custom_fields_values[email]z	lead.nameu   Название лидаzlead.status_idu   Статусzlead.custom_fields_values[date]u   Дата)r   r   r   rQ   u   Имя клиентаexternal_idu   Внешний ID из CRM)r"   r'   r   r   uC   Поля для этого провайдера не найденыr   )r   )r  
fields_maps     r6   get_available_fieldsr  ;  s6    &0IS[\*5ExX&1A7S&'J	 $.MW_`&1LV^_%0GQ[\(<R(>8T
" &0IS[\<GWahi<wX_` #-HRZ['.(S8:Wab
 )97K'B(?R$/KU]^	
9$JL z!4yzzhr8   z/field-mappingc                 f   |j                  t              j                  t        t        j                  | j
                  k(  t        j                  |j                  k(              j                         }|st        dd      |j                  t              j                  t        j
                  | j
                  k(        j                         }|rs| j                  |_
        | j                  |_        | j                  xs i |_        t        j                         |_        |j!                          |j#                  |       |S t        | j
                  | j                  | j                  | j                  xs i       }|j%                  |       |j!                          |j#                  |       |S )uR   Создать сопоставление полей CRM (Шаг 2 мастера)r   r   r   )ri   r   r  r  )rz   r   r{   r
   rX   ri   rY   r   r   r   r   r  r  r   r3   r_   r   r   r   )r   rw   rx   r   existing_mappingr   s         r6   create_field_mappingr  k  sb    ((;'..NNd111!!\%;%;;	

 eg  4^__ xx077&&$*=*==eg  *.*=*='*.*=*=',0,A,A,GR)&.oo&7#
		


#$ ******..4"	G FF7OIIKJJwNr8   z/{integration_id}/field-mappingc                    |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  t              j                  t        j                  | k(        j                         }|st        dd      |S )uR   Получить сопоставление полей для интеграцииr   r   r   u=   Сопоставление полей не настроено)
rz   r   r{   r
   rX   rY   r   r   r   ri   )ri   rw   rx   r   r   s        r6   get_field_mappingr    s     ((;'..NNn,!!\%;%;;	

 eg  4^__hh'..&&.8eg  4sttNr8   z#/{integration_id}/test-notification	test_datac                 L  K   |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      	 ddlm	} |j                  j                  d      d   }|j                  |      j                  t        |j
                  |j
                  k(  |j                  |j                  k(              j                         }|r|j                  nd} ||j
                  d|j                  |dd	gd
| dd	|j                  d      }	|j                  |	       |j                          |j                  |	       ddlm}
m} ddlm}  |
|j
                  ddddgdddddg      }|j                  |       |j                          |j                  |        ||j
                  |j                  |	j                  d
| dddd      }|j                  |       |j                          |j                  |       ddlm}  |       }|j+                  |j                         d{   }g }|j-                  di       j-                  d      r|j/                  d       |j-                  di       j-                  d      r|j/                  d       |s?g }|r|j/                  d       |j                  r|j/                  d       |r|}d }ndg}d }nd!}dd"d#j1                  |       | |d
| d|j                  |j                  dd$dd%d&S 7 # t2        $ rC}dd'ddgd
|j                  j                  d      d    d|j                  d$d(d)d*d&cY d}~S d}~ww xY ww)+uT   Отправить тестовое уведомление (Шаг 3 мастера)r   r   r   r   r   @Ntest
crm_wizardu   Тестовый клиент (r   )rQ   r   user_id)rY   r   r   
tg_chat_idr;   r   )TemplateNotificationr   u'   Тестовое уведомлениеztest-notificationr   telegramT)primaryfailoveru   Привет, {{customer_name}}! Это тестовое уведомление от {{app_name}}. Система уведомлений работает корректно!customer_nameapp_name)rY   rQ   slugchannel_strategycontent	variableszNotification Service)r  r  r)   )rY   template_idcustomer_idpayloadrZ   )NotificationWorkerr   uO    (демо режим - реальная отправка недоступна)ru   uJ   ✅ Уведомление успешно доставлено через r   u9   Регистрирующийся пользователь)r  customer_emailnotification_idtemplate_name	recipientchannels_used)r   r   rD   detailsuq   ✅ Уведомление успешно доставлено через Email и Telegram (демо режим)zemail, telegramuL   Демо режим - реальная отправка недоступна)r  r  r  r  note)rz   r   r{   r
   rX   rY   r   r   r   r   r   splitr  r   r   r   r  r  r   app.workers.notificationsr  send_notificationr0   appendr   r   )ri   r  rw   rx   r   r   	user_namer  r  test_customerr  r  r   test_templatenotificationr  workerresultsuccessful_channelsavailable_channelsmessage_suffixr   s                         r6   send_test_notificationr    s     ((;'..NNn,!!\%;%;;	

 eg  4^__y
* !&&,,S1!4	 HHX.55""l&<&<<,"4"44

 %' 	 6G&11D
 ",,$$!,'9)AF&'??
 	}
		


=! 	9% !",,:$*1:)>DQ D&
3
 	}
		


=! $",,%((%((#B9+Q!O2 	
 	|
		


<  	A#%//@@ !::j"%)))4&&z2::gr"&&y1&&w/ #!#"))*5!!"))'2!&8#!r'.i#!rN cdhdmdm  oB  eC  dD  ES  DT  U+#B9+Q!O"."4"4#/??!JX!(	
 	
5 AP  
  K *-#B<CUCUC[C[\_C`abCcBdde!f"."4"4X!2f	
 	

sJ   A8N$;G0M +M,C&M N$M 	N!8NN!N$N!!N$r(   eventwebhook_urlc                   K   	 | j                  d       d}t        j                         4 d{   }|j                  ||||dd       d{   }|j                  dk(  rE|j                         }|j                  d      r$d	|j                  d      icddd      d{    S 	 ddd      d{    y7 7 l7 7 # 1 d{  7  sw Y   yxY w# t        $ r Y yw xY ww)
u4   Зарегистрировать webhook в Bitrix24r   z/rest/event.bind.jsonN)authr  handlerru  )r   r   r   r  
webhook_idr   r   ry  rz  r   r   r0   r   )r%   r(   r  r  rest_urlr|  r}  r   s           r6   register_bitrix24_webhookr  H  s     nnS)**?@$$& 	 	&#[[("*
  )  H ##s*}}88H%($((8*<=	 	 	  !	 	 		 	 	 	 	"  s   C',C B;C CB=ACC #B?$C (C')C*C 5C6C :C';C =C?C C C	C
CC C'C 	C$!C'#C$$C'c                   K   	 | j                  d       d}t        j                         4 d{   }|j                  ||d|gidd| ddd	
       d{   }|j                  dv rJ|j                         }d|v r6d|d   v r/|d   d   d   }d|j                  d      icddd      d{    S 	 ddd      d{    y7 7 p7 7 # 1 d{  7  sw Y   yxY w# t        $ r Y yw xY ww)u2   Зарегистрировать webhook в amoCRMr   z/api/v4/webhooksNevents)destinationrE  r   r   r   ru  r  )r   r   r   webhooksr   r  rX   r  )	r%   r(   r  r  webhook_api_urlr|  r}  r   r$  s	            r6   register_amocrm_webhookr  g  s0     %^^C011AB$$& 	 	&#[[#. 5'! (/|n%=$6  )  H ##z1}}$&:k9J+J";/
;A>G('++d*;<)	 	 	, -	 	 		 	 	 	 	.  s   C4,C% CC% %CC
A
C$C% 0C1C% 5C46C7C% CC% C4C% 
CC% C% C"CC"C% !C4"C% %	C1.C40C11C4z#/{integration_id}/register-webhooksc           	        K   |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  t              j                  t        j                  | k(        j                         }|st        dd      |j                  xs i }d}|j                  dk7  r,|j                  d      }|st        dd	      	 t        |      }t!               }	|j                  dk(  rd|	j"                   d|  d}
nd|	j"                   d|j                   d}
g }	 |j                  dk(  r|j                  d      xs |j                  d      }|st        dd      |j$                  D ]F  }t'        ||||
       d{   }|j)                  ||
|rdnd|r|j                  d      ndd       H n|j                  dk(  rv|j                  d      }|st        dd      |j$                  D ]F  }t+        ||||
       d{   }|j)                  ||
|rdnd|r|j                  d      ndd       H n|j$                  D cg c]	  }||
ddd }}|
|j                  d<   ||j                  d <   d!|_        t/        j0                         |_        |j5                          |j7                  |       d"|
|d#t9        |       d$d%S # t        $ r}t        d
dt        |             d}~ww xY w7 u7 c c}w # t        $ r}t        d
dt        |             d}~ww xY ww)&u6   Зарегистрировать вебхуки в CRMr   r   r   r   uG   Сначала настройте сопоставление полейNr   rd  us   Интеграция не авторизована. Сначала завершите OAuth авторизацию.r   u2   Ошибка расшифровки токена: r)  z/api/v1/integrations/z/webhookz/api/v1/crm-webhooks/z/lead-createdr"   r%   r  u5   Не указан api_url в конфигурации)r%   r(   r  r  
registeredr   r  )r  r  rZ   r  r'   r)   ut   Автоматическая регистрация не поддерживается для этого типа CRM)r  r  rZ   r  u.   Ошибка регистрации webhooks: r  registered_eventsr!   Tu!   Зарегистрировано u    вебхуков)r   r  r  r   )rz   r   r{   r
   rX   rY   r   r   r   ri   r.   r/   r0   r   r   rK   r   r`  r  r  r  r  rZ   r   r3   r_   r   r   r   )ri   rw   rx   r   r   r.   r(   rd  r   rE  r  r  r%   r  r  s                  r6   register_webhooksr    s     ((;'..NNn,!!\%;%;;	

 eg  4^__ hh'..&&.8eg  4}~~ %2F L8#!::&89 M 	()9:L ~H8# !4!4 55J>JZZbc !4!4 55J;K[K[J\\ij <
z)jj+Cvzz(/CG# #R  !// 8#!- +	   "(("*.4l(>D&**\":$	*  )jj+G# #R  !// 6#!- +	   "(("*.4l(>D&**\":$	* * #11!3
 	 &# O	" !3 !3 )4K}%.?K*+$K%__.KIIKJJ{ ".6s;L7M6NN_`	 q  	KCPQF8T 	8.!3  
CCF8L
 	

s   DM2L AM2&A#M 	L>
BM MAM MM !A3M2	L;L66L;;M2>M M M 	M/M**M//M2c                   4    e Zd ZU dZeed<   eed<   dZeed<   y)DuplicateCleanupRequestuL   Запрос на очистку дублирующих интеграцийr   keep_integration_idTmerge_customersN)	rG   rH   rI   rJ   rK   rL   rf   r  rU   rN   r8   r6   r  r    s    V OT r8   r  z/cleanup-duplicatesc                    |j                  t              j                  t        t        j                  | j
                  k(  t        j                  |j                  k(              j                         }|st        dd      |j                  t              j                  t        t        j                  |j                  k(  t        j                  | j                  k(  t        j                  | j
                  k7              j                         }|sdddddS d}d}	 | j                  r/t        ||j                  |D cg c]  }|j                   c}      }|D ]  }|j                  t              j                  t        j                  |j                  k(        j!                          |j                  t"              j                  t"        j                  |j                  k(        j!                          |j!                  |       |dz  } |j%                          dd	|||j                  |j&                  |j                  d
dS c c}w # t(        $ r.}	|j+                          t        ddt-        |	             d}	~	ww xY w)ua   Очистить дублирующие интеграции и объединить данныеr   u9   Основная интеграция не найденаr   Tu?   Дублирующие интеграции не найденыr   )r   r   merged_customersremoved_integrationsr   u0   Очистка завершена успешно)rX   rQ   r/   )r   r   r  r  kept_integrationr   uP   Ошибка при очистке дублирующих интеграций: N)rz   r   r{   r
   rX   r  rY   r   r   r/   r   r~   r  "_merge_customers_from_integrationsr   ri   r   r   r   rQ   r   r   rK   )
r'  rw   rx   primary_integrationduplicate_integrationsmerged_customers_countremoved_integrations_countrf   	duplicater   s
             r6   cleanup_duplicate_integrationsr  "  sE    ((;/66NNg999!!\%;%;;	

 eg  4opp  XXk299!!\%;%;; 8 88NNg999	
 
ce  "X !$%	
 	
 !")
""%G'**?U,VSVV,V&"
 0 	,IHH_%,,..),,>fhHH'(//"11Y\\Afh IIi &!+&	, 			 I 6$>),,+00+00!

 
	
) -W@  

efijkflemn
 	

s+   !I ?I
C7I 
I 	J)JJz/duplicatesc                 D   |j                  t              j                  t        j                  | j                  k(        j	                         }i }|D ]J  }|j
                   d|j                  j                  dd       }||vrg ||<   ||   j                  |       L g }|j                         D ]  \  }}t        |      dkD  s|j                  d d       |j                  |d   j
                  |d   j                  j                  dd	      t        |      |D cg c]K  }|j                  |j                  |j                  |j                  |j                   |j"                  xs i d
M c}|d   j                  d        |t%        d |D              dS c c}w )u6   Найти дублирующие интеграции_r  	no_domainr   c                     | j                   S N)r^   )xs    r6   <lambda>z-find_duplicate_integrations.<locals>.<lambda>  s
    Q\\ r8   T)keyreverser   u   Не указан)rX   rQ   rZ   r^   r[   r]   )r/   r  countr9   recommended_keepc              3   >   K   | ]  }t        |d          dz
    yw)r9   r   N)r   ).0dups     r6   	<genexpr>z.find_duplicate_integrations.<locals>.<genexpr>  s     SC$7 81 <Ss   )
duplicatestotal_duplicates)rz   r   r{   rY   r~   r/   r.   r0   r  itemsr   sortrX   rQ   rZ   r^   r[   r]   sum)	rw   rx   r9   groupedr   r  r  grouprf   s	            r6   find_duplicate_integrationsr  u  s    88K(//!7!77	ce 
 G# )!!"!K$6$6$:$:8[$Q#RSgGCLK(	) Jmmo 
Uu:>JJ14J@a(//--h8KLU  %
!  "ff #"%**&)nn(+(8(8&)nn&:
! %*!HKK 0 !S
SS 
!s   AFprimary_integration_idduplicate_integration_idsc                    ddl m} d}| j                  |      j                  t	        |j
                  j                  d       |j                  j                  d      d      j                  |D cg c]  }d| 	 c}                  j                         }|D ]  }|j                  si |_        |j                  j                  dg       |j                  d<   |j                  d   j                  |       ||j                  d<   t        j                         j                         |j                  d	<   |d
z  } |S c c}w )uV   Объединить клиентов из дублирующих интеграцийr   r   N->>crm_typeIntegration_merged_from_integrationsr  last_merged_atr   )r   r   rz   r{   r
   rY   isnotr   opin_r~   r0   extendr   r3   r   )rx   r  r  r   merged_countrX   customers_to_mergecustomers           r6   r  r    s(    'L (+22$$T*#HMMU#J/33Sl4mR|B45H4mn	
 
ce  ' }}HM 5=MM4E4EF`bd4e0101889RS2H./*2//*;*E*E*G&' # 5ns   0D?z/{integration_id}/error-detailsc                    |j                  t              j                  t        t        j                  | k(  t        j
                  |j
                  k(              j                         }|st        dd      |j                  dk7  s|j                  st        dd      t        |j                  |j                        }|j                  t              j                  t        j                  | k(        j                  t        j                  j!                               j#                  d      j%                         }| |j&                  |j                  |j                  |j(                  ||D cg c]G  }|j                  |j                  |j                  |j*                  |j,                  |j.                  dI c}t1        |d	         t3        |d	         d
	S c c}w )u_   Получить детальную информацию об ошибке интеграцииr   r   r   r-   r   u+   У интеграции нет ошибокr+   )rX   rZ   rp   rq   ro   rk   r/   )	ri   integration_namer   ro   r2   error_analysisrecent_logssuggested_actionstroubleshooting_steps)rz   r   r{   r
   rX   rY   r   r   rZ   r1   _analyze_errorr/   r   ri   r|   rp   r}   r   r~   rQ   r_   rq   ro   rk   _get_suggested_actions_get_troubleshooting_steps)ri   rw   rx   r   
error_infor  r   s          r6   get_integration_error_detailsr    s    ((;'..NNn,!!\%;%;;	

 eg  4^__W$K,B,B4abb   6 68H8HIJ ((-.55))^;h!,,1134UU1Xcce 
 )',,',,$//&11$ #

  ff**!nn # 0 0!$!2!2%(%:%:

 4Jv4FG!;Jv<N!O' 

s   /AGro   r   c                 X   | j                         t        fddD              r	ddddddd	S t        fd
dD              r	ddddddd	S t        fddD              r	ddddddd	S t        fddD              r	ddddddd	S t        fd d!D              r	d"d#dd$d%d&d	S d'd(dd)d*d+d	S ),uT   Анализирует ошибку и определяет тип и решениеc              3   &   K   | ]  }|v  
 y wr  rN   r  keyworderror_lowers     r6   r  z!_analyze_error.<locals>.<genexpr>       
ng7k!
n   )unauthorizedinvalid_tokenr(   expiredr  u   Авторизацияr-   uX   Проблема с токеном доступа или учетными даннымиuF   Необходимо переподключить интеграциюut   Истек срок действия токена доступа. Переподключите интеграцию.)r/   categoryseverityr  solutionuser_friendly_messagec              3   &   K   | ]  }|v  
 y wr  rN   r  s     r6   r  z!_analyze_error.<locals>.<genexpr>  s     
eg7k!
er  )r   
connectionnetworkunreachabler   u%   Сетевое подключениеwarninguB   Проблемы с подключением к CRM системеuL   Проверьте доступность CRM и настройки сетиu}   Не удается подключиться к CRM системе. Проверьте интернет-соединение.c              3   &   K   | ]  }|v  
 y wr  rN   r  s     r6   r  z!_analyze_error.<locals>.<genexpr>  r  r  )
permission	forbiddeninsufficientaccess_deniedpermissionsu   Права доступаu<   Недостаточно прав для работы с CRMuF   Обновите права доступа в настройках CRMuZ   У приложения нет необходимых прав для работы с CRM.c              3   &   K   | ]  }|v  
 y wr  rN   r  s     r6   r  z!_analyze_error.<locals>.<genexpr>%  s     
cg7k!
cr  )invalid	malformedr.   bad_requestr.   u   КонфигурацияuB   Неправильные настройки подключенияu:   Проверьте настройки интеграцииuJ   Неправильные настройки подключения к CRM.c              3   &   K   | ]  }|v  
 y wr  rN   r  s     r6   r  z!_analyze_error.<locals>.<genexpr>0  s     
pg7k!
pr  )
rate_limitquotalimit_exceededtoo_many_requestsr.  u   Лимиты APIu6   Превышены лимиты API CRM системыuP   Подождите и попробуйте синхронизацию позжеuY   Превышены лимиты запросов к CRM. Попробуйте позже.unknownu#   Неизвестная ошибкаu%   Неопознанная ошибкаA   Обратитесь в техническую поддержкуui   Произошла непредвиденная ошибка. Обратитесь в поддержку.)lowerany)ro   r   r  s     @r6   r  r    s   %%'K 
n1m
nn0u` &\
 	
 
e1d
ee?!_f &e
 	
 
n1m
nn!3Y` &B
 	
 
c1b
cc2_T%q
 	
 
p1o
pp *!Sj &A
 	
 9>W "M r8   r\   c           
          dddddddddd	d
dgddddddddddddgddddddddgddddddddgddddddddgddddddddgd}|j                  | |d         S )u]   Возвращает рекомендуемые действия для типа ошибки	reconnectu1   Переподключить интеграциюr  )actionr  r/   r>   u   Обновить токенdefaultr   r   dangerretryu!   Попробовать снова	check_urlu   Проверить URLcontact_supportu*   Обратиться в поддержкуupdate_permissionsu"   Обновить права в CRMedit_configu#   Изменить настройкиrecreateu   Создать зановоretry_lateru!   Попробовать позжеschedule_syncu5   Запланировать синхронизациюr  r   r(  r.   r.  r2  r2  r0   )r\   actionss     r6   r  r  E  s     #-`jst&1NXab*OYab
 )LV_`"-EyY(3_irs
 ,6Zdmn"-`jst

 %/T^gh!,IS\]

 %/R\ef&1hr{|

 )LV_`(3_irs
/G: ;;z79#566r8   c                 V    g dg dg dg dg dg dd}|j                  | |d         S )	ug   Возвращает пошаговые инструкции по устранению проблемы)u2   Удалите текущую интеграциюuG   Создайте новую интеграцию того же типаuC   Пройдите процесс авторизации зановоuQ   Убедитесь что все токены получены корректно)uP   Проверьте доступность CRM системы в браузереuG   Убедитесь что URL интеграции правильныйuF   Проверьте настройки файрвола и проксиuV   Попробуйте синхронизацию с другого устройства)u>   Войдите в админку вашей CRM системыuY   Перейдите в настройки приложений или интеграцийu<   Найдите ваше приложение в спискеuA   Добавьте права: crm, crm.lead, crm.contact, crm.deal)u;   Проверьте что URL CRM содержит https://uU   Убедитесь что все обязательные поля заполненыuS   Проверьте формат данных в полях конфигурацииuc   Создайте интеграцию заново с правильными настройками)uR   Подождите 15-30 минут перед повторной попыткойur   Настройте автоматическую синхронизацию на менее частое времяuY   Обратитесь в поддержку CRM для увеличения лимитовuY   Рассмотрите возможность пакетной синхронизации)u9   Скопируйте полный текст ошибкиr3  uA   Укажите ID интеграции и время ошибкиu4   Приложите скриншот проблемыrC  r2  rD  )r\   stepss     r6   r  r  g  s@    





?%EN 99Zy!122r8   rY   r.   c                    |dv rY|j                   }|rI|j                  d      rddlm}  ||      j                  }| j                  t              j                  t        t        j                  |k(  t        j                  |k(  t        j                  j                  d      d      |k(              j                         }|r|S | j                  t              j                  t        t        j                  |k(  t        j                  |k(  t        j                  j                  d      d      j                  d| d                  j                         }|r|S y
|d	v rb| j                  t              j                  t        t        j                  |k(  t        j                  |k(              j                         }|r|S y
)uY   Проверить существование дублирующей интеграцииr.  httpr   urlparser  r  r%   %)r   r   r    N)r%   r   urllib.parserK  netlocrz   r   r{   r
   rY   r/   r.   r  r   like)rx   rY   r   r.   r  rK  existings          r6   r   r     s    11  (1!&)00 xx,33))Y6$$(88&&))%0:fD eg   xx,33))Y6$$(88&&))%0;@@1VHAO eg    
4	488K(//%%2  $44

 %' 	 Or8   c                    ddddd}|j                  ||j                               }|j                  }|r0|j                  d      rddlm}  ||      j                  }| d	| S | j                  t              j                  t        t        j                  |k(  t        j                  |k(              j                         }|dkD  r
| d
|dz    S |S )uP   Генерировать уникальное имя для интеграцииr!  r#  1Cz
Custom CRM)r"   r'   r   r   rI  r   rJ  z - z #r   )r0   rl  r%   r   rM  rK  rN  rz   r   r{   r
   rY   r/   r  )	rx   rY   r   r.   
base_names	base_namer  rK  existing_counts	            r6   r   r     s     	J /1A1G1G1IJI ^^FV$-f%,,FCx(( XXk*11!!Y. 00	

 eg  B~1233r8   z/amocrm/oauth/callback.zAuthorization code from AmoCRM)r  zIntegration IDr[  refererplatformc                 `   K   ddl m} d|  d| }|r|d| z  }|r|d| z  } ||      S w)ud   
    OAuth callback для amoCRM - перенаправляет на основной callback
    r   )RedirectResponsez/api/v1/amocrm/callback?code=rZ  z	&referer=z
&platform=)url)fastapi.responsesrY  )rb  r[  rV  rW  rw   rx   rY  callback_urls           r6   amocrm_oauth_callbackr]    sP      324&wGL)G9--*XJ//--s   ,.z/{integration_id}/webhookc                 6  K   |j                  t              j                  t        t        j                  | k(  t        j
                  dk(  t        j                  dk(              j                         }|st        dd      	 |j                          d{   }|j                  d	      }|j                  d
      }|j                  dd      }|j                  d      }|s|st        dd      d}	|rf|j                         j                  dd      j                  dd      j                  dd      j                  dd      }	|	j                  d      sd|	 }	d}
|ru|j                  t              j                  t        t        j                  |j                  k(  t        j                   d   j"                  |k(              j                         }
|
sj|	rh|j                  t              j                  t        t        j                  |j                  k(  t        j$                  |	k(              j                         }
|
sj|rh|j                  t              j                  t        t        j                  |j                  k(  t        j&                  |k(              j                         }
|
r|	r|
j$                  |	k7  r|	|
_        |r|
j&                  |k7  r||
_        |
j                   r^|r||
j                   d<   ||
j                   d<   d|
j                   d<   t)        j*                         j-                         |
j                   d<   |j/                          |j1                  |
       ntt        |j                  |	|ddg||ddt)        j*                         j-                         d      }
|j3                  |
       |j/                          |j1                  |
       dd|
j                  |
j$                  |
j&                  dS 7 n#  t        dd      xY ww)u;  
    Обработка webhook от custom интеграции
    
    Принимает данные в формате JSON с полями:
    - phone: номер телефона
    - email: email
    - name: имя клиента
    - external_id: внешний ID из CRM (опционально)
    r   Tr   u/   Custom интеграция не найденаr   Nr   uC   Неверный формат данных. Ожидается JSONr   r   rQ   u   Клиентr  u6   Необходимо указать phone или email ru   (r   -+custom_webhookr   last_updater   r$  )rQ   r  r   created_fromrd  r   r   u0   Данные клиента обработаны)rZ   r   r  r   r   )rz   r   r{   r
   rX   r/   rT   r   r   r   r0   r   replacer   r   rY   r   astextr   r   r   r3   r   r   r   r   )ri   r'  rx   r   r   	phone_rawr   rQ   r  r   r  s              r6   handle_custom_webhookri  
	  s      ((;'..NNn,(!!T)	
 eg  4eff{\\^#
 !IHHWE88FN+D((=)KU4lmm E!))#r2::3CKKCQST\\]`bde$wKE H 88H%,,""k&;&;;m,33{B

 %' 	 88H%,,""k&;&;;%'

 %' 	 88H%,,""k&;&;;%'

 %' 	 X^^u,"HNX^^u,"HN==/:m,$(HMM&!&6HMM(#+3??+<+F+F+HHMM-(
		


8 !++"J/** )'0::<
 	x
		


8 E{{ i ${4yzzs1   B PP PP M)PP PPr  )Zfastapir   r   r   r   r   r   sqlalchemy.ormr	   
sqlalchemyr
   typingr   r   r   r   r   pydanticr   r   r   rU  app.db.sessionr   r   r   r   r   r   app.api.depsr   rA  r   app.utils.encryptionr   r   rK   r7   routerr=   rP   rS   rW   rh   r0   rU   r   rz  r   rf   r   putr   r   r   r   r  r  r  r  r  r  r  r&  r7  rF  ra  rr  rD  rm  rn  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r]  ri  rN   r8   r6   <module>rt     s
   V V "  , ,  *   ! P P ) ( =*k *c *X 
/0@	A-	 -"	 %	 %Y ( & BtN34 !12&/ $	 3- ~	 56 RC@ !!12&/a
aa 	a AaH ? !!12&/ 	 @& ? !!12&/	!!
! ! 		! @!H "# !!12&/5u5u5u 	5u $5up %& !!12&/	%  		 '< %& !!12&/ w
w
%w
 w
 		w

 w
 'w
t &' !!12&/''' 	' ('T $T*5EF !!12&/ 	 	
  G>) 6 6
i 
!y ! Lk):;% <%P ] !!12&/jjj 	j jZ ,- !!12&/B
B
B
 	B
 .B
J 01 !!12&/h
h
h
 	h
 2h
V )*
 !!12&/q
q

q
 q
 	q

 	q
 +q
r  $>>> > 	>
 *> 
>L  $7
7
7
 7
 	7

 *7
 
7
t *+, 3 ,  ,, ^ o3O !!12&/-
-- 	- P-` -oN !!12&/ 	 O8 23  !12&/	K
K
K
 K
 		K
 4K
\  	
 
D[>$$$ $ 	$
 
D[$N 23 !!12&/GGG 	G 4GX!i ! "# !!12&/O
$O
O
 	O
 $O
d M !12&//// /d!!!  $Cy! 		!H -. !!12&//// 	/ //dC# C Cc3h CL7s 7tDcN/C 7D)33 )349 )3X555 5 	5
 k5p%%% % 	%
 	%P $%c'GHs(89"4[#Dk !12&/.
.. c]. sm	.
 . 	. &., () &/vvv 	v *vr8   