
    ג[i>#                     P    d Z ddlZddlmZmZmZmZ ddlm	Z	  G d d          Z
dS )a/  
Update Engine Service

This module handles selective field updates for duplicate records.
Users can choose which fields to update in existing MongoDB records.

Key features:
- Field-level update selection
- Preview updates before applying
- Support for nested field updates
- Preserve unchanged fields
    N)DictAnyListOptional)JSONFlattenerc            	       l   e Zd ZdZd Zdeeeef                  de	j
        fdZde	j
        deeee         f         fdZde	j
        deeeef                  deeeef                  fdZ	 dd
e	j
        deee                  de	j
        fdZd
e	j
        de	j
        fdZde	j
        deeef         fdZd	S )UpdateEnginez
    Engine for handling selective field updates on duplicate records.
    
    Allows users to choose which fields to update in MongoDB
    when JSON contains updated information for existing records.
    c                 ,    t                      | _        dS )zInitialize update engine.N)r   	flattener)selfs    2/var/www/html/IGF-ODF-V3/services/update_engine.py__init__zUpdateEngine.__init__   s    &    
duplicatesreturnc                    g }t          |          D ]_\  }}|d         }|d         }|                    d          }d |                                D             }d |                                D             }	t          |                                          t          |	                                          z  }
t          |
          D ]}|                    |          }|	                    |          }||v r	||	vrd}d}n||vr	||	v rd}d	}n||k    rd
}d	}nd}d	}|                    ||rt          |          nd|||t          |          nd|t          |          nd|d           at          j	        |          S )aa  
        Build a DataFrame for update preview with field selection.
        
        Args:
            duplicates: List of duplicate records with json_record and db_record
            
        Returns:
            DataFrame with columns:
            - _record_index: Index of the duplicate record
            - _db_id: MongoDB _id for update operation
            - field: Field name
            - status: 'new', 'different', 'missing_in_json', 'match'
            - json_value: Value from JSON
            - db_value: Value from MongoDB
            - _update_decision: 'skip', 'update' (user choice)
        json_record	db_record_idc                 D    i | ]\  }}|                     d           ||S _
startswith.0kvs      r   
<dictcomp>z?UpdateEngine.build_update_preview_dataframe.<locals>.<dictcomp>;   s0    YYYDAqq||TWGXGXY1aYYYr   c                 D    i | ]\  }}|                     d           ||S r   r   r   s      r   r   z?UpdateEngine.build_update_preview_dataframe.<locals>.<dictcomp><   s0    UUU$!Q1<<PSCTCTUAUUUr   newupdatemissing_in_jsonskip	differentmatchN )_record_index_db_idfieldstatus
json_valuedb_value_update_decision)
	enumerategetitemssetkeyssortedappendstrpd	DataFrame)r   r   rowsidxdupr   r   db_idjson_fields	db_fields
all_fieldsr*   r,   r-   r+   default_decisions                   r   build_update_preview_dataframez+UpdateEngine.build_update_preview_dataframe   s   ( !*-- %	 %	HCm,KK(IMM%((E ZYK,=,=,?,?YYYKUU)//*;*;UUUI[--//003y~~7G7G3H3HHJ
++  (__U33
$==// K' .E,B ."F'/$$+- .%92D ..F'-$$8+ .(F'-$$$F'-$%(,1;c%jjjt"$5?"S#j///QS19 MH2(8     %8 |D!!!r   
preview_dfc                     g g d}|                                 D ]X\  }}|                    dd          }|dk    r|d                             |           =|d                             |           Y|S )z
        Extract update decisions from preview DataFrame.
        
        Args:
            preview_df: Preview DataFrame with update decisions
            
        Returns:
            Dictionary with 'update' and 'skip' lists of row indices
        )r"   r$   r.   r$   r"   )iterrowsr0   r5   )r   rB   	decisionsr:   rowdecisions         r   extract_update_decisionsz%UpdateEngine.extract_update_decisions^   s     
 
	
 #++-- 	. 	.HCww16::H8# .(#**3////&!((----r   c                    i }|                                 D ]M\  }}|d         dk    r|d         }|d         }|d         }||vr|d         i d||<   |||         d         |<   Ng }	|                                D ]\  }}
|
d         s||         d	         }|
d                                         }d
 |                                D             }| j                            |          }|	                    d|
d         id|i|d           |	S )a  
        Prepare MongoDB update operations based on user selections.
        
        Args:
            preview_df: Preview DataFrame with update decisions
            duplicates: Original duplicate records
            
        Returns:
            List of update operations for MongoDB bulk_write
            Each operation: {
                'filter': {'_id': ObjectId},
                'update': {'$set': {field: value, ...}},
                'record_index': int
            }
        r.   r"   r(   r*   r,   r)   )r<   fieldsrJ   r   c                 D    i | ]\  }}|                     d           ||S r   r   r   s      r   r   z:UpdateEngine.prepare_update_operations.<locals>.<dictcomp>   s3    cccAQRQ]Q]^aQbQbc1cccr   r   r<   z$set)filterr"   record_index)rD   r1   copyr   	unflattenr5   )r   rB   r   updates_by_recordr:   rF   
record_idxr*   r,   
operationsupdate_infor   fields_to_updateunflattened_updatess                 r   prepare_update_operationsz&UpdateEngine.prepare_update_operationsy   s   * "++-- 	H 	HHC%&(2 _-JLE\*J!22  ] 1 1!*- >Hj)(3E:: 
'8'>'>'@'@ 	 	#Jx(  %Z0?K  +8499;;  dc1A1G1G1I1Iccc #'.":":;K"L"L +g"67!#67 *      r   Ndfstatus_filterc                     |                                 }|r(|d                             |          }d|j        |df<   nd|d<   |S )a  
        Mark all fields (or filtered fields) for update.
        
        Args:
            df: Preview DataFrame
            status_filter: Optional list of statuses to update (e.g., ['new', 'different'])
            
        Returns:
            Updated DataFrame
        r+   r"   r.   )rN   isinloc)r   rW   rX   masks       r   mark_all_for_updatez UpdateEngine.mark_all_for_update   sU     WWYY 	.h<$$]33D/7BF4++,,%-B!"	r   c                 8    |                                 }d|d<   |S )z
        Mark all fields to skip (no updates).
        
        Args:
            df: Preview DataFrame
            
        Returns:
            Updated DataFrame
        r$   r.   )rN   )r   rW   s     r   mark_all_for_skipzUpdateEngine.mark_all_for_skip   s!     WWYY!'	r   c                 <   |d                                                                          }|d                                                                          }||d         dk             d                                         }t          ||d         dk                       }t          |          ||                    dd          ||                    dd          |                    dd          |                    d	d          |                    d
d          dS )z
        Get summary of pending updates.
        
        Args:
            preview_df: Preview DataFrame with update decisions
            
        Returns:
            Dictionary with update statistics
        r+   r.   r"   r(   r$   r   r!   r%   r#   r&   )total_fieldsrT   fields_to_skiprecords_to_update
new_fieldsdifferent_fieldsmissing_fieldsmatching_fields)value_countsto_dictnuniquelenr0   )r   rB   status_countsdecision_countsrc   rT   s         r   get_update_summaryzUpdateEngine.get_update_summary   s    #8,99;;CCEE %%78EEGGOOQQ 'z2D'E'QRSbckkmm z*5G*HH*TUVV  
OO 0-11&!<<!2'++E155 - 1 1+q A A+//0A1EE,00!<<	
 	
 		
r   )N)__name__
__module____qualname____doc__r   r   r   r6   r   r7   r8   rA   intrH   rV   r   r]   r_   rn    r   r   r	   r	      s        ) ) )="c3h(=" 
=" =" =" ="~L 
c49n	   6BLB c3h(B 
d38n		B B B BN .2 L  S	* 
	   2L 
   ""
L"
 
c3h"
 "
 "
 "
 "
 "
r   r	   )rr   pandasr7   typingr   r   r   r   services.json_flattenerr   r	   rt   r   r   <module>rx      s         , , , , , , , , , , , , 1 1 1 1 1 1v
 v
 v
 v
 v
 v
 v
 v
 v
 v
r   