From a8f650c263fde29556c0e1484a3bcbaef8913fe1 Mon Sep 17 00:00:00 2001 From: Rohan Date: Wed, 24 Mar 2021 15:47:22 +0530 Subject: [PATCH] fix: set integration details for Shopify Items + fix test imports (#14) --- shopify_integration/customers.py | 1 - shopify_integration/fulfilments.py | 4 +- shopify_integration/hooks.py | 1 + shopify_integration/products.py | 84 ++++++---- shopify_integration/setup.py | 19 ++- .../shopify_settings/shopify_settings.json | 10 +- .../test_data/custom_field.json | 158 +----------------- .../test_data/shopify_order.json | 18 +- .../shopify_settings/test_shopify_settings.py | 7 +- 9 files changed, 101 insertions(+), 201 deletions(-) diff --git a/shopify_integration/customers.py b/shopify_integration/customers.py index 478326e..604d144 100644 --- a/shopify_integration/customers.py +++ b/shopify_integration/customers.py @@ -27,7 +27,6 @@ def create_customer(shopify_customer): "name": shopify_customer.get("id"), "customer_name": cust_name, "shopify_customer_id": shopify_customer.get("id"), - "sync_with_shopify": 1, "customer_group": shopify_settings.customer_group, "territory": get_root_of("Territory"), "customer_type": _("Individual") diff --git a/shopify_integration/fulfilments.py b/shopify_integration/fulfilments.py index 6ba7436..d8dd12b 100644 --- a/shopify_integration/fulfilments.py +++ b/shopify_integration/fulfilments.py @@ -42,8 +42,8 @@ def create_delivery_notes(shopify_order, so): delivery_notes = [] for fulfillment in shopify_order.get("fulfillments"): - if not frappe.db.get_value("Delivery Note", {"shopify_fulfillment_id": fulfillment.get("id")}, "name")\ - and so.docstatus == 1: + if so.docstatus == 1 and not frappe.db.get_value("Delivery Note", + {"shopify_fulfillment_id": fulfillment.get("id")}, "name"): dn = make_delivery_note(so.name) dn.shopify_order_id = shopify_order.get("id") diff --git a/shopify_integration/hooks.py b/shopify_integration/hooks.py index 405da86..615f4fa 100644 --- a/shopify_integration/hooks.py +++ b/shopify_integration/hooks.py @@ -60,6 +60,7 @@ # before_install = "shopify_integration.install.before_install" # after_install = "shopify_integration.install.after_install" +before_migrate = "shopify_integration.setup.setup_custom_fields" # Desk Notifications # ------------------ diff --git a/shopify_integration/products.py b/shopify_integration/products.py index a64b62e..f91803e 100644 --- a/shopify_integration/products.py +++ b/shopify_integration/products.py @@ -158,21 +158,28 @@ def set_new_attribute_values(item_attr, values): def create_item(shopify_item, warehouse, has_variant=False, attributes=None, variant_of=None): item_title = shopify_item.get("title", "").strip() + item_description = shopify_item.get("body_html") or item_title item_name = f"{variant_of} - {item_title}" if variant_of else item_title + if variant_of: + variant_name = frappe.db.get_value("Item", variant_of, "item_name") + item_name = f"{variant_name} - {item_title}" + else: + item_name = item_title + item_dict = { "doctype": "Item", "shopify_product_id": shopify_item.get("product_id"), "shopify_variant_id": shopify_item.get("variant_id"), - "disabled_on_shopify": not shopify_item.get("product_exists"), + "disabled_on_shopify": not shopify_item.get("product_exists", True), "variant_of": variant_of, - "sync_with_shopify": 1, "is_stock_item": 1, - "item_code": cstr(shopify_item.get("item_code")) or item_title, + "item_code": cstr(shopify_item.get("item_code") or shopify_item.get("id") or item_title), "item_name": item_name, - "description": shopify_item.get("body_html") or item_title, - "shopify_description": shopify_item.get("body_html") or item_title, - "item_group": get_item_group(shopify_item.get("product_type")), + "description": item_description, + "shopify_description": item_description, + "item_group": frappe.db.get_single_value("Shopify Settings", "default_item_group"), + "marketplace_item_group": get_item_group(shopify_item.get("product_type")), "has_variants": has_variant, "attributes": attributes or [], "stock_uom": WEIGHT_UOM_MAP.get(shopify_item.get("uom")) or _("Nos"), @@ -182,18 +189,22 @@ def create_item(shopify_item, warehouse, has_variant=False, attributes=None, var "weight_uom": WEIGHT_UOM_MAP.get(shopify_item.get("weight_unit")), "weight_per_unit": shopify_item.get("weight"), "default_supplier": get_supplier(shopify_item), - "item_defaults": [ - { - "company": get_default_company() - } - ] + "integration_doctype": "Shopify Settings", + "integration_doc": "Shopify Settings", + "item_defaults": [{ + "company": get_default_company() + }] } if not is_item_exists(item_dict, attributes, variant_of=variant_of): - item_details = get_item_details(shopify_item) - item_code = "" + item_code = None + existing_item = get_existing_item(shopify_item) - if not item_details: + if existing_item: + existing_item_doc = frappe.get_doc("Item", existing_item) + existing_item_doc.update(item_dict) + existing_item_doc.save(ignore_permissions=True) + else: new_item = frappe.get_doc(item_dict) # this fails during the `validate_name_with_item_group` call in item.py @@ -206,7 +217,7 @@ def create_item(shopify_item, warehouse, has_variant=False, attributes=None, var item_code = new_item.name if not item_code: - item_code = item_details.name + item_code = existing_item if not has_variant: add_to_price_list(shopify_item, item_code) @@ -215,8 +226,10 @@ def create_item(shopify_item, warehouse, has_variant=False, attributes=None, var def create_item_variants(shopify_item, warehouse, attributes): - template_item = frappe.db.get_value("Item", filters={"shopify_product_id": shopify_item.get("product_id")}, - fieldname=["name", "stock_uom"], as_dict=True) + template_item = frappe.db.get_value("Item", + filters={"shopify_product_id": shopify_item.get("product_id")}, + fieldname=["name", "stock_uom"], + as_dict=True) if template_item: for variant in shopify_item.get("variants", []): @@ -333,16 +346,13 @@ def get_supplier_group(): return supplier_group -def get_item_details(shopify_item): - item_details = frappe.db.get_value("Item", {"shopify_product_id": shopify_item.get("product_id")}, - ["name", "stock_uom", "item_name"], as_dict=1) - - if item_details: - return item_details +def get_existing_item(shopify_item): + existing_item = frappe.db.get_value("Item", {"shopify_product_id": shopify_item.get("product_id")}) + if existing_item: + return existing_item - item_details = frappe.db.get_value("Item", {"shopify_variant_id": shopify_item.get("variant_id")}, - ["name", "stock_uom", "item_name"], as_dict=1) - return item_details + existing_item = frappe.db.get_value("Item", {"shopify_variant_id": shopify_item.get("variant_id")}) + return existing_item def is_item_exists(shopify_item, attributes=None, variant_of=None): @@ -372,19 +382,29 @@ def is_item_exists(shopify_item, attributes=None, variant_of=None): # as we are putting condition basis on OR it will fetch all items matching either of conditions # thus comparing matching conditions with len(attributes) # which will give exact matching variant item. - conditions = ["(iv.attribute='{0}' and iv.attribute_value = '{1}')" .format(attr.get("attribute"), attr.get("attribute_value")) for attr in attributes] conditions = "( {0} ) and iv.parent = it.name ) = {1}".format(" or ".join(conditions), len(attributes)) - parent = frappe.db.sql(""" select * from tabItem it where - ( select count(*) from `tabItem Variant Attribute` iv - where {conditions} and it.variant_of = %s """.format(conditions=conditions), - variant_of, as_list=1) + parent = frappe.db.sql_list(""" + SELECT + name + FROM + tabItem it + WHERE + ( + SELECT + COUNT(*) + FROM + `tabItem Variant Attribute` iv + WHERE + {conditions} + AND it.variant_of = %s + """.format(conditions=conditions), variant_of) if parent: - variant = frappe.get_doc("Item", parent[0][0]) + variant = frappe.get_doc("Item", parent[0]) variant.flags.ignore_mandatory = True variant.shopify_product_id = shopify_item.get("shopify_product_id") diff --git a/shopify_integration/setup.py b/shopify_integration/setup.py index 2bcf300..311d05b 100644 --- a/shopify_integration/setup.py +++ b/shopify_integration/setup.py @@ -18,7 +18,7 @@ def get_setup_stages(args=None): ] -def setup_custom_fields(args): +def setup_custom_fields(args=None): custom_fields = { "Customer": [ dict(fieldname='shopify_customer_id', label='Shopify Customer ID', @@ -33,14 +33,27 @@ def setup_custom_fields(args): fieldtype='Data', insert_after='fax', read_only=1, print_hide=1) ], "Item": [ + # Shopify details dict(fieldname='shopify_variant_id', label='Shopify Variant ID', fieldtype='Data', insert_after='item_code', read_only=1, print_hide=1), dict(fieldname='shopify_product_id', label='Shopify Product ID', fieldtype='Data', insert_after='item_code', read_only=1, print_hide=1), + dict(fieldname='disabled_on_shopify', label='Disabled on Shopify', + fieldtype='Check', insert_after='disabled', read_only=1, print_hide=1), + dict(fieldname='marketplace_item_group', label='Marketplace Item Group', + fieldtype='Data', insert_after='item_group', read_only=1, print_hide=1), dict(fieldname='shopify_description', label='Shopify Description', fieldtype='Text Editor', insert_after='description', read_only=1, print_hide=1), - dict(fieldname='disabled_on_shopify', label='Disabled on Shopify', - fieldtype='Check', insert_after='disabled', read_only=1, print_hide=1) + + # Integration section + dict(fieldname='integration_details', label='Shopify', fieldtype='Section Break', + insert_after='description'), + dict(fieldname='integration_doctype', label='Integration DocType', + fieldtype='Link', options='DocType', insert_after='integration_details', + hidden=1, print_hide=1), + dict(fieldname='cb_shopify', fieldtype='Column Break', insert_after='integration_doctype'), + dict(fieldname='integration_doc', label='Integration Doc', fieldtype='Data', + insert_after='cb_shopify', hidden=1, print_hide=1), ], "Sales Order": [ dict(fieldname='shopify_order_id', label='Shopify Order ID', diff --git a/shopify_integration/shopify_integration/doctype/shopify_settings/shopify_settings.json b/shopify_integration/shopify_integration/doctype/shopify_settings/shopify_settings.json index 8e22344..e6c8416 100644 --- a/shopify_integration/shopify_integration/doctype/shopify_settings/shopify_settings.json +++ b/shopify_integration/shopify_integration/doctype/shopify_settings/shopify_settings.json @@ -20,6 +20,7 @@ "webhooks", "sb_company", "company", + "default_item_group", "cb_company", "cost_center", "sb_customer", @@ -281,10 +282,17 @@ "fieldtype": "Link", "label": "Payment Fee Account", "options": "Account" + }, + { + "default": "All Item Groups", + "fieldname": "default_item_group", + "fieldtype": "Link", + "label": "Default Item Group", + "options": "Item Group" } ], "issingle": 1, - "modified": "2021-01-27 00:55:35.414257", + "modified": "2021-03-15 03:28:40.516690", "modified_by": "Administrator", "module": "Shopify Integration", "name": "Shopify Settings", diff --git a/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/custom_field.json b/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/custom_field.json index db6c3d5..2056f14 100644 --- a/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/custom_field.json +++ b/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/custom_field.json @@ -1,39 +1,4 @@ [ - { - "allow_on_submit": 0, - "collapsible": 0, - "collapsible_depends_on": null, - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Print Settings", - "fieldname": "compact_item_print", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "with_letterhead", - "label": "Compact Item Print", - "modified": "2016-06-06 15:18:17.025602", - "name": "Print Settings-compact_item_print", - "no_copy": 0, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "unique": 0, - "width": null - }, { "allow_on_submit": 0, "collapsible": 0, @@ -52,7 +17,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "naming_series", - "label": "Shopify Customer Id", + "label": "Shopify Customer ID", "modified": "2016-01-15 17:25:28.991818", "name": "Customer-shopify_customer_id", "no_copy": 1, @@ -87,7 +52,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "fax", - "label": "Shopify Address Id", + "label": "Shopify Address ID", "modified": "2016-01-15 17:50:52.213743", "name": "Address-shopify_address_id", "no_copy": 1, @@ -122,7 +87,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "title", - "label": "Shopify Order Id", + "label": "Shopify Order ID", "modified": "2016-01-18 09:55:50.764524", "name": "Sales Order-shopify_order_id", "no_copy": 1, @@ -157,7 +122,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "item_code", - "label": "Shopify Product Id", + "label": "Shopify Product ID", "modified": "2016-01-19 15:44:16.132952", "name": "Item-shopify_product_id", "no_copy": 1, @@ -192,7 +157,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "naming_series", - "label": "Shopify Order Id", + "label": "Shopify Order ID", "modified": "2016-01-19 16:30:12.261797", "name": "Sales Invoice-shopify_order_id", "no_copy": 1, @@ -227,7 +192,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "title", - "label": "Shopify Order Id", + "label": "Shopify Order ID", "modified": "2016-01-19 16:30:31.201198", "name": "Delivery Note-shopify_order_id", "no_copy": 1, @@ -279,76 +244,6 @@ "unique": 0, "width": null }, - { - "allow_on_submit": 0, - "collapsible": 0, - "collapsible_depends_on": null, - "default": "0", - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Item", - "fieldname": "sync_with_shopify", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "is_stock_item", - "label": "Sync With Shopify", - "modified": "2015-10-12 15:54:31.997714", - "name": "Item-sync_with_shopify", - "no_copy": 0, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "unique": 0, - "width": null - }, - { - "allow_on_submit": 0, - "collapsible": 0, - "collapsible_depends_on": null, - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Customer", - "fieldname": "sync_with_shopify", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "is_frozen", - "label": "Sync With Shopify", - "modified": "2015-10-01 17:31:55.758826", - "name": "Customer-sync_with_shopify", - "no_copy": 0, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "unique": 0, - "width": null - }, { "allow_on_submit": 0, "collapsible": 0, @@ -367,7 +262,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "item_code", - "label": "Variant Id", + "label": "Variant ID", "modified": "2015-11-09 18:26:50.825858", "name": "Item-shopify_variant_id", "no_copy": 1, @@ -384,41 +279,6 @@ "unique": 0, "width": null }, - { - "allow_on_submit": 0, - "collapsible": 0, - "collapsible_depends_on": null, - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Item", - "fieldname": "sync_qty_with_shopify", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "item_code", - "label": "Sync Quantity With Shopify", - "modified": "2015-12-29 08:37:46.183295", - "name": "Item-sync_qty_with_shopify", - "no_copy": 0, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "unique": 0, - "width": null - }, { "allow_on_submit": 0, "collapsible": 0, @@ -437,7 +297,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "title", - "label": "Shopify Fulfillment Id", + "label": "Shopify Fulfillment ID", "modified": "2016-01-20 23:50:35.609543", "name": "Delivery Note-shopify_fulfillment_id", "no_copy": 1, @@ -472,7 +332,7 @@ "in_filter": 0, "in_list_view": 0, "insert_after": "supplier_name", - "label": "Shopify Supplier Id", + "label": "Shopify Supplier ID", "modified": "2016-02-01 15:41:25.818306", "name": "Supplier-shopify_supplier_id", "no_copy": 1, diff --git a/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/shopify_order.json b/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/shopify_order.json index 8f50ca7..4000f3f 100644 --- a/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/shopify_order.json +++ b/shopify_integration/shopify_integration/doctype/shopify_settings/test_data/shopify_order.json @@ -3,8 +3,8 @@ "id": 2414345735, "email": "andrew@wyatt.co.in", "closed_at": null, - "created_at": "2016-01-20T17:26:39+05:30", - "updated_at": "2016-01-20T17:27:15+05:30", + "created_at": "2021-01-20T17:26:39+05:30", + "updated_at": "2021-01-20T17:27:15+05:30", "number": 5, "note": "", "token": "660fed25987517b733644a8c9ec7c8e0", @@ -34,7 +34,7 @@ "location_id": null, "source_identifier": null, "source_url": null, - "processed_at": "2016-01-20T17:26:39+05:30", + "processed_at": "2021-01-20T17:26:39+05:30", "device_id": null, "browser_ip": null, "landing_site_ref": null, @@ -151,9 +151,9 @@ "id": 1849629255, "order_id": 2414345735, "status": "success", - "created_at": "2016-01-20T17:27:15+05:30", + "created_at": "2021-01-20T17:27:15+05:30", "service": "manual", - "updated_at": "2016-01-20T17:27:15+05:30", + "updated_at": "2021-01-20T17:27:15+05:30", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], @@ -191,9 +191,9 @@ "id": 1849628167, "order_id": 2414345735, "status": "success", - "created_at": "2016-01-20T17:26:58+05:30", + "created_at": "2021-01-20T17:26:58+05:30", "service": "manual", - "updated_at": "2016-01-20T17:26:58+05:30", + "updated_at": "2021-01-20T17:26:58+05:30", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], @@ -233,8 +233,8 @@ "id": 2324518599, "email": "andrew@wyatt.co.in", "accepts_marketing": false, - "created_at": "2016-01-20T17:18:35+05:30", - "updated_at": "2016-01-20T17:26:39+05:30", + "created_at": "2021-01-20T17:18:35+05:30", + "updated_at": "2021-01-20T17:26:39+05:30", "first_name": "Andrew", "last_name": "Wyatt", "orders_count": 1, diff --git a/shopify_integration/shopify_integration/doctype/shopify_settings/test_shopify_settings.py b/shopify_integration/shopify_integration/doctype/shopify_settings/test_shopify_settings.py index 926b1f1..be44cbc 100644 --- a/shopify_integration/shopify_integration/doctype/shopify_settings/test_shopify_settings.py +++ b/shopify_integration/shopify_integration/doctype/shopify_settings/test_shopify_settings.py @@ -12,7 +12,7 @@ from frappe.utils import cstr from shopify_integration.customers import create_customer -from shopify_integration.orders import sync_sales_order +from shopify_integration.orders import create_shopify_documents from shopify_integration.products import make_item from shopify_integration.utils import get_shopify_document @@ -22,8 +22,7 @@ def setUp(self): frappe.set_user("Administrator") # use the fixture data - import_doc(path=frappe.get_app_path("shopify_integration", "shopify_integration/doctype/shopify_settings/test_data/custom_field.json"), - ignore_links=True, overwrite=True) + import_doc(frappe.get_app_path("shopify_integration", "shopify_integration/doctype/shopify_settings/test_data/custom_field.json")) frappe.reload_doctype("Customer") frappe.reload_doctype("Sales Order") @@ -46,7 +45,7 @@ def test_order(self): # create order with open(os.path.join(os.path.dirname(__file__), "test_data", "shopify_order.json")) as shopify_order: shopify_order = json.loads(shopify_order.read()) - sync_sales_order(shopify_order.get("order")) + create_shopify_documents(shopify_order.get("order")) # verify sales order IDs shopify_order_id = cstr(shopify_order.get("order", {}).get("id"))