
    Nwg)                         d dl mZ d dlmZmZ d dlmZmZmZ d dl	m
Z
 d dlmZmZ dZ G d de      Z G d	 d
ej                         Z G d d      Zy)    )settings)
connectionmodels)OuterRefQuerySetSubquery)timezone)get_app_model_primary_key_nameget_change_reason_from_object_historyc                   X     e Zd ZdZ fdZd Z fdZd Zd Z fdZ	 fdZ
d	 Z xZS )
HistoricalQuerySetaS  
    Enables additional functionality when working with historical records.

    For additional history on this topic, see:
        - https://github.com/jazzband/django-simple-history/pull/229
        - https://github.com/jazzband/django-simple-history/issues/354
        - https://github.com/jazzband/django-simple-history/issues/397
    c                     t        |   |i | d| _        d | _        | j                  j
                  j                  j                  j                  | _	        y )NF)
super__init___as_instances_as_ofmodelinstance_type_metapkattname_pk_attrselfargskwargs	__class__s      M/var/www/horilla/myenv/lib/python3.12/site-packages/simple_history/manager.pyr   zHistoricalQuerySet.__init__   sG    $)&)"

006699AA    c                 t    | j                   s| j                  d      }d|_         |S | j                         }|S )z
        Return a queryset that generates instances instead of historical records.
        Queries against the resulting queryset will translate `pk` into the
        primary key field of the original type.

        Returns a queryset.
        -)history_typeT)r   exclude_clone)r   results     r   as_instanceszHistoricalQuerySet.as_instances    s>     !!\\s\3F#'F   [[]Fr    c                 ~    | j                   r"d|v r|j                  d      || j                  <   t        |   |i |S )a  
        If a `pk` filter arrives and the queryset is returning instances
        then the caller actually wants to filter based on the original
        type's primary key, and not the history_id (historical record's
        primary key); this happens frequently with DRF.
        r   )r   popr   r   filterr   s      r   r*   zHistoricalQuerySet.filter/   s?     $&.$*JJt$4F4==!w~t.v..r    c                    t         j                  }|dk(  rwi }| j                  dd      D ]>  }t        || j                        |vs|j
                  |t        || j                        <   @ | j                  |j                               }|S |dk(  r[| j                  | j                  dd      j                  | j                        j                  dd      }| j                  |      }|S  | j                  di | j                  t        | j                        ij                  dd      j                  d      d	d
 }| j                  t        |            }|S )z
        Ensures results in the queryset are the latest historical record for each
        primary key.  Deletions are not removed.

        Returns a queryset.
        mysqlz-history_datez-pk)history_id__in
postgresqlr   T)flatN    )r   vendororder_bygetattrr   r   r*   valuesdistinctvalues_listr   r   )r   backendhistory_idsitemlatest_historicslatest_pk_attr_historic_idss         r   latest_of_eachz!HistoricalQuerySet.latest_of_each:   sR    ##gKou= H4/{B@DKdmm <=H  ${{+:L:L:N{O"  ! $dmm_eD$--(T- (
  ${{:U{V   Gt}}ht}}.EFG/51bq" (
  ${{'(CD  +    r    c                     | j                   j                  D cg c](  }t        |t        j                        r|j
                  * }} | j                  | S c c}w )z
        A convenience method that calls ``select_related()`` with all the names of
        the model's history-tracked ``ForeignKey`` fields.
        )r   tracked_fields
isinstancer   
ForeignKeynameselect_related)r   fieldfield_namess      r   $_select_related_history_tracked_objsz7HistoricalQuerySet._select_related_history_tracked_objs^   sY     22
%!2!23 JJ
 

 #t""K00
s   -Ac                     t         |          }| j                  |_        | j                  |_        | j                  |_        |S N)r   r%   r   r   r   )r   cr   s     r   r%   zHistoricalQuerySet._clonej   s7    GN,,;;]]
r    c                 B    t         |           | j                          y rH   )r   
_fetch_all_instanceizer   r   s    r   rK   zHistoricalQuerySet._fetch_allq   s    r    c                 L   | j                   r| j                  rt        | j                   d   | j                        rb| j                   D cg c]  }|j                   c}| _         | j                   D ])  }t        |t              }t        |d| j                         + yyyyc c}w )z
        Convert the result cache to instances if possible and it has not already been
        done.  If a query extracts `.values(...)` then the result cache will not contain
        historical objects to be converted.
        r   r   N)	_result_cacher   r@   r   instancer4    SIMPLE_HISTORY_REVERSE_ATTR_NAMEsetattrr   )r   r:   historics      r   rL   zHistoricalQuerySet._instanceizeu   s     ""4--a0$**=<@<N<N!OD$--!OD** 9"4)IJ(DKK89 > #  "Ps   
B!)__name__
__module____qualname____doc__r   r'   r*   r=   rF   r%   rK   rL   __classcell__r   s   @r   r   r      s2    B	/" H
19r    r   c                   P     e Zd Zd fd	Z fdZd Zd Zd Z	 	 	 	 	 	 ddZ xZ	S )	HistoryManagerc                 >    t         |           || _        || _        y rH   )r   r   r   rP   )r   r   rP   r   s      r   r   zHistoryManager.__init__   s    
 r    c                      t         |          S rH   )r   get_querysetrM   s    r   get_super_querysetz!HistoryManager.get_super_queryset   s    w#%%r    c                     | j                         }| j                  |S t        | j                        } | j                         j                  di || j                  j                  iS )Nr1   )r_   rP   r
   r*   r   )r   qskey_names      r   r^   zHistoryManager.get_queryset   s[    $$&== I1$--@/t&&(//O8T]]=M=M2NOOr    c                    | j                   s8t        dj                  | j                  j                  j
                              g }| j                  j                  D ]V  }t        |t        j                        r|j                  |j                  dz          <|j                  |j                         X t        |      }	  | j                         j                  | d   } | j                   j"                  di |S # t        $ r= | j                   j!                  d| j                   j                  j
                  z        w xY w)zX
        Returns the most recent copy of the instance available in the history.
        z.Can't use most_recent() without a {} instance._idr   z%s has no historical record.r1   )rP   	TypeErrorformatr   r   object_namer?   r@   r   rA   appendrB   tupler^   r5   
IndexErrorDoesNotExistr   )r   tmprD   fieldsr5   s        r   most_recentzHistoryManager.most_recent   s    }}@GGJJ$$00 
 ZZ.. 	'E%!2!23

5::-.

5::&		'
 s	/T&&(//8;F
 't}}&&000	  	--,,.1D1D1P1PP 	s    C> >AEc                 R   | j                         j                  |      }| j                  s7t        |t              r||_        |j                         j                         }|S 	 |d   }|j                  dk(  r<| j                  j                  d| j                  j                  j                  z        |j                  }t        |t              }t        |d|       |S # t        $ r= | j                  j                  d| j                  j                  j                  z        w xY w)a  
        Get a snapshot as of a specific date.

        When this is used on an instance, it will return the instance based
        on the specific date.  If the instance did not exist yet, or had been
        deleted, then a DoesNotExist error is railed.

        When this is used on a model's history manager, the resulting queryset
        will locate the most recent historical record before the specified date
        for each primary key, generating instances.  If the most recent historical
        record is a deletion, that instance is dropped from the result.

        A common usage pattern for querying is to accept an optional time
        point `date` and then use:

            `qs = <Model>.history.as_of(date) if date else <Model>.objects`

        after which point one can add filters, values - anything a normal
        queryset would support.

        To retrieve historical records, query the model's history directly;
        for example:
            `qs = <Model>.history.filter(history_date__lte=date, pk=...)`

        To retrieve the most recent historical record, including deletions,
        you could then use:
            `qs = qs.latest_of_each()`
        )history_date__lter   z%s had not yet been created.r"   z%s had already been deleted.r   )r^   r*   rP   r@   r   r   r=   r'   rj   rk   r   rg   r#   r4   rQ   rR   )r   datequerysethistory_objr&   rS   s         r   as_ofzHistoryManager.as_of   s   : $$&---E}}($67"&..0==?HO	"1+K
 ##s*--,,.1D1D1P1PP  %%6#CD(D)  	--,,.1D1D1P1PP 	s   %C   AD&c                 x   t        t        dd      syd}|rd}g }	|D ]  }
t        |
d|xs | j                  j                  |
            } | j                  dt        |
d|xs t	        j
                               |t        |
      xs ||d| j                  j                  D ci c]#  }|j                  t        |
|j                        % c}|xs i }t        | j                  d	      r|
j                  |_        |	j                  |        | j                  j                  j                  |	|
      S c c}w )z
        Bulk create the history for the objects specified by objs.
        If called by bulk_update_with_history, use the update boolean and
        save the history_type accordingly.
        SIMPLE_HISTORY_ENABLEDTN+~_history_user_history_date)history_datehistory_userhistory_change_reasonr#   history_relation)
batch_sizer1   )r4   r   r   get_default_history_userr	   nowr   r?   r   hasattrr   history_relation_idrh   objectsbulk_create)r   objsr   updatedefault_userdefault_change_reasondefault_datecustom_historical_attrsr#   historical_instancesrP   r|   rD   rows                 r   bulk_history_createz"HistoryManager.bulk_history_create   sI    x!94@L! 	-H"M

 C CH ML
 $** $o|/Mx||~ *&CH&M ')() "&!:!: MM78U]]#CC +0bC tzz#56*2++' '',-	-0 zz!!-- Z . 
 	
s   #(D7rH   )NFN NN)
rT   rU   rV   r   r_   r^   rn   rt   r   rX   rY   s   @r   r[   r[      s7    !
&P142n   $1
r    r[   c                       e Zd ZeefdZd Zy)HistoryDescriptorc                 .    || _         || _        || _        y rH   )r   queryset_classmanager_class)r   r   managerrr   s       r   r   zHistoryDescriptor.__init__  s    
&$r    c                 n     | j                   j                  | j                        | j                  |      S rH   )r   from_querysetr   r   )r   rP   owners      r   __get__zHistoryDescriptor.__get__  s1    Dt!!//0C0CDJJ
 	
r    N)rT   rU   rV   r[   r   r   r   r1   r    r   r   r     s    &4?Q %

r    r   N)django.confr   	django.dbr   r   django.db.modelsr   r   r   django.utilsr	   simple_history.utilsr
   r   rQ   r   Managerr[   r   r1   r    r   <module>r      sM      ( 9 9 ! $.  s9 s9lP
V^^ P
f	
 	
r    