o
    ܦhh                     @   s   d dl mZ d dlmZ ddlmZmZ d dlmZ G dd dZ	d dl mZ d dl
mZ d dlmZ ddlmZmZ G d	d dZ	G d
d dZG dd dZG dd dZdS )    )transaction)Decimal   )CustomerCustomerBalanceTransaction)Invoicec                   @   s\   e Zd ZeejdddZeejdddZeejdd Zedd	d
Z	dd Z
dS )CustomerBalanceServiceNc              
   C   sL   | j }|  j tt|7  _ |   tjj| d|||pd|| j |d | j S )z'Add money to customer's account balancecredit customertransaction_typeamountdescriptionreference_idbalance_beforebalance_afterprocessed_byaccount_balancer   strsaver   objectscreater   r   r   r   r   r    r   2/var/www/html/optinet_system/customers/services.pyadd_balance	      "CustomerBalanceService.add_balancec              
   C   sL   | j }|  j tt|8  _ |   tjj| d|||pd|| j |d | j S )z,Deduct money from customer's account balancedebitr
   r   r   r   r   r   r   deduct_balance   r   %CustomerBalanceService.deduct_balancec              	   C   s   | j }|j| jkr9tj|| jd| j | jd d| _|   ddlm	} |j
j| || jddd| j d	d
 dS d| _|   dd| j d|j fS )zCAutomatically pay invoice from customer balance if sufficient fundszPayment for invoice )r   r   r   r   paidr   )Paymentbalance_deduction	completedzAUTO-z'Automatically paid from account balance)invoicer   r   payment_methodstatusreference_numbernotesT/Invoice paid automatically from account balanceunpaidFz Insufficient balance. Required: , Available: N)Tr,   )r   r   total_amountr   r!   invoice_numberr)   r   payments.modelsr$   r   r   )r'   r   r$   r   r   r   process_invoice_payment5   s0   


z.CustomerBalanceService.process_invoice_payment2   c                 C   s   t jj| dd| S )z*Get customer's balance transaction historyr   N)r   r   filterr   limitr   r   r   get_balance_history[   s   *CustomerBalanceService.get_balance_historyc           	      K   sv   ddl m} | j||d| |dd|dd}|j}|d d	kr9|d
 r9||}|r9| jd7  _|  |S )zGProcess payment and attempt to resume service if customer was suspendedr   )ServicePeriodManagerzPayment via r   r
   r   )r   r   r   r   r   r)   	suspended
can_resumez - Service resumed)billing.servicesr:   r   getcurrent_service_statusresume_customer_servicer   r   )	selfr   r   r(   kwargsr:   r   service_statussuccessr   r   r   "process_payment_and_resume_service`   s   
	
z9CustomerBalanceService.process_payment_and_resume_serviceNNr3   )__name__
__module____qualname__staticmethodr   atomicr   r!   r2   r8   rE   r   r   r   r   r      s    $r   )timezonec                   @   sN   e Zd ZeejdddZedd ZeejdddZedd	d
Z	dS )r   Nc              
   C   s   zM| j }|tt| }tjj| d|||pd|||d || _ |   tj| dd| t	|t	|d||d t
| t	| t| t	|t	| W dS  tyi } ztd	t|  W Y d
}~dS d
}~ww )z?Add balance to customer account with comprehensive verificationr	   r
   r   payment_receivedzPayment received: )r   new_balance)r   action_typer   	new_valueperformed_byr   TzError adding balance: NF)r   r   r   r   r   r   r   CustomerActionService
log_actionfloatCustomerServiceManagerverify_and_activate_serviceCustomerNotificationService"send_payment_received_notification	Exceptionprintr   r   r   r   r   current_balancerO   er   r   r   r   }   sB   
r   c                 C   s   | j sdddS | j}| jdkr,| j j| j j }||kr!t| S dd| d| dS | jdkrI| j j}||kr>t| S dd| d| dS | jdkr]| jr]t	
 | jkr]t| S dd	dS )
zCVerify if payment plus balance is sufficient for service activationFNo service package assignedrD   messagepending_activationzInsufficient funds. Required: r.   r;   trialz*Service status does not require activation)servicer   rC   priceinstallation_feerV   activate_paid_servicereconnect_servicetrial_end_daterM   nowprocess_trial_completion)r   payment_amounttotal_availablerequired_amountr   r   r   rW      s"   







z2CustomerBalanceService.verify_and_activate_servicec              
   C   s   z%| j }|tt| }tjj| d|||pd|||d || _ |   W dS  tyA } ztdt|  W Y d}~dS d}~ww )z$Deduct balance from customer accountr    r
   r   TzError deducting balance: NF)	r   r   r   r   r   r   r   rZ   r[   r\   r   r   r   r!      s*   r"   r3   c                 C   s   t jj| ddd| S )z(Get customer balance transaction historyr4   z-created_atN)r   r   r5   order_byr6   r   r   r   r8      s
   r9   rF   rG   )
rH   rI   rJ   rK   r   rL   r   rW   r!   r8   r   r   r   r   r   |   s    .
c                   @   s2   e Zd ZdZe			d	ddZed
ddZdS )rS   z(Service for logging all customer actionsNFc
                 C   s@   ddl m}
 |	p	d}	|pd}|
jj| |||||||||	d
 dS )zLog a customer actionr   CustomerActionLogr
   )
r   rP   r   	old_valuerQ   rR   system_actionr   
ip_address
user_agentN)modelsrq   r   r   )r   rP   r   rr   rQ   rR   rs   r   rt   ru   rq   r   r   r   rT      s   
z CustomerActionService.log_actiond   c                 C   s"   ddl m} |jj| dd| S )zGet customer action timeliner   rp   r4   N)rv   rq   r   r5   )r   r7   rq   r   r   r   get_customer_timeline  s   z+CustomerActionService.get_customer_timeline)NNNFNNN)rw   )rH   rI   rJ   __doc__rK   rT   rx   r   r   r   r   rS      s    rS   c                   @   s   e Zd ZdZeejdddZeejdd Zeejdd Z	eejdd
dZ
eejdddZeejdddZedd Zedd ZdS )rV   z/Service for managing customer service lifecycleNc                 C   s   | j sdddS t }|tdd }|| _|| _d| _|   tj	| dd| j j
 | | | j j
d	||d
u d t|  d|dS )z)Activate a new customer with trial periodFr_   r`   r   )hoursrc   trial_startedz 1-hour trial period started for )trial_start	trial_endrd   N)r   rP   r   rQ   rR   rs   T)rD   r}   )rd   rM   rj   	timedeltatrial_start_dateri   rC   r   rS   rT   name	isoformatrX   send_trial_started_notification)r   r   r|   r}   r   r   r   activate_new_customer  s*   


z,CustomerServiceManager.activate_new_customerc                 C   s@   | j sdddS | jj| jj }| j|krt| S t| dS )zCProcess trial completion and activate service if payment sufficientFzNo active trial periodr`   insufficient_balance)is_trial_activerd   re   rf   r   rV   rg   suspend_service)r   total_requiredr   r   r   rk   8  s   


z/CustomerServiceManager.process_trial_completionc                 C   s   | j sdddS | j j| j j }tj| |d| j j ddd t }t	|| j j
}|| _d| _|   d	d
lm} |jj| | j ||dd tj| dd| j j | | t|ddd t|  d|dS )z!Activate paid service after trialFr_   r`   zService activation: z + installationNr   r   r   r   activer   ServicePeriodr   rd   service_startservice_endr)   service_activatedzService activated: )r   r   amount_deductedT)r   rP   r   rQ   rs   rD   r   )rd   re   rf   r   r!   r   rM   rj   rV   calculate_next_billing_datebilling_cycleservice_start_daterC   r   billing.modelsr   r   r   rS   rT   r   rU   rX   #send_service_activated_notification)r   
total_costr   r   r   r   r   r   rg   H  sD   
	

z,CustomerServiceManager.activate_paid_servicemanualc              	   C   s   | j }|pt }d| _ || _|r|| _|   ddlm} |jj	| dd}|j
d|d tj| dd| d|id|d	||d
u d d|dS )zSuspend customer servicer;   r   r   r   r   r)   )r)   suspended_atzService suspended due to: r)   r)   reasonN)r   rP   r   rr   rQ   rR   rs   T)rD   suspension_date)rC   rM   rj   last_suspension_datemanual_suspension_overrider   r   r   r   r5   updaterS   rT   )r   r   override_daterR   
old_statusr   r   active_periodsr   r   r   r   }  s.   

z&CustomerServiceManager.suspend_servicec                 C   st   | j }d| _ d| _|   ddlm} |jj| ddgd}|jdd	 tj	| dd
| d|id|d|d ddiS )z'Permanently disconnect customer servicedisconnectedFr   r   r   r;   )r   
status__in	cancelledr)   z"Service permanently disconnected: r)   r   )r   rP   r   rr   rQ   rR   rD   T)
rC   	is_activer   r   r   r   r5   r   rS   rT   )r   r   rR   r   r   r   r   r   r   disconnect_service  s&   	z)CustomerServiceManager.disconnect_servicec              	   C   s  | j dkr
dddS | jr| j| jjkrtj| | jjd| jj |d t }t	
|| jj}d| _ || _d| _d| _|   d	d
lm} |jj| | j||dd |jj| dd}|jdd tj| ddd| | t| jjd|d t|  d|dS dddS )zReconnect suspended servicer;   FzService is not suspendedr`   zService reactivation: r   r   Nr   r   r   r   r   r   reconnectedz+Service reconnected with new billing period)r)   r   r   r   )r   rP   r   rQ   rR   Tr   z%Insufficient balance for reconnection)rC   rd   r   re   r   r!   r   rM   rj   rV   r   r   r   r   r   r   r   r   r   r   r5   r   rS   rT   r   rU   rX   %send_service_reactivated_notification)r   rR   r   r   r   suspended_periodsr   r   r   rh     sV   

	



z(CustomerServiceManager.reconnect_servicec                 C   s   | j s| jdvrd| _|   dS | jdkr)| j r)| j| j jkr't|  dS dS | jdkrC| jr?t	 | jkrAt
|  dS dS dS | jdkr]| j r_| j| j j| j j krat|  dS dS dS dS )z/Check if service can be activated after payment)rb   r   inactiveNr;   rc   rb   )rd   rC   r   r   re   rV   rh   ri   rM   rj   rk   rf   rg   r4   r   r   r   check_service_activation  s$   

z/CustomerServiceManager.check_service_activationc              	   C   s   |dkrF| j dkr| jd }d}n| j}| j d }z
| j||d}W |S  tyE   ddl}|||d }| j||t| j|d}Y |S w |dkrQ| td	d
 S z
| j| jd dW S  tyn   | j| jd dd Y S w )z9Calculate next billing date with smart month-end handlingmonthly   r   )yearmonthr   N)r   r   day	quarterlyZ   )days)r      )r   r   )	r   r   replace
ValueErrorcalendar
monthrangeminr   r~   )current_dater   	next_year
next_month	next_dater   last_dayr   r   r   r     s4   



z2CustomerServiceManager.calculate_next_billing_date)N)r   NN)r   N)rH   rI   rJ   ry   rK   r   rL   r   rk   rg   r   r   rh   r   r   r   r   r   r   rV     s0    !3 ?
rV   c                   @   sd   e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	edd Z
edd ZdS )rX   z*Service for sending customer notificationsc                 C   <   ddl m} d| jj d| j }|j| j|| jdd dS )z'Send SMS notification when trial startsr   
SMSServicez*Welcome to OptiNet! Your 1-hour trial for zF has started. Please ensure payment to continue service. Customer ID: sms_trial_startedphone_numberra   customer_idtemplate_typeNnotifications.servicesr   rd   r   r   send_smsphoneidr   r   ra   r   r   r   r   =     
z;CustomerNotificationService.send_trial_started_notificationc                 C   sL   ddl m} d| jj d| j d| j d| j }|j| j|| j	dd d	S )
z+Send notification when service is activatedr   r   zYour OptiNet service z is now active! Login: z | Password: z Customer ID: sms_service_activatedr   N)
r   r   rd   r   pppoe_usernamepppoe_passwordr   r   r   r   r   r   r   r   r   L  s   
z?CustomerNotificationService.send_service_activated_notificationc                 C   s>   ddl m} d| d| d| j }|j| j|| jdd dS )	z*Send notification when payment is receivedr   r   zPayment of KES z received. New balance: KES z. Thank you! Customer ID: sms_payment_receivedr   Nr   r   r   r   r   r   )r   r   rO   r   ra   r   r   r   rY   \  s   
z>CustomerNotificationService.send_payment_received_notificationc                 C   s8   ddl m} d| d| j }|j| j|| jdd dS )z+Send notification when service is suspendedr   r   z/Your OptiNet service has been suspended due to zE. Please contact us or make payment to restore service. Customer ID: sms_service_suspendedr   Nr   )r   r   r   ra   r   r   r   #send_service_suspended_notificationk  s   
z?CustomerNotificationService.send_service_suspended_notificationc                 C   s4   ddl m} d| j d}|j| j|| jdd dS )z*Send welcome notification to new customersr   r   z!Welcome to OptiNet! Your account z` has been created. We will notify you once your service is ready. Contact us for any assistance.sms_welcomer   Nr   r   r   r   r   send_welcome_notificationz  s   
z5CustomerNotificationService.send_welcome_notificationc                 C   r   )z-Send notification when service is reactivatedr   r   zGreat! Your OptiNet service zK has been reactivated! Your internet service is now restored. Customer ID: sms_service_reactivatedr   Nr   r   r   r   r   r     r   zACustomerNotificationService.send_service_reactivated_notificationc                 C   sB   ddl m} d| d| jj d| j }|j| j|| jdd dS )	z1Send reminder notification before service expiresr   r   z*Reminder: Your OptiNet service expires in z days. Please top up KES z- to avoid service interruption. Customer ID: sms_service_reminderr   N)r   r   rd   re   r   r   r   r   )r   days_remainingr   ra   r   r   r   send_service_expiry_reminder  s   
z8CustomerNotificationService.send_service_expiry_reminderN)rH   rI   rJ   ry   rK   r   r   rY   r   r   r   r   r   r   r   r   rX   :  s     





rX   N)	django.dbr   decimalr   rv   r   r   r   r   r   django.utilsrM   rS   rV   rX   r   r   r   r   <module>   s   nt"  *