-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import Business Central Attributes API added (#27)
- Loading branch information
Showing
9 changed files
with
198 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
|
||
from datetime import datetime, timezone | ||
import logging | ||
|
||
from django.utils.module_loading import import_string | ||
|
||
from apps.workspaces.models import Workspace, BusinessCentralCredentials | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
logger.level = logging.INFO | ||
|
||
|
||
# Import your Workspace and BusinessCentralCredentials models here | ||
# Also, make sure you have 'logger' defined and imported from a logging module | ||
def check_interval_and_sync_dimension(workspace: Workspace, business_central_credential: BusinessCentralCredentials) -> bool: | ||
""" | ||
Check the synchronization interval and trigger dimension synchronization if needed. | ||
:param workspace: Workspace Instance | ||
:param business_central_credential: BusinessCentralCredentials Instance | ||
:return: True if synchronization is triggered, False if not | ||
""" | ||
|
||
if workspace.destination_synced_at: | ||
# Calculate the time interval since the last destination sync | ||
time_interval = datetime.now(timezone.utc) - workspace.destination_synced_at | ||
|
||
if workspace.destination_synced_at is None or time_interval.days > 0: | ||
# If destination_synced_at is None or the time interval is greater than 0 days, trigger synchronization | ||
sync_dimensions(business_central_credential, workspace.id) | ||
return True | ||
|
||
return False | ||
|
||
|
||
def sync_dimensions(business_central_credential: BusinessCentralCredentials, workspace_id: int) -> None: | ||
""" | ||
Synchronize various dimensions with Business Central using the provided credentials. | ||
:param business_central_credential: BusinessCentralCredentials Instance | ||
:param workspace_id: ID of the workspace | ||
This function syncs dimensions like accounts, vendors, commitments, jobs, categories, and cost codes. | ||
""" | ||
|
||
# Initialize the Business Central connection using the provided credentials and workspace ID | ||
business_central_connection = import_string('apps.business_central.utils.BusinessCentralConnector')(business_central_credential, workspace_id) | ||
|
||
# List of dimensions to sync | ||
dimensions = ['accounts', 'vendors', 'employees', 'locations'] | ||
|
||
for dimension in dimensions: | ||
try: | ||
# Dynamically call the sync method based on the dimension | ||
sync = getattr(business_central_connection, 'sync_{}'.format(dimension)) | ||
sync() | ||
except Exception as exception: | ||
# Log any exceptions that occur during synchronization | ||
logger.info(exception) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import logging | ||
from datetime import datetime | ||
from rest_framework import serializers | ||
from rest_framework.response import Response | ||
from rest_framework.views import status | ||
|
||
from apps.workspaces.models import Workspace, BusinessCentralCredentials | ||
from apps.business_central.helpers import sync_dimensions, check_interval_and_sync_dimension | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
logger.level = logging.INFO | ||
|
||
|
||
class ImportBusinessCentralAttributesSerializer(serializers.Serializer): | ||
""" | ||
Import Business Central Attributes serializer | ||
""" | ||
|
||
def create(self, validated_data): | ||
try: | ||
# Get the workspace ID from the URL kwargs | ||
workspace_id = self.context['request'].parser_context['kwargs']['workspace_id'] | ||
|
||
# Check if the 'refresh' field is provided in the request data | ||
refresh_dimension = self.context['request'].data.get('refresh', False) | ||
|
||
# Retrieve the workspace and Business Central credentials | ||
workspace = Workspace.objects.get(pk=workspace_id) | ||
business_central_credentials = BusinessCentralCredentials.objects.get( | ||
workspace_id=workspace.id | ||
) | ||
|
||
if refresh_dimension: | ||
# If 'refresh' is true, perform a full sync of dimensions | ||
sync_dimensions(business_central_credentials, workspace.id) | ||
else: | ||
# If 'refresh' is false, check the interval and sync dimension accordingly | ||
check_interval_and_sync_dimension(workspace, business_central_credentials) | ||
|
||
# Update the destination_synced_at field and save the workspace | ||
workspace.destination_synced_at = datetime.now() | ||
workspace.save(update_fields=['destination_synced_at']) | ||
|
||
# Return a success response | ||
return Response(status=status.HTTP_200_OK) | ||
|
||
except BusinessCentralCredentials.DoesNotExist: | ||
# Handle the case when business central credentials are not found or invalid | ||
raise serializers.ValidationError( | ||
{'message': 'Business Central credentials not found / invalid in workspace'} | ||
) | ||
|
||
except Exception as exception: | ||
# Handle unexpected exceptions and log the error | ||
logger.error( | ||
'Something unexpected happened workspace_id: %s %s', | ||
workspace_id, | ||
exception, | ||
) | ||
# Raise a custom exception or re-raise the original exception | ||
raise |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from django.urls import path | ||
|
||
from apps.business_central.views import ImportBusinessCentralAttributesView | ||
|
||
|
||
urlpatterns = [ | ||
path( | ||
"import_attributes/", | ||
ImportBusinessCentralAttributesView.as_view(), | ||
name="import-business-central-attributes", | ||
) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import logging | ||
|
||
from rest_framework import generics | ||
|
||
from apps.business_central.serializers import ImportBusinessCentralAttributesSerializer | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
logger.level = logging.INFO | ||
|
||
|
||
class ImportBusinessCentralAttributesView(generics.CreateAPIView): | ||
""" | ||
Import Business Central Attributes View | ||
""" | ||
serializer_class = ImportBusinessCentralAttributesSerializer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import json | ||
from django.urls import reverse | ||
|
||
from apps.workspaces.models import BusinessCentralCredentials | ||
|
||
|
||
def test_sync_dimensions(api_client, test_connection, mocker, create_temp_workspace, add_business_central_creds): | ||
workspace_id = 1 | ||
|
||
access_token = test_connection.access_token | ||
url = reverse('import-business-central-attributes', kwargs={'workspace_id': workspace_id}) | ||
|
||
api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(access_token)) | ||
|
||
mocker.patch('apps.business_central.helpers.sync_dimensions', return_value=None) | ||
|
||
response = api_client.post(url) | ||
assert response.status_code == 201 | ||
|
||
business_central_credentials = BusinessCentralCredentials.objects.get(workspace_id=workspace_id) | ||
business_central_credentials.delete() | ||
|
||
response = api_client.post(url) | ||
assert response.status_code == 400 | ||
|
||
response = json.loads(response.content) | ||
assert response['message'] == 'Business Central credentials not found / invalid in workspace' |