-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Objective
Implement a webservice integration layer to communicate guest data to:
- Alloggiati Web (Italian Police - Polizia di Stato)
- Ross1000 (Hotel management software)
Background
The Italian Police provides a SOAP webservice for accommodations to report guest data:
- URL:
https://alloggiatiweb.poliziadistato.it/service/service.asmx - Protocol: SOAP/XML
- Authentication: Credentials → WSKEY → Temporary Token
- Record Format: 170 characters per guest (168 + CR/LF)
Current Database Compatibility
Our database already contains all required data:
| Alloggiati Web Field | Our Database |
|---|---|
| Guest Type (16-20) | stay_guest.guest_type_id |
| Arrival Date | stay.check_in_date |
| Days of Stay | stay.nights (auto-calculated) |
| Surname/Name | guest.@anagrafica_id.cognome/nome |
| Gender (1=M, 2=F) | guest.@anagrafica_id.sesso |
| Birth data | guest.@anagrafica_id.*_nascita |
| Citizenship | guest.@anagrafica_id.cittadinanza |
| Document | guest.document_* |
Proposed Implementation
1. AlloggiatiWebClient (SOAP Client)
File: resources/services/alloggiati_webservice.py
class AlloggiatiWebClient:
"""SOAP client for Alloggiati Web (Italian Police)"""
WSDL_URL = "https://alloggiatiweb.poliziadistato.it/service/service.asmx?wsdl"
def __init__(self, utente, password, wskey):
"""Initialize client with credentials"""
def generate_token(self):
"""Generate authentication token (valid ~1 hour)"""
# Method: GenerateToken
# Returns: TokenInfo (issued, expires, token)
def test_schedine(self, schedine_list):
"""Test guest records without sending (dry-run)"""
# Method: Test
# Returns: ElencoSchedineEsito with validation errors
def send_schedine(self, schedine_list):
"""Send guest records to Police system"""
# Method: Send
# Returns: ElencoSchedineEsito with submission results
def download_ricevuta(self, data):
"""Download receipt PDF for specific date"""
# Method: Ricevuta
# Returns: PDF as byte array
def download_tabelle(self, tipo_tabella):
"""Download reference tables (Luoghi, Tipi_Documento, etc.)"""
# Method: Tabella
# Returns: CSV string2. AlloggiatiExporter (170-char Record Builder)
File: resources/services/alloggiati_export.py
class AlloggiatiExporter:
"""Generates 170-character records for Alloggiati Web"""
def export_stay(self, db, stay_id):
"""Export all guests for a stay as 170-char records"""
# Returns: List of strings (170 chars each)
def build_schedina_line(self, stay, stay_guest, guest, anagrafica):
"""Build single 170-character line for one guest"""
# Format according to TABELLA 1 specification
def _format_field(self, value, length, field_type):
"""Pad value to specified length"""
# N = numeric (left-pad with zeros)
# A/AN = alpha/alphanumeric (right-pad with spaces)Record Structure (170 chars):
Position Length Field Format Required
-------- ------ ----------------------- ---------- ---------
0-1 2 Guest Type N Yes
2-11 10 Arrival Date gg/mm/aaaa Yes
12-13 2 Days of Stay N Yes (max 30)
14-63 50 Surname A Yes
64-93 30 Name A Yes
94-94 1 Gender N Yes (1=M, 2=F)
95-104 10 Birth Date gg/mm/aaaa Yes
105-113 9 Birth Municipality N If Italy
114-115 2 Birth Province A If Italy
116-124 9 Birth Country N Yes
125-133 9 Citizenship N Yes
134-138 5 Document Type AN Yes (leader only)
139-158 20 Document Number AN Yes (leader only)
159-167 9 Document Issue Place N Yes (leader only)
168-169 2 CR+LF - All except last
3. Ross1000Exporter (To Be Defined)
File: resources/services/ross1000_export.py
class Ross1000Exporter:
"""Export guest data for Ross1000 hotel software"""
def export_stay(self, db, stay_id, format='csv'):
"""Export stay in Ross1000 format"""
# Format to be defined based on Ross1000 specs
# Supported formats: csv, xml, json4. Integration Service
File: resources/services/guest_reporting_service.py
class GuestReportingService:
"""Main service coordinating all external integrations"""
def __init__(self, db):
self.db = db
self.alloggiati_client = None # Lazy init with credentials
self.alloggiati_exporter = AlloggiatiExporter()
self.ross1000_exporter = Ross1000Exporter()
def report_to_police(self, stay_id, test_mode=False):
"""Report stay to Alloggiati Web (Police)"""
# 1. Generate 170-char records
# 2. Test records (dry-run)
# 3. Send records (if test passed)
# 4. Save receipt
# 5. Update stay status
def report_to_ross1000(self, stay_id):
"""Export stay to Ross1000"""
# Generate Ross1000 format
# Send/Save file
def report_all(self, stay_id):
"""Report to all configured systems"""
# Police + Ross1000 + any other integrationsUI Integration
Table Handler Updates
File: resources/tables/stay/th_stay.py
Add button in stay form:
def th_form(self, form):
# ... existing code ...
# Add button for reporting
toolbar = top.div(margin='10px')
toolbar.button('Report to Police (Test)',
fire='.report_police_test',
icon='test')
toolbar.button('Report to Police (Send)',
fire='.report_police_send',
icon='send',
disabled='^.status != "ready"')
toolbar.button('Download Receipt',
fire='.download_receipt',
icon='download')Configuration
Add to site config (instanceconfig.xml or env):
<police_reporting>
<alloggiati_web>
<utente>XX002458</utente>
<password>***</password>
<wskey>***</wskey>
</alloggiati_web>
</police_reporting>Data Flow
1. User creates stay in host system
↓
2. AlloggiatiExporter generates 170-char records from stay_guest
↓
3. AlloggiatiWebClient tests records (dry-run)
↓
4. If validation passes, send records to Police
↓
5. Receive and store receipt PDF
↓
6. Update stay status
↓
7. (Optional) Export to Ross1000
Dependencies
- Python SOAP Library:
zeeporsuds-communitypip install zeep
Benefits
- Zero Data Duplication - All data already in our database
- Code Reuse - Similar to existing
police_export.py(178 chars) - Aligned Lookups -
guest_type,document_typealready compliant - Automatic Calculations -
nights,tax_amountauto-computed - Audit Trail - Store receipts and submission logs
Testing Strategy
- Unit Tests - Record formatting, field padding
- Integration Tests - SOAP client with test credentials
- Dry-run Mode - Always test before sending
- Validation - Use
Testmethod beforeSend
Acceptance Criteria
- SOAP client successfully authenticates with token
- Export generates valid 170-character records
- Test method validates records before sending
- Send method submits records to Police system
- Receipt PDF is downloaded and stored
- Ross1000 export format defined and implemented
- UI buttons trigger reporting workflow
- Error handling and logging implemented
- Documentation updated
References
- Alloggiati Web Manual:
/Users/dgpaci/Downloads/MANUALEWS.pdf - WSDL:
https://alloggiatiweb.poliziadistato.it/service/service.asmx?wsdl - Police Export Service:
resources/services/police_export.py(existing)
Estimated Effort
- AlloggiatiWebClient: 2-3 days
- AlloggiatiExporter: 1-2 days
- Ross1000Exporter: 1-2 days (pending specs)
- Integration Service: 1 day
- UI Integration: 1 day
- Testing: 2 days
Total: ~8-10 days
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels