o
    -h!                     @   s   d dl mZ d dlZd dl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 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 )    )appsN)	timedelta)uuid4)models)ValidationError)slugify)now)Supplierc                       s   e Zd Z fddZ  ZS )ActiveManagerc                    s   t   jddS )NT)deleted_at__isnull)superget_querysetfilterself	__class__ %/var/www/html/pos/inventory/models.pyr      s   zActiveManager.get_queryset)__name__
__module____qualname__r   __classcell__r   r   r   r   r
      s    r
   c                   @   sr   e Zd ZejdddZejdddZejddddZ	ej
ddddejd	Zejddd
Zdd ZG dd dZdS )Category   T)
max_lengthuniqueblanknullzcategory_images/	upload_tor   r   r   subcategories)r   r   related_name	on_deleter   r   c                 C      | j S Nnamer   r   r   r   __str__      zCategory.__str__c                   @      e Zd ZdgZdS )zCategory.Metar)   Nr   r   r   orderingr   r   r   r   Meta   s    
r/   N)r   r   r   r   	CharFieldr)   	TextFielddescription
ImageField	thumbnail
ForeignKeyCASCADEparentDateTimeField
deleted_atr*   r/   r   r   r   r   r      s    r   c                       sZ  e Zd ZejddZejddddddZejd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ddZejdddZejddZejdddej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Ze Ze Zdd Z dd Z! fddZ"e#dd Z$dd Z%d d! Z&d"d# Z'd$d% Z(d&d' Z)d-d)d*Z*G d+d, d,Z+  Z,S ).Productr   )r   T)r   r   r   r   db_index
      
max_digitsdecimal_placesr   r   r?   r@   r   default2   r   r   r   r   auto_now_addr   products)r   r   r$   r;   r#   product_images/r    )rC   r;   r%   c                 C   r&   r'   r(   r   r   r   r   r*   :   r+   zProduct.__str__c                 C   sF   | j dur| j| j krtd| jdk rtd| jdk r!tddS )z6
        Validation logic for product fields.
        N0Selling price must be greater than buying price.r   z"Stock quantity cannot be negative.z'Low stock threshold cannot be negative.)buying_priceselling_pricer   stock_quantitylow_stock_thresholdr   r   r   r   clean=   s   

zProduct.cleanc                    s.   | j s|  | _ |   t j|i | dS )zD
        Override save method to handle barcode generation.
        N)barcodegenerate_barcoderO   r   saver   argskwargsr   r   r   rR   H   s   
zProduct.savec                   C   s   d tjtjddS )z6
        Generates a random 12-digit barcode.
            )k)joinrandomchoicesstringdigitsr   r   r   r   rQ   R   s   zProduct.generate_barcodec                 O   s   t  | _|   dS )z[
        Soft-delete the product by setting `deleted_at` to the current timestamp.
        N)r   r9   rR   rS   r   r   r   deleteY   s   zProduct.deletec                 C   s   d| _ |   dS )zT
        Restore a soft-deleted product by clearing the `deleted_at` field.
        N)r9   rR   r   r   r   r   restore`   s   zProduct.restorec                 C   s   | j | jkS )zN
        Check if the product stock is below the low stock threshold.
        )rM   rN   r   r   r   r   is_low_stockg   s   zProduct.is_low_stockc                 C   s$   | j rt  | j tdd kS dS )zH
        Check if the product is nearing expiry within 30 days.
           )daysF)expiry_dater   dater   r   r   r   r   is_nearing_expirym   s   zProduct.is_nearing_expiryc                 C   s   | j rt  | j kS dS )z3
        Check if the product has expired.
        F)rc   r   rd   r   r   r   r   has_expiredu   s   zProduct.has_expiredNc                 C   sr   | j pd}||kr|| _ |r|| _|   dS ||k r7| jdkr.|| _ |r(|| _|   dS dd| j dfS dS )zD
        Update product pricing based on new batch pricing.
        r   )Tz'Price updated immediately (higher cost))Tz,Price updated immediately (no current stock)Fz&Price update deferred (current stock: ))FzNo price update needed)rK   rL   rR   rM   )r   new_batch_buying_pricenew_batch_selling_pricecurrent_buying_pricer   r   r   update_pricing_from_batch}   s    

z!Product.update_pricing_from_batchc                   @   r,   )zProduct.Metar)   Nr-   r   r   r   r   r/          
r/   r'   )-r   r   r   r   r0   r)   rP   DecimalFieldrK   rL   PositiveIntegerFieldrM   rN   packaging_type	DateFieldrc   r8   
created_atr5   SET_NULLcategoryr1   r2   r3   imageBooleanField	is_activer9   r
   objectsManagerall_objectsr*   rO   rR   staticmethodrQ   r^   r_   r`   re   rf   rk   r/   r   r   r   r   r   r:   %   s:    


r:   c                   @   sV   e Zd ZejedejdZejddZ	ej
ddZejdddd	Zd
d Zdd ZdS )ProductImageimagesr#   r$   rI   )r!   FrB   r   TrE   c                 C   s*   | j r| jjjdd rtdd S d S )NT)
is_primaryz.Only one primary image is allowed per product.)r~   productr|   r   existsr   r   r   r   r   rO      s   zProductImage.cleanc                 C   s   d| j j S )Nz
Image for )r   r)   r   r   r   r   r*      s   zProductImage.__str__N)r   r   r   r   r5   r:   r6   r   r3   rt   ru   r~   r0   alt_textrO   r*   r   r   r   r   r{      s    r{   c                       s  e Zd Zg dZejddejdZejddddZ	e
 Zejdd	d
Zejdd	dddZejdddZejddZejdddZejedZejdeddZejdddZejeejdddZe Ze Zdd Z  fddZ!e"dd Z#dd Z$G dd dZ%  Z&S )Batch))activeActive)expiredExpired)sold_outzSold Outr:   batchesr}   r   TrE   r<   r=   rA   r>   r   rF   r%   rB      r   )r   r[   rC   )r$   r   r   c                 C   sR   | j r| j t  k rtd| jdk rtd| jr%| j| jkr'tddS dS )z<
        Validation logic to ensure data integrity.
        z"Expiry date cannot be in the past.r   z"Batch quantity cannot be negative.rJ   N)rc   r   rd   r   quantityrL   rK   r   r   r   r   rO      s   
zBatch.cleanc                    s&   | j s|  | _ t j|i | dS )zG
        Override save to generate batch code if not provided.
        N)
batch_codegenerate_batch_coder   rR   rS   r   r   r   rR      s   
z
Batch.savec                   C   s   dt  jdd   S )z0
        Generates a unique batch code.
        zBATCH-N   )r   hexupperr   r   r   r   r      s   zBatch.generate_batch_codec                 C   s   d| j  d| jj S )NzBatch z for )r   r   r)   r   r   r   r   r*      s   zBatch.__str__c                   @   r,   )z
Batch.Metareceived_dateNr-   r   r   r   r   r/      rl   r/   )'r   r   r   STATUS_CHOICESr   r5   r6   r   r0   r   rn   r   rm   rK   rL   rp   rc   r8   rq   r9   r   r   statusr1   notesr	   rr   supplierr
   rw   rx   ry   rO   rR   rz   r   r*   r/   r   r   r   r   r   r      s,    	
r   )django.appsr   rZ   r\   datetimer   uuidr   	django.dbr   django.core.exceptionsr   django.utils.textr   django.utils.timezoner   suppliers.modelsr	   rx   r
   Modelr   r:   r{   r   r   r   r   r   <module>   s    w