7 Commits

Author SHA1 Message Date
Jonas Linter
16de553095 Added is_regular and awarness detection 2025-12-03 17:59:30 +01:00
Jonas Linter
4a9c0b91a1 And fixed typo 2025-12-03 17:47:30 +01:00
Jonas Linter
859716d0ea Added migration for awarness guest column 2025-12-03 17:47:23 +01:00
Jonas Linter
325f64fbc3 Awarness guest now for real 2025-12-03 17:44:05 +01:00
Jonas Linter
ea1d207438 Added awarnesss flag for conversion_guests 2025-12-03 17:43:51 +01:00
Jonas Linter
24d64bf28f Seems to mostly work now. Regular matching is still wrong 2025-12-03 17:05:58 +01:00
Jonas Linter
c4ecf3802f Fine this needs more work 2025-12-03 16:12:07 +01:00
6 changed files with 499 additions and 847 deletions

View File

@@ -0,0 +1,32 @@
"""boolean to signify awarness match in guests
Revision ID: 1daea5172a03
Revises: 263bed87114f
Create Date: 2025-12-03 17:44:29.657898
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = '1daea5172a03'
down_revision: Union[str, Sequence[str], None] = '263bed87114f'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('conversion_guests', sa.Column('is_awareness_guest', sa.Boolean(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('conversion_guests', 'is_awareness_guest')
# ### end Alembic commands ###

View File

@@ -42,7 +42,7 @@ select res.id, res.created_at, con.created_at as "Con Created at", con.updated_a
left join alpinebits.conversions as con on con.reservation_id = res.id
left join alpinebits.conversion_guests as g on g.guest_id = con.guest_id
where hotel_code = '39054_001'
where hotel_id = '39054_001'
order by res.created_at desc limit 400

View File

@@ -1197,7 +1197,9 @@ async def _process_conversion_xml_background(
# Now process the conversion XML
_LOGGER.info("Starting database processing of %s", filename)
conversion_service = ConversionService(session_maker, hotel.hotel_id)
processing_stats = await conversion_service.process_conversion_xml(xml_content)
processing_stats = await conversion_service.process_conversion_xml(xml_content, run_full_guest_matching=True)
await conversion_service.classify_regular_guests(24)
_LOGGER.info(
"Conversion processing complete for %s: %s", filename, processing_stats

File diff suppressed because it is too large Load Diff

View File

@@ -406,6 +406,11 @@ class ConversionGuest(Base):
is_regular = Column(
Boolean, default=False
) # True if guest has many prior stays before appearing in our reservations
# Guest classification
is_awareness_guest = Column(
Boolean, default=False
) # True if guests first stay was from our campaigns
# Metadata
first_seen = Column(DateTime(timezone=True))

View File

@@ -142,7 +142,7 @@ class TestConversionServiceWithImportedData:
## Need to check if reservations and customers are now actually available in the db before proceeding
conversion_service = ConversionService(test_db_session)
conversion_service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await conversion_service.process_conversion_xml(xml_content)
# BASELINE ASSERTIONS:
@@ -224,7 +224,7 @@ class TestConversionServiceWithImportedData:
# File already has proper XML structure, just use it as-is
xml_content = xml_content.strip()
conversion_service = ConversionService(test_db_session)
conversion_service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await conversion_service.process_conversion_xml(xml_content)
# Verify conversions were created
@@ -300,7 +300,7 @@ class TestConversionServiceWithImportedData:
# File already has proper XML structure, just use it as-is
xml_content = xml_content.strip()
conversion_service = ConversionService(test_db_session)
conversion_service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await conversion_service.process_conversion_xml(xml_content)
# Verify conversions were processed
@@ -332,7 +332,7 @@ class TestConversionServiceWithImportedData:
"""Test ConversionService handles invalid XML gracefully."""
invalid_xml = "<invalid>unclosed tag"
conversion_service = ConversionService(test_db_session)
conversion_service = ConversionService(test_db_session, hotel_id="39054_001")
with pytest.raises(ValueError, match="Invalid XML"):
await conversion_service.process_conversion_xml(invalid_xml)
@@ -342,7 +342,7 @@ class TestConversionServiceWithImportedData:
"""Test ConversionService handles empty/minimal XML."""
minimal_xml = '<?xml version="1.0"?><root></root>'
conversion_service = ConversionService(test_db_session)
conversion_service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await conversion_service.process_conversion_xml(minimal_xml)
assert stats["total_reservations"] == 0
@@ -421,7 +421,7 @@ class TestConversionServiceWithImportedData:
xml_content1 = multi_builder1.build_xml()
# Process first batch
service = ConversionService(test_db_session)
service = ConversionService(test_db_session, hotel_id="39054_001")
stats1 = await service.process_conversion_xml(xml_content1)
assert stats1["total_reservations"] == 2
@@ -577,7 +577,7 @@ class TestXMLBuilderUsage:
)
# Process the XML
service = ConversionService(test_db_session)
service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await service.process_conversion_xml(xml_content)
assert stats["total_reservations"] == 1
@@ -616,7 +616,7 @@ class TestXMLBuilderUsage:
.build_xml()
)
service = ConversionService(test_db_session)
service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await service.process_conversion_xml(xml_content)
assert stats["total_reservations"] == 1
@@ -677,7 +677,7 @@ class TestXMLBuilderUsage:
xml_content = multi_builder.build_xml()
# Process the XML
service = ConversionService(test_db_session)
service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await service.process_conversion_xml(xml_content)
assert stats["total_reservations"] == 2
@@ -768,7 +768,7 @@ class TestHashedMatchingLogic:
</reservation>
</root>"""
service = ConversionService(test_db_session, hotel_id="hotel_1")
service = ConversionService(test_db_session, hotel_id="39054_001")
stats = await service.process_conversion_xml(xml_content)
# Verify conversion was created