Skip to content

Commit

Permalink
Mapping settings added to import settings
Browse files Browse the repository at this point in the history
  • Loading branch information
ruuushhh committed Nov 6, 2023
1 parent 015355b commit 6b3301c
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 45 deletions.
37 changes: 37 additions & 0 deletions apps/mappings/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

# from datetime import datetime

# from django_q.models import Schedule

# from fyle_accounting_mappings.models import MappingSetting
# from apps.fyle.models import DependentFieldSetting


# def schedule_or_delete_fyle_import_tasks(workspace_id: int):
# """
# :param configuration: Workspace Configuration Instance
# :return: None
# """
# project_mapping = MappingSetting.objects.filter(
# source_field='PROJECT',
# workspace_id=workspace_id,
# import_to_fyle=True
# ).first()
# dependent_fields = DependentFieldSetting.objects.filter(workspace_id=workspace_id, is_import_enabled=True).first()

# if project_mapping and dependent_fields:
# start_datetime = datetime.now()
# Schedule.objects.update_or_create(
# func='apps.mappings.tasks.auto_import_and_map_fyle_fields',
# args='{}'.format(workspace_id),
# defaults={
# 'schedule_type': Schedule.MINUTES,
# 'minutes': 24 * 60,
# 'next_run': start_datetime
# }
# )
# elif not (project_mapping and dependent_fields):
# Schedule.objects.filter(
# func='apps.mappings.tasks.auto_import_and_map_fyle_fields',
# args='{}'.format(workspace_id)
# ).delete()
19 changes: 19 additions & 0 deletions apps/workspaces/migrations/0003_alter_importsetting_workspace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.1.2 on 2023-11-06 10:33

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('workspaces', '0002_sage300credential_importsetting_fylecredential_and_more'),
]

operations = [
migrations.AlterField(
model_name='importsetting',
name='workspace',
field=models.OneToOneField(help_text='Reference to Workspace model', on_delete=django.db.models.deletion.PROTECT, related_name='import_settings', to='workspaces.workspace'),
),
]
1 change: 1 addition & 0 deletions apps/workspaces/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ class ImportSetting(BaseModel):
id = models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)
import_categories = BooleanFalseField(help_text='toggle for import of chart of accounts from sage300')
import_vendors_as_merchants = BooleanFalseField(help_text='toggle for import of vendors as merchant from sage300')
workspace = models.OneToOneField(Workspace, on_delete=models.PROTECT, help_text='Reference to Workspace model', related_name="import_settings")

class Meta:
db_table = 'import_settings'
Expand Down
132 changes: 116 additions & 16 deletions apps/workspaces/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
from django.conf import settings
from django.core.cache import cache
from rest_framework import serializers
from fyle_accounting_mappings.models import MappingSetting
from fyle_rest_auth.helpers import get_fyle_admin
from fyle_rest_auth.models import AuthToken
from fyle_accounting_mappings.models import ExpenseAttribute
from django.db import transaction
from django.db.models import Q

from sage_desktop_api.utils import assert_valid
from sage_desktop_sdk.sage_desktop_sdk import SageDesktopSDK
Expand All @@ -27,6 +30,7 @@
)
from apps.users.models import User
from apps.fyle.helpers import get_cluster_domain
from apps.workspaces.triggers import ImportSettingsTrigger


class WorkspaceSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -157,32 +161,128 @@ def create(self, validated_data):
return export_settings


class ImportSettingsSerializer(serializers.ModelSerializer):
class MappingSettingFilteredListSerializer(serializers.ListSerializer):
"""
Export Settings serializer
Serializer to filter the active system, which is a boolen field in
System Model. The value argument to to_representation() method is
the model instance
"""
def to_representation(self, data):
data = data.filter(~Q(
destination_field__in=[
'ACCOUNT',
'CCC_ACCOUNT',
'CHARGE_CARD_NUMBER',
'EMPLOYEE',
'EXPENSE_TYPE',
'TAX_DETAIL',
'VENDOR'
])
)
return super(MappingSettingFilteredListSerializer, self).to_representation(data)


class MappingSettingSerializer(serializers.ModelSerializer):
class Meta:
model = MappingSetting
list_serializer_class = MappingSettingFilteredListSerializer
fields = [
'source_field',
'destination_field',
'import_to_fyle',
'is_custom',
'source_placeholder'
]


class ImportSettingFilterSerializer(serializers.ModelSerializer):
"""
Import Settings Filtered serializer
"""
class Meta:
model = ImportSetting
fields = '__all__'
read_only_fields = ('id', 'workspace', 'created_at', 'updated_at')
fields = [
'import_categories',
'import_vendors_as_merchants',
]

def create(self, validated_data):

class ImportSettingsSerializer(serializers.ModelSerializer):
"""
Import Settings serializer
"""
import_settings = ImportSettingFilterSerializer()
mapping_settings = MappingSettingSerializer(many=True)
workspace_id = serializers.SerializerMethodField()

class Meta:
model = Workspace
fields = [
'import_settings',
'mapping_settings',
'workspace_id'
]
read_only_fields = ['workspace_id']

def get_workspace_id(self, instance):
return instance.id

def update(self, instance, validated):
"""
Create Export Settings
Create Import Settings
"""

workspace_id = self.context['request'].parser_context.get('kwargs').get('workspace_id')
import_settings, _ = ImportSetting.objects.update_or_create(
workspace_id=workspace_id,
defaults=validated_data
)
mapping_settings = validated.pop('mapping_settings')
import_settings = validated.pop('import_settings')
# dependent_field_settings = validated.pop('dependent_field_settings')

with transaction.atomic():
print("inside function")
ImportSetting.objects.update_or_create(
workspace_id=instance.id,
defaults={
'import_categories': import_settings.get('import_categories'),
'import_vendors_as_merchants': import_settings.get('import_vendors_as_merchants')
}
)

trigger: ImportSettingsTrigger = ImportSettingsTrigger(
mapping_settings=mapping_settings,
workspace_id=instance.id
)

for setting in mapping_settings:
MappingSetting.objects.update_or_create(
destination_field=setting['destination_field'],
workspace_id=instance.id,
defaults={
'source_field': setting['source_field'],
'import_to_fyle': setting['import_to_fyle'] if 'import_to_fyle' in setting else False,
'is_custom': setting['is_custom'] if 'is_custom' in setting else False,
'source_placeholder': setting['source_placeholder'] if 'source_placeholder' in setting else None
}
)

trigger.post_save_mapping_settings()

# Update workspace onboarding state
workspace = import_settings.workspace
if workspace.onboarding_state == 'IMPORT_SETTINGS':
workspace.onboarding_state = 'ADVANCED_SETTINGS'
workspace.save()
if instance.onboarding_state == 'IMPORT_SETTINGS':
instance.onboarding_state = 'ADVANCED_SETTINGS'
instance.save()

return instance

def validate(self, data):
if not data.get('import_settings'):
raise serializers.ValidationError('Import Settings are required')

if data.get('mapping_settings') is None:
raise serializers.ValidationError('Mapping settings are required')

if not data.get('dependent_field_settings'):
pass

return import_settings
return data


class AdvancedSettingSerializer(serializers.ModelSerializer):
Expand Down
43 changes: 43 additions & 0 deletions apps/workspaces/triggers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import Dict, List
from django.db.models import Q

# from apps.mappings.helpers import schedule_or_delete_fyle_import_tasks
from fyle_accounting_mappings.models import MappingSetting


class ImportSettingsTrigger:
"""
All the post save actions of Import Settings API
"""
def __init__(self, mapping_settings: List[Dict], workspace_id):
self.__mapping_settings = mapping_settings
self.__workspace_id = workspace_id

def post_save_mapping_settings(self):
"""
Post save actions for mapping settings
Here we need to clear out the data from the mapping-settings table for consecutive runs.
"""
# We first need to avoid deleting mapping-settings that are always necessary.
destination_fields = [
'ACCOUNT',
'CCC_ACCOUNT',
'CHARGE_CARD_NUMBER',
'EMPLOYEE',
'EXPENSE_TYPE',
'TAX_DETAIL',
'VENDOR'
]

# Here we are filtering out the mapping_settings payload and adding the destination-fields that are present in the payload
# So that we avoid deleting them.
for setting in self.__mapping_settings:
if setting['destination_field'] not in destination_fields:
destination_fields.append(setting['destination_field'])

# Now that we have all the system necessary mapping-settings and the mapping-settings in the payload
# This query will take care of deleting all the redundant mapping-settings that are not required.
MappingSetting.objects.filter(
~Q(destination_field__in=destination_fields),
workspace_id=self.__workspace_id
).delete()
12 changes: 7 additions & 5 deletions apps/workspaces/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
Workspace,
Sage300Credential,
ExportSetting,
ImportSetting,
AdvancedSetting
)
from apps.workspaces.serializers import (
Expand Down Expand Up @@ -99,14 +98,17 @@ class ExportSettingView(generics.CreateAPIView, generics.RetrieveAPIView):
queryset = ExportSetting.objects.all()


class ImportSettingView(generics.CreateAPIView, generics.RetrieveAPIView):
class ImportSettingView(generics.RetrieveUpdateAPIView):
"""
Retrieve or Create Export Settings
Retrieve or Create Import Settings
"""
authentication_classes = []
permission_classes = []

serializer_class = ImportSettingsSerializer
lookup_field = 'workspace_id'

queryset = ImportSetting.objects.all()
def get_object(self):
return Workspace.objects.filter(id=self.kwargs['workspace_id']).first()


class AdvancedSettingView(generics.CreateAPIView, generics.RetrieveAPIView):
Expand Down
2 changes: 1 addition & 1 deletion centralized_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ python manage.py migrate
python manage.py createcachetable --database cache_db

# Running development server
gunicorn -c gunicorn_config.py sage_desktop_api.wsgi -b 0.0.0.0:8008
gunicorn -c gunicorn_config.py sage_desktop_api.wsgi -b 0.0.0.0:8010
24 changes: 1 addition & 23 deletions tests/test_workspaces/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,29 +191,7 @@ def test_import_settings(api_client, test_connection):
'''
Test export settings
'''
url = reverse('workspaces')
api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token))
response = api_client.post(url)
workspace_id = response.data['id']
url = reverse(
'import-settings',
kwargs={'workspace_id': workspace_id}
)

payload = {
'import_categories': True,
'import_vendors_as_merchants': True
}
response = api_client.post(url, payload)
import_settings = ImportSetting.objects.filter(workspace_id=workspace_id).first()
assert response.status_code == 201
assert import_settings.import_categories is True
assert import_settings.import_vendors_as_merchants is True

response = api_client.get(url)
assert response.status_code == 200
assert import_settings.import_categories is True
assert import_settings.import_vendors_as_merchants is True
pass


def test_advanced_settings(api_client, test_connection):
Expand Down

0 comments on commit 6b3301c

Please sign in to comment.