
    Čil                     P   d dl Z d dlmZ d dlmZ d dl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 d d
lmZ d dl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"  e jF                  e$      Z%de&de&fdZ'd Z(d Z)d Z*dZ+d Z,de&fdZ-d Z.d Z/d Z0d Z1d Z2d Z3ddZ4y)     N)time)ZoneInfo)transactionIntegrityErrormodels)Q)timezone)urlparsestatus)Response)User)CompanyType)CompanyOfficeHoursHolidaySalesTimingCompanyBotSettingsCompanyHistoryService)ProfileServices)get_company_timeurlreturnc                     | s| S t        d| v r| nd|        }|j                  j                         }|j                  d      r|dd }|j	                  d      S )ag  
    Normalize a website URL into a consistent comparable format.

    This function ensures all website URLs are stored and compared
    in a uniform way by removing protocol, 'www', trailing slashes,
    and converting to lowercase.

    Steps performed:
    1. Adds 'http://' if the URL has no scheme (so it can be parsed).
    2. Extracts the domain part (netloc) only.
    3. Removes 'www.' prefix if present.
    4. Converts to lowercase.
    5. Removes any trailing slashes.

    Example:
        >>> normalize_website("https://www.ABC.com/")
        'abc.com'
        >>> normalize_website("abc.com")
        'abc.com'
        >>> normalize_website("http://abc.com:8000/test")
        'abc.com:8000'

    Args:
        url (str): The website URL to normalize.

    Returns:
        str: Normalized domain (e.g. "abc.com") or the original value if empty/None.
    z://zhttp://zwww.   N/)r
   netloclower
startswithrstrip)r   parsedr   s      =/var/www/html/dp2/backend_v2.1/server/apps/companies/utils.pynormalize_websiter$      s^    : 
Uc\c?F]]  "F ==    c                    	 t         j                  j                  | d      }|j                  }t	        |      }t        |j                         j                         dz        }d}|j                         }t        j                  j                  ||||d      j                         }|rd}t        j                  j                  |dd      j                         }|r3|j                  |j                         cxk  xr |j                  k  nc }	nd}	t         j                  j                  |d      j#                  d	      }
g }|
D ]  }t%        |d	      s|j&                  j(                  s'|j&                  j*                   d
|j&                  j,                   j/                         }|j1                  | d|j2                           |rdj5                  |      nd}|	||r|j6                  nd||j8                  |dS # t         j:                  $ r ddddddcY S t        j:                  $ r ddddddcY S t<        $ r*}t>        jA                  d|        ddddddcY d}~S d}~ww xY w)z8
    Check if it's sales time based on phone number
    Tphone_number	is_active  Fcompanybotsstart_date__lteend_date__gter)   hazel)r,   botr)   )	companiesr)   profile 	 have id , No advisor dataNo holiday today.)is_office_hours
is_holidayholiday_messagetimezone_offsetcompany_nameadvisor_data i)r9   r:   r;   r<   r>   )r9   r<   r:   r;   r>   zcheck_sales_time_by_phone N)!r   objectsgetr,   r   int	utcoffsettotal_secondsdater   filterfirstr   
start_timer   end_timer   select_relatedhasattrr3   r(   
first_name	last_namestripappendidjoinmessagenameDoesNotExist	Exceptionloggerwarning)r(   r1   r,   current_timer<   r:   todayholidaysales_timingis_sales_timecompany_usersadvisor_listuseradvisor_namer>   es                   r#   check_sales_time_by_phonerb   A   sp   M
 ((,,,RV,W++'0l446DDFMN
!!#//((! ) 
 %' 	 J"**11'wZ^1_eeg(33|7H7H7JclNcNccM!M ++ , 
 .
# 	
 !DtY'DLL,E,E"&,,"9"9!:!DLL<R<R;STZZ\##|nIdggY$GH "
 3?tyy.DU  -$29w?R.#LL(
 	
 ** 
$!!-
 	
 ## 
$!!-
 	
  
3A378$!!-
 	

s7   EH H .BH I. I.<I.I)#I.)I.c                 0
   | j                   }|j                  st        ddit        j                        S | j
                  j                  dd      st        ddit        j                        S |j                  j                  d      j                  |j                  j                  	      }|j                         st        dd
it        j                        S g }g }|D ]A  }|j                  d|      r|j                  |       '|j                  |j                         C |st        d|dt        j                        S t         j"                  j                  |j                        j%                  d      }|j                         st        ddit        j                        S t'        |      }|rt        d|it        j                        S 	 t)        j*                         5  t         j"                  j                  |      j-                          t.        j"                  j                  |j                        D ci c]  }|j0                  | }	}g }
|D ]L  }t.        j"                  j                  |      D ci c]  }|j0                  | }}|j3                         D ]0  \  }}||	v s|	|   }|j4                  |_        |j7                          2 |D ]  }t         j"                  j9                  ||j                  |j:                  |j<                  |j>                  |j4                        }|j@                  jC                         D cg c]  }|j0                  |v r||j0                     ! }}|r|j@                  jE                  |       |
j                  |        O g }|jG                         }|D ]I  }|j                  tI        ||dddd| d|j                  j                   d|j                                K tH        j"                  jK                  |d       ddd       dtM        |       dtM        |      |jG                         |r|nd|j                  j                  |jG                         d}t        ||st        jN                        S t        jP                        S c c}w c c}w c c}w # 1 sw Y   xY w# tR        $ r3}t        ddtU        |       it        jV                        cY d}~S d}~ww xY w) zOApply current company's holidays to all user's companies with bot relationshipserrorNo active companyr   confirmF*You must confirm to apply to all companiesTr)   rP   No other companies foundedit_company!No permission to edit any companyrd   denied_companiesr,   r-   z$No holidays found in current companycompany__in)r,   rS   rR   
start_dateend_dater)   bulk_replacer   N	Replaced z holidays from     → r,   
updated_byaction
model_name	object_iddetailsd   
batch_sizezHolidays applied to 
 companiesrR   applied_counttotal_companiesskipped_companiessource_companyitems_countOperation failed: ),r_   active_companyr   r   HTTP_400_BAD_REQUESTdatarA   r2   rF   excluderP   existshas_company_permissionrO   rS   HTTP_403_FORBIDDENr   r@   prefetch_relatedvalidate_holidaysr   atomicdeleter   bot_nameitemsr)   savecreaterR   rr   rs   r-   allsetcountr   bulk_createlenHTTP_200_OKHTTP_206_PARTIAL_CONTENTrU   strHTTP_500_INTERNAL_SERVER_ERROR)requestr_   user_companiesallowed_companiesdeniedr,   current_holidaysvalidation_errorr1   source_botscreated_holidaystarget_botsr   
target_bot
source_botrZ   new_holidaymatching_botshistory_logsr   response_datara   s                         r#   apply_holidays_to_all_companiesr      s   <<D"56v?Z?Z[[ <<Iu-"NOX^XsXstt ^^**T*:BBdFYFYF\F\B]N  ""<=fFaFabb F!&&~w?$$W-MM',,'	 " 8 &
 ++- 	- --d6I6I-J[[\bc""$"HIRXRmRmnn ))9:"23F<W<WXXJp!OO""/@"AHHJ .55<<TEXEX<YYC c!Y  
  ",  299@@@QQ LL#%Q  
 -8,=,=,?(Hj;.%0%:
/9/C/C
,") -@  0G")//"8"8 '$\\ '#*#5#5!(!1!1")"3"3 #9 #K +2,,*:*:*<%*<J%..+= $J$7$78*< " % %#((,,];$++K8'  0 -H L$**,E,##N##)("'wod>Q>Q>V>V=WW\]d]i]i\jk%  - ""..|.Lu "| .c2C.D-EZP !23-335+1t"1166+113
 f.@.@ttTZTsTsttG,%E "!P  p$6s1vh"?@InInoopsp   S +ASR>,SSS7B S$S
;B6S1A7S )S >SSS 	T"(T
TTc           	      	   	 t         j                  j                  | d      }|j                  }t        |j                        }t        j                         }t        |      }t        j                  d
       t        j                  d|        t        j                  d|        t        j                  d|        |j                         j                         dz  }|j                  d      j                         }d}|j!                         }	t        j                  d|	        t"        j                  j%                  ||||d      j'                         }
t        j                  d|
        |
rd}	 t(        j                  j                  ||      }t        j                  d|        |j*                  sd}n|j-                         }|j.                  |cxk  xr |j0                  k  nc }t        j                  d|j2                          t        j                  d|j4                          t        j                  d|        t        j                  d|j.                          t        j                  d|j0                          t        j                  d|        t        j                  d|        | xr |}d}t6        j                  j%                  |dd      j9                  d      }g }|D ]j  }t;        |d      s|j<                  j>                  s'tA        jB                  |      }|j<                  j>                  }|jE                  d | d!| d"       l |r|d#jG                  |      d#z   z  }|jH                  r|d$|jH                   d%z  }|d&z  }g }|D ]  }t;        |d      s|j<                  j>                  s'|j<                  jJ                   d#|j<                  jL                   jO                         }|jE                  | d'|j2                           d(jG                  |      }tQ        |      }|j4                  ||
r|
jR                  nd|tU        |      |r|s|nd)||d*S # t        j
                  $ r dddddddd	cY S w xY w# t(        j
                  $ r d}Y w xY w)+ab  
    Check if company is currently in working hours based on phone number

    Args:
        phone_number (str): Company phone number

    Returns:
        dict: {
            'is_office_hours': bool,  # false if holiday OR outside working hours, true if NOT holiday AND within working hours
            'is_holiday': bool,  # true if today is a holiday, false otherwise
            'holiday_message': str,  # Holiday message if applicable, None otherwise
            'timezone_offset': int,  # UTC offset like -7
            'transfer_instructions': str  # Transfer instructions for the company
        }
    Tr'   zno company configuresFr8   r   zCompany not foundr7   )r=   r9   r:   r;   r<   transfer_instructionsr>   zN================================= COMPANY INFO ===============================zCurrent time UTC: zCurrent company time: zCompany timezone: r*   %AzToday date in timezone: r+   z
Holiday : )r,   dayzOffice hours: zcompany id: zcompany name: zcurrent day: zoffice_hours.start_time: zoffice_hours.end_time: zcurrent_time_only: zis_within_hours: r?   )r2   r)   is_availabler3   )r_   z-If the user wants to reach, speak or talk to  then transfer to ; r4   zFIf the user wants to schedule a meeting then transfer the call to BDC z) and say 'I'll transfer you to our BDC'; zIf the user asks for an advisor who is not in the list, say 'I'm sorry, we don't have an advisor by that name at our company. Would you like to connect with someone else?'r5   r6   z`Cannot transfer calls in off hours or holidays. Please record a message for the advisor instead.)r=   r9   r;   r:   r<   r   r>   service_costs)+r   r@   rA   r,   r   rT   r   r	   nowr   rV   inforC   rD   strftimer   rE   r   rF   rG   r   is_openr   rH   rI   rP   rS   r   rJ   rK   r3   r(   r   resolve_display_namerO   rQ   
bdc_numberrL   rM   rN   get_company_services_for_botrR   rB   )r(   company_bot_settingsr,   company_timezonecurrent_time_utccurrent_time_companyr<   current_dayr:   rY   rZ   office_hoursr9   current_time_onlyis_within_hoursr   r]   user_instructionsr_   r`   advisor_phoner^   r>   servicess                           r#   get_company_working_infor     s   "
199==%  >  
 '..   0 01  ||~+G4
KK`a
KK$%5$678
KK()=(>?@
KK$%5$678 +446DDFMO '//5;;=K J %%'E
KK*5'23oo$$!,* %  eg  KK*WI&'
 "**.. / 

 	n\N34###O !5 9 9 ;*559JclNcNccOKK,wzzl34KK.78KK-}56KK3L4K4K3LMNKK1,2G2G1HIJKK-.?-@ABKK+O+<=> #-n@O  LL'' (  nY	  4#(A(A*??TJL LL55M$$?~M_`m_nnpq	  *;!<s!BB TU\UgUgTh i7 8	
  	v L4#(A(A"ll556a8N8N7OPVVXL<.	$'' CD 
 99\*L+G4H  *.57??;N / z "E %! y  	
3$2 %8-
 	
	
T ##   s$   -R 9ER) R&%R&)SSa,  

from apps.companies.utils import get_rabeeca_ai_context
get_rabeeca_ai_context('+15673471975')

from apps.companies.utils import get_rabeeca_working_info
get_rabeeca_working_info('+15673471975')

from apps.companies.utils import get_company_ai_context
get_company_ai_context('+16813956085')

from apps.companies.utils import get_company_working_info
get_company_working_info('+16813956085')

from apps.companies.utils import get_company_services_for_bot
from apps.companies.models import Company
get_company_services_for_bot(Company.objects.get(id=53))

c                 2   t         j                  j                  | d      }|j                         syt	        j
                         j                         }g }|D ]#  }|j                  }|j                  j                  | d      j                  t        |      t        d      z        j                  t        |      t        d      z        j                  d      j                         }|rvd	t        |j                         }|j                  rd	t        |j                         nd }t        |j                         }	|rd
| d| d| d| d| d| d|	 d}
n| d| }
n| d}
|j#                  |
       & dj%                  |      dz   }d| S )NT)r,   r)   zOCurrently, the company has no service to provide on call. You need to visit us.)effective_from__lte)effective_from__isnull)effective_to__gte)effective_to__isnullz-effective_from$zThe base price for the z service starts at z< dollar. Only if the customer asks about the labor rate for z , tell them: The labor rate for z is z$ dollar per hour Estimated time for r4   z Service starting at z Service is available z. .z-Our company provides the following services: )r   r@   rF   r   r	   r   rE   rS   pricesr   order_byrG   format_price
base_pricelabor_rate_per_hourformat_minutesestimated_hoursrO   rQ   )r,   r   rY   service_linesserviceservice_namepricer   
labor_rateestimated_timelineservices_texts               r#   r   r     s   %%g%FH??`LLN!EM||%% & 
 &%(1D+II

&&)EE

($
%eeg 	 \%*:*:;<=J ,, L!:!:;<=26  ,E,A,ABN .l^ <))3 5'. )**6tJ< H**6tN;K1N  ''<ZLI"^#9:DT"G J IIm,s2M:=/JJr%   c                     | syt        t        |             } t        | d      \  }}|r|r| d|dkD  rdnd d| d|dkD  rd S d S |r| d|dkD  rd S d S | d|dkD  rd S d S )	Nz	0 minutes<   z hour   sr?   r4   z minute)rB   rounddivmod)minuteshoursremaining_minutess      r#   r   r     s    %.!G%gr2E"UQYcB7q9J8K7ZknoZoSVRxyyuwRxyy	UQYc788B788#$G3Dq3HC+QRRb+QRRr%   c                 H    | y | | j                         k(  rt        |       S | S N)to_integralrB   )values    r#   r   r     s)    }%"3"3"553u:@5@r%   c                 j   	 t         j                  j                  | d      }|j                  }t	        |j
                        }t        j                         j                  |      }|j                  d      j                         }|j                         }|dk(  rt        dd      }t        dd      }nt        dd      }t        dd      }||cxk  xr |k  nc }	t        j                  j                  t        j                  	      }
g }d
}|
D ]2  }|j                  r|j                  nd}|d|j                    d| dz  }4 |	|j                   |dS # t         j"                  $ r	 ddddcY S t$        $ r:}t&        j)                  dt+        |              ddt+        |      dcY d}~S d}~ww xY w)aS  
    Get AI-friendly routing table with dealerships, departments, and phone numbers for a company
    
    Args:
        phone_number (str): Company phone number
        
    Returns:
        dict: {
            'routing_table': [
                {
                    'dealership_name': str,
                    'dealership_phone': str,
                    'departments': [
                        {
                            'department_name': str,
                            'phone_number': str
                        }
                    ]
                }
            ]
        }
    Tr'   r   sunday	   r         )company_typer?   Nz7If the user wants to talk, speak, transfer or reach to r   r   )r9   r=   r   zDealer Pulsez9Company bot settings not found for the given phone number)r9   r=   rd   zError in get_pac_working_info: )r   r@   rA   r,   r   r	   r   
astimezoner   r   r   r   rF   r   
DEALERSHIPcontact_phonerS   rT   rU   rV   rd   r   )r(   r   r,   
company_tzr   r   r   rH   rI   r9   dealershipsrouting_tabler   
dealershipdealership_phonera   s                   r#   get_pac_working_infor     s   .=
199==%  >  
 '..g../
'||~88D*33D9??A0557("aJB{HaJB{H%):FhFoo,,$// - 
  "%J "// ,,  "'^_i_n_n^o  pB  CS  BT  TV  &W  W! &  /#LL%:
 	
 ** 
#*P
 	

  
6s1vh?@#*V
 	

s$   EE F20F28/F-'F2-F2c                 L    t         j                  j                  | |||||      S )z&Helper function to log company changesrw   )r   r@   r   )r,   r_   ry   rz   r{   r|   s         r#   log_company_changer   f  s2    !!(( )  r%   c                 6   | j                  t        j                  d      t        j                  d      z        }|j                         ry| D ]G  }|j                  s|j
                  s|j                  |j
                  kD  s7d|j                   dc S  y)zValidate holidays dataT)start_date__isnull)end_date__isnullz:Invalid holidays: some holidays are missing start/end datezInvalid holiday "z%": start date must be before end dateN)rF   r   r   r   rr   rs   rS   )holidaysinvalid_holidaysrZ   s      r#   r   r   r  s    D)FHHd,KK  K '"2"2w7I7IGL\L\7\&w||n4YZZ  r%   c                     | j                  d      j                  t        j                  d      t        j                  d      z        }|j                         ryy)zValidate office hours dataT)r   start_time__isnullend_time__isnullz?Invalid office hours: some open days are missing start/end timeNrF   r   r   r   )r   invalid_hourss     r#   validate_office_hoursr    sU     '' ( fD)FHHd,KK 
 Pr%   c                     | j                  t        j                  d      t        j                  d      z        }|j                         ryy)zValidate sales timings dataTr  r  z>Invalid sales timings: some timings are missing start/end timeNr	  )sales_timingsinvalid_timingss     r#   validate_sales_timingsr    s@    #**D)FHHd,KKO Or%   c                 	   | j                   }|j                  st        ddit        j                        S | j
                  j                  dd      st        ddit        j                        S |j                  j                  d      j                  |j                  j                  	      }|j                         st        dd
it        j                        S g }g }|D ]A  }|j                  d|      r|j                  |       '|j                  |j                         C |st        d|dt        j                        S |j                   j                  |j                        }	|	j                         s/t        dd|j#                          dit        j                        S |r' ||	      }
|
rt        d|
it        j                        S 	 t%        j&                         5  |j                   j                  |      j)                          g }|D ]  }|	D ]  } |d)d|i|j*                  j,                  D ci c]M  }|j                  dk7  r<|j                  dk7  r-|j.                  s!|j                  t1        ||j                        O c}}|j                  |         |j                   j3                  |d      }g }|	j5                         }|D ]Z  }|j                  t7        ||d|dd| d|j#                          d|j                  j                   d|j                                \ t6        j                   j3                  |d       ddd       | dt9        |       dt9        |      |j5                         |r|nd|j                  j                  |	j5                         d }t        ||st        j:                        S t        j<                        S c c}w # 1 sw Y   xY w# t>        $ r}tA        |      }d!|v r4t        dd"|j#                          d#it        j                        cY d}~S d$|v r"t        dd%it        j                        cY d}~S t        dd&| it        j                        cY d}~S d}~wtB        $ r  t        dd'it        j                        cY S tD        $ r3}t        dd(tA        |       it        jF                        cY d}~S d}~ww xY w)*a}  
    Generic utility to apply current company's data to all user's companies

    Args:
        request: Django request object
        model_class: The model class (OfficeHours, SalesTiming, etc.)
        model_name: String name for logging (e.g., 'OfficeHours', 'SalesTiming')
        validation_func: Optional custom validation function

    Returns:
        Response object
    rd   re   r   rf   Frg   Trh   ri   rj   rk   rl   rm   ro   zNo z found in current companyrp   r,   rP   i  r~   rt   Nru   r4   z from rv   rw   r}   z applied to r   r   zUNIQUE constraint failedz
Duplicate z found. Please try again.zFOREIGN KEY constraint failedzInvalid company referencezData constraint violation: zPermission deniedr    )$r_   r   r   r   r   r   rA   r2   rF   r   rP   r   r   rO   rS   r   r@   r   r   r   r   _metafieldsauto_createdgetattrr   r   r   r   r   r   r   r   PermissionErrorrU   r   )r   model_classrz   validation_funcr_   r   r   r   r,   current_datar   new_recordsitemfield
new_recordcreated_recordsr   r   r   ra   	error_msgs                        r#   apply_to_all_companies_bulkr     s    <<D"56v?Z?Z[[ <<Iu-"NOX^XsXstt ^^**T*:BBdFYFYF\F\B]N  ""<=fFaFabb F!&&~w?$$W-MM',,'	 " 8 &
 ++- 	- &&--d6I6I-JL C
(8(8(:';;T"UV%::< 	< *<8W&67@[@[\\;p!&&3D&ELLN K,(D!, " '"NYN_N_NfNf iNfU#jjD0UZZ95LUZUgUg !::wtUZZ'@@Nf i"J
  &&z2 ) - *11==kVY=ZO L &&(E,##N##))"'wa
0@0@0B/C6$J]J]JbJbIcchipiuiuhvw%  - ""..|.LA "H %\#6G2H1IT !23-335+1t"1166'--/
 f.@.@ttTZTsTsttCi "!\  vF	%2W
:3C3C3E2FF_&`a#)#>#>@ @,	9W&AB6KfKfggW(CI;&OPY_YtYtuu Z"56v?X?XYY p$6s1vh"?@InInoops   O9 )AO->AO(C	O-A9O9 O9 (O--O62O9 9	S6=R?S6 R%S6+R
S6)S6;S6(S1+S61S6r   )5loggingdatetimer   zoneinfor   	django.dbr   r   r   django.db.modelsr   django.utilsr	   urllib.parser
   rest_frameworkr   rest_framework.responser   apps.core.modelsr   apps.companies.constantsr   apps.companies.modelsr   r   r   r   r   r   r   apps.userprofile.servicesr   utils.timezone_utilsr   	getLogger__name__rV   r   r$   rb   r   r   db_shell_testingr   r   r   r   r   r   r  r  r   r  r%   r#   <module>r2     s       9 9  ! ! ! , ! 0   6 1			8	$$3 $3 $NQ
hsplbJ *0KfSs S AT
n	 	qpr%   