diff --git a/apps/bamboohr/migrations/0007_bamboohr_webhook_id.py b/apps/bamboohr/migrations/0007_bamboohr_webhook_id.py deleted file mode 100644 index d5025295..00000000 --- a/apps/bamboohr/migrations/0007_bamboohr_webhook_id.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2024-01-02 16:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('bamboohr', '0006_bamboohr_is_credentials_expired'), - ] - - operations = [ - migrations.AddField( - model_name='bamboohr', - name='webhook_id', - field=models.IntegerField(help_text='ID of the webhook created by BambooHr', null=True), - ), - ] diff --git a/apps/bamboohr/models.py b/apps/bamboohr/models.py index 59bbf41e..de284aa0 100644 --- a/apps/bamboohr/models.py +++ b/apps/bamboohr/models.py @@ -19,7 +19,6 @@ class BambooHr(models.Model): updated_at = models.DateTimeField(auto_now=True, help_text='Updated at datetime') employee_exported_at = models.DateTimeField(auto_now_add=True, help_text='Employee exported to Fyle at datetime') is_credentials_expired = models.BooleanField(default=False, help_text='BambooHr Credential Status') - webhook_id = models.IntegerField(null=True, help_text='ID of the webhook created by BambooHr') class Meta: db_table = 'bamboohr' diff --git a/apps/bamboohr/signals.py b/apps/bamboohr/signals.py index 80548941..0de2851c 100644 --- a/apps/bamboohr/signals.py +++ b/apps/bamboohr/signals.py @@ -1,12 +1,9 @@ -from django.db.models.signals import pre_save, post_save, pre_delete +from django.db.models.signals import pre_save from django.dispatch import receiver -from admin_settings.settings import API_URL from workato import Workato - -from bamboosdk.bamboohrsdk import BambooHrSDK -from apps.bamboohr.models import BambooHrConfiguration, BambooHr +from apps.bamboohr.models import BambooHrConfiguration from apps.orgs.models import Org @receiver(pre_save, sender=BambooHrConfiguration) @@ -14,26 +11,3 @@ def run_pre_save_configuration_triggers(sender, instance: BambooHrConfiguration, connector = Workato() org = Org.objects.get(id=instance.org_id) connector.recipes.post(org.managed_user_id, instance.recipe_id, None, 'stop') - - -@receiver(post_save, sender=BambooHr) -def run_post_save_bamboohr_triggers(sender, instance: BambooHr, **kwargs): - - bamboohrsdk = BambooHrSDK(api_token=instance.api_token, sub_domain=instance.sub_domain) - - webhook_payload = { - 'postFields': { - 'firstName': 'firstName', - 'lastName': 'lastName', - 'department': 'department', - 'workEmail': 'workEmail', - 'status': 'status' - }, - 'name': instance.org.name, - 'monitorFields': ['firstName', 'lastName', 'department', 'workEmail', 'status'], - 'url': API_URL + f'/orgs/{instance.org.id}/bamboohr/webhook_callback/', - 'format': 'json' - } - - response = bamboohrsdk.webhook.post(payload=webhook_payload) - BambooHr.objects.filter(id=instance.id).update(webhook_id=int(response['id'])) diff --git a/apps/bamboohr/tasks.py b/apps/bamboohr/tasks.py deleted file mode 100644 index 77a760a1..00000000 --- a/apps/bamboohr/tasks.py +++ /dev/null @@ -1,40 +0,0 @@ -from apps.bamboohr.models import BambooHr -from apps.fyle_hrms_mappings.models import DestinationAttribute -from fyle_employee_imports.bamboo_hr import BambooHrEmployeeImport -from apps.users.models import User - -def refresh_employees(org_id: int, user: User): - """ - Sync Employees from BambooHR to Fyle - """ - bambooHrImporter = BambooHrEmployeeImport(org_id=org_id, user=user) - bambooHrImporter.sync_employees() - -def update_employee(org_id: int, user: User, payload: dict): - - """ - Update employee in fyle when employee in Bamboohr is added or updated - """ - bamboohr = BambooHr.objects.get(org_id__in=[org_id], is_credentials_expired=False) - bamboohr_importer = BambooHrEmployeeImport(org_id=org_id, user=user) - - employee_payload = {'employees': []} - payload = payload['employees'][0] - employee = {} - employee['id'] = payload['id'] - employee['firstName'] = payload['fields']['firstName']['value'] - employee['lastName'] = payload['fields']['lastName']['value'] - for field in payload['changedFields']: - employee[field] = payload['fields'][field]['value'] - - employee_payload['employees'].append(employee) - - bamboohr_importer.upsert_employees(employees=employee_payload) - - hrms_employees = DestinationAttribute.objects.filter( - attribute_type='EMPLOYEE', - org_id=org_id, - updated_at__gte=bamboohr.employee_exported_at, - ).order_by('value', 'id') - bamboohr_importer.import_departments(hrms_employees=hrms_employees) - bamboohr_importer.fyle_employee_import(hrms_employees=hrms_employees) diff --git a/apps/bamboohr/urls.py b/apps/bamboohr/urls.py index 06677144..5de8f5b4 100644 --- a/apps/bamboohr/urls.py +++ b/apps/bamboohr/urls.py @@ -1,12 +1,11 @@ from django.urls import path from .views import PostFolder, PostPackage, BambooHrConnection, BambooHrView, BambooHrConfigurationView, \ - DisconnectView, SyncEmployeesView, HealthCheck, WebhookCallbackAPIView + DisconnectView, SyncEmployeesView, HealthCheck app_name = 'bamboohr' urlpatterns = [ - path('webhook_callback/', WebhookCallbackAPIView.as_view(), name='webhook-callback'), path('health_check/', HealthCheck.as_view(), name='health-check'), path('', BambooHrView.as_view(), name='bamboohr'), path('packages/', PostPackage.as_view(), name='package'), diff --git a/apps/bamboohr/views.py b/apps/bamboohr/views.py index d9e448fe..0af911d6 100644 --- a/apps/bamboohr/views.py +++ b/apps/bamboohr/views.py @@ -13,7 +13,7 @@ from apps.bamboohr.actions import disconnect_bamboohr, sync_employees from apps.names import BAMBOO_HR -from django_q.tasks import async_task +from rest_framework.views import APIView logger = logging.getLogger(__name__) logger.level = logging.INFO @@ -48,24 +48,6 @@ def get(self, request, *args, **kwargs): status=status.HTTP_404_NOT_FOUND ) - -class WebhookCallbackAPIView(generics.CreateAPIView): - - def post(self, request, *args, **kwargs): - - org_id = kwargs['org_id'] - user = self.request.user - payload = request.data - - async_task('apps.bamboohr.tasks.update_employee', org_id, user, payload) - - return Response( - { - 'status': 'success' - }, - status=status.HTTP_201_CREATED - ) - class BambooHrView(generics.ListAPIView): serializer_class = BambooHrSerializer @@ -213,11 +195,17 @@ class DisconnectView(generics.CreateAPIView): def post(self, request, *args, **kwargs): try: + configuration = BambooHrConfiguration.objects.get(org__id=kwargs['org_id']) bamboohr = BambooHr.objects.filter(org__id=kwargs['org_id']).first() - bambamboohrsdk = BambooHrSDK(api_token=bamboohr.api_token, sub_domain=bamboohr.sub_domain) - response = bambamboohrsdk.webhook.delete(id=bamboohr.webhook_id) + + connection = disconnect_bamboohr(kwargs['org_id'], configuration, bamboohr) + + # in case of an error response + if isinstance(connection, Response): + return connection + return Response( - data=response, + data=connection, status=status.HTTP_200_OK ) except BambooHr.DoesNotExist: @@ -227,6 +215,11 @@ def post(self, request, *args, **kwargs): }, status = status.HTTP_404_NOT_FOUND ) + except BambooHrConfiguration.DoesNotExist: + return Response( + data={'message': 'BambooHr Configuration does not exist for this Workspace'}, + status=status.HTTP_404_NOT_FOUND + ) class SyncEmployeesView(generics.UpdateAPIView): @@ -237,9 +230,20 @@ class SyncEmployeesView(generics.UpdateAPIView): def post(self, request, *args, **kwargs): - async_task('apps.bamboohr.tasks.refresh_employees', kwargs['org_id'], self.request.user) + try: + config = BambooHrConfiguration.objects.get(org__id=kwargs['org_id']) + sync_recipe = sync_employees(kwargs['org_id'], config) - return Response( - data = {'message': 'success'}, - status=status.HTTP_201_CREATED - ) + # in case of an error response + if isinstance(sync_recipe, Response): + return sync_recipe + + return Response( + data=sync_recipe, + status=status.HTTP_200_OK + ) + except BambooHrConfiguration.DoesNotExist: + return Response( + data={'message': 'BambooHr Configuration does not exist for this Workspace'}, + status=status.HTTP_404_NOT_FOUND + ) diff --git a/bamboosdk/api/api_base.py b/bamboosdk/api/api_base.py index c62c24bd..dcba2457 100644 --- a/bamboosdk/api/api_base.py +++ b/bamboosdk/api/api_base.py @@ -90,7 +90,8 @@ def _delete_request(self, module_api_path): url= self.API_BASE_URL.format(self.__sub_domain) + module_api_path response = requests.delete(url=url, headers=self.headers) if response.status_code == 200: - return {'message':'Web hook has been deleted'} + result = json.loads(response.text) + return result if response.status_code == 403: error_msg = json.loads(response.text) diff --git a/fyle_employee_imports/bamboo_hr.py b/fyle_employee_imports/bamboo_hr.py index fbfd8b76..fa5fbac7 100644 --- a/fyle_employee_imports/bamboo_hr.py +++ b/fyle_employee_imports/bamboo_hr.py @@ -10,7 +10,8 @@ class BambooHrEmployeeImport(FyleEmployeeImport): def __init__(self, org_id: int, user: User): super().__init__(org_id, user) - self.bamboohr_sdk = BambooHrSDK(api_token=self.bamboohr.api_token, sub_domain=self.bamboohr.sub_domain) + bamboo_hr = BambooHr.objects.get(org_id__in=org_id) + self.bamboohr_sdk = BambooHrSDK(api_token=bamboo_hr.api_token, sub_domain=bamboo_hr.sub_domain) def sync_hrms_employees(self): employees = self.bamboohr_sdk.employees.get_all() @@ -19,23 +20,18 @@ def sync_hrms_employees(self): def upsert_employees(self, employees: Dict): attributes = [] for employee in employees['employees']: - supervisor = [employee.get('supervisorEmail', None)] - active_status = True if employee.get('status', None) == 'Active' else False - - display_name = employee.get('displayName', None) - if not display_name: - display_name = employee['firstName'] + ' ' + employee['lastName'] - + supervisor = [employee['supervisorEmail']] + active_status = True if employee['status'] == 'Active' else False detail = { - 'email': employee.get('workEmail', None), - 'department_name': employee.get('department', None), - 'full_name': display_name, + 'email': employee['workEmail'] if employee['workEmail'] else None, + 'department_name': employee['department'] if employee['department'] else None, + 'full_name': employee['displayName'] if employee['displayName'] else None, 'approver_emails': supervisor, } attributes.append({ 'attribute_type': 'EMPLOYEE', - 'value': display_name, + 'value': employee['displayName'], 'destination_id': employee['id'], 'detail': detail, 'active': active_status diff --git a/fyle_employee_imports/base.py b/fyle_employee_imports/base.py index 5211fda0..20afb557 100644 --- a/fyle_employee_imports/base.py +++ b/fyle_employee_imports/base.py @@ -12,7 +12,7 @@ class FyleEmployeeImport(): def __init__(self, org_id: int, user): self.org_id = org_id self.user = user - self.bamboohr = BambooHr.objects.get(org_id__in=[self.org_id]) + self.bamboohr = BambooHr.objects.get(org_id__in=self.org_id) refresh_token = AuthToken.objects.get(user__user_id=self.user).refresh_token cluster_domain = Org.objects.get(user__user_id=self.user).cluster_domain self.platform_connection = PlatformConnector(refresh_token, cluster_domain) @@ -115,6 +115,7 @@ def get_employee_and_approver_payload(self, hrms_employees): def fyle_employee_import(self, hrms_employees): fyle_employee_payload, employee_approver_payload = self.get_employee_and_approver_payload(hrms_employees) + if fyle_employee_payload: self.platform_connection.bulk_post_employees(employees_payload=fyle_employee_payload) @@ -140,6 +141,6 @@ def sync_employees(self): org_id=self.org_id, updated_at__gte=self.bamboohr.employee_exported_at, ).order_by('value', 'id') - + self.import_departments(hrms_employees) self.fyle_employee_import(hrms_employees)