diff --git a/.env b/.env index ab11788..e947011 100644 --- a/.env +++ b/.env @@ -15,5 +15,5 @@ PASSWORD="odoo" ADDONS="--addons-path=/opt/odoo/addons/,/opt/odoo/customaddons/$CUSTOMADDONS_DIR" # ARGS="" # ARGS="-d bross" -#ARGS="-d cybro_hms -u bross_hms,exely_integration,bross_bank_management" +ARGS="-d cybro_hms -u bross_hms,exely_integration,bross_bank_management" # DEBUG="-m debugpy --listen 0.0.0.0:5678 --wait-for-client" diff --git a/bross.py b/bross.py index 45b4e95..bfe5901 100755 --- a/bross.py +++ b/bross.py @@ -10,38 +10,46 @@ headers = { 'Content-Type': 'application/json', } #url = "https://connect.hopenapi.com/api/exelypms/v1/analytics/services" - #payload = {'startDate': '20240909', 'endDate': '20240910', 'dateKind': 0, 'language': 'en'} #response = requests.get(url, data=payload, headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/services?startDate=20241008&endDate=20241008&dateKind=4", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20240301-503875-1211582391", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20241217-503875-1220773707", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20240122-503875-1210423183", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20240909-503875-1219004943", headers=headers) +# SERVICES TIME PERIODS +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/services?startDate=20241008&endDate=20241008&dateKind=0", headers=headers) +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/services/cancelled?startDate=20241008&endDate=20241008&dateKind=0", headers=headers) + +# PAYMENTS TIME PERIOD +response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/payments?startDateTime=202408010000&endDateTime=202408072359&includeServices=true", headers=headers) + +# BOOKINGS TIME PERIOD +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings?modifiedFrom=2024-01-01T00:00&modifiedTo=2024-01-30T23:59&state=Active", headers=headers) +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings?modifiedFrom=2024-01-01T00:00&modifiedTo=2024-01-30T23:59&state=Cancelled", headers=headers) + +# BOOKING # response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20241009-503875-1220777184", headers=headers) # Room move -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/guests/9007199255607320", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/rooms", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/companies", headers=headers) +# INVOICES +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20241009-503875-1220777184/invoices?language=en", headers=headers) +# BOOKINGS ROOMS # response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings/20241009-503875-1220777184/rooms", headers=headers) +# ALL COMPANIES +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/companies", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/services", headers=headers) +# GUESTS needs guest id +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/guests/9007199255607320", headers=headers) +# ROOM STAYS needs guest id +# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/guests/9007199255607320/room-stays", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/payments", headers=headers) -response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/analytics/payments?startDateTime=202408010000&endDateTime=202408012359&includeServices=true", headers=headers) - -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings?modifiedFrom=2024-01-01T00:00&modifiedTo=2024-01-30T23:59&state=Active", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings?modifiedFrom=2024-01-31T23:59&modifiedTo=2024-02-290T23:59&state=Active", headers=headers) -# response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/bookings?modifiedFrom=2024-10-08T20:00&modifiedTo=2024-10-08T22:00&state=Cancelled", headers=headers) - +# ALL ROOMS # response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/rooms", headers=headers) + + # response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/rooms?roomTypeId=5020078", headers=headers) # response = requests.get("https://connect.hopenapi.com/api/exelypms/v1/rooms?roomTypeId=5019645", headers=headers) + if response.status_code == 200: data = response.json() print(data) diff --git a/bross_bank_management/__manifest__.py b/bross_bank_management/__manifest__.py index af82397..dee887e 100644 --- a/bross_bank_management/__manifest__.py +++ b/bross_bank_management/__manifest__.py @@ -12,10 +12,12 @@ 'data': [ 'security/ir.model.access.csv', 'data/bank_conf.xml', + 'cron/crons.xml', 'views/main_menu.xml', 'views/bank_views.xml', 'views/bank_account_views.xml', 'views/bank_settings_views.xml', + 'views/raw_movements.xml', ], 'installable': True, 'application': True, diff --git a/bross_bank_management/cron/crons.xml b/bross_bank_management/cron/crons.xml new file mode 100644 index 0000000..197840e --- /dev/null +++ b/bross_bank_management/cron/crons.xml @@ -0,0 +1,15 @@ + + + + + Get Movements Data + + code + model.get_movements() + + 1 + + 100 + + + \ No newline at end of file diff --git a/bross_bank_management/models/__init__.py b/bross_bank_management/models/__init__.py index 7c0093c..ec25dfc 100644 --- a/bross_bank_management/models/__init__.py +++ b/bross_bank_management/models/__init__.py @@ -1,3 +1,4 @@ from . import bank from . import bank_account from . import bank_settings +from . import bank_models diff --git a/bross_bank_management/models/bank_models.py b/bross_bank_management/models/bank_models.py new file mode 100644 index 0000000..11dd0fa --- /dev/null +++ b/bross_bank_management/models/bank_models.py @@ -0,0 +1,57 @@ +import base64 +import tempfile +import hashlib +import json +import os +from odoo import models, fields, _ +from tbc_bank_integration_service_lib.client import TBCBankClient +from odoo.exceptions import UserError + + +class BankMovements(models.Model): + _name = 'bank.raw.movements' + _description = 'Bank Movements' + + json_data = fields.Json(string="Json Data") + json_hash_code = fields.Char(string="Hash Code") + bid = fields.Char(string="Movement Id") + + parent_id = fields.Many2one('bank.raw.movements', string="Parent Record") + history_ids = fields.One2many(comodel_name="bank.raw.movements", inverse_name='parent_id', string="History") + + def create_or_update_raw_data(self, data, model, bid): + json_data = json.dumps(data, sort_keys=True, indent=4, ensure_ascii=False) + 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_movements(self): + client = self.env['bank.settings'].get_request_object() + try: + movement_id = '013762510743.2' + movements_by_id = client.get_account_movements_by_id('111111', movement_id) + self.create_or_update_raw_data(movements_by_id, 'bank.raw.movements', movements_by_id['data'].get('movementId')) + except Exception as e: + _logger.error(e) \ No newline at end of file diff --git a/bross_bank_management/models/bank_settings.py b/bross_bank_management/models/bank_settings.py index b5fb7fd..9bf9a4f 100644 --- a/bross_bank_management/models/bank_settings.py +++ b/bross_bank_management/models/bank_settings.py @@ -19,18 +19,19 @@ class BankSettings(models.Model): nonce = fields.Char(string='Nonce', required=True) def get_request_object(self): - cert_data = base64.b64decode(self.cert_file_path) + config = self.env.ref('bross_bank_management.bank_api_configuration') + cert_data = base64.b64decode(config.cert_file_path) with tempfile.NamedTemporaryFile(delete=False, suffix='.pfx') as temp_cert_file: temp_cert_file.write(cert_data) temp_cert_file_path = temp_cert_file.name client = TBCBankClient( - self.wsdl_url, + config.wsdl_url, temp_cert_file_path, - self.cert_password, - self.username, - self.current_password + config.cert_password, + config.username, + config.current_password ) return client diff --git a/bross_bank_management/security/ir.model.access.csv b/bross_bank_management/security/ir.model.access.csv index b6f9671..8e6edee 100644 --- a/bross_bank_management/security/ir.model.access.csv +++ b/bross_bank_management/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_brosse_bank_user,access_brosse_bank,model_brosse_bank,base.group_user,1,1,1,1 access_brosse_bank_account_user,access_brosse_bank_account,model_brosse_bank_account,base.group_user,1,1,1,1 -access_bank_settings_admin,access_bank_settings,model_bank_settings,base.group_system,1,1,1,1 \ No newline at end of file +access_bank_settings_admin,access_bank_settings,model_bank_settings,base.group_system,1,1,1,1 +bross_bank_management.access_bank_raw_movements,access_bank_raw_movements,bross_bank_management.model_bank_raw_movements,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/bross_bank_management/views/raw_movements.xml b/bross_bank_management/views/raw_movements.xml new file mode 100644 index 0000000..f954819 --- /dev/null +++ b/bross_bank_management/views/raw_movements.xml @@ -0,0 +1,60 @@ + + + + bank.raw.movements.list + bank.raw.movements + + + + + + + + + + + + bank.raw.movements.form + bank.raw.movements + +
+
+ +
+ + +

+
+ + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Bank Raw Movements + bank.raw.movements + list,form + + + +
+
diff --git a/exely_integration/__manifest__.py b/exely_integration/__manifest__.py index 0fcc4bd..d3e48a3 100644 --- a/exely_integration/__manifest__.py +++ b/exely_integration/__manifest__.py @@ -22,6 +22,7 @@ 'views/raw_customers.xml', 'views/raw_roomstays.xml', 'views/raw_guests.xml', + 'views/raw_payments.xml', ], # only loaded in demonstration mode 'demo': [ diff --git a/exely_integration/cron/crons.xml b/exely_integration/cron/crons.xml index 561bdc7..a702bce 100644 --- a/exely_integration/cron/crons.xml +++ b/exely_integration/cron/crons.xml @@ -12,6 +12,17 @@ 100 + + Get Exely Payments + + code + model.get_exely_payments() + + 1 + + 100 + + Process Exely Data diff --git a/exely_integration/models/exely_raw_data.py b/exely_integration/models/exely_raw_data.py index f2d3e64..85be3c0 100644 --- a/exely_integration/models/exely_raw_data.py +++ b/exely_integration/models/exely_raw_data.py @@ -88,6 +88,18 @@ class ExelyRawGuests(models.Model): 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' @@ -98,13 +110,13 @@ class ExelyModifiedData(models.Model): booking_number = fields.Char(string="Booking Number") status = fields.Char(string="Status") - def generate_date_ranges(self, start_date, end_date): + 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=29), end_date) + 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) @@ -112,8 +124,8 @@ class ExelyModifiedData(models.Model): period_end = end_date date_ranges.append(( - period_start.strftime("%Y-%m-%dT%H:%M"), - period_end.strftime("%Y-%m-%dT%H:%M") + period_start.strftime(format), + period_end.strftime(format) )) current_date = period_end + timedelta(days=1) @@ -155,6 +167,30 @@ class ExelyModifiedData(models.Model): '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 get_exely_data(self): exely_api_conf = self.env['exely.api.conf'].search([], limit=1) if exely_api_conf: @@ -179,7 +215,7 @@ class ExelyModifiedData(models.Model): start_date = datetime(2024, 1, 1) end_date = datetime.now() - date_ranges = self.generate_date_ranges(start_date, end_date) + date_ranges = self.generate_date_ranges(start_date, end_date, 29, "%Y-%m-%dT%H:%M") to_create = [] for status in STATES: diff --git a/exely_integration/security/ir.model.access.csv b/exely_integration/security/ir.model.access.csv index 325991d..16dea48 100644 --- a/exely_integration/security/ir.model.access.csv +++ b/exely_integration/security/ir.model.access.csv @@ -7,4 +7,5 @@ exely_integration.access_exely_raw_companies,access_exely_raw_companies,exely_in exely_integration.access_exely_raw_rooms,access_exely_raw_rooms,exely_integration.model_exely_raw_rooms,base.group_user,1,1,1,1 exely_integration.access_exely_raw_customers,access_exely_raw_customers,exely_integration.model_exely_raw_customers,base.group_user,1,1,1,1 exely_integration.access_exely_raw_roomstays,access_exely_raw_roomstays,exely_integration.model_exely_raw_roomstays,base.group_user,1,1,1,1 -exely_integration.access_exely_raw_guests,access_exely_raw_guests,exely_integration.model_exely_raw_guests,base.group_user,1,1,1,1 \ No newline at end of file +exely_integration.access_exely_raw_guests,access_exely_raw_guests,exely_integration.model_exely_raw_guests,base.group_user,1,1,1,1 +exely_integration.access_exely_raw_payments,access_exely_raw_payments,exely_integration.model_exely_raw_payments,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/exely_integration/views/raw_payments.xml b/exely_integration/views/raw_payments.xml new file mode 100644 index 0000000..e3a163b --- /dev/null +++ b/exely_integration/views/raw_payments.xml @@ -0,0 +1,67 @@ + + + + + exely.raw.payments.list + exely.raw.payments + + + + + + + + + + + + + exely.raw.payments.form + exely.raw.payments + +
+
+ +
+ + +

+
+ + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + exely.raw.payments + exely.raw.payments + list,form + +

+ Create your first raw payments record. +

+
+
+ + +
+