|
@@ -2,7 +2,7 @@ import asyncio
|
|
|
from datetime import date, timedelta
|
|
from datetime import date, timedelta
|
|
|
from typing import TYPE_CHECKING
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
|
|
-from room_cal.cal import get_calendar
|
|
|
|
|
|
|
+from room_cal.cal import get_backend
|
|
|
from room_cal.closed import Closed
|
|
from room_cal.closed import Closed
|
|
|
from room_cal.discount import Discount
|
|
from room_cal.discount import Discount
|
|
|
from room_cal.pricing.price_calendar import CalPrice
|
|
from room_cal.pricing.price_calendar import CalPrice
|
|
@@ -74,9 +74,12 @@ async def _diff_prices(
|
|
|
"""
|
|
"""
|
|
|
from room_cal.reservations import Reservation
|
|
from room_cal.reservations import Reservation
|
|
|
|
|
|
|
|
- cal = get_calendar()
|
|
|
|
|
|
|
+ from datetime import datetime
|
|
|
|
|
+ backend = get_backend()
|
|
|
|
|
+ start_dt = datetime(start_date.year, start_date.month, start_date.day)
|
|
|
|
|
+ end_dt = datetime(end_date.year, end_date.month, end_date.day) + timedelta(days=1)
|
|
|
events, api_prices, res_events = await asyncio.gather(
|
|
events, api_prices, res_events = await asyncio.gather(
|
|
|
- cal.fetch_date_range(start_date, end_date),
|
|
|
|
|
|
|
+ backend.fetch_range(start_dt, end_dt),
|
|
|
api.get_prices_range(start_date, end_date),
|
|
api.get_prices_range(start_date, end_date),
|
|
|
Reservation().list(start_date, end_date),
|
|
Reservation().list(start_date, end_date),
|
|
|
)
|
|
)
|
|
@@ -86,19 +89,18 @@ async def _diff_prices(
|
|
|
svc_keys = [s.key for s in _services()]
|
|
svc_keys = [s.key for s in _services()]
|
|
|
cal_prices: dict[str, PriceData] = {}
|
|
cal_prices: dict[str, PriceData] = {}
|
|
|
for e in filter_events(events, _PRICE_PREFIX, all_day=True):
|
|
for e in filter_events(events, _PRICE_PREFIX, all_day=True):
|
|
|
- d = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ d = safe_json_loads(e.x_data)
|
|
|
if d is not None:
|
|
if d is not None:
|
|
|
- cal_prices[e['start'].date().isoformat()] = PriceData.from_dict(d, svc_keys)
|
|
|
|
|
-
|
|
|
|
|
|
|
+ cal_prices[e.start.date().isoformat()] = PriceData.from_dict(d, svc_keys)
|
|
|
|
|
|
|
|
booked_svc_by_date: dict[date, str] = {}
|
|
booked_svc_by_date: dict[date, str] = {}
|
|
|
for e in res_events:
|
|
for e in res_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
if xd:
|
|
if xd:
|
|
|
svc = xd.get('service')
|
|
svc = xd.get('service')
|
|
|
if svc:
|
|
if svc:
|
|
|
- last_night = e['end'].date() - timedelta(days=1)
|
|
|
|
|
- for d in iter_dates(e['start'].date(), last_night):
|
|
|
|
|
|
|
+ last_night = e.end.date() - timedelta(days=1)
|
|
|
|
|
+ for d in iter_dates(e.start.date(), last_night):
|
|
|
booked_svc_by_date[d] = svc
|
|
booked_svc_by_date[d] = svc
|
|
|
|
|
|
|
|
today = local_today()
|
|
today = local_today()
|
|
@@ -147,9 +149,9 @@ async def _diff_closed(
|
|
|
cal_events = await closed_cal.list(start_date, end_date)
|
|
cal_events = await closed_cal.list(start_date, end_date)
|
|
|
cal_by_date: dict[str, list[str]] = {}
|
|
cal_by_date: dict[str, list[str]] = {}
|
|
|
for e in cal_events:
|
|
for e in cal_events:
|
|
|
- d = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ d = safe_json_loads(e.x_data)
|
|
|
if d is not None:
|
|
if d is not None:
|
|
|
- cal_by_date[e['start'].date().isoformat()] = sorted(d.get('closed_services', []))
|
|
|
|
|
|
|
+ cal_by_date[e.start.date().isoformat()] = sorted(d.get('closed_services', []))
|
|
|
|
|
|
|
|
api_by_date = await api.get_closed_by_date(start_date, end_date)
|
|
api_by_date = await api.get_closed_by_date(start_date, end_date)
|
|
|
api_by_date = {ds: sorted(svcs) for ds, svcs in api_by_date.items()}
|
|
api_by_date = {ds: sorted(svcs) for ds, svcs in api_by_date.items()}
|
|
@@ -185,9 +187,9 @@ async def _diff_reservations(
|
|
|
cal_events = await res_cal.list(start_date, end_date)
|
|
cal_events = await res_cal.list(start_date, end_date)
|
|
|
cal_by_id: dict[str, dict] = {}
|
|
cal_by_id: dict[str, dict] = {}
|
|
|
for e in cal_events:
|
|
for e in cal_events:
|
|
|
- if e['start'].date() < start_date:
|
|
|
|
|
|
|
+ if e.start.date() < start_date:
|
|
|
continue # checkin before range — belongs to a prior period's scope
|
|
continue # checkin before range — belongs to a prior period's scope
|
|
|
- d = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ d = safe_json_loads(e.x_data)
|
|
|
if d:
|
|
if d:
|
|
|
rid = d.get('reservation_id')
|
|
rid = d.get('reservation_id')
|
|
|
if rid:
|
|
if rid:
|
|
@@ -195,8 +197,8 @@ async def _diff_reservations(
|
|
|
'reservation_id': rid,
|
|
'reservation_id': rid,
|
|
|
'guest_name': d.get('guest_name', ''),
|
|
'guest_name': d.get('guest_name', ''),
|
|
|
'service': d.get('service', ''),
|
|
'service': d.get('service', ''),
|
|
|
- 'checkin_date': e['start'].date(),
|
|
|
|
|
- 'checkout_date': e['end'].date(),
|
|
|
|
|
|
|
+ 'checkin_date': e.start.date(),
|
|
|
|
|
+ 'checkout_date': e.end.date(),
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
service_reservations = await api.get_reservations(start_date, end_date)
|
|
service_reservations = await api.get_reservations(start_date, end_date)
|
|
@@ -251,9 +253,9 @@ async def _diff_user_cal_closed(
|
|
|
|
|
|
|
|
room_dates: set[date] = set()
|
|
room_dates: set[date] = set()
|
|
|
for e in room_events:
|
|
for e in room_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
if xd and xd.get('source', {}).get('domain') == 'user_cal':
|
|
if xd and xd.get('source', {}).get('domain') == 'user_cal':
|
|
|
- room_dates.add(e['start'].date())
|
|
|
|
|
|
|
+ room_dates.add(e.start.date())
|
|
|
|
|
|
|
|
user_cal_dates: set[date] = set()
|
|
user_cal_dates: set[date] = set()
|
|
|
for ev in user_cal_events:
|
|
for ev in user_cal_events:
|
|
@@ -292,11 +294,11 @@ async def _diff_ical_feeds_closed(
|
|
|
feed_name = entry.name
|
|
feed_name = entry.name
|
|
|
room_dates: set[date] = set()
|
|
room_dates: set[date] = set()
|
|
|
for e in room_events:
|
|
for e in room_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
if xd:
|
|
if xd:
|
|
|
src = xd.get('source', {})
|
|
src = xd.get('source', {})
|
|
|
if src.get('domain') == 'ical_feeds' and src.get('id') == feed_name:
|
|
if src.get('domain') == 'ical_feeds' and src.get('id') == feed_name:
|
|
|
- room_dates.add(e['start'].date())
|
|
|
|
|
|
|
+ room_dates.add(e.start.date())
|
|
|
|
|
|
|
|
feed_events = await fetch_calendar(entry)
|
|
feed_events = await fetch_calendar(entry)
|
|
|
feed_dates: set[date] = set()
|
|
feed_dates: set[date] = set()
|
|
@@ -333,11 +335,11 @@ async def _diff_rule_discounts(
|
|
|
for name in room_cal.rules.list_pipelines(type_='discount'):
|
|
for name in room_cal.rules.list_pipelines(type_='discount'):
|
|
|
room_by_date: dict[date, dict] = {}
|
|
room_by_date: dict[date, dict] = {}
|
|
|
for e in room_events:
|
|
for e in room_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
if xd:
|
|
if xd:
|
|
|
src = xd.get('source', {})
|
|
src = xd.get('source', {})
|
|
|
if src.get('domain') == 'rules' and src.get('id') == name:
|
|
if src.get('domain') == 'rules' and src.get('id') == name:
|
|
|
- room_by_date[e['start'].date()] = {'type': xd['type'], 'value': xd['value']}
|
|
|
|
|
|
|
+ room_by_date[e.start.date()] = {'type': xd['type'], 'value': xd['value']}
|
|
|
|
|
|
|
|
pipeline_out = await room_cal.rules.run_pipeline(name, start_date, end_date)
|
|
pipeline_out = await room_cal.rules.run_pipeline(name, start_date, end_date)
|
|
|
rule_by_date = {d: {'type': rec.type, 'value': rec.value} for d, rec in pipeline_out.items()}
|
|
rule_by_date = {d: {'type': rec.type, 'value': rec.value} for d, rec in pipeline_out.items()}
|
|
@@ -371,11 +373,11 @@ async def _diff_rule_closed(
|
|
|
for name in room_cal.rules.list_pipelines(type_='closed'):
|
|
for name in room_cal.rules.list_pipelines(type_='closed'):
|
|
|
room_dates: set[date] = set()
|
|
room_dates: set[date] = set()
|
|
|
for e in room_events:
|
|
for e in room_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
if xd:
|
|
if xd:
|
|
|
src = xd.get('source', {})
|
|
src = xd.get('source', {})
|
|
|
if src.get('domain') == 'rules' and src.get('id') == name:
|
|
if src.get('domain') == 'rules' and src.get('id') == name:
|
|
|
- room_dates.add(e['start'].date())
|
|
|
|
|
|
|
+ room_dates.add(e.start.date())
|
|
|
|
|
|
|
|
pipeline_out = await room_cal.rules.run_pipeline(name, start_date, end_date)
|
|
pipeline_out = await room_cal.rules.run_pipeline(name, start_date, end_date)
|
|
|
rule_dates: set[date] = {d for d, rec in pipeline_out.items() if rec.services}
|
|
rule_dates: set[date] = {d for d, rec in pipeline_out.items() if rec.services}
|
|
@@ -410,17 +412,17 @@ async def _diff_rule_prices(
|
|
|
|
|
|
|
|
booked: set[date] = set()
|
|
booked: set[date] = set()
|
|
|
for e in res_events:
|
|
for e in res_events:
|
|
|
- last_night = e['end'].date() - timedelta(days=1)
|
|
|
|
|
- for d in iter_dates(e['start'].date(), last_night):
|
|
|
|
|
|
|
+ last_night = e.end.date() - timedelta(days=1)
|
|
|
|
|
+ for d in iter_dates(e.start.date(), last_night):
|
|
|
booked.add(d)
|
|
booked.add(d)
|
|
|
|
|
|
|
|
local_base_by_date: dict[date, int] = {}
|
|
local_base_by_date: dict[date, int] = {}
|
|
|
for e in price_events:
|
|
for e in price_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
if xd:
|
|
if xd:
|
|
|
base = xd.get('base') or xd.get('net')
|
|
base = xd.get('base') or xd.get('net')
|
|
|
if base is not None:
|
|
if base is not None:
|
|
|
- local_base_by_date[e['start'].date()] = base
|
|
|
|
|
|
|
+ local_base_by_date[e.start.date()] = base
|
|
|
|
|
|
|
|
results: dict[str, list[dict]] = {}
|
|
results: dict[str, list[dict]] = {}
|
|
|
for name in room_cal.rules.list_pipelines(type_='price'):
|
|
for name in room_cal.rules.list_pipelines(type_='price'):
|
|
@@ -448,7 +450,11 @@ async def _diff_orphans(
|
|
|
|
|
|
|
|
Each row: {'date', 'event_type': 'closed'|'discount', 'title', 'source': dict|None}
|
|
Each row: {'date', 'event_type': 'closed'|'discount', 'title', 'source': dict|None}
|
|
|
"""
|
|
"""
|
|
|
- events = await get_calendar().fetch_date_range(start_date, end_date)
|
|
|
|
|
|
|
+ from datetime import datetime
|
|
|
|
|
+ backend = get_backend()
|
|
|
|
|
+ start_dt = datetime(start_date.year, start_date.month, start_date.day)
|
|
|
|
|
+ end_dt = datetime(end_date.year, end_date.month, end_date.day) + timedelta(days=1)
|
|
|
|
|
+ events = await backend.fetch_range(start_dt, end_dt)
|
|
|
|
|
|
|
|
closed_events = filter_events(events, 'Closed: ', all_day=True, require_x_data=False)
|
|
closed_events = filter_events(events, 'Closed: ', all_day=True, require_x_data=False)
|
|
|
discount_events = filter_events(events, 'Discount: ', all_day=True, require_x_data=False)
|
|
discount_events = filter_events(events, 'Discount: ', all_day=True, require_x_data=False)
|
|
@@ -456,24 +462,24 @@ async def _diff_orphans(
|
|
|
orphans: list[dict] = []
|
|
orphans: list[dict] = []
|
|
|
|
|
|
|
|
for e in closed_events:
|
|
for e in closed_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
domain = xd.get('source', {}).get('domain') if xd else None
|
|
domain = xd.get('source', {}).get('domain') if xd else None
|
|
|
if domain not in registered_domains():
|
|
if domain not in registered_domains():
|
|
|
orphans.append({
|
|
orphans.append({
|
|
|
- 'date': e['start'].date(),
|
|
|
|
|
|
|
+ 'date': e.start.date(),
|
|
|
'event_type': 'closed',
|
|
'event_type': 'closed',
|
|
|
- 'title': e['title'],
|
|
|
|
|
|
|
+ 'title': e.title,
|
|
|
'source': (xd.get('source') if xd else None),
|
|
'source': (xd.get('source') if xd else None),
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
for e in discount_events:
|
|
for e in discount_events:
|
|
|
- xd = safe_json_loads(e['x_data'])
|
|
|
|
|
|
|
+ xd = safe_json_loads(e.x_data)
|
|
|
domain = xd.get('source', {}).get('domain') if xd else None
|
|
domain = xd.get('source', {}).get('domain') if xd else None
|
|
|
if domain not in registered_domains():
|
|
if domain not in registered_domains():
|
|
|
orphans.append({
|
|
orphans.append({
|
|
|
- 'date': e['start'].date(),
|
|
|
|
|
|
|
+ 'date': e.start.date(),
|
|
|
'event_type': 'discount',
|
|
'event_type': 'discount',
|
|
|
- 'title': e['title'],
|
|
|
|
|
|
|
+ 'title': e.title,
|
|
|
'source': (xd.get('source') if xd else None),
|
|
'source': (xd.get('source') if xd else None),
|
|
|
})
|
|
})
|
|
|
|
|
|