o
    ܦhZe                     @   s  d dl mZ d dlmZ d dlmZ d dlZd dlmZ d dl	m
Z
 d dlZd dlZe ZG dd dejZG d	d
 d
ejZeZG dd dejZG dd dejZG dd dejZG dd dejZG dd dejZG dd dejZG dd dejZdS )    )models)get_user_model)DecimalNtimezone)	timedeltac                   @   sX   e Zd ZejdddZejddZejddddZej	dd	Z
d
d ZG dd dZdS )CustomerTag2   T)
max_lengthuniqueblank   z#007bffzHex color code for the tag)r
   default	help_textauto_now_addc                 C      | j S N)nameself r   0/var/www/html/optinet_system/customers/models.py__str__   s   zCustomerTag.__str__c                   @      e Zd ZdgZdS )zCustomerTag.Metar   N__name__
__module____qualname__orderingr   r   r   r   Meta       
r!   N)r   r   r   r   	CharFieldr   	TextFielddescriptioncolorDateTimeField
created_atr   r!   r   r   r   r   r      s    r   c                   @   s   e Zd Zg dZejddZejddZejddddZ	ej
d	d
dZejdeddZej
d	d
eddZejddZejddZdd ZG dd dZdS )Service))monthlyMonthly)	quarterly	Quarterly)annuallyAnnuallyd   r
   zSpeed in Mbpsr   zFair Usage Policy in GBT)r   nullr   
      
max_digitsdecimal_places   r*   r
   choicesr   0.00)r7   r8   r   r   r   c                 C      | j  d| j dS )N - Mbps)r   
speed_mbpsr   r   r   r   r   )      zService.__str__c                   @   s   e Zd ZdZdZdS )zService.Metar)   ServicesN)r   r   r   verbose_nameverbose_name_pluralr   r   r   r   r!   ,   s    r!   N)r   r   r   BILLING_CYCLE_CHOICESr   r#   r   IntegerFieldrA   fup_gbDecimalFieldpricebilling_cycler   installation_feeBooleanField	is_activer'   r(   r   r!   r   r   r   r   r)      s    r)   c                       sf  e Zd ZddgZg dZejeejddddZ	ej
dddd	Zej
ded
dZejdejddddZejddZejdddZej
ddddZej
ddddZej
ddddZej
ddddZej
ddddZej
dddddZej
dddddZejdddZej
ddddZejdd dZej
d!dd"dZej
ddddZ ej
d!d#Z!e Z"ej#d$d%ddd&Z$ej#d'd%ddd&Z%e Z&ej
d(ddd)d*Z'ej
ddd+dZ(ej
ddd,dZ)eje*ej+dd-Z,ej
ded.dZ-e.d/d0 Z/ej0dddd1d2Z1ej0ddd3d4Z2ej0ddd5d4Z3ej0ddd6d4Z4ej0dddZ5ej0ddd7d4Z6ejdd8Z7ej8e9dd9d:Z:ej#d;d<e;d=d>d?Z<ejddZ=ej0dd@Z>ej0ddAZ?dBdC Z@ fdDdEZAdidGdHZBe.dIdJ ZCe.dKdL ZDdMdN ZEdOdP ZFe.dQdR ZGe.dSdT ZHe.dUdV ZIe.dWdX ZJe.dYdZ ZKe.d[d\ ZLe.d]d^ ZMe.d_d` ZNe.dadb ZOdcdd ZPdedf ZQdgdh ZR  ZSS )jCustomer)
individual
Individual)institutionInstitution))activeActive)	suspended	Suspended)disconnectedDisconnected)trialzTrial Period)pending_activationzPending Activation)inactiveInactivecustomer_profileT)	on_deleterelated_namer3   r   r9   F)r
   r   editablerP   r:   r   sub_accountsr_   r3   r   r`   r=   r3   r      zFor individual customersr
   r   r   r	   )r
   r   r3   zFor institutional customersr0   zContact person's first namezContact person's last namezBusiness registration number)r
   r   r3   r   zVAT registration numberzRegistered company addressr   r   zBilling contact personzBilling contact email   zBilling contact phoner1   r4      r7   r8   r3   r         z0Auto-populated from MikroTik on first connection)r
   r   ra   r   z*PPPoE username for MikroTik authenticationz*PPPoE password for MikroTik authentication)r_   r3   r[   c                 C   r   r   )servicer   r   r   r   packageq   s   zCustomer.packagez"Auto-populated on first connection)r3   r   ra   r   zTrial period startr3   r   r   zTrial period endz Actual service start after trialzManual override for suspensionr   	customers)r   r`      r5   r<   z/Customer's account balance for advance payments)r7   r8   r   r   r   auto_nowc                    s,   t jt j d  d fddtdD S )zOGenerate a random 6-character password with alphanumeric and special charactersz!@#$%&* c                 3   s    | ]}t  V  qd S r   )secretschoice).0_
charactersr   r   	<genexpr>   s    z3Customer.generate_pppoe_password.<locals>.<genexpr>   )stringascii_lettersdigitsjoinranger   r   ry   r   generate_pppoe_password   s   z Customer.generate_pppoe_passwordc                    s   | j sX| jr2| jr2| jj }| js(tjj| jddd }|r%|jd nd| _| d| j | _ n&tjjdddd	 }|rOt	|j d
d  }|d }nd}d|d| _ | j
sb| j rb| j | _
| jsj|  | _t j|i | d S )NT)parent_customeris_sub_accountz-sub_account_number   -OPTF)customer_id__startswithr   z-customer_id   06d)customer_idr   r   sub_account_numberrO   objectsfilterorder_byfirstintpppoe_usernamepppoe_passwordr   supersave)r   argskwargs	parent_idlast_sublast_customerlast_number
new_number	__class__r   r   r      s8   



zCustomer.saveNc                 C   s   | j r| j S |s|  }| jdkr| j}| j}n)| jr#| jdd nd}| jr?t| jddkr?d| jddd nd}t	j
j| j| j|||dd}|| _ |   |S )	z'Create a user account for this customerrR    r   rt   r   Nclient)usernameemailpassword
first_name	last_namerole)userr   customer_typecontact_person_first_namecontact_person_last_name	full_namesplitlenr   Userr   create_userr   r   r   )r   r   r   r   r   r   r   r   create_user_account   s(   
8
zCustomer.create_user_accountc                 C   s,   | j dkr| jp| j d| j  S | jS )z/Returns appropriate name based on customer typerR   r   )r   company_namer   r   stripr   r   r   r   r   display_name   s   
zCustomer.display_namec                 C   s$   | j dkr| j d| j  S dS )z4Returns full name of contact person for institutionsrR   r   rt   )r   r   r   r   r   r   r   r   contact_person_full_name   s   
z!Customer.contact_person_full_namec                 C   st   ddl m} | jdkr| js|ddidS | jdkr6| js$|ddi| js-|d	d
i| js8|ddidS dS )z$Validate customer data based on typer   ValidationErrorrP   r   z/Full name is required for individual customers.rR   r   z5Company name is required for institutional customers.r   zBContact person first name is required for institutional customers.r   zAContact person last name is required for institutional customers.N)django.core.exceptionsr   r   r   r   r   r   r   r   r   r   r   clean   s   

zCustomer.cleanc                 C   s   | j  d| j S )Nr?   )r   r   r   r   r   r   r      s   zCustomer.__str__c                 C   r   )z<Returns account balance (positive = credit, negative = debt))account_balancer   r   r   r   current_balance   s   zCustomer.current_balancec                 C   s.   ddl m} |jj| dd}tdd |D S )z'Returns total amount of unpaid invoicesr   Invoiceunpaid)customerstatusc                 s   s    | ]}|j V  qd S r   )total_amount)rw   invoicer   r   r   r{      s    z.Customer.outstanding_amount.<locals>.<genexpr>)billing.modelsr   r   r   sum)r   r   unpaid_invoicesr   r   r   outstanding_amount   s   zCustomer.outstanding_amountc                 C   s:   ddl m} ddlm} |jj| d|  d}| S )Nr   r   r   r   )r   r   due_date__lt)	r   r   django.utilsr   r   r   nowdateexists)r   r   r   overdue_invoicesr   r   r   
is_overdue  s   
zCustomer.is_overduec                 C   s   | j | j S )zaReturns net balance (outstanding - account balance). Positive = owes money, Negative = has credit)r   r   r   r   r   r   net_balance  s   zCustomer.net_balancec                 C   s   ddl m} || S )z9Returns current service status using ServicePeriodManagerr   )ServicePeriodManager)billing.servicesr   #get_customer_current_service_status)r   r   r   r   r   current_service_status  s   
zCustomer.current_service_statusc                 C   s   | j }|d dkr|d S dS )z$Returns when current service expiresr   rT   
expires_atN)r   )r   r   r   r   r   service_expires_at  s   zCustomer.service_expires_atc                 C   s   | j o	| j| j jkS )z@Returns True if customer has sufficient balance for auto-renewal)rm   r   rJ   r   r   r   r   can_auto_renew  s   zCustomer.can_auto_renewc                 C   s4   | j r| jsdS t }| j |  ko| jkS   S )z$Check if customer is in trial periodF)trial_start_datetrial_end_dater   r   )r   r   r   r   r   is_trial_active$  s   zCustomer.is_trial_activec                 C   s*   | j sdS | jt  }td| d S )zGet remaining trial hoursr   i  )r   r   r   r   maxtotal_seconds)r   	remainingr   r   r   trial_remaining_hours,  s   zCustomer.trial_remaining_hoursc                 K   sN   | j rtdtjjd	| d| j|dd|dd|d| jd|}|S )
z(Create a sub-account under this customerz1Sub-accounts cannot create their own sub-accountsTr   rt   phonephysical_address)r   r   r   r   r   r   Nr   )r   
ValueErrorrO   r   creater   getr   )r   r   sub_accountr   r   r   create_sub_account4  s   

	zCustomer.create_sub_accountc                 C   s   | j rtj S | j S )z(Get all sub-accounts under this customer)r   rO   r   nonerb   allr   r   r   r   get_all_sub_accountsD  s   

zCustomer.get_all_sub_accountsc                 C   s   | j r| jS | S )z'Get the main account (for sub-accounts))r   r   r   r   r   r   get_main_accountJ     zCustomer.get_main_accountr   )Tr   r   r   CUSTOMER_TYPE_CHOICESSERVICE_STATUS_CHOICESr   OneToOneFieldr   CASCADEr   r#   r   r   
ForeignKeyr   rM   r   PositiveIntegerFieldr   r   id_passportr   r   r   business_registration_number
vat_numberr$   company_addressbilling_contact_name
EmailFieldbilling_contact_emailbilling_contact_phonekra_pinr   r   rI   gps_latitudegps_longituder   
router_macr   r   r)   SET_NULLrm   service_statuspropertyrn   r'   installation_dater   r   service_start_datelast_suspension_datemanual_suspension_overridenotesManyToManyFieldr   tagsr   r   rN   r(   
updated_atr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   rO   3   s    	

&











rO   c                       s   e Zd ZejeejddZeje	j
ddZejddZe ZejddZejdddZ fd	d
Zedd Zedd Zdd Z  ZS )CustomerInvitation
invitationr_   r`   T)r   r   r   Fr=   rd   c                    s0   | j st tdd | _ t j|i | d S )Nr   days)r   r   r   r   r   r   r   r   r   r   r   r   r   V  s   zCustomerInvitation.savec                 C   s   t  | jkS r   )r   r   r   r   r   r   r   
is_expired[  s   zCustomerInvitation.is_expiredc                 C   s   | j  o| j S r   )is_usedr  r   r   r   r   is_valid_  r   zCustomerInvitation.is_validc                 C   s"   d| j j d| jrd S d S )NzInvitation for r?   UsedPending)r   r   r  r   r   r   r   r   c     "zCustomerInvitation.__str__)r   r   r   r   r   rO   r   r   	UUIDFielduuiduuid4tokenr'   r(   r   rM   r  used_atr   r   r  r  r   r  r   r   r   r   r  N  s    

r  c                   @   s   e Zd Zg dZejeejddZej	dedZ
ejdddZej	d	d
Zej	ddddZejdddZejdddZejeejdddZejddZdd ZG dd dZdS )CustomerBalanceTransaction))creditzCredit (Payment/Top-up))debitzDebit (Bill Payment))refundRefund)
adjustmentzManual Adjustmentbalance_transactionsr	  r9   r
   r;   r4   r5   r6   re   r1   r0   TzPayment ID, Invoice ID, etc.rf   rq   r_   r3   r   r   c                 C   s   | j j d|   d| j S )Nr?   z: )r   r   get_transaction_type_displayamountr   r   r   r   r   x     z"CustomerBalanceTransaction.__str__c                   @   r   )zCustomerBalanceTransaction.Meta-created_atNr   r   r   r   r   r!   {  r"   r!   N)r   r   r   TRANSACTION_TYPE_CHOICESr   r   rO   r   r   r#   transaction_typerI   r"  r%   reference_idbalance_beforebalance_afterr   r   processed_byr'   r(   r   r!   r   r   r   r   r  f  s    r  c                       s  e Zd Zg dZejeejddZej	ddZ
ej	ddZejdedd	Zejd
ddZejd
ddZejd
ddZejd
dZejd
dZejd
dZejdddZejdddZejdddZejdddZejdddZejdddZejdddZejdddZejdddZejdddZejeej ddddZ!ej"dddZ#ejddZ$ej"dd Z%ej"dd!Z&d"d# Z' fd$d%Z(e)d&d' Z*e)d(d) Z+d*d+ Z,G d,d- d-Z-  Z.S ).MarketingWeeklyReport))draftDraft)	submitted	Submitted)reviewedReviewed)approvedApprovedmarketing_reportsr	  zMonday of the reporting weekr2   zSunday of the reporting weekr9   r,  r:   r   z'Number of customers/prospects contactedr   r   zNumber of physical site visitsz Number of service demonstrationsr=   Tz7Summary of customer feedback, concerns, and suggestionsrg   z6Observed competitor activities, pricing, or strategiesz/New market trends or customer behavior patternsz=Suggestions for improving services based on customer feedbackz7Pricing strategy suggestions based on market conditionsz1Marketing approach improvements or new strategiesz+Main challenges encountered during the weekz-Solutions tried or implemented for challengesz,Planned activities and targets for next weekz+Support or resources needed from managementreviewed_marketing_reportsrc   rd   r   r   rr   c                 C   s>   ddl m} | j| jkr|d| j| j jdkr|dd S )Nr   r   z1Week ending date must be after week starting dater|   z7Report period must be exactly 7 days (Monday to Sunday))r   r   week_endingweek_startingr  r   r   r   r   r     s   zMarketingWeeklyReport.cleanc                    s4   | j r| js| j tdd | _t j|i | d S )Nr|   r
  )r8  r7  r   r   r   r  r   r   r   r     s   zMarketingWeeklyReport.savec                 C   $   | j dkrt| j| j  d dS dS Nr   r0   r5   )new_leads_generatedroundleads_convertedr   r   r   r   conversion_rate     
z%MarketingWeeklyReport.conversion_ratec                 C   r9  r:  )r;  r<  qualified_leadsr   r   r   r   qualification_rate  r?  z(MarketingWeeklyReport.qualification_ratec                 C   s"   d| j   d| j d| j dS )NzMarketing Report -  (z to ))marketing_staffget_full_namer8  r7  r   r   r   r   r     r  zMarketingWeeklyReport.__str__c                   @   s   e Zd ZddgZddgZdS )zMarketingWeeklyReport.MetarD  r8  z-week_startingmarketing_staff__first_nameN)r   r   r   unique_togetherr    r   r   r   r   r!     s    r!   )/r   r   r   REPORT_STATUS_CHOICESr   r   r   r   rD  	DateFieldr8  r7  r#   r   rG   customers_contactedsite_visits_conducteddemos_conductedr;  r@  r=  r$   customer_feedback_summarycompetitor_activitiesmarket_trends_observed#service_improvement_recommendationspricing_recommendations"marketing_strategy_recommendationschallenges_facedsolutions_implementednext_week_targetssupport_neededr   reviewed_byr'   reviewed_atreview_commentsr(   r  r   r   r   r>  rA  r   r!   r  r   r   r   r   r+    s    	

r+  c                   @   s  e Zd Zg dZg dZejeejddZ	e
 ZejdedZejddZejd	dZejddZejeejd
d
dZejdedZejddZejeejd
d
dZejddd
d
dZejddZej
d
d
dZejd
dZejd
dZ dd Z!G dd dZ"dS )MarketingLeadInteraction))
phone_callz
Phone Call)
site_visitz
Site Visit)r   Email)demozService Demo)	follow_upz	Follow Up)complaint_resolutionzComplaint Resolution)otherOther))positivePositive)neutralNeutral)negativeNegative)	convertedzConverted to Customer)lostz	Lost Leadlead_interactionsr	     r  re   r1   rh   Tr   r9   z$Detailed notes about the interactionr2   r4   r5   rj   Fr=   rd   r   r   c                 C   s   | j  d|   d| j dS )Nr?   rB  rC  )	lead_nameget_interaction_type_displayinteraction_dater   r   r   r   r   2  r#  z MarketingLeadInteraction.__str__c                   @   r   )zMarketingLeadInteraction.Metaz-interaction_dateNr   r   r   r   r   r!   5  r"   r!   N)#r   r   r   INTERACTION_TYPE_CHOICESOUTCOME_CHOICESr   r   r+  r   weekly_reportrI  ro  r#   interaction_typerm  
lead_phonelead_locationrO   r   existing_customeroutcomer$   r  r)   service_interestedrI   estimated_valuerM   follow_up_requiredfollow_up_datefollow_up_notesr'   r(   r   r!   r   r   r   r   rZ     s0    
rZ  c                   @   sp   e Zd ZdZejddZejdddZe Z	ej
ddZejeejd	Zejdd
Zdd ZG dd dZdS )MarketingReportTemplatez.Templates for common marketing report sectionsr0   r1   r	   z4Which section of the report this template applies to)r
   r   Tr=   )r_   r   c                 C   r>   )NrB  rC  )r   sectionr   r   r   r   r   B  rB   zMarketingReportTemplate.__str__c                   @   s   e Zd ZddgZdS )zMarketingReportTemplate.Metar~  r   Nr   r   r   r   r   r!   E  s    r!   N)r   r   r   __doc__r   r#   r   r~  r$   template_contentrM   rN   r   r   r   
created_byr'   r(   r   r!   r   r   r   r   r}  9  s    r}  c                   @   s   e Zd Zg dZejeejddZej	dedZ
ejddZejddd	d
Zejdddd
ZejdddZejddZejeejdddZejdddZej	ddddZejddZG dd dZdd ZdS )CustomerActionLog))createdzCustomer Created)updatedzCustomer Updated)rV   zService Suspended)rX   zService Disconnected)reconnectedzService Reconnected)trial_startedzTrial Period Started)trial_endedzTrial Period Ended)service_activatedzService Activated)payment_receivedzPayment Received)balance_adjustedzBalance Adjusted)service_changedzService Package Changed)notes_updatedzNotes Updated)credentials_resetzCredentials Reset)manual_overridezManual Override Applied)sub_account_createdzSub-Account Created)linked_to_parentzLinked to Parent Account)contact_updatedzContact Information Updated)installation_completedzInstallation Completedaction_logsr	  rl  r  z"Detailed description of the actionr2   TzPrevious value (for updates)ro   zNew value (for updates)rd   r   r   Fz&True if action was performed by systemr5  r0   z9Reference to related object (payment ID, ticket ID, etc.)rf   r   c                   @   s@   e Zd ZdgZejddgdejddgdejddgdgZdS )zCustomerActionLog.Metar$  r   )fieldsaction_typeperformed_byN)r   r   r   r    r   Indexindexesr   r   r   r   r!   p  s    r!   c                 C   s0   | j r| j  nd}| jj d|   d| S )NSystemr?   z by )r  rE  r   r   get_action_type_display)r   	performerr   r   r   r   x  s   zCustomerActionLog.__str__N)r   r   r   ACTION_TYPE_CHOICESr   r   rO   r   r   r#   r  r$   r%   	JSONField	old_value	new_valueGenericIPAddressField
ip_address
user_agentr   r   r  rM   system_actionr'  r'   r(   r!   r   r   r   r   r   r  I  s    r  )	django.dbr   django.contrib.authr   decimalr   r  r   r   datetimer   r}   ru   r   Modelr   r)   PackagerO   r  r  r+  rZ  r}  r  r   r   r   r   <module>   s,      9