
    `j                    J   d Z ddlmZ ddl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 dd	lmZ dd
lmZmZ ddlmZ ddlmZ  ej2                  e      ZdZdZ G d de      Z G d de      Z G d de      Z  G d de      Z! G d de!      Z"	 	 	 	 	 	 	 	 	 	 ddZ#y)u   Ross1000 export orchestration service.

Implements the strategy pattern for two output modes:
- "xml"  → plain UTF-8 XML (default)
- "soap" → SOAP 1.1 envelope wrapping the XML payload

Architecture:
    Ross1000ExportService
        ├── XmlExportStrategy   → serialize_movement_days_xml()
        └── SoapEnvelopeStrategy → build_soap_envelope(xml_payload)

This service is the single entry point for the Ross1000 export pipeline.
It does NOT touch TXT export, C59, or Alloggiati pipelines.
    )annotationsN)ABCabstractmethod)date)Ross1000ValidationError)Ross1000ExportResultRoss1000MovementDayPayload)build_movement_days)build_soap_envelope)validate_date_rangevalidate_structure)serialize_movement_days_xml)	Structurezapplication/xml; charset=utf-8ztext/xml; charset=utf-8c                  6    e Zd ZdZe	 	 	 	 	 	 	 	 	 	 dd       Zy)BaseMovementExportStrategyz4Abstract strategy for Ross1000 export serialization.c                    y)z3Serialize movement days to (content, content_type).N )selfdaysstructure_code
start_dateend_dates        2/backend/istat/ross1000/services/export_service.py	serializez$BaseMovementExportStrategy.serialize/           N
r   z list[Ross1000MovementDayPayload]r   strr   r   r   r   returnztuple[str, str])__name__
__module____qualname____doc__r   r   r   r   r   r   r   ,   sN    >B.B 	B
 B B 
B Br   r   c                  ,    e Zd ZdZ	 	 	 	 	 	 	 	 	 	 ddZy)XmlExportStrategyzSerialize to plain UTF-8 XML.c               0    t        ||||      }|t        fS )Nr   r   r   )r   ROSS1000_XML_CONTENT_TYPE)r   r   r   r   r   contents         r   r   zXmlExportStrategy.serialize>   s(     .)!	
 111r   Nr   )r    r!   r"   r#   r   r   r   r   r%   r%   ;   s:    '2.2 	2
 2 2 
2r   r%   c                  <    e Zd ZdZdddddZ	 	 	 	 	 	 	 	 	 	 ddZy)	SoapEnvelopeStrategyz>Serialize to SOAP 1.1 envelope wrapping the plain XML payload. usernamepasswordc                    || _         || _        y )N)	_username	_password)r   r.   r/   s      r   __init__zSoapEnvelopeStrategy.__init__R   s    !!r   c               t    t        ||||      }t        || j                  | j                        }|t        fS )Nr'   r-   )r   r   r1   r2   ROSS1000_SOAP_CONTENT_TYPE)r   r   r   r   r   xml_payloadsoap_contents          r   r   zSoapEnvelopeStrategy.serializeV   sE     2)!	
 +^^^^

 777r   N)r.   r   r/   r   r   Noner   )r    r!   r"   r#   r3   r   r   r   r   r+   r+   O   sD    H*,b "8.8 	8
 8 8 
8r   r+   c                  6    e Zd ZdZe	 	 	 	 	 	 	 	 	 	 dd       Zy)BaseTourismExportServicez3Abstract base for regional tourism export services.c                    y)z3Generate an export result for the given parameters.Nr   )r   structure_idr   r   modes        r   exportzBaseTourismExportService.exports   r   r   N)
r<   intr   r   r   r   r=   r   r   r   )r    r!   r"   r#   r   r>   r   r   r   r:   r:   p   sP    =B B 	B
 B B 
B Br   r:   c                  ^    e Zd ZdZdddd	 	 	 	 	 	 	 	 	 	 	 	 	 ddZe	 	 	 	 	 	 	 	 d	d       Zy)
Ross1000ExportServicea6  Production-grade Ross1000 export service for Regione Liguria.

    Usage:
        service = Ross1000ExportService()
        result = service.export(
            structure_id=1,
            start_date=date(2026, 4, 1),
            end_date=date(2026, 4, 30),
            mode="xml",   # or "soap"
        )
    xmlr,   )r=   soap_usernamesoap_passwordc               H   t        ||      \  }}t        j                  j                  |      j	                         }	|	t        d| d      t        |	       t        |	j                        j                         }
| j                  |||      }t        |	||      }|j                  ||
||      \  }}t        |
|||      }t        j                  d||
|j!                         |j!                         |t#        |      |d	d
       t%        |||t#        |      |      S )a  Generate a Ross1000 export for a structure and date range.

        Args:
            structure_id:   ID of the Structure to export
            start_date:     First day of the reporting period (inclusive)
            end_date:       Last day of the reporting period (inclusive)
            mode:           "xml" (default) or "soap"
            soap_username:  ISTAT credential username (SOAP mode only)
            soap_password:  ISTAT credential password (SOAP mode only)

        Returns:
            Ross1000ExportResult with filename, content, content_type, day_count, mode

        Raises:
            Ross1000ValidationError: On invalid inputs or missing data
        )idz
Structure z
 not foundr=   r.   r/   )	structurer   r   r'   )r   r   r   r=   zRoss1000 export generatedsuccess)r<   r   r   r   r=   	day_countfilenamestatus)extra)rK   r)   content_typerJ   r=   )r   r   objectsfilterfirstr   r   r   
istat_codestrip_get_strategyr
   r   _build_filenameloggerinfo	isoformatlenr   )r   r<   r   r   r=   rC   rD   valid_start	valid_endrH   r   strategyr   r)   rN   rK   s                   r   r>   zRoss1000ExportService.export   sR   4 "5Z!JY%%,,,=CCE	)J|nJ*OPP9%Y11288: %%"" & 
 #"
 !) 2 2)"	 !3 !
 #)"	
 	' ,"0)335%//1 Y$#	 	 	
 $%$i
 	
r   c                b    | dk(  rt        ||      S | dk(  r
t               S t        d|  d      )Nsoapr-   rB   zUnknown export mode 'z'. Valid modes: 'xml', 'soap')r+   r%   r   rG   s      r   rT   z#Ross1000ExportService._get_strategy   sB     6>'HMM5=$&&%#D6)FG
 	
r   N)r<   r?   r   r   r   r   r=   r   rC   r   rD   r   r   r   )r=   r   r.   r   r/   r   r   r   )r    r!   r"   r#   r>   staticmethodrT   r   r   r   rA   rA      s    
$ S
 S
 	S

 S
 S
 S
 S
 
S
j 


 
 
$	
 
r   rA   c                    | j                  dd      j                  dd      }d}d| d|j                  d       d|j                  d       d| S )	z&Build a descriptive download filename./- _rB   	Ross1000_z%Y%m%d.)replacestrftime)r   r   r   r=   	safe_codeexts         r   rU   rU      sd     &&sC088cBI
C
I;a
 3 3H =>
Hh'(#	0r   )
r   r   r   r   r   r   r=   r   r   r   )$r#   
__future__r   loggingabcr   r   datetimer   istat.ross1000.exceptionsr   &istat.ross1000.models.movement_payloadr   r	   (istat.ross1000.services.movement_builderr
   $istat.ross1000.soap.envelope_builderr   +istat.ross1000.validators.payload_validatorr   r   &istat.ross1000.xml.movement_serializerr   structures.modelsr   	getLoggerr    rV   r(   r5   r   r%   r+   r:   rA   rU   r   r   r   <module>rw      s    #  #  = I D _ N ' 
		8	$< 6 B B22 2(85 8BBs B&n
4 n
b  	
  	r   