
    `j
e                        d dl Z d dlmZ d dlmZmZ d dlmZ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mZ d d	lmZ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#m$Z$ d dl%m&Z& d dl'm(Z(m)Z)m*Z*m+Z+ d dl,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 d dl4m5Z5m6Z6m7Z7 d dl8m9Z9m:Z: g dZ;dddddddddddddddddddddd ddd!ddd"ddd#ddd$ddd%Z<d&d&d'd(d)id*d*d'd+d+d'd(d,id(d-id(d.id/Z= e>e=j                               Z@d0 ZAd1 ZBd2 ZCd3 ZDd4 ZEd5 ZFd6 ZGd7 ZHd8 ZId9 ZJd: ZKd; ZLd< ZMd= ZNd> ZOd? ZPd@ ZQdA ZRddBdCZSdD ZTdE ZUdF ZVdG ZWdH ZXdI ZYdJ ZZdK Z[dL Z\dM Z]dN Z^dO Z_dP Z`y)Q    N)
monthrange)Counterdefaultdict)date	timedelta)BlockedPeriod)Booking)modelstransaction)FFuncValue)CastCoalesce)capfirst)Property)ValidationError)	Structure)Guest)ISTAT_NOT_SPECIFIEDISTAT_NOT_SPECIFIED_DISPLAYnormalize_guest_for_istat)resolve_residence)IstatCountryIstatGuestTypeIstatTourismTypeIstatTransportType)TOURISM_VALUE_PAIRSTRANSPORT_VALUE_PAIRS_build_country_lookup_build_value_map_resolve_country_codebuild_istat_previewgenerate_istat_export)country_name_from_iso2is_iso2_countrynormalize_country)generate_guest_nightswith_guest_night_prefetch)1617181920zMissing Arrival Datemanual_only)labelfix_typezMissing Birth DatezMissing Residence CountryselectzMissing Country of BirthzMissing GenderzMissing Guest TypezMissing NationalityzMissing Position CodezMissing Residence MunicipalityzMissing Residence ProvincezMissing Tourism TypezMissing Transport Type)arrival_date
birth_datecountrycountry_of_birthgender
guest_typenationalityposition_coderesidence_municipalityresidence_provincetourism_typetransport_typer7   )model_fieldextra_data_keyr?   r6   r9   r5   r8   r=   r>   )r7   r6   r9   r5   r8   r=   r>   c           	      |    t        | d   | d   d      }t        | d   | d   t        | d   | d         d         }||fS )Nyear
from_month   to_month)r   r   )period
start_dateend_dates      /backend/istat/services.pyget_period_date_rangerJ      sW    fVnf\&:A>Jvz6&>6*#56q9H
 x    c                     t        | ||      S Nstructure_idrG   rH   )r#   rN   s      rI   generate_preview_for_date_rangerP      s    ! rK   c                 :    t        |      \  }}t        | ||      S rM   )rJ   rP   rO   rF   rG   rH   s       rI   generate_preview_for_periodrS      s'    08J*! rK   c                     t        | ||      S rM   )r$   rN   s      rI   generate_export_for_date_rangerU      s     ! rK   c                 :    t        |      \  }}t        | ||      S rM   )rJ   rU   rR   s       rI   generate_export_for_periodrW      s'    08J)! rK   c                 	   t         j                  j                  |       j                         }|st	        d      t        t        j                  j                  |t        j                  j                        j                  d      j                  d            }|D cg c]  }|j                   }}|D ci c];  }|j                  t        t        t        |j                  dd      xs d      d      = }}t!        |      }t#        |j%                               }	t'        d	      }
||
z   }i }|}||k  r4t)               t)               t+        t              dddd
||<   ||
z  }||k  r4|rt,        j                  j                  ||||      j/                  ddd      }|D ]F  \  }}}t        ||      }t1        ||      }||k  s%||   d   j3                  |       ||
z  }||k  r"H t        t5        t6        j                  j                  |||            j                  dd            }t9        |||      }|D ]  }||j:                     }|dxx   dz  cc<   |j<                  r|dxx   dz  cc<   |j>                  r|dxx   dz  cc<   |j@                  s^|d   j3                  |j@                         |d   |j@                  xx   dz  cc<    g }t;        |jB                  |jD                  d      }||k  rt        ||      }t1        t;        |jB                  |jD                  tG        |jB                  |jD                        d         |      }g }|}||k  r||   }|d   }|d   }d}|D ]*  }||v r||   |jI                  |d      z
  }|dkD  s&||z  }, |jK                  ||jL                  t        |t!        |      z
  d      |t!        |d         |d   |d   |d   dd	       ||
z  }||k  r|jK                  |jB                  |jD                  |jO                  d      ||	|d       |jD                  dk(  rt;        |jB                  dz   dd      }n$t;        |jB                  |jD                  dz   d      }||k  r|j                  |jP                  |jB                  |jD                  |jD                  d|dS c c}w c c}w )N)idzStructure not found.)	structureavailabilityproperty_typerY   num_bedsr   rD   )days)blocked_propertiesoccupied_propertiesoccupied_guests_by_propertyarrivals
departures	presences)rZ   property_id__instart_date__lteend_date__gtproperty_idrG   rH   r_   )rZ   check_in_date__ltecheck_out_date__gtcheck_in_date)period_startperiod_end_exclusiverd   rb   rc   r`   ra   open)	r   dayavailable_roomsavailable_bedsoccupied_roomsrb   rc   rd   statusz%B %Y)rB   monthr0   total_rooms
total_bedsr^      )rB   rC   rE   )rO   structure_namerF   months))r   objectsfilterfirst
ValueErrorlistr   Availability	AVAILABLEselect_relatedorder_byrY   maxintgetattrr\   lensumvaluesr   setr   r   values_listminaddr)   r	   r(   r   is_arrival_nightis_departure_nightrh   rB   rt   r   getappendro   strftimename) rO   rG   rH   rZ   sellable_propertiespropsellable_property_idsbeds_by_property_idru   rv   day_stepend_date_exclusive
days_indexcursorblocked_periodsrh   block_start	block_endfinalbookingsguest_nightsguest_nightday_payloadry   month_cursormonth_start	month_endr^   r_   ra   rq   remaining_bedss                                    rI   #build_daily_calendar_for_date_ranger      sO   !!((L(9??AI/00!..88 	  	
 
	(	$ 2EE1DTWW1DE ('D 	S!3!3ZCHqI1MM'   )*K(//12Ja H!H,JF
H
"%%#&5+6s+;

6 	( H
 '//661$#	 7 

 +m\:
> 	 4C/Kij1F	#56E5.6"#78<<[I(" 5. 4C !OO""##+#- # 	
 (?D
)H )/L $ !1!12K A% ''
#q(#))%*%""-.22;3J3JK56{7N7NOSTTO $ F
)9)91=L
(
",
3!!""<,,l.@.@A!D
 
	 	!$V,K!,-A!B*56S*T'N4"44 (4155k1EF  "A%"n4N  5 KK"!::'*;=O9P+PRS'T&4&)+6K*L&M +J 7"-l";!,[!9$
 hF= 	!@ 	$))%++%..w7*(		
 # 1 1A 5q!<L 1 1<3E3E3I1MLw (
"| "#..OO$** 

 	 	C Fs    S9A Sc                 :    t        |      \  }}t        | ||      S rM   )rJ   r   rR   s       rI   build_daily_calendar_for_periodr   G  s'    08J.! rK   c                    t        | |      }t        |d         }|sdg iS t               }|d   D cg c]  }|j                  d      dk(  r|d    }}t	        | ||t        |      j                  t              |      }g }t        |j                         d	 
      D ]  \  }	}
t        j                  |	i       }|j                  dd      }|	|j                  dt        |	            t        |
      t        |
      |d}|dk(  r#t        |	|      |d<   |j                  |	      |d<   |j                  |        d|iS c c}w )NrO   rF   invalid_recordsissuesrecord_payloadsrs   validguest_id)rO   rF   valid_guest_idsfieldslookup_bundlec                 <    t        | d          t        | d         fS )NrD   r   )r   _issue_label)items    rI   <lambda>z&build_issues_summary.<locals>.<lambda>g  s    3tAw<-d1g)>?rK   )keyr1   r/   r0   )fieldr0   count	guest_idsr1   r2   options	suggested)rS   _group_issue_guest_ids_build_fix_lookup_bundler   _build_suggested_valuesr   intersectionBULK_FIXABLE_FIELDSsorteditemsISSUE_FIELD_CONFIG_default_issue_labelr   _options_for_fieldr   )rO   rF   previewgrouped_issue_idsr   recordr   suggested_valuesr   r   r   configr1   issues                 rI   build_issues_summaryr   P  sm   )|FSG.w7H/IJ"~,.M /00F::h7* 	z0  
 /!'$%223FG# F"!?y $''r2::j-8ZZ)=e)DE^	* 
 x1%GE)!1!5!5e!<E+e!$ fAs    D?c                    t        | |      }t        |d         }t               }g }t               }|D ]  }|d   }	|	t        vrt        dd|	 dgi      t        |d         }
|j                  |	t                     }t        |
|z
        }|rt        dd| d	|	 d
gi      t        |	|d   |      }|j                  |	|t        |
      d       |j                  |
        t        |      \  }}t        j                         5  |D ]  }t        | |||d   |d   |d           	 d d d        t        | |      }dt        |      t        |d         dS # 1 sw Y   1xY w)Nr   r   r   fixesField '' does not support bulk fixes.r   z
Guest IDs z do not currently have the 'z' issue in the selected period.value)r   	raw_valuer   )r   r   r   )rO   rG   rH   r   canonical_valuer   T)successupdated_countremaining_issues)rS   r   r   r   r   r   r   r   _normalize_fix_valuer   updaterJ   r   atomic_apply_bulk_fixr   )rO   rF   r   r   r   r   normalized_fixesupdated_guest_idsfixr   requested_guest_idseligible_guest_idsinvalid_guest_idsr   rG   rH   refreshed_previews                    rI   apply_bulk_issue_fixesr   z  s   )|FSG.w7H/IJ,.MG++!WUG+IJKL  "#k"23.225#%@"#69K#KL!():(; <))./NP	 	 /'l'

 	(#$78	
 	  !45E H 18J				#C)%!'l #Gk* $ 
 4!
 ./ 12C DE  
	s   "EE#c                    |r|si S t        |      \  }}|D ci c]  }|t                }}t        | |||      j                  d      }	|	D ]*  }
|D ]#  }t	        |
||      }|s||   |xx   dz  cc<   % , |j                         D ci c]  \  }}|r||j                  d      d   d   ! c}}S c c}w c c}}w )NrO   rG   rH   r   booking)guestr   r   rD   r   )rJ   r   _guest_querysetr   _effective_field_valuer   most_common)rO   rF   r   r   r   rG   rH   r   countersquerysetr   r   counters                rI   r   r     s    &	08J.45fUwy fH5!!	
 nY  E*+E
 &!+&   'nn..NE7 	w""1%a(++. % 6$s   B5$B:c                     t        t              }| D ]>  }|j                  d      }|j                  dg       D ]  }||   j                  |        @ |S )Nr   errors)r   r   r   r   )r   groupedr   r   r   s        rI   r   r     sR    #G!::j)ZZ"-EENx( . " NrK   c                  *   t               } t        t        t              }t        t        t
              }t        t        j                  j                  d      j                  dd            }|st        j                         }| |||t        |      dS )N)modelalias_pairscodeTflat)r5   r=   r>   guest_type_optionsguest_type_set)_build_country_bundle_build_named_option_bundler   r   r   r   r~   r   rz   r   r   DEFAULT_GUEST_TYPE_OPTIONScopyr   )country_bundletourism_bundletransport_bundler   s       rI   r   r     s    *,N/'N 2 ) ''/;;F;N 7<<> "&*001 rK   c                  *   t               } i }g }t        j                  j                  d      j	                  ddd      D ]  }t        |j                  xs |j                        }|rt        |      s4|j                  |       |j                  r||t        |j                        <   |j                  r||t        |j                        <   |j                  s||t        |j                        <    | |t        t        j                  |            dS )Nr   r   iso_code)lookupspreferred_by_coder   )r    r   rz   r   onlyr'   r  r   r&   r   
_normalizer   r~   dictfromkeys)r  r  r   r5   options        rI   r   r     s    #%GG''008==
F #7#3#3#Cw||D_V4v<<:@j67<<:@j67>Dj)9)9:; .g./ rK   c                    t        | j                  j                  d      j                  dd            }|D ci c]  }t	        |      | }}i }|j                  t	        t                    }|r||t	        t              <   |rEt        |      }|j                         D ]'  \  }}	|j                  t	        |	            }
|
s#|
||<   ) |||dS c c}w )Nr   Tr   )indexalias_indexr   )
r~   rz   r   r   r  r   r   r   r!   r   )r   r   r   r	  normalized_indexr  not_specifiedtranslated_valuesr   translated_value	canonicals              rI   r   r     s    5==))&1==f4=PQGAHIv
6*F2IK$((4O)PQM7DJ234,[9+<+B+B+D'I'(,,Z8H-IJI)2I& ,E ""  Js   Cc                    t        |       } t        | j                        }|dk(  r\t        |j	                  d      xs | j
                  | j                  |j	                  d      | j                  |      }|j                  S |dk(  rjt        |j	                  d      xs | j
                  | j                  |j	                  d      | j                  |      }|j                  r|j                  S d S |dk(  r(t        |j	                  d      xs | j                        S |dk(  r?t        | j                  xs$ |j	                  d      xs |j	                  d      |d         S |d	k(  r,t        |j	                  d	      xs | j                  |d         S |dk(  r,t        |j	                  d      xs | j
                  |d         S |d
k(  r+| j                   xs |j	                  d
      }t#        ||      S |dk(  rEt%        | j&                  xs* |j	                  d      xs t)        | j*                  dd       |d         S |dk(  rEt%        | j,                  xs* |j	                  d      xs t)        | j*                  dd       |d         S y )Nr;   r5   province)r5   cityr  region
extra_datar<   r7   r6   place_of_birthr9   r8   r=   r>   )r   _coerce_extra_datar  r   r   r5   r  r  municipality_nameprovince_matchesprovince_code_canonical_gender_optionr7   _display_country_optionr6   r9   r8   _canonical_guest_type_option_canonical_named_optionr=   r   r   r>   )r   r   r   r  	residencer   s         rI   r   r   *  s|   %e,E#E$4$45J((%NN9->^^J/<<!
	 ***$$%NN9->^^J/<<!
	 +4*D*Dy&&N$N'
x(@(PELLQQ""&"" 0~~010~~./)$	
 	
 &NN=)>U->->)$
 	
 	&NN9%6)$
 	
 $$D
|(D	+I}EE& <~~n-<u}}nd;.)	
 	
   &   >~~./>u}}&6=*+	
 	
 rK   c                 h   | dk(  rt        |      }|st        ddgi      |S | dv r(t        ||d         }|st        dd| d|  dgi      |S | d	k(  r"t        ||      }|st        dd| d
gi      |S | dv r(t	        |||          }|st        dd| d|  dgi      |S t        dd|  dgi      )Nr7   r   z!Gender fixes must use 'M' or 'F'.>   r5   r9   r6   r5   'z%' is not a valid country option for ''.r8   z,' is not a valid guest type for bulk fixing.>   r=   r>   z' is not a valid option for 'r   r   )r  r    _canonical_country_storage_valuer  r  )r   r   r   r   s       rI   r   r   g  sQ   29=!>?@  >>:)$
 !I;&KE7RTU  6y-P!I;&RS  221% 
 !I;&CE7"M  
	WUG#ABCD rK   c                    t         |   }t        ||      }t        | |||      }|d   |i}	|j                  d      }
|
rt	        |
|      |	d<    |j
                  d	i |	}|t        |      k7  rt        dd| dgi      y )
Nr   r?   r@   r   r   r  r   z3One or more guests could not be updated for field 'r#   )AUTO_FIX_FIELD_CONFIG_storage_value_for_fieldr   r   _jsonb_set_extra_data_valuer   r   r   )rO   rG   rH   r   r   r   r   stored_valuer   update_kwargsr@   updated_rowss               rI   r   r     s    "5)F+E?CL!	H M*L9MZZ 01N&A'
l#
 #8??3]3Ls9~%!7"&	
 		
 &rK   c                      | dk(  rddd|   S |S )Nr7   malefemale)Mr   r'  )r   r   s     rI   r)  r)    s     (+O<<rK   )r   c                 t    t         j                  j                  | d||      }||j                  |      }|S )NT)booking__structure_idbooking__is_checked_inbooking__check_in_date__gtebooking__check_out_date__lte)id__in)r   rz   r{   )rO   rG   rH   r   r   s        rI   r   r     sD    }}##*#$.%-	 $ H ??)?4OrK   c                 D   t        t        t        d      t        i t	        j
                                     t        d|  d      t        t        t        j                  |            t	        j
                               t        d      dt	        j
                               S )Nr  )output_field{}T	jsonb_set)functionr9  )	r   r   r   r   r
   	JSONFieldr   jsondumpsr&  s     rI   r*  r*    st    <%9I9I9K"LM3%rlU4::e$%v'7'7'9:d%%' rK   c                 \    | dk(  rddgS | dv r|d   d   S | dk(  r|d   S | d	v r||    d   S g S )
Nr7   r1  r   >   r5   r9   r6   r5   r   r8   r   >   r=   r>   r'  )r   r   s     rI   r   r     s_    Sz>>Y'	2212222U#I..IrK   c                 .    t        |       }|dv ry|dv ryy )N>   1mr/  maschior1  >   2fr0  femminar   )r  )r   
normalizeds     rI   r  r    s'    E"J2244rK   c                 8    t        |       }|rt        |      sy |S Nr'   r&   r   r   rI  s      rI   r  r    s    "5)J_Z8rK   c                 8    t        |       }|rt        |      r|S y rK  rL  rM  s      rI   r$  r$    s    "5)Joj1rK   c                 V    t        | xs d      j                         }|sy ||d   v r|S y )N r   strstrip)r   r   r   s      rI   r  r    s6    EKR &&(IM"233rK   c                 d    t        |       }|sy ||d   v r|d   |   S |d   j                  |      S )Nr  r  )r  r   )r   option_bundlerI  s      rI   r  r    sE    E"J]7++W%j11'++J77rK   c                 *    t        | t              r| S i S rK  )
isinstancer  r   s    rI   r  r    s    %IrK   c                  V    | D ]$  }|t        |      j                         }|s"|c S  y rK  rQ  )r   r   rI  s      rI   _first_presentrZ    s4    =Z%%'
  rK   c                     t        t        | j                  xs d      t        | j                  xs d      z   d      }t	        | j
                  j                               }|dk  r|S ||k  r|S |S )Nr   )r   r   adults_countchildren_countr   guestsall)r   booking_countactual_guest_counts      rI   _effective_booking_guest_countrb  !  ss    G  %A&W-C-C-Hq)II	M W^^//12!!M)rK   c                 V    | yt        |       j                         j                         S )NrP  )rR  rS  lowerrX  s    rI   r  r  /  s&    }u:##%%rK   c                 `    t         j                  | i       j                  dt        |             S )Nr0   )r   r   r   r   s    rI   r   r   5  s(    !!%,00:Nu:UVVrK   c                 >    dt        | j                  dd             S )NzMissing _ )r   replacerf  s    rI   r   r   9  s     hu}}S#67899rK   )ar?  calendarr   collectionsr   r   datetimer   r   availability.modelsr   bookings.modelsr	   	django.dbr
   r   django.db.modelsr   r   r   django.db.models.functionsr   r   django.utils.textr   properties.modelsr   rest_framework.exceptionsr   structures.modelsr   guests.modelsr   guests.guest_defaultsr   r   r   istat.municipalitiesr   istat.modelsr   r   r   r   services.istat_export_servicer   r   r    r!   r"   r#   r$   services.country_utilsr%   r&   r'   services.guest_night_servicer(   r)   r   r   r(  	frozensetkeysr   rJ   rP   rS   rU   rW   r   r   r   r   r   r   r   r   r   r   r   r   r)  r   r*  r   r  r  r$  r  r  r  rZ  rb  r  r   r   r'  rK   rI   <module>r     s?     , $ - # ) + + 5 & & 5 '  
 3    
 Z <  (!
 &!
 -
 ,
 "
 &
 '
 )!
 2!
 .!
 (
 *[1 j  "
 	) %'
 !#
 	| 	~ 	'- 6   5 : : <=  Wt'T?D<22*:z5p
@ FJ 		8&W:rK   