
    ^|iF                     n   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
  e       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 G d dej"                        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 G d de      Zy)    )models)ValidationError)get_user_model)AbstractTimeStampModel)BotNameCompanyTypec                       e Zd ZdZ ej
                  dej                  d      Z ej                  de	      Z
 ej                  ddddd	
      Z ej                  dd      Zd Zy)CompanyBotSettingsz0Settings for company-specific bot configurationsCompanybot_settings	on_deleterelated_name2   
max_lengthchoices   TzPhone number of the botr   uniquenullblank	help_textz"Whether this bot setting is activedefaultr   c                 L    | j                   j                   d| j                   S N - )companynamebot_nameselfs    >/var/www/html/dp2/backend_v2.1/server/apps/companies/models.py__str__zCompanyBotSettings.__str__   s"    ,,##$C77    N)__name__
__module____qualname____doc__r   
ForeignKeyCASCADEr   	CharFieldr   r!   phone_numberBooleanField	is_activer%    r&   r$   r
   r
      sy    :f..#G
  v2w?H#6##+	L $##6I
8r&   r
   c                   |    e Zd ZdZ ej
                  dej                  d      Z ej                  dd      Z	 ej                  ddd	
      Z ej                  d      Z ej                  d      Z ej                  dd      Z ej"                  dddd      Z G d d      Zd Z fdZ fdZd Z xZS )Holidayz+Holiday model for company-specific holidaysr   holidaysr      z#Holiday name (e.g., Christmas, EID)r   r   TzHoliday messager   r   r   zStart date of holiday periodr   zEnd date of holiday periodzWhether this holiday is activer   r
   zBots this holiday applies tor   r   r   c                       e Zd Zg dZdgZdZy)Holiday.Meta)r   r    
start_dater<   HolidaysNr'   r(   r)   unique_togetherorderingverbose_name_pluralr1   r&   r$   Metar;   0   s    ; >(r&   rB   c                    | j                   | j                  k(  r3| j                  j                   d| j                   d| j                    dS | j                  j                   d| j                   d| j                    d| j                   dS )Nr   z ()z to )r<   end_dater   r    r"   s    r$   r%   zHoliday.__str__5   sw    ??dmm+ll''(DII;b8IKK,,##$C		{"T__4ET$--XYZZr&   c                     t         |           | j                  r2| j                  r%| j                  | j                  kD  rt	        d      yyy)zValidate holiday datesz-End date must be after or equal to start dateN)supercleanr<   rE   r   r#   	__class__s    r$   rH   zHoliday.clean:   sA    ??t}}.%&UVV /  -?r&   c                 D    | j                          t        |   |i | y NrH   rG   saver#   argskwargsrJ   s      r$   rN   zHoliday.saveB       

d%f%r&   c                     | j                   r2| j                  r&| j                  | j                   z
  j                  dz   S y)z$Get number of days in holiday period   r   )r<   rE   daysr"   s    r$   get_duration_dayszHoliday.get_duration_daysF   s0    ??t}}MMDOO399A==r&   )r'   r(   r)   r*   r   r+   r,   r   r-   r    	TextFieldmessage	DateFieldr<   rE   r/   r0   ManyToManyFieldbotsrB   r%   rH   rN   rV   __classcell__rJ   s   @r$   r3   r3   !   s    5f	V^^R\]G6s6[\DfD@QRG!!!,JKJv*FGH###D<\]I!6!!0	D) )
[
W&r&   r3   c                   0    e Zd ZdZg dZ ej                  dej                  d      Z ej                  de      Z
 ej                  dd	
      Z ej                  ddd      Z ej                  ddd      Z G d d      Zd Z fdZ fdZ xZS )OfficeHoursz3Office hours configuration for each day of the week))mondayMonday)tuesdayTuesday)	wednesday	Wednesday)thursdayThursday)fridayFriday)saturdaySaturday)sundaySundayr   office_hoursr   
   r   Fz&Whether the office is open on this dayr   TzOffice opening timer7   zOffice closing timec                       e Zd ZddgZdgZdZy)OfficeHours.Metar   dayzOffice HoursNr>   r1   r&   r$   rB   rq   ^   s    $e,7,r&   rB   c                     | j                   rC| j                  j                   d| j                          d| j                   d| j
                   S | j                  j                   d| j                          dS )Nr   : : Closed)is_openr   r    get_day_display
start_timeend_timer"   s    r$   r%   zOfficeHours.__str__c   sq    <<ll''(D,@,@,B+C2dooEVVYZ^ZgZgYhii,,##$C(<(<(>'?xHHr&   c                     t         |           | j                  rH| j                  r| j                  st        d      | j                  | j                  k\  rt        d      yy)z#Validate office hours configurationz4Start and end times are required when office is open!End time must be after start timeN)rG   rH   rv   rx   ry   r   rI   s    r$   rH   zOfficeHours.cleanh   sR    <<??$--%&\]]$--/%&IJJ 0	 r&   c                 D    | j                          t        |   |i | y rL   rM   rO   s      r$   rN   zOfficeHours.saves   rR   r&   )r'   r(   r)   r*   DAY_CHOICESr   r+   r,   r   r-   rr   r/   rv   	TimeFieldrx   ry   rB   r%   rH   rN   r\   r]   s   @r$   r_   r_   L   s    =K  f	V^^R`aG
&

b+
>C!f!!%;cdG!!!t4CXYJvTAVWH- -
I
	K& &r&   r_   c                   (    e Zd ZdZdgZ ej                  dej                  d      Z ej                  d      Z
 ej                  d      Z ej                  d	d
      Z ej                  ded      Z G d d      Zd Z fdZ fdZ xZS )SalesTimingz#Sales timing configuration for bots)hazelHazelr   sales_timingsr   zSales start timer8   zSales end timeTz#Whether this sales timing is activer   d   z Bot this sales timing applies to)r   r   r   c                       e Zd ZdZddgZy)SalesTiming.MetazSales Timingsr   rx   Nr'   r(   r)   rA   r@   r1   r&   r$   rB   r      s    -|,r&   rB   c                     | j                   j                   d| j                   d| j                   d| j                   S )Nr   rt   )r   r    botrx   ry   r"   s    r$   r%   zSalesTiming.__str__   s7    ,,##$CzDOO3DCWWr&   c                     t         |           | j                  r| j                  st	        d      | j                  | j                  k\  rt	        d      y)z#Validate sales timing configurationz Start and end times are requiredr{   N)rG   rH   rx   ry   r   rI   s    r$   rH   zSalesTiming.clean   sF    dmm!"DEE??dmm+!"EFF ,r&   c                 D    | j                          t        |   |i | y rL   rM   rO   s      r$   rN   zSalesTiming.save   rR   r&   )r'   r(   r)   r*   BOT_CHOICESr   r+   r,   r   r~   rx   ry   r/   r0   r-   r   rB   r%   rH   rN   r\   r]   s   @r$   r   r   w   s    -K  f	V^^RabG!!!,>?Jv*:;H###D<abI
&

c;Jl
mC- -XG& &r&   r   c                   ~    e Zd ZdZ ej
                  dej                  d      Z ej                  dd      Z	 ej                  dg d	d
d      Z
 ej                  edd      Z ej                  edd      Z ej                  dd      Z ej"                  d      Z G d d      Zd Z fdZ fdZ xZS )CatchPhrasezCatchphrases for companiesr   catch_phrasesr   r5   zShort catch phraser6   r   )stringzString Match)wordzWord Boundary)semanticzSemantic (LLM)r   z"How this phrase should be detected)r   r   r   r   Tz#Alternative phrasings or variations)r   r   r   ze.g. ['user', 'agent']gffffff?z'Ignore detections below this confidencer   r   c                   H    e Zd ZdZdZddgZ ej                  ddg      gZy)CatchPhrase.MetazCatch Phrases)r   phraser   r   r0   fieldsN)	r'   r(   r)   rA   r?   r@   r   Indexindexesr1   r&   r$   rB   r      s1    -/x(FLLK 89
r&   rB   c                 L    | j                   j                   d| j                   S r   )r   r    r   r"   s    r$   r%   zCatchPhrase.__str__   s"    ,,##$C}55r&   c                     t         |           | j                  r| j                  j                         st	        d      y)zValidate catchphrasezCatch phrase cannot be emptyN)rG   rH   r   stripr   rI   s    r$   rH   zCatchPhrase.clean   s3    {{$++"3"3"5!"@AA #6r&   c                 D    | j                          t        |   |i | y rL   rM   rO   s      r$   rN   zCatchPhrase.save   rR   r&   )r'   r(   r)   r*   r   r+   r,   r   r-   r   
match_type	JSONFieldlistsynonymsallowed_speakers
FloatFieldmin_confidencer/   r0   rB   r%   rH   rN   r\   r]   s   @r$   r   r      s    $f..$G
 V&F
 "!!

 6	J  v7H (v''* 'V&&;N
 $##D1I
 
6B& &r&   r   c                      e Zd Z ej                  dej
                  d      Z ej                  dej
                  d      Z ej                  dej
                        Z ej                  dg d	d
d
      Z
 ej                  d
d
d      Z ej                  dg d      Z ej                  d
d      Z ej                   d
d      Z ej                  dd
d      Z G d d      Zd Zy)CallCatchPhrasez
calls.Callr   r   r   occurrenceszcompanies.Company)r   r   ))agentAgent)userUser)advisorAdvisorT)r   r   r   r   z Confidence score between 0 and 1r7   )r   )
assemblyai
AssemblyAI)llmLLMr   z.Exact utterance text that triggered the phrase)r   r   zWhen phrase was detected)auto_now_addr   r   z%AI / model version used for detection)r   r   r   c                   b    e Zd ZdZ ej
                  ddg       ej
                  dg      gZy)CallCatchPhrase.Meta)callr   r   r   r   r   Nr'   r(   r)   r?   r   r   r   r1   r&   r$   rB   r     s1    ,FLLH 56FLL)
r&   rB   c                 L    | j                    d| j                  j                   S )Nu    → )call_idr   r"   s    r$   r%   zCallCatchPhrase.__str__  s"    ,,uT[[%7%7$899r&   N)r'   r(   r)   r   r+   r,   r   r   r   r-   speakerr   
confidencesourcerW   matched_textDateTimeFielddetected_atmodel_versionrB   r%   r1   r&   r$   r   r      s   6..$D
 V.."F
  f..G
 f

 	G #""4J V
F $6##BL
 '&&&,K
 %F$$9M
 
:r&   r   c                   J   e Zd ZdZ ej
                  dej                  d      Z ej
                  dej                  d      Z ej                  dd	      Z
 ej                  d
d	      Z ej                  ddd      Z ej                  ddd      Z G d d      Zd Zy)CompanyHistoryz0History tracking for all company-related changesr   historyr   z	core.Usercompany_actionsr   z+Action performed: created, updated, deletedr6   r   z"Name of the model that was changedTzID of the changed objectr7   z*Human readable description of what changed)r   r   r   c                       e Zd ZdZdgZy)CompanyHistory.MetazCompany Historyz-created_atNr   r1   r&   r$   rB   r   $  s    /!?r&   rB   c           	          | j                   j                   d| j                   d| j                   d| j                   d| j
                  j                   	S )Nr    z (ID: z) by )r   r    action
model_name	object_id
updated_byusernamer"   s    r$   r%   zCompanyHistory.__str__(  sM    ,,##$C}Adoo5FfT^^L\\abfbqbqbzbza{||r&   N)r'   r(   r)   r*   r   r+   r,   r   r   r-   r   r   IntegerFieldr   rW   detailsrB   r%   r1   r&   r$   r   r     s    :f	V^^R[\G""";&..WhiJV7deF!!!S<`aJ###TE_`If)U\`hlmG# #}r&   r   c                   "   e Zd ZdZ ej
                  ddddd      Z ej
                  d      Z ej
                  ddd      Z ej                  dd	      Z
 ej
                  ddd      Z ej
                  dd
      Z ej                  eddd      Z ej                   eej"                  dddd      Z ej                  dd	      Z ej                  dd	      Z ej
                  dej,                   ej.                         dd      Z ej2                  ddd      Z ej
                  ddd      Z ej
                  ddd      Z ej2                  d      Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d  Z'd! Z( G d" d#      Z)y$)%r   zCompany model for multi-tenancyr5   Tz!Unique identifier from GHL systemr   r   r   )r   r   r   )r   r   UTCr   r   missing_call_notify_companiesz0Users who will be notified when calls are missedr9   default_transfer_companiesz@Default user to receive calls when no other agents are available)r   r   r   r   r   )r   r   r   r   r   F)r   r   r   r   r   r   r   c                 D    | j                    d| j                  rd S d S )Nr   ActiveInactive)r    r0   r"   s    r$   r%   zCompany.__str__T  s)    ))CDNNKLL
KLLr&   c                 6    | j                   j                         S )z'Get the number of users in this company)userscountr"   s    r$   get_user_countzCompany.get_user_countW  s    zz!!r&   c                 :    | j                   j                  d      S )$Get all active users in this companyTr0   r   filterr"   s    r$   get_active_userszCompany.get_active_users[  s    zz  4 00r&   c                 6    | j                   j                         S )r   r   r"   s    r$   get_all_userszCompany.get_all_users_  s    zz  ""r&   c                 H    | j                   r| j                   j                  S y)z&Get the name of default transfer staffzNot Set)default_transfer_staffr   r"   s    r$   get_default_transfer_staff_namez'Company.get_default_transfer_staff_namec  s     &&..777r&   c                     	 | j                   j                  |j                               S # t        j                  $ r Y yw xY w)z#Get office hours for a specific day)rr   N)rn   getlowerr_   DoesNotExist)r#   day_names     r$   get_office_hours_for_dayz Company.get_office_hours_for_dayi  s@    	$$((X^^-=(>>'' 		s   ), AAc                    g }dD ]  }| j                  |      }|rH|j                  r<|j                  |j                          d|j                   d|j
                          ^|j                         }|j                  | d        |S )z)Get a summary of office hours for display)r`   rb   rd   rf   rh   rj   rl   rt   r   ru   )r   rv   appendrw   rx   ry   title)r#   summaryrr   hoursday_displays        r$   get_office_hours_summaryz Company.get_office_hours_summaryp  s    aC11#6E%"7"7"9!:"U=M=M<NcRWR`R`Qabc "iik+h78 b r&   c                 :    | j                   j                  d      S )z-Get all active sales timings for this companyTr   )r   r   r"   s    r$   get_active_sales_timingsz Company.get_active_sales_timings  s    !!((4(88r&   c                     g }| j                         D ]9  }|j                  |j                   d|j                   d|j                          ; |r|S dgS )z*Get a summary of sales timings for displayrt   r   zNo active sales timings)r   r   r   rx   ry   )r#   r   timings      r$   get_sales_timings_summaryz!Company.get_sales_timings_summary  sX    335FNNfjj\F,=,=+>c&//ARST 6!wB(A'BBr&   c                 N    t        | j                  j                  dd            S )z-Get list of all catchphrases for this companyr   T)flat)r   r   values_listr"   s    r$   get_catch_phrases_listzCompany.get_catch_phrases_list  s#    D&&228$2GHHr&   c                 0    | j                         }|r|S dgS )z)Get a summary of catchphrases for displayzNo catch phrases set)r   )r#   phrasess     r$   get_catch_phrases_summaryz!Company.get_catch_phrases_summary  s!    --/!w?(>'??r&   c                       e Zd ZdZy)Company.Meta	CompaniesN)r'   r(   r)   rA   r1   r&   r$   rB   r    s    )r&   rB   N)*r'   r(   r)   r*   r   r-   ghl_company_idr    phonerW   office_time
bdc_numbertimezonerZ   r   missing_call_notify_tor+   SET_NULLr   websitebior   SIMPLEmodel_choicescompany_typer/   is_dealershipcontact_person_namecontact_phoner0   r%   r   r   r   r   r   r   r   r   r   r  rB   r1   r&   r$   r   r   +  s   )%V%%t5N
 6s+DF$TBE"&""D9K!!!Rt$GJv2u=H3V334D	 /V..//1T fT5G
&

D
1C#6##"")))+	L (F''DMM*&**cDQ$F$$TJM###D1IM"1#9CI@
* *r&   r   c                       e Zd Z ej                  eej                  d      Z ej                  d      Z	 ej                  d      Z
 ej                  dd      Z G d d	      Zd
 Zy)
Dealershipdealershipsr   r5   r   r   T)r   r   c                       e Zd ZdZy)Dealership.Metar   r    Nr'   r(   r)   r?   r1   r&   r$   rB   r    s    -r&   rB   c                 N    | j                   dz   | j                  j                   z   S r   )r    r   r"   s    r$   r%   zDealership.__str__  s     yy5 4<<#4#444r&   N)r'   r(   r)   r   r+   r   r,   r   r-   r    r  r  rB   r%   r1   r&   r$   r  r    se    f6>>P]^G6s+D*&**c:$F$$4@M. .5r&   r  c                       e Zd Z ej                  d      Z ej                  ddd      Z ej                  eej                  d      Z
 G d d	      Zd
 Zy)DealershipDepartmentr5   r   r   Tr   departmentsr   c                       e Zd ZdZy)DealershipDepartment.Meta)
dealershipr    Nr  r1   r&   r$   rB   r!    s    0r&   rB   c                 N    | j                   dz   | j                  j                   z   S r   )r    r"  r"   s    r$   r%   zDealershipDepartment.__str__  s     yy5 4??#7#777r&   N)r'   r(   r)   r   r-   r    r.   r+   r  r,   r"  rB   r%   r1   r&   r$   r  r    s^    6s+D#6##L #"".."J1 18r&   r  c                   
   e Zd ZdZ ej
                  eej                  dd      Z ej                  dd      Z
 ej                  ddd      Z ej                  dd	      Z ej                  d
      Z G d d      Zd Zy)ServicezT
    Represents a service offered by a company (fully dynamic, no BookingType).
    servicesTr   r   db_index   )r   r(  z;Unique service identifier inside a company, e.g. OIL_CHANGE)r   r(  r   r   r   r   c                   d    e Zd ZdZ ej
                  ddg       ej
                  ddg      gZy)Service.Meta)r   coder   r0   r   r    Nr   r1   r&   r$   rB   r,    s4    -FLLK 89FLLF 34
r&   rB   c                 L    | j                   j                   d| j                   S r   r  r"   s    r$   r%   zService.__str__  s"    ,,##$C		{33r&   N)r'   r(   r)   r*   r   r+   r   r,   r   r-   r    r-  rW   descriptionr/   r0   rB   r%   r1   r&   r$   r%  r%    s      f..	G 6D
 6OD #&""D9K###D1I
 
4r&   r%  c                      e Zd ZdZ ej
                  eej                  dd      Z ej
                  e	ej                  dd      Z
 ej                  dd      Z ej                  dddd	      Z ej                  d
ddd	      Z ej                  d      Z ej"                  dd      Z ej                  d      Z ej(                  dd      Z ej(                  dd      Z G d d      Zd Zed        Zy)ServicePricezt
    Price configuration for a service per company.
    Supports future price versions and labor based pricing.
    pricesTr'  service_pricesro      )
max_digitsdecimal_places)r5  r6  r   r      r   USDr   r*  c                       e Zd ZdZ ej
                  ddg       ej
                  ddg       ej
                  ddg      gZy)	ServicePrice.Meta)servicer   effective_fromr   r0   r   r;  r<  effective_toNr   r1   r&   r$   rB   r:    sH    BFLLK 89FLLK 89FLL!1> BC
r&   rB   c                     | j                   r2| j                  r%| j                   | j                  kD  rt        d      yyy)z[
        Prevent overlapping active price ranges for the same service and company.
        z+effective_from cannot be after effective_toN)r<  r=  r   r"   s    r$   rH   zServicePrice.clean  sB     4#4#4""T%6%66%&STT 7 $5r&   c                     | j                   r5| j                  r)| j                  | j                   | j                  dz  z  z   S | j                  S )N<   )labor_rate_per_hourestimated_hours
base_pricer"   s    r$   total_pricezServicePrice.total_price  sE     ##(<(<??d&>&>$BVBVY[B[&\]]r&   N)r'   r(   r)   r*   r   r+   r%  r,   r;  r   r   DecimalFieldrC  rA  rB  r/   starting_atr-   currencyr0   rY   r<  r=  rB   rH   propertyrD  r1   r&   r$   r1  r1    s&   
  f..	G  f..%	G %$$1EJ-&--a
 *f))QO
 &&%%d3Kv2u=H###D1I%V%%4t<N#6##T:L
 
U  r&   r1  N)	django.dbr   django.core.exceptionsr   django.contrib.authr   coresite.mixinr   apps.companies.constantsr   r   r   r
   r3   r_   r   r   Modelr   r   r   r  r  r%  r1  r1   r&   r$   <module>rO     s     2 . 1 9 8/ 8,)$ )V)&( )&V&( &@>&( >&@B:fll B:H}+ } i*$ i*V
5' 
581 8$!4$ !4F=) =r&   