U
    hL                     @   sr  d 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 dd
lmZ ddlmZmZ ddlmZ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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eeeZ$G d#d$ d$e$ee ee"Z%dS )%a  
Enterprise-Ready Common Models Module

This module provides base model classes, abstract models, and common functionality
that can be inherited by other models throughout the application. It follows
Django best practices and enterprise patterns for scalability and maintainability.

Features:
- Base timestamp models with created/updated tracking
- Soft delete functionality with audit trails
- UUID primary keys for enhanced security
- Versioning and change tracking
- Common field types and validators
- Audit logging capabilities
- Status and workflow management
- Metadata and tagging support

Author: Adtals Development Team
Version: 2.0.0
License: Proprietary
    N)modelsreverse)timezone)ValidationError)gettext_lazy)get_user_model)ContentType)GenericForeignKey)MinLengthValidatorRegexValidator)BaseManagerSoftDeleteManagerc                       s^   e Zd ZdZejeddeddZejeddeddZG d	d
 d
Z	 fddZ
  ZS )TimestampedModelaa  
    Abstract base model providing timestamp fields.
    
    This model provides automatic tracking of creation and modification
    timestamps for all models that inherit from it.
    
    Attributes:
        created_at (DateTimeField): Timestamp when object was created
        updated_at (DateTimeField): Timestamp when object was last modified
    z
Created AtTz&Timestamp when this object was created)auto_now_add	help_textz
Updated Atz,Timestamp when this object was last modified)auto_nowr   c                   @   s   e Zd ZdZdgZdS )zTimestampedModel.MetaTz-created_atN__name__
__module____qualname__abstractordering r   r   -/var/www/html/Focus/src/apps/common/models.pyMeta?   s   r   c                    s,   | j st | _t | _t j|| dS )z1Override save to ensure updated_at is always set.N)pkr   now
created_at
updated_atsupersaveselfargskwargs	__class__r   r   r!   C   s    

zTimestampedModel.save)r   r   r   __doc__r   DateTimeField_r   r   r   r!   __classcell__r   r   r&   r   r   &   s   r   c                   @   s6   e Zd ZdZejdejdeddZ	G dd dZ
dS )		UUIDModelz
    Abstract base model using UUID as primary key.
    
    This model provides UUID primary keys for enhanced security
    and to prevent enumeration attacks.
    
    Attributes:
        id (UUIDField): UUID primary key
    TFz!Unique identifier for this object)primary_keydefaulteditabler   c                   @   s   e Zd ZdZdS )zUUIDModel.MetaTNr   r   r   r   r   r   r   r   r   ^   s   r   N)r   r   r   r(   r   	UUIDFielduuiduuid4r*   idr   r   r   r   r   r,   K   s   r,   c                	       s   e Zd ZdZejeddeddZejedddedd	Z	ej
d
ejdddededdZe Ze ZG dd dZdddZdddZ fddZedd Zedd Z  ZS )SoftDeleteModela  
    Abstract base model providing soft delete functionality.
    
    This model allows objects to be marked as deleted without
    actually removing them from the database, enabling recovery
    and audit trail maintenance.
    
    Attributes:
        is_deleted (BooleanField): Whether object is soft-deleted
        deleted_at (DateTimeField): When object was soft-deleted
        deleted_by (ForeignKey): User who soft-deleted the object
    z
Is DeletedFz)Whether this object has been soft-deletedr.   r   z
Deleted AtTz+Timestamp when this object was soft-deleted)nullblankr   accounts.Userz%(class)s_deletedz
Deleted Byz!User who soft-deleted this object	on_deleter7   r8   related_nameverbose_namer   c                   @   s   e Zd ZdZdS )zSoftDeleteModel.MetaTNr0   r   r   r   r   r      s   r   Nc                 O   s0   d| _ t | _|r|| _| jdddgd dS )z
        Perform soft delete instead of hard delete.
        
        Args:
            user: The user performing the delete operation
        T
is_deleted
deleted_at
deleted_byupdate_fieldsN)r>   r   r   r?   r@   r!   )r#   userr$   r%   r   r   r   delete   s
    
zSoftDeleteModel.deletec                 C   s(   d| _ d| _d| _|r|| _|   dS )z
        Restore a soft deleted object.
        
        Args:
            user: The user performing the restore operation
        FN)r>   r?   r@   
updated_byr!   )r#   rC   r   r   r   restore   s    zSoftDeleteModel.restorec                    s   t    dS )z,Permanently delete the object from database.N)r    rD   r#   r&   r   r   hard_delete   s    zSoftDeleteModel.hard_deletec                 C   s   | j jddS )z
        Get a queryset of non-deleted objects.
        
        Returns:
            QuerySet: All objects where is_deleted=False
        Fr>   objectsfilterclsr   r   r   get_active_objects   s    z"SoftDeleteModel.get_active_objectsc                 C   s   | j jddS )z
        Get a queryset of soft deleted objects.
        
        Returns:
            QuerySet: All objects where is_deleted=True
        TrI   rJ   rM   r   r   r   get_deleted_objects   s    z#SoftDeleteModel.get_deleted_objects)N)N)r   r   r   r(   r   BooleanFieldr*   r>   r)   r?   
ForeignKeySET_NULLr@   r   rK   r   Zall_objectsr   rD   rF   rH   classmethodrO   rP   r+   r   r   r&   r   r5   b   s>   



	r5   c                       sP   e Zd ZdZejddededdZG dd dZ fd	d
Z	dd Z
  ZS )	SlugModelz
    Abstract model that provides slug functionality.
    
    This model adds a slug field that can be used for SEO-friendly URLs.
    The slug is automatically generated from a specified field.
       TZSlugzSEO-friendly URL identifier)
max_lengthuniquer=   r   c                   @   s   e Zd ZdZdS )zSlugModel.MetaTNr0   r   r   r   r   r      s   r   c                    s<   | j s*t| dr*ddlm} ||  | _ t j|| dS )z
        Override save method to auto-generate slug if not provided.
        
        Child models should define a get_slug_source() method
        that returns the field value to generate the slug from.
        get_slug_sourcer   )slugifyN)slughasattrdjango.utils.textrZ   rY   r    r!   )r#   r$   r%   rZ   r&   r   r   r!      s    zSlugModel.savec                 C   s
   t | jS )a  
        Get the source value for slug generation.
        
        This method should be overridden in child models
        to specify which field should be used for slug generation.
        
        Returns:
            str: The value to generate slug from
        )strr   rG   r   r   r   rY      s    
zSlugModel.get_slug_source)r   r   r   r(   r   	SlugFieldr*   r[   r   r!   rY   r+   r   r   r&   r   rU      s   rU   c                   @   sF   e Zd ZdZejdededdZG dd dZdd	 Z	d
d Z
dS )SortableModelz
    Abstract model that provides sorting functionality.
    
    This model adds an order field that can be used to sort records
    in a specific order defined by the user.
    r   Orderz.Order for sorting (lower numbers appear first))r.   r=   r   c                   @   s   e Zd ZdZddgZdS )zSortableModel.MetaTorderr4   Nr   r   r   r   r   r      s   r   c                 C   sn   zT| j jj| jdd }|rR|j}| j|_|| _|jdgd | jdgd W n tk
rh   Y nX dS )z
        Move this item up in the sort order.
        
        Swaps the order with the item that has the next lower order value.
        )Z	order__ltz-orderrb   rA   Nr'   rK   rL   rb   order_byfirstr!   	Exception)r#   Zprevious_itemZprevious_orderr   r   r   move_up  s    zSortableModel.move_upc                 C   sn   zT| j jj| jdd }|rR|j}| j|_|| _|jdgd | jdgd W n tk
rh   Y nX dS )z
        Move this item down in the sort order.
        
        Swaps the order with the item that has the next higher order value.
        )Z	order__gtrb   rA   Nrc   )r#   	next_itemZ
next_orderr   r   r   	move_down  s    zSortableModel.move_downN)r   r   r   r(   r   PositiveIntegerFieldr*   rb   r   rg   ri   r   r   r   r   r`      s   r`   c                	       sr   e Zd ZdZejdejdddededdZejdejddded	ed
dZ	G dd dZ
 fddZ  ZS )
AuditModelaB  
    Abstract base model for tracking user actions.
    
    This model tracks which user created and last modified an object,
    providing audit trail capabilities.
    
    Attributes:
        created_by (ForeignKey): User who created this object
        updated_by (ForeignKey): User who last modified this object
    r9   Tz%(class)s_createdz
Created ByzUser who created this objectr:   z%(class)s_updatedz
Updated Byz"User who last modified this objectc                   @   s   e Zd ZdZdS )zAuditModel.MetaTNr0   r   r   r   r   r   R  s   r   c                    s8   t | dd}| js|r|| _|r&|| _t j|| dS )z
        Override save method to handle user tracking.
        
        This method automatically sets created_by and updated_by
        based on the current user in the request context.
        Z_current_userN)getattrr   
created_byrE   r    r!   )r#   r$   r%   rC   r&   r   r   r!   U  s    
zAuditModel.save)r   r   r   r(   r   rR   rS   r*   rm   rE   r   r!   r+   r   r   r&   r   rk   3  s*   	
rk   c                   @   s   e Zd ZdZdedfdedfdedfded	fd
edfdedfgZejeddeddZejeddeddZ	ej
eddededdZG dd dZdd Zdd Zdd  Zd!d" Zd#S )$StatusModelaz  
    Abstract base model providing status tracking.
    
    This model provides common status fields that can be used
    across different models for workflow management.
    
    Attributes:
        is_active (BooleanField): Whether object is active
        is_published (BooleanField): Whether object is published
        status (CharField): Current status of the object
    ZdraftZDraftpendingZPendingZapprovedZApprovedZrejectedZRejectedZ	publishedZ	PublishedarchivedZArchivedz	Is ActiveTzWhether this object is activer6   zIs PublishedFz Whether this object is publishedStatus   zCurrent status of this object)rW   choicesr.   r   c                   @   s   e Zd ZdZdS )zStatusModel.MetaTNr0   r   r   r   r   r     s   r   c                 C   s   d| _ | jdgd dS )zActivate this record.T	is_activerA   Nrt   r!   rG   r   r   r   activate  s    zStatusModel.activatec                 C   s   d| _ | jdgd dS )zDeactivate this record.Frt   rA   Nru   rG   r   r   r   
deactivate  s    zStatusModel.deactivatec                 C   s    d| _ d| _| jddgd dS )zSuspend this record.Z	suspendedFstatusrt   rA   Nrx   rt   r!   rG   r   r   r   suspend  s    zStatusModel.suspendc                 C   s    d| _ d| _| jddgd dS )zArchive this record.rp   Frx   rt   rA   Nry   rG   r   r   r   archive  s    zStatusModel.archiveN)r   r   r   r(   r*   ZSTATUS_CHOICESr   rQ   rt   Zis_published	CharFieldrx   r   rv   rw   rz   r{   r   r   r   r   rn   j  s<   





	rn   c                       s^   e Zd ZdZejeddeddZejeddedd	Z	G d
d dZ
 fddZ  ZS )VersionedModelaH  
    Abstract base model providing versioning functionality.
    
    This model tracks version numbers and changes for objects,
    enabling version control and change history.
    
    Attributes:
        version (PositiveIntegerField): Current version number
        change_reason (TextField): Reason for the last change
    Version   z%Current version number of this objectr6   zChange ReasonTz.Reason for the last change made to this object)r8   r   c                   @   s   e Zd ZdZdS )zVersionedModel.MetaTNr0   r   r   r   r   r     s   r   c                    s&   | j r|  jd7  _t j|| dS )zIncrement version on save.r   N)r   versionr    r!   r"   r&   r   r   r!     s    zVersionedModel.save)r   r   r   r(   r   rj   r*   r   	TextFieldZchange_reasonr   r!   r+   r   r   r&   r   r}     s   r}   c                   @   s|   e Zd ZdZejedededdZej	edddedd	Z
G d
d dZdd Zdd Zdd ZdddZdd ZdS )MetadataModelaQ  
    Abstract base model providing metadata functionality.
    
    This model provides flexible metadata storage using JSON fields
    for storing additional information that doesn't warrant separate fields.
    
    Attributes:
        metadata (JSONField): Flexible metadata storage
        tags (CharField): Comma-separated tags
    ZMetadataTz#Additional metadata for this object)r.   r8   r   Tagsi  z'Comma-separated tags for categorizationrW   r8   r   c                   @   s   e Zd ZdZdS )zMetadataModel.MetaTNr0   r   r   r   r   r     s   r   c                 C   s    | j rdd | j dD S g S )zReturn tags as a list.c                 S   s   g | ]}|  r|  qS r   )strip).0tagr   r   r   
<listcomp>  s      z/MetadataModel.get_tags_list.<locals>.<listcomp>,)tagssplitrG   r   r   r   get_tags_list  s    zMetadataModel.get_tags_listc                 C   s*   |   }||kr&|| d|| _dS )zAdd a tag to the object., N)r   appendjoinr   r#   r   r   r   r   r   add_tag  s    
zMetadataModel.add_tagc                 C   s*   |   }||kr&|| d|| _dS )zRemove a tag from the object.r   N)r   remover   r   r   r   r   r   
remove_tag  s    
zMetadataModel.remove_tagNc                 C   s   | j ||S )zGet a metadata value.)metadataget)r#   keyr.   r   r   r   get_metadata  s    zMetadataModel.get_metadatac                 C   s   || j |< | jdgd dS )zSet a metadata value.r   rA   N)r   r!   )r#   r   valuer   r   r   set_metadata  s    
zMetadataModel.set_metadata)N)r   r   r   r(   r   	JSONFieldr*   dictr   r|   r   r   r   r   r   r   r   r   r   r   r   r     s&   
r   c                   @   s   e Zd ZdZejedddeddZejeddded	dZejed
ddeddZ	ejedddeddZ
ejedddeddZejedddddeddZejedddddeddZG dd dZdd Zdd ZdS ) AddressModela  
    Abstract model for address information.
    
    This model provides common address fields that can be
    used by various models that need location information.
    
    Attributes:
        street_address (CharField): Street address
        city (CharField): City name
        state_province (CharField): State or province
        postal_code (CharField): Postal/ZIP code
        country (CharField): Country name
        latitude (DecimalField): Latitude coordinate
        longitude (DecimalField): Longitude coordinate
    zstreet addressrV   Tz/Street address including number and street namer   cityd   z	City namezstate/provincezState or province namezpostal coderr   zPostal or ZIP codecountryzCountry namelatitude
      zLatitude coordinate)
max_digitsdecimal_placesr7   r8   r   	longitude   zLongitude coordinatec                   @   s   e Zd ZdZdZdS )zAddressModel.Metaz(Meta configuration for the AddressModel.TN)r   r   r   r(   r   r   r   r   r   r   O  s   r   c                 C   s(   | j | j| j| j| jg}dtd|S )z
        Get the complete address as a formatted string.
        
        Returns:
            str: Formatted address string
        r   N)street_addressr   state_provincepostal_coder   r   rL   )r#   address_partsr   r   r   get_full_addressS  s    zAddressModel.get_full_addressc                 C   s   | j dk	o| jdk	S )z
        Check if the address has geographic coordinates.
        
        Returns:
            bool: True if both latitude and longitude are set
        N)r   r   rG   r   r   r   has_coordinatesc  s    zAddressModel.has_coordinatesN)r   r   r   r(   r   r|   r*   r   r   r   r   r   DecimalFieldr   r   r   r   r   r   r   r   r   r     sd   		r   c                   @   s.   e Zd ZdZG dd dZdd Zdd ZdS )		BaseModela%  
    Comprehensive base model combining all common functionality.
    
    This model combines UUID primary keys, timestamps, user tracking,
    soft delete, and status management into a single base class that
    provides enterprise-level functionality for all models.

    This model includes:    
    - UUID :: UUID primary key for better security
    - Timestamps :: Created and updated timestamps
    - Soft delete :: Soft delete functionality
    - Audit trail :: Created and updated by user tracking 
    - Common methods for all models 
    c                   @   s   e Zd ZdZdS )zBaseModel.MetaTNr0   r   r   r   r   r   }  s   r   c                 C   s   | j j d| j dS )z:Default string representation using the model name and ID.z ())r'   r   r4   rG   r   r   r   __str__  s    zBaseModel.__str__c                 C   sF   ddl m} | jj }z|| dd| jidW S    Y dS X dS )z
        Get the absolute URL for this model instance.
        
        This method should be overridden in child models to provide
        the correct URL for the model's detail view.
        r   r   z-detailr   )r%   #N)django.urlsr   r'   r   lowerr   )r#   r   
model_namer   r   r   get_absolute_url  s    zBaseModel.get_absolute_urlN)r   r   r   r(   r   r   r   r   r   r   r   r   m  s   r   c                   @   s   e Zd ZdZG dd dZdS )FullBaseModela.  Complete base model with all functionality.
    
    This model combines all available base functionality:
    - UUID primary key
    - Timestamps
    - Soft delete
    - Audit trail
    - Status management
    - Metadata storage
    
    Use this for models that need comprehensive functionality.
    c                   @   s   e Zd ZdZdS )zFullBaseModel.MetaTNr0   r   r   r   r   r     s   r   N)r   r   r   r(   r   r   r   r   r   r     s   r   )&r(   r2   	django.dbr   r   r   django.utilsr   django.core.exceptionsr   django.utils.translationr   r*   django.contrib.authr   "django.contrib.contenttypes.modelsr	   Z"django.contrib.contenttypes.fieldsr
   django.core.validatorsr   r   Zapps.common.managersr   r   Modelr   r,   r5   rU   r`   rk   rn   r}   r   r   r   r   r   r   r   r   <module>   s.   %b-B7B!:f&