# -*- coding: utf-8 -*- import requests import logging import hashlib import json from odoo import models, fields, api, _ from datetime import datetime, timedelta from odoo.exceptions import UserError _logger = logging.getLogger(__name__) STATES = ['Active', 'Cancelled'] class ExelyRawBookings(models.Model): _name = 'exely.raw.bookings' _description = 'Exely Raw Bookings' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Booking Id") parent_id = fields.Many2one('exely.raw.bookings', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.bookings", inverse_name='parent_id', string="History") modified_booking_id = fields.Many2one(comodel_name="exely.modified.bookings", string="Modified Bookings Id") class ExelyRawCompanies(models.Model): _name = 'exely.raw.companies' _description = 'Exely Raw Companies' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Company Id") parent_id = fields.Many2one('exely.raw.companies', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.companies", inverse_name='parent_id', string="History") class ExelyRawRooms(models.Model): _name = 'exely.raw.rooms' _description = 'Exely Raw Rooms' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Room Id") parent_id = fields.Many2one('exely.raw.rooms', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.rooms", inverse_name='parent_id', string="History") class ExelyRawCustomers(models.Model): _name = 'exely.raw.customers' _description = 'Exely Raw Customers' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Customer Id") parent_id = fields.Many2one('exely.raw.customers', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.customers", inverse_name='parent_id', string="History") class ExelyRawRoomstays(models.Model): _name = 'exely.raw.roomstays' _description = 'Exely Raw Roomstays' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Roomstays Id") parent_id = fields.Many2one('exely.raw.roomstays', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.roomstays", inverse_name='parent_id', string="History") class ExelyRawGuests(models.Model): _name = 'exely.raw.guests' _description = 'Exely Raw Guests' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Guest Id") parent_id = fields.Many2one('exely.raw.guests', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.guests", inverse_name='parent_id', string="History") class ExelyRawPayments(models.Model): _name = 'exely.raw.payments' _description = 'Exely Raw Payments' json_data = fields.Json(string="Json Data") json_hash_code = fields.Char(string="Hash Code") bid = fields.Char(string="Guest Id") parent_id = fields.Many2one('exely.raw.payments', string="Parent Record") history_ids = fields.One2many(comodel_name="exely.raw.payments", inverse_name='parent_id', string="History") class ExelyModifiedData(models.Model): _name = 'exely.modified.bookings' _description = 'Exely Modified Bookings' _rec_name = 'booking_number' mod_period_start = fields.Datetime(string="Start Date") mod_period_end = fields.Datetime(string="End Date") booking_number = fields.Char(string="Booking Number") status = fields.Char(string="Status") def generate_date_ranges(self, start_date, end_date, period, format): date_ranges = [] current_date = start_date while current_date < end_date: period_start = current_date.replace(hour=0, minute=0, second=0, microsecond=0) period_end = min(current_date + timedelta(days=period), end_date) if period_end.date() < end_date.date(): period_end = period_end.replace(hour=23, minute=59) else: period_end = end_date date_ranges.append(( period_start.strftime(format), period_end.strftime(format) )) current_date = period_end + timedelta(days=1) return date_ranges def get_exely_data_api(self, url, headers): response = requests.get(url, headers=headers) if response.status_code == 200: data = response.json() return data else: return False def create_or_update_raw_data(self, data, model, bid): json_data = json.dumps(data, sort_keys=True) hash_object = hashlib.sha256(json_data.encode()) hash_hex = hash_object.hexdigest() found_raw_record = self.env[model].search([ ('bid', '=', bid), ]) if found_raw_record: if found_raw_record.json_hash_code != hash_hex: # found_raw_record.write({ # 'json_data': json_data, # 'json_hash_code': hash_hex # }) new_created_record = self.env[model].create({ 'json_data': json_data, 'json_hash_code': hash_hex, 'bid': bid, }) found_raw_record.parent_id = new_created_record.id else: found_raw_record = self.env[model].create({ 'json_data': json_data, 'json_hash_code': hash_hex, 'bid': bid }) def get_exely_payments(self): exely_api_conf = self.env['exely.api.conf'].search([], limit=1) if exely_api_conf: headers = { 'X-API-KEY': exely_api_conf.api_key, 'Content-Type': 'application/json', } else: raise UserError(_("Please configure Exely API Key")) start_date = datetime(2024, 1, 1) end_date = datetime.now() date_ranges = self.generate_date_ranges(start_date, end_date, 7, "%Y%m%d%H%M") to_create = [] for start, end in date_ranges: print(f"{start} to {end}") payments = self.get_exely_data_api(f"https://connect.hopenapi.com/api/exelypms/v1/analytics/payments?startDateTime={start}&endDateTime={end}&includeServices=true", headers) if payments: self.create_or_update_raw_data(payments, 'exely.raw.payments', f"{start}{end}") def process_exely_payments(self): found_payment_record = self.env['hms.bookings'].search([], order="write_date desc", limit=1) if False: max_date = found_payment_record.write_date else: max_date = datetime.strptime('1970-01-01', "%Y-%m-%d").date() to_process_payments = self.env['exely.raw.payments'].search([('write_date', '>', max_date), ('parent_id', '=', False)]) to_create = [] for payment in to_process_payments: data = json.loads(payment.json_data) payment_data = data.pop('data', None) if payment_data: customers_dict = {} all_customers = payment_data.pop('customers', None) if all_customers: for customer in all_customers: customer['bid'] = customer.pop('id') customer['customerIndex'] = customer.pop('index') customer['customerKind'] = str(customer.pop('customerKind')) email = customer.pop('email', None) if email: customer['emails'] = [(4, self.env['hms.email'].search([('email', '=', email)], limit=1).id or self.env['hms.email'].create({'email': email}).id)] phone = customer.pop('phone', None) if customer: customer['phones'] = [(4, self.env['hms.phones'].search([('phone', '=', phone)], limit=1).id or self.env['hms.phones'].create({'phone': phone}).id)] found_customer = self.env['hms.customer'].search([('bid', '=', customer['bid'])]) if not found_customer: customer_obj = self.env['hms.customer'].create(customer) customers_dict[customer_obj.customerIndex] = customer_obj.id else: found_customer.write(customer) customers_dict[customer.get('customerIndex')] = found_customer.id agents_dict = {} all_agents = payment_data.pop('agents', None) if all_agents: for agent in all_agents: agent['bid'] = agent.pop('id') email = agent.get('email', None) if email: agent['email'] = self.env['hms.email'].search([('email', '=', email)], limit=1).id or self.env['hms.email'].create({'email': email}).id phone = agent.get('phone', None) if phone: agent['phone'] = self.env['hms.phones'].search([('phone', '=', phone)], limit=1).id or self.env['hms.phones'].create({'phone': phone}).id found_agent = self.env['hms.agents'].search([('bid', '=', agent['bid'])]) if not found_agent: customer_obj = self.env['hms.agents'].create(agent) agents_dict[customer_obj.index] = customer_obj.id else: found_agent.write(agent) agents_dict[agent.get('index')] = found_agent.id all_roomtypes = payment_data.pop('roomTypes', None) if all_roomtypes: for roomtype in all_roomtypes: roomtype['bid'] = roomtype.pop('id') found_roomtype = self.env['hms.room.types'].search([('bid', '=', roomtype['bid'])]) if not found_roomtype: self.env['hms.room.types'].create(roomtype) else: found_roomtype.write(roomtype) reservations_dict = {reservation.bid: reservation.id for reservation in self.env['hms.reservations'].search([])} all_reservations = payment_data.pop('reservations', None) if all_reservations: for reservation in all_reservations: reservation['bid'] = reservation.pop('id') customerindex = reservation.pop('customerIndex', None) if customerindex: reservation['customerIndex'] = customers_dict[customerindex] agentindex = reservation.pop('agentIndex', None) if agentindex: reservation['agentIndex'] = agents_dict[agentindex] currency = reservation.pop('currency', None) if currency: reservation['currency'] = self.env['res.currency'].search([('name', '=', currency)]).id bookingnumber = reservation.pop('bookingNumber', None) if bookingnumber: reservation['bookingNumber'] = self.env['hms.bookings'].search([('number', '=', bookingnumber)]).id roomnumber = reservation.pop('roomNumber', None) if roomnumber: reservation['roomNumber'] = self.env['hms.rooms'].search([('name', '=', roomnumber)]).id guestid = reservation.pop('guestId', None) if guestid: guestid = guestid.split('_')[1] reservation['guestId'] = self.env['hms.guests'].search([('bid', '=', guestid)]).id checkindatetime = reservation.pop('checkInDateTime', None) if checkindatetime: reservation['checkInDateTime_date'] = datetime.strptime(checkindatetime, "%Y%m%d%H%M").strftime("%Y-%m-%d %H:%M:%S") checkoutdatetime = reservation.pop('checkOutDateTime', None) if checkoutdatetime: reservation['checkOutDateTime_date'] = datetime.strptime(checkoutdatetime, "%Y%m%d%H%M").strftime("%Y-%m-%d %H:%M:%S") paymentmethod = reservation.pop('paymentMethod', None) if paymentmethod: reservation['paymentMethod'] = self.env['hms.payment.methods'].search([('hms_id', '=', paymentmethod)]).id roomtypeid = reservation.pop('roomTypeId', None) if roomtypeid: reservation['roomTypeId'] = self.env['hms.room.types'].search([('bid', '=', roomtypeid)]).id creationdatetime = reservation.pop('creationDateTime', None) if creationdatetime: reservation['creationDateTime_date'] = datetime.strptime(creationdatetime, "%Y%m%d%H%M").strftime("%Y-%m-%d %H:%M:%S") bookingsource = reservation.pop('bookingSource', None) if bookingsource: found_bookingsource = self.env['hms.booking.source'].search([('name', '=', bookingsource)]) if found_bookingsource: reservation['bookingSource'] = found_bookingsource.id else: reservation['bookingSource'] = self.env['hms.booking.source'].create({'name': bookingsource}).id found_reservation = self.env['hms.reservations'].search([('bid', '=', reservation['bid'])]) if not found_reservation: reservation_obj =self.env['hms.reservations'].create(reservation) else: reservation_obj = found_reservation if not reservation_obj.bid in reservations_dict: reservations_dict[reservation_obj.bid] = reservation_obj.id all_services = payment_data.pop('services', None) if all_services: for service in all_services: service['bid'] = service.pop('id') kind = service.pop('kind', None) if kind: service['kind'] = self.env['hms.service.kinds'].search([('hms_id', '=', kind)]).id vat_kind = service.pop('vatKind', None) if vat_kind: service['vat_kind'] = self.env['hms.service.vat.kinds'].search([('hms_id', '=', vat_kind)]).id service['service_date'] = datetime.strptime(service.pop('date', None), "%Y%m%d").strftime("%Y-%m-%d") reservationid = service.pop('reservationId', None) if reservationid: service['reservationId'] = reservations_dict[str(reservationid)] found_service = self.env['hms.services'].search([('bid', '=', service['bid'])]) if not found_service: self.env['hms.services'].create(service) def get_exely_data(self): exely_api_conf = self.env['exely.api.conf'].search([], limit=1) if exely_api_conf: headers = { 'X-API-KEY': exely_api_conf.api_key, 'Content-Type': 'application/json', } else: raise UserError(_("Please configure Exely API Key")) companies = self.get_exely_data_api("https://connect.hopenapi.com/api/exelypms/v1/companies", headers) if companies: for company in companies: self.create_or_update_raw_data(company, 'exely.raw.companies', company['id']) rooms = self.get_exely_data_api("https://connect.hopenapi.com/api/exelypms/v1/rooms", headers) if rooms: for room in rooms: self.create_or_update_raw_data(room, 'exely.raw.rooms', room['id']) start_date = datetime(2024, 1, 1) end_date = datetime.now() date_ranges = self.generate_date_ranges(start_date, end_date, 29, "%Y-%m-%dT%H:%M") to_create = [] for status in STATES: for start, end in date_ranges: print(f"{start} to {end}") data = self.get_exely_data_api(f"https://connect.hopenapi.com/api/exelypms/v1/bookings?modifiedFrom={start}&modifiedTo={end}&state={status}", headers) if data: for booking_number in data['bookingNumbers']: start_write = datetime.strptime(start, "%Y-%m-%dT%H:%M") - timedelta(hours=4) end_write = datetime.strptime(end, "%Y-%m-%dT%H:%M") - timedelta(hours=4) modified_booking_id = self.env['exely.modified.bookings'].search([ ('mod_period_start', '=', start_write), ('mod_period_end', '=', end_write), ('booking_number', '=', booking_number), ('status', '=', status)] ) if not modified_booking_id: modified_booking_id = self.env['exely.modified.bookings'].create({ 'mod_period_start': start_write, 'mod_period_end': end_write, 'booking_number': booking_number, 'status': status }) booking = self.get_exely_data_api(f"https://connect.hopenapi.com/api/exelypms/v1/bookings/{booking_number}", headers) if booking: self.create_or_update_raw_data(booking, 'exely.raw.bookings', booking['id']) customer = booking['customer'] self.create_or_update_raw_data(customer, 'exely.raw.customers', customer['id']) roomstays = booking['roomStays'] for roomstay in roomstays: self.create_or_update_raw_data(roomstay, 'exely.raw.roomstays', roomstay['id']) guests = roomstay['guestsIds'] for bid in guests: guest = self.get_exely_data_api(f"https://connect.hopenapi.com/api/exelypms/v1/guests/{bid}", headers) self.create_or_update_raw_data(guest, 'exely.raw.guests', bid) def process_exely_data(self): found_booking_record = self.env['hms.bookings'].search([], order="write_date desc", limit=1) if found_booking_record: max_date = found_booking_record.write_date else: max_date = datetime.strptime('1970-01-01', "%Y-%m-%d").date() to_process_modified_bookings = self.env['exely.raw.bookings'].search([('write_date', '>', max_date), ('parent_id', '=', False)]) to_create = [] for modified in to_process_modified_bookings: data = json.loads(modified.json_data) data['bid'] = data.pop('id') customer = data.pop('customer', None) if customer: customer['bid'] = customer.pop('id') if customer.get('emails', None): customer['emails'] = [(6, 0, [ self.env['hms.email'].search([('email', '=', email)], limit=1).id or self.env['hms.email'].create({'email': email}).id for email in customer['emails'] ])] if customer.get('phones', None): customer['phones'] = [(6, 0, [ self.env['hms.phones'].search([('phone', '=', phone)], limit=1).id or self.env['hms.phones'].create({'phone': phone}).id for phone in customer['phones'] ])] found_customer = self.env['hms.customer'].search([('bid', '=', customer['bid'])]) if found_customer: customer_id = found_customer.id else: customer_id = self.env['hms.customer'].create(customer).id data['customer'] = customer_id roomstays = data.pop('roomStays', None) if roomstays: roomstays_ids = [] for roomstay in roomstays: roomstay['bid'] = roomstay.pop('id') status = roomstay.pop('status', None) if status: found_status_id = self.env['hms.status'].search([('name', '=', status)]) if found_status_id: status_id = found_status_id.id else: status_id = self.env['hms.status'].create({'name': status}).id roomstay['status'] = status_id bookingstatus = roomstay.pop('bookingStatus', None) if bookingstatus: found_bookingstatus_id = self.env['hms.booking.status'].search([('name', '=', bookingstatus)]) if found_bookingstatus_id: bookingstatus_id = found_bookingstatus_id.id else: bookingstatus_id = self.env['hms.booking.status'].create({'name': bookingstatus}).id roomstay['bookingStatus'] = bookingstatus_id roomTypeId = roomstay.get('roomTypeId', None) if roomTypeId: found_roomtype = self.env['hms.room.types'].search([('bid', '=', roomTypeId)]) if found_roomtype: roomtype_id = found_roomtype.id else: roomtype_id = self.env['hms.room.types'].create({'bid': roomTypeId}).id roomstay['roomTypeId'] = roomtype_id roomId = roomstay.get('roomId', None) if roomId: found_raw_room = self.env['exely.raw.rooms'].search([('bid', '=', roomId)]) if found_raw_room: room_data = json.loads(found_raw_room.json_data) room_data['bid'] = room_data.pop('id') roomTypeId = room_data.get('roomTypeId', None) if roomTypeId: found_roomtype = self.env['hms.room.types'].search([('bid', '=', roomTypeId)]) if found_roomtype: roomtype_id = found_roomtype.id else: roomtype_id = self.env['hms.room.types'].create({'bid': roomTypeId}).id room_data['roomTypeId'] = roomtype_id found_room = self.env['hms.rooms'].search([('bid', '=', roomId)]) if found_room: room_id = found_room.id else: room_id = self.env['hms.rooms'].create(room_data).id roomstay['roomId'] = room_id guests = roomstay.pop('guestsIds', None) if guests: guest_ids = [] for guest in guests: guest_data = json.loads(self.env['exely.raw.guests'].search([('bid', '=', guest)]).json_data) guest_data['bid'] = guest_data.pop('id') if guest_data: if guest_data.get('emails', None): guest_data['emails'] = [(6, 0, [ self.env['hms.email'].search([('email', '=', email)], limit=1).id or self.env['hms.email'].create({'email': email}).id for email in guest_data['emails'] ])] if guest_data.get('phones', None): guest_data['phones'] = [(6, 0, [ self.env['hms.phones'].search([('phone', '=', phone)], limit=1).id or self.env['hms.phones'].create({'phone': phone}).id for phone in guest_data['phones'] ])] found_guest = self.env['hms.guests'].search([('bid', '=', guest)]) if found_guest: guest_id = found_guest.id else: guest_id = self.env['hms.guests'].create(guest_data).id guest_ids.append(guest_id) if guest_ids: roomstay['guestsIds'] = [(6, 0, guest_ids)] amenities = roomstay.pop('amenities', None) if not amenities: amenity_ids = [] for amenity in amenities: found_amenity = self.env['hms.amenities'].search([('name', '=', amenity)]) if found_amenity: amenity_id = found_amenity.id else: amenity_id = self.env['hms.amenities'].create({'name': amenity}).id amenity_ids.append(amenity_id) if amenity_ids: roomstay['amenities'] = [(6, 0, amenity_ids)] found_roomstay = self.env['hms.roomstays'].search([('bid', '=', roomstay['bid'])]) if found_roomstay: roomstay_id = found_roomstay.id else: roomstay_id = self.env['hms.roomstays'].create(roomstay).id roomstays_ids.append(roomstay_id) if roomstays_ids: data['roomStays'] = [(6, 0, roomstays_ids)] sourceChannelName = data.pop('sourceChannelName', None) if sourceChannelName: found_source_channel = self.env['hms.source.channel'].search([('name', '=', sourceChannelName)]) if found_source_channel: source_channel_id = found_source_channel.id else: source_channel_id = self.env['hms.source.channel'].create({'name': sourceChannelName}).id data['sourceChannelName'] = source_channel_id to_create.append(data) if to_create: for i in to_create: try: self.env['hms.bookings'].create(i) except Exception as e: _logger.warning(f"##############################: {i}") class HmsBookings(models.Model): _inherit = 'hms.bookings' _description = 'Hms Bookings' _rec_name = 'bid'