Skip to content

Commit

Permalink
Import xero suppliers as merchants in fyle (#256)
Browse files Browse the repository at this point in the history
* Import xero suppliers as merchants in fyle

* test cases resolved

* comments resolved

* post merchant function updated

* param change

* comment resolved

* version bumped

* dummy change
  • Loading branch information
ruuushhh authored Sep 5, 2023
1 parent 3a35a6b commit 479f5de
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 21 deletions.
4 changes: 2 additions & 2 deletions apps/mappings/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def schedule_or_delete_fyle_import_tasks(configuration: WorkspaceGeneralSettings
:return: None
"""
project_mapping = MappingSetting.objects.filter(source_field='PROJECT', workspace_id=configuration.workspace_id).first()
if configuration.import_categories or (project_mapping and project_mapping.import_to_fyle):
if configuration.import_categories or (project_mapping and project_mapping.import_to_fyle) or configuration.import_suppliers_as_merchants:
start_datetime = datetime.now()
Schedule.objects.update_or_create(
func='apps.mappings.tasks.auto_import_and_map_fyle_fields',
Expand All @@ -23,7 +23,7 @@ def schedule_or_delete_fyle_import_tasks(configuration: WorkspaceGeneralSettings
'next_run': start_datetime
}
)
elif not configuration.import_categories and not (project_mapping and project_mapping.import_to_fyle):
elif not configuration.import_categories and not (project_mapping and project_mapping.import_to_fyle) and not configuration.import_suppliers_as_merchants:
Schedule.objects.filter(
func='apps.mappings.tasks.auto_import_and_map_fyle_fields',
args='{}'.format(configuration.workspace_id)
Expand Down
17 changes: 17 additions & 0 deletions apps/mappings/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from apps.xero.utils import XeroConnector
from apps.tasks.models import Error
from apps.workspaces.models import XeroCredentials, FyleCredential, WorkspaceGeneralSettings
from apps.mappings.models import TenantMapping
from .constants import FYLE_EXPENSE_SYSTEM_FIELDS

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -699,6 +700,19 @@ def schedule_tax_groups_creation(import_tax_codes, workspace_id):
schedule.delete()


def auto_create_suppliers_as_merchants(workspace_id):
fyle_credentials: FyleCredential = FyleCredential.objects.get(workspace_id=workspace_id)
fyle_connection = PlatformConnector(fyle_credentials)

xero_credentials = XeroCredentials.get_active_xero_credentials(workspace_id)
xero_connection = XeroConnector(xero_credentials, workspace_id=workspace_id)

merchant_names = xero_connection.get_suppliers()

if merchant_names:
fyle_connection.merchants.post(merchant_names, skip_existing_merchants=True)


def auto_import_and_map_fyle_fields(workspace_id):
"""
Auto import and map fyle fields
Expand All @@ -713,6 +727,9 @@ def auto_import_and_map_fyle_fields(workspace_id):

if project_mapping and project_mapping.import_to_fyle:
chain.append('apps.mappings.tasks.auto_create_project_mappings', workspace_id)

if workspace_general_settings.import_suppliers_as_merchants:
chain.append('apps.mappings.tasks.auto_create_suppliers_as_merchants', workspace_id)

if chain.length() > 0:
chain.run()
4 changes: 3 additions & 1 deletion apps/workspaces/apis/export_settings/triggers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from apps.mappings.tasks import schedule_auto_map_employees
from apps.workspaces.models import WorkspaceGeneralSettings
from fyle_accounting_mappings.models import MappingSetting
from apps.workspaces.utils import delete_cards_mapping_settings
from apps.workspaces.utils import delete_cards_mapping_settings, schedule_or_delete_import_supplier_schedule


class ExportSettingsTrigger:
Expand All @@ -26,5 +26,7 @@ def run_workspace_general_settings_triggers(workspace_general_settings_instance:

delete_cards_mapping_settings(workspace_general_settings_instance)

schedule_or_delete_import_supplier_schedule(workspace_general_settings_instance)

schedule_auto_map_employees(workspace_general_settings_instance.auto_map_employees,
workspace_general_settings_instance.workspace_id)
5 changes: 3 additions & 2 deletions apps/workspaces/apis/import_settings/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Meta:
class WorkspaceGeneralSettingsSerializer(serializers.ModelSerializer):
class Meta:
model = WorkspaceGeneralSettings
fields = ['import_categories', 'charts_of_accounts', 'import_tax_codes', 'import_customers']
fields = ['import_categories', 'charts_of_accounts', 'import_tax_codes', 'import_customers', 'import_suppliers_as_merchants']


class GeneralMappingsSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -105,7 +105,8 @@ def update(self, instance, validated):
'import_categories': workspace_general_settings.get('import_categories'),
'charts_of_accounts': workspace_general_settings.get('charts_of_accounts'),
'import_tax_codes': workspace_general_settings.get('import_tax_codes'),
'import_customers': workspace_general_settings.get('import_customers')
'import_customers': workspace_general_settings.get('import_customers'),
'import_suppliers_as_merchants': workspace_general_settings.get('import_suppliers_as_merchants')
}
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.1.14 on 2023-08-24 13:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('workspaces', '0036_auto_20230323_0846'),
]

operations = [
migrations.AddField(
model_name='workspacegeneralsettings',
name='import_suppliers_as_merchants',
field=models.BooleanField(default=False, help_text='Auto import suppliers to Fyle'),
),
]
1 change: 1 addition & 0 deletions apps/workspaces/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class WorkspaceGeneralSettings(models.Model):
skip_cards_mapping = models.BooleanField(default=False, help_text='Skip cards mapping')
import_tax_codes = models.BooleanField(default=False, help_text='Auto import tax codes to Fyle', null=True)
import_customers = models.BooleanField(default=False, help_text='Auto import customers to Fyle')
import_suppliers_as_merchants = models.BooleanField(default=False, help_text='Auto import suppliers to Fyle')
is_simplify_report_closure_enabled = models.BooleanField(default=True, help_text='Simplify report closure is enabled')
created_at = models.DateTimeField(auto_now_add=True, help_text='Created at')
updated_at = models.DateTimeField(auto_now=True, help_text='Updated at')
Expand Down
14 changes: 14 additions & 0 deletions apps/workspaces/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import jwt

from django.conf import settings
from django_q.models import Schedule

from future.moves.urllib.parse import urlencode

Expand Down Expand Up @@ -242,3 +243,16 @@ def delete_cards_mapping_settings(workspace_general_settings: WorkspaceGeneralSe
).first()
if mapping_setting:
mapping_setting.delete()


def schedule_or_delete_import_supplier_schedule(workspace_general_settings: WorkspaceGeneralSettings):
if not workspace_general_settings.corporate_credit_card_expenses_object:
workspace_general_settings.import_suppliers_as_merchants = False
workspace_general_settings.save()
schedule: Schedule = Schedule.objects.filter(
func='apps.mappings.tasks.auto_create_suppliers_as_merchants',
args='{}'.format(workspace_general_settings.workspace_id)
).first()

if schedule:
schedule.delete()
11 changes: 6 additions & 5 deletions apps/xero/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from .utils import XeroConnector

from datetime import datetime, timezone
from apps.workspaces.models import XeroCredentials, Workspace, WorkspaceGeneralSettings
from django_q.tasks import Chain

from fyle_accounting_mappings.models import DestinationAttribute, MappingSetting
from fyle_accounting_mappings.models import MappingSetting

def get_xero_connector(workspace_id):
xero_credentials = XeroCredentials.get_active_xero_credentials(workspace_id=workspace_id)
Expand All @@ -16,7 +17,6 @@ def sync_tenant(workspace_id):
return tenants

def sync_dimensions(workspace_id):

workspace = Workspace.objects.get(id=workspace_id)
if workspace.destination_synced_at:
time_interval = datetime.now(timezone.utc) - workspace.destination_synced_at
Expand All @@ -31,11 +31,11 @@ def sync_dimensions(workspace_id):


def refersh_xero_dimension(workspace_id):

workspace_id = workspace_id
xero_connector = get_xero_connector(workspace_id=workspace_id)

mapping_settings = MappingSetting.objects.filter(workspace_id=workspace_id, import_to_fyle=True)
workspace_general_settings: WorkspaceGeneralSettings = WorkspaceGeneralSettings.objects.get(workspace_id=workspace_id)
chain = Chain()

for mapping_setting in mapping_settings:
Expand All @@ -48,6 +48,9 @@ def refersh_xero_dimension(workspace_id):
elif mapping_setting.is_custom:
# run async_auto_create_custom_field_mappings
chain.append('apps.mappings.tasks.async_auto_create_custom_field_mappings', int(workspace_id))
elif workspace_general_settings.import_suppliers_as_merchants:
# run auto_create_suppliers_as_merchant
chain.append('apps.mappings.tasks.auto_create_suppliers_as_merchants', workspace_id)

if chain.length() > 0:
chain.run()
Expand All @@ -57,5 +60,3 @@ def refersh_xero_dimension(workspace_id):
workspace = Workspace.objects.get(id=workspace_id)
workspace.destination_synced_at = datetime.now()
workspace.save(update_fields=['destination_synced_at'])


13 changes: 13 additions & 0 deletions apps/xero/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ def __init__(self, credentials_object: XeroCredentials, workspace_id: int):
credentials_object.save()


def get_suppliers(self):
tenant_mapping = TenantMapping.objects.get(workspace_id=self.workspace_id)
self.connection.set_tenant_id(tenant_mapping.tenant_id)

suppliers_generator = self.connection.contacts.list_all_generator()
merchant_names : List[str] = []
for suppliers in suppliers_generator:
for supplier in suppliers['Contacts']:
if supplier['IsSupplier'] and supplier['ContactStatus'] == 'ACTIVE':
merchant_names.append(supplier['Name'])
return merchant_names


def get_or_create_contact(self, contact_name: str, email: str = None, create: bool = False):
"""
Call xero api to get or create contact
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ enum34==1.1.10
future==0.18.2
fyle==0.30.0
fyle-accounting-mappings==1.26.2
fyle-integrations-platform-connector==1.30.0
fyle-integrations-platform-connector==1.32.2
fyle-rest-auth==1.3.1
gevent==22.10.2
gunicorn==20.1.0
Expand Down
14 changes: 8 additions & 6 deletions tests/sql_fixtures/reset_db_fixtures/reset_db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
-- PostgreSQL database dump
--

-- Dumped from database version 15.3 (Debian 15.3-1.pgdg110+1)
-- Dumped by pg_dump version 15.2 (Debian 15.2-1.pgdg100+1)
-- Dumped from database version 15.4 (Debian 15.4-1.pgdg120+1)
-- Dumped by pg_dump version 15.3 (Debian 15.3-1.pgdg100+1)

SET statement_timeout = 0;
SET lock_timeout = 0;
Expand Down Expand Up @@ -1429,7 +1429,8 @@ CREATE TABLE public.workspace_general_settings (
import_customers boolean NOT NULL,
change_accounting_period boolean NOT NULL,
auto_create_merchant_destination_entity boolean NOT NULL,
is_simplify_report_closure_enabled boolean NOT NULL
is_simplify_report_closure_enabled boolean NOT NULL,
import_suppliers_as_merchants boolean NOT NULL
);


Expand Down Expand Up @@ -2485,6 +2486,7 @@ COPY public.django_migrations (id, app, name, applied) FROM stdin;
137 fyle_accounting_mappings 0021_auto_20230323_0557 2023-04-10 08:19:53.627683+00
138 fyle 0017_expense_posted_at 2023-06-22 06:52:23.798799+00
139 fyle_accounting_mappings 0022_auto_20230411_1118 2023-06-22 06:52:23.813446+00
140 workspaces 0037_workspacegeneralsettings_import_suppliers_as_merchants 2023-08-29 13:13:53.212703+00
\.


Expand Down Expand Up @@ -4894,8 +4896,8 @@ COPY public.users (password, last_login, id, email, user_id, full_name, active,
-- Data for Name: workspace_general_settings; Type: TABLE DATA; Schema: public; Owner: postgres
--

COPY public.workspace_general_settings (id, reimbursable_expenses_object, corporate_credit_card_expenses_object, created_at, updated_at, workspace_id, sync_fyle_to_xero_payments, sync_xero_to_fyle_payments, import_categories, auto_map_employees, auto_create_destination_entity, map_merchant_to_contact, skip_cards_mapping, import_tax_codes, charts_of_accounts, import_customers, change_accounting_period, auto_create_merchant_destination_entity, is_simplify_report_closure_enabled) FROM stdin;
1 PURCHASE BILL BANK TRANSACTION 2022-08-02 20:25:24.644164+00 2022-08-02 20:25:24.644209+00 1 f t t EMAIL t t f t {EXPENSE} t t f f
COPY public.workspace_general_settings (id, reimbursable_expenses_object, corporate_credit_card_expenses_object, created_at, updated_at, workspace_id, sync_fyle_to_xero_payments, sync_xero_to_fyle_payments, import_categories, auto_map_employees, auto_create_destination_entity, map_merchant_to_contact, skip_cards_mapping, import_tax_codes, charts_of_accounts, import_customers, change_accounting_period, auto_create_merchant_destination_entity, is_simplify_report_closure_enabled, import_suppliers_as_merchants) FROM stdin;
1 PURCHASE BILL BANK TRANSACTION 2022-08-02 20:25:24.644164+00 2022-08-02 20:25:24.644209+00 1 f t t EMAIL t t f t {EXPENSE} t t f f f
\.


Expand Down Expand Up @@ -5008,7 +5010,7 @@ SELECT pg_catalog.setval('public.django_content_type_id_seq', 38, true);
-- Name: django_migrations_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
--

SELECT pg_catalog.setval('public.django_migrations_id_seq', 139, true);
SELECT pg_catalog.setval('public.django_migrations_id_seq', 140, true);


--
Expand Down
1 change: 1 addition & 0 deletions tests/test_workspaces/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
'map_merchant_to_contact':True,
'change_accounting_period':True,
'import_categories':True,
'import_suppliers_as_merchants':True,
'auto_map_employees':'EMAIL',
'auto_create_destination_entity':True,
'skip_cards_mapping':False,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"COST of goods"
],
"import_tax_codes": True,
"import_customers": True
"import_customers": True,
"import_suppliers_as_merchants": True
},
"general_mappings": {
"default_tax_code": {
Expand Down Expand Up @@ -131,6 +132,7 @@
"EXPENSE"
],
"import_tax_codes": False,
"import_suppliers_as_merchants": False,
"import_customers": False
},
"general_mappings": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"import_categories": True,
"charts_of_accounts": ["Expense", "COST of goods"],
"import_tax_codes": True,
"import_customers": True
"import_customers": True,
"import_suppliers_as_merchants": True
},
"general_mappings": {
"default_tax_code": {
Expand Down Expand Up @@ -34,7 +35,8 @@
"import_categories": True,
"charts_of_accounts": ["Expense", "COST of goods"],
"import_tax_codes": True,
"import_customers": False
"import_customers": False,
"import_suppliers_as_merchants": False
},
"general_mappings": {
"default_tax_code": {
Expand Down Expand Up @@ -67,7 +69,8 @@
"COST of goods"
],
"import_tax_codes": True,
"import_customers": True
"import_customers": True,
"import_suppliers_as_merchants": True
},
"general_mappings": {
"default_tax_code": {
Expand Down

0 comments on commit 479f5de

Please sign in to comment.