diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py deleted file mode 100644 index 5d5b2e19ce..0000000000 --- a/erpnext/erpnext_integrations/connectors/shopify_connection.py +++ /dev/null @@ -1,353 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe import _ -import json -from frappe.utils import cstr, cint, nowdate, getdate, flt, get_request_session, get_datetime -from erpnext.erpnext_integrations.utils import validate_webhooks_request -from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice -from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import sync_item_from_shopify -from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer -from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log, dump_request_data -from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import get_shopify_url, get_header - -@frappe.whitelist(allow_guest=True) -@validate_webhooks_request("Shopify Settings", 'X-Shopify-Hmac-Sha256', secret_key='shared_secret') -def store_request_data(order=None, event=None): - if frappe.request: - order = json.loads(frappe.request.data) - event = frappe.request.headers.get('X-Shopify-Topic') - - dump_request_data(order, event) - -def sync_sales_order(order, request_id=None, old_order_sync=False): - frappe.set_user('Administrator') - shopify_settings = frappe.get_doc("Shopify Settings") - frappe.flags.request_id = request_id - - if not frappe.db.get_value("Sales Order", filters={"shopify_order_id": cstr(order['id'])}): - try: - validate_customer(order, shopify_settings) - validate_item(order, shopify_settings) - create_order(order, shopify_settings, old_order_sync=old_order_sync) - except Exception as e: - make_shopify_log(status="Error", exception=e) - - else: - make_shopify_log(status="Success") - -def prepare_sales_invoice(order, request_id=None): - frappe.set_user('Administrator') - shopify_settings = frappe.get_doc("Shopify Settings") - frappe.flags.request_id = request_id - - try: - sales_order = get_sales_order(cstr(order['id'])) - if sales_order: - create_sales_invoice(order, shopify_settings, sales_order) - make_shopify_log(status="Success") - except Exception as e: - make_shopify_log(status="Error", exception=e, rollback=True) - -def prepare_delivery_note(order, request_id=None): - frappe.set_user('Administrator') - shopify_settings = frappe.get_doc("Shopify Settings") - frappe.flags.request_id = request_id - - try: - sales_order = get_sales_order(cstr(order['id'])) - if sales_order: - create_delivery_note(order, shopify_settings, sales_order) - make_shopify_log(status="Success") - except Exception as e: - make_shopify_log(status="Error", exception=e, rollback=True) - -def get_sales_order(shopify_order_id): - sales_order = frappe.db.get_value("Sales Order", filters={"shopify_order_id": shopify_order_id}) - if sales_order: - so = frappe.get_doc("Sales Order", sales_order) - return so - -def validate_customer(order, shopify_settings): - customer_id = order.get("customer", {}).get("id") - if customer_id: - if not frappe.db.get_value("Customer", {"shopify_customer_id": customer_id}, "name"): - create_customer(order.get("customer"), shopify_settings) - -def validate_item(order, shopify_settings): - for item in order.get("line_items"): - if item.get("product_id") and not frappe.db.get_value("Item", {"shopify_product_id": item.get("product_id")}, "name"): - sync_item_from_shopify(shopify_settings, item) - -def create_order(order, shopify_settings, old_order_sync=False, company=None): - so = create_sales_order(order, shopify_settings, company) - if so: - if order.get("financial_status") == "paid": - create_sales_invoice(order, shopify_settings, so, old_order_sync=old_order_sync) - - if order.get("fulfillments") and not old_order_sync: - create_delivery_note(order, shopify_settings, so) - -def create_sales_order(shopify_order, shopify_settings, company=None): - product_not_exists = [] - customer = frappe.db.get_value("Customer", {"shopify_customer_id": shopify_order.get("customer", {}).get("id")}, "name") - so = frappe.db.get_value("Sales Order", {"shopify_order_id": shopify_order.get("id")}, "name") - - if not so: - items = get_order_items(shopify_order.get("line_items"), shopify_settings, getdate(shopify_order.get('created_at'))) - - if not items: - message = 'Following items exists in the shopify order but relevant records were not found in the shopify Product master' - message += "\n" + ", ".join(product_not_exists) - - make_shopify_log(status="Error", exception=message, rollback=True) - - return '' - - so = frappe.get_doc({ - "doctype": "Sales Order", - "naming_series": shopify_settings.sales_order_series or "SO-Shopify-", - "shopify_order_id": shopify_order.get("id"), - "shopify_order_number": shopify_order.get("name"), - "customer": customer or shopify_settings.default_customer, - "transaction_date": getdate(shopify_order.get("created_at")) or nowdate(), - "delivery_date": getdate(shopify_order.get("created_at")) or nowdate(), - "company": shopify_settings.company, - "selling_price_list": shopify_settings.price_list, - "ignore_pricing_rule": 1, - "items": items, - "taxes": get_order_taxes(shopify_order, shopify_settings), - "apply_discount_on": "Grand Total", - "discount_amount": get_discounted_amount(shopify_order), - }) - - if company: - so.update({ - "company": company, - "status": "Draft" - }) - so.flags.ignore_mandatory = True - so.save(ignore_permissions=True) - so.submit() - - else: - so = frappe.get_doc("Sales Order", so) - - frappe.db.commit() - return so - -def create_sales_invoice(shopify_order, shopify_settings, so, old_order_sync=False): - if not frappe.db.get_value("Sales Invoice", {"shopify_order_id": shopify_order.get("id")}, "name")\ - and so.docstatus==1 and not so.per_billed and cint(shopify_settings.sync_sales_invoice): - - if old_order_sync: - posting_date = getdate(shopify_order.get('created_at')) - else: - posting_date = nowdate() - - si = make_sales_invoice(so.name, ignore_permissions=True) - si.shopify_order_id = shopify_order.get("id") - si.shopify_order_number = shopify_order.get("name") - si.set_posting_time = 1 - si.posting_date = posting_date - si.due_date = posting_date - si.naming_series = shopify_settings.sales_invoice_series or "SI-Shopify-" - si.flags.ignore_mandatory = True - set_cost_center(si.items, shopify_settings.cost_center) - si.insert(ignore_mandatory=True) - si.submit() - make_payament_entry_against_sales_invoice(si, shopify_settings, posting_date) - frappe.db.commit() - -def set_cost_center(items, cost_center): - for item in items: - item.cost_center = cost_center - -def make_payament_entry_against_sales_invoice(doc, shopify_settings, posting_date=None): - from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry - payment_entry = get_payment_entry(doc.doctype, doc.name, bank_account=shopify_settings.cash_bank_account) - payment_entry.flags.ignore_mandatory = True - payment_entry.reference_no = doc.name - payment_entry.posting_date = posting_date or nowdate() - payment_entry.reference_date = posting_date or nowdate() - payment_entry.insert(ignore_permissions=True) - payment_entry.submit() - -def create_delivery_note(shopify_order, shopify_settings, so): - if not cint(shopify_settings.sync_delivery_note): - return - - 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: - - dn = make_delivery_note(so.name) - dn.shopify_order_id = fulfillment.get("order_id") - dn.shopify_order_number = shopify_order.get("name") - dn.set_posting_time = 1 - dn.posting_date = getdate(fulfillment.get("created_at")) - dn.shopify_fulfillment_id = fulfillment.get("id") - dn.naming_series = shopify_settings.delivery_note_series or "DN-Shopify-" - dn.items = get_fulfillment_items(dn.items, fulfillment.get("line_items"), shopify_settings) - dn.flags.ignore_mandatory = True - dn.save() - dn.submit() - frappe.db.commit() - -def get_fulfillment_items(dn_items, fulfillment_items, shopify_settings): - return [dn_item.update({"qty": item.get("quantity")}) for item in fulfillment_items for dn_item in dn_items\ - if get_item_code(item) == dn_item.item_code] - -def get_discounted_amount(order): - discounted_amount = 0.0 - for discount in order.get("discount_codes"): - discounted_amount += flt(discount.get("amount")) - return discounted_amount - -def get_order_items(order_items, shopify_settings, delivery_date): - items = [] - all_product_exists = True - product_not_exists = [] - - for shopify_item in order_items: - if not shopify_item.get('product_exists'): - all_product_exists = False - product_not_exists.append({'title':shopify_item.get('title'), - 'shopify_order_id': shopify_item.get('id')}) - continue - - if all_product_exists: - item_code = get_item_code(shopify_item) - items.append({ - "item_code": item_code, - "item_name": shopify_item.get("name"), - "rate": shopify_item.get("price"), - "delivery_date": delivery_date, - "qty": shopify_item.get("quantity"), - "stock_uom": shopify_item.get("uom") or _("Nos"), - "warehouse": shopify_settings.warehouse - }) - else: - items = [] - - return items - -def get_item_code(shopify_item): - item_code = frappe.db.get_value("Item", {"shopify_variant_id": shopify_item.get("variant_id")}, "item_code") - if not item_code: - item_code = frappe.db.get_value("Item", {"shopify_product_id": shopify_item.get("product_id")}, "item_code") - if not item_code: - item_code = frappe.db.get_value("Item", {"item_name": shopify_item.get("title")}, "item_code") - - return item_code - -def get_order_taxes(shopify_order, shopify_settings): - taxes = [] - for tax in shopify_order.get("tax_lines"): - taxes.append({ - "charge_type": _("On Net Total"), - "account_head": get_tax_account_head(tax), - "description": "{0} - {1}%".format(tax.get("title"), tax.get("rate") * 100.0), - "rate": tax.get("rate") * 100.00, - "included_in_print_rate": 1 if shopify_order.get("taxes_included") else 0, - "cost_center": shopify_settings.cost_center - }) - - taxes = update_taxes_with_shipping_lines(taxes, shopify_order.get("shipping_lines"), shopify_settings) - - return taxes - -def update_taxes_with_shipping_lines(taxes, shipping_lines, shopify_settings): - """Shipping lines represents the shipping details, - each such shipping detail consists of a list of tax_lines""" - for shipping_charge in shipping_lines: - if shipping_charge.get("price"): - taxes.append({ - "charge_type": _("Actual"), - "account_head": get_tax_account_head(shipping_charge), - "description": shipping_charge["title"], - "tax_amount": shipping_charge["price"], - "cost_center": shopify_settings.cost_center - }) - - for tax in shipping_charge.get("tax_lines"): - taxes.append({ - "charge_type": _("Actual"), - "account_head": get_tax_account_head(tax), - "description": tax["title"], - "tax_amount": tax["price"], - "cost_center": shopify_settings.cost_center - }) - - return taxes - -def get_tax_account_head(tax): - tax_title = tax.get("title").encode("utf-8") - - tax_account = frappe.db.get_value("Shopify Tax Account", \ - {"parent": "Shopify Settings", "shopify_tax": tax_title}, "tax_account") - - if not tax_account: - frappe.throw(_("Tax Account not specified for Shopify Tax {0}").format(tax.get("title"))) - - return tax_account - -@frappe.whitelist(allow_guest=True) -def sync_old_orders(): - frappe.set_user('Administrator') - shopify_settings = frappe.get_doc('Shopify Settings') - - if not shopify_settings.sync_missing_orders: - return - - url = get_url(shopify_settings) - session = get_request_session() - - try: - res = session.get(url, headers=get_header(shopify_settings)) - res.raise_for_status() - orders = res.json()["orders"] - - for order in orders: - if is_sync_complete(shopify_settings, order): - stop_sync(shopify_settings) - return - - sync_sales_order(order=order, old_order_sync=True) - last_order_id = order.get('id') - - if last_order_id: - shopify_settings.load_from_db() - shopify_settings.last_order_id = last_order_id - shopify_settings.save() - frappe.db.commit() - - except Exception as e: - raise e - -def stop_sync(shopify_settings): - shopify_settings.sync_missing_orders = 0 - shopify_settings.last_order_id = '' - shopify_settings.save() - frappe.db.commit() - -def get_url(shopify_settings): - last_order_id = shopify_settings.last_order_id - - if not last_order_id: - if shopify_settings.sync_based_on == 'Date': - url = get_shopify_url("admin/api/2021-04/orders.json?limit=250&created_at_min={0}&since_id=0".format( - get_datetime(shopify_settings.from_date)), shopify_settings) - else: - url = get_shopify_url("admin/api/2021-04/orders.json?limit=250&since_id={0}".format( - shopify_settings.from_order_id), shopify_settings) - else: - url = get_shopify_url("admin/api/2021-04/orders.json?limit=250&since_id={0}".format(last_order_id), shopify_settings) - - return url - -def is_sync_complete(shopify_settings, order): - if shopify_settings.sync_based_on == 'Date': - return getdate(shopify_settings.to_date) < getdate(order.get('created_at')) - else: - return cstr(order.get('id')) == cstr(shopify_settings.to_order_id) - diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/__init__.py b/erpnext/erpnext_integrations/doctype/shopify_log/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.js b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.js deleted file mode 100644 index d3fe7d2b4d..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Shopify Log', { - refresh: function(frm) { - if (frm.doc.request_data && frm.doc.status=='Error'){ - frm.add_custom_button('Resync', function() { - frappe.call({ - method:"erpnext.erpnext_integrations.doctype.shopify_log.shopify_log.resync", - args:{ - method:frm.doc.method, - name: frm.doc.name, - request_data: frm.doc.request_data - }, - callback: function(r){ - frappe.msgprint(__("Order rescheduled for sync")) - } - }) - }).addClass('btn-primary'); - } - } -}); diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.json b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.json deleted file mode 100644 index ab373eedb4..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.json +++ /dev/null @@ -1,268 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-03-14 10:02:06.227184", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "System", - "editable_grid": 0, - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Queued", - "fieldname": "status", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "method", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Method", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "message", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Message", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "traceback", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Traceback", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "request_data", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Request Data", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 1, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-04-20 16:23:36.862381", - "modified_by": "Administrator", - "module": "ERPNext Integrations", - "name": "Shopify Log", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Administrator", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "title", - "track_changes": 0, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py deleted file mode 100644 index a2b6af99b2..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -import json -from frappe.model.document import Document -from erpnext.erpnext_integrations.utils import get_webhook_address - -class ShopifyLog(Document): - pass - - -def make_shopify_log(status="Queued", exception=None, rollback=False): - # if name not provided by log calling method then fetch existing queued state log - make_new = False - - if not frappe.flags.request_id: - make_new = True - - if rollback: - frappe.db.rollback() - - if make_new: - log = frappe.get_doc({"doctype":"Shopify Log"}).insert(ignore_permissions=True) - else: - log = log = frappe.get_doc("Shopify Log", frappe.flags.request_id) - - log.message = get_message(exception) - log.traceback = frappe.get_traceback() - log.status = status - log.save(ignore_permissions=True) - frappe.db.commit() - -def get_message(exception): - message = None - - if hasattr(exception, 'message'): - message = exception.message - elif hasattr(exception, '__str__'): - message = exception.__str__() - else: - message = "Something went wrong while syncing" - return message - -def dump_request_data(data, event="create/order"): - event_mapper = { - "orders/create": get_webhook_address(connector_name='shopify_connection', method="sync_sales_order", exclude_uri=True), - "orders/paid" : get_webhook_address(connector_name='shopify_connection', method="prepare_sales_invoice", exclude_uri=True), - "orders/fulfilled": get_webhook_address(connector_name='shopify_connection', method="prepare_delivery_note", exclude_uri=True) - } - - log = frappe.get_doc({ - "doctype": "Shopify Log", - "request_data": json.dumps(data, indent=1), - "method": event_mapper[event] - }).insert(ignore_permissions=True) - - frappe.db.commit() - frappe.enqueue(method=event_mapper[event], queue='short', timeout=300, is_async=True, - **{"order": data, "request_id": log.name}) - -@frappe.whitelist() -def resync(method, name, request_data): - frappe.db.set_value("Shopify Log", name, "status", "Queued", update_modified=False) - frappe.enqueue(method=method, queue='short', timeout=300, is_async=True, - **{"order": json.loads(request_data), "request_id": name}) diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log_list.js b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log_list.js deleted file mode 100644 index 0913ce4ef3..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log_list.js +++ /dev/null @@ -1,12 +0,0 @@ -frappe.listview_settings['Shopify Log'] = { - add_fields: ["status"], - get_indicator: function(doc) { - if(doc.status==="Success"){ - return [__("Success"), "green", "status,=,Success"]; - } else if(doc.status ==="Error"){ - return [__("Error"), "red", "status,=,Error"]; - } else if(doc.status ==="Queued"){ - return [__("Queued"), "orange", "status,=,Queued"]; - } - } -} diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.js b/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.js deleted file mode 100644 index d22b6d5240..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Shopify Log", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Shopify Log - () => frappe.tests.make('Shopify Log', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py b/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py deleted file mode 100644 index 5892e1d6c4..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_log/test_shopify_log.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt -from __future__ import unicode_literals - -import frappe -import unittest - -# test_records = frappe.get_test_records('Shopify Log') - -class TestShopifyLog(unittest.TestCase): - pass diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/__init__.py b/erpnext/erpnext_integrations/doctype/shopify_settings/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js deleted file mode 100644 index 1574795dfa..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -frappe.provide("erpnext_integrations.shopify_settings"); - -frappe.ui.form.on("Shopify Settings", "onload", function(frm){ - frappe.call({ - method:"erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings.get_series", - callback:function(r){ - $.each(r.message, function(key, value){ - set_field_options(key, value); - }); - } - }); - erpnext_integrations.shopify_settings.setup_queries(frm); -}) - -frappe.ui.form.on("Shopify Settings", "app_type", function(frm) { - frm.toggle_reqd("api_key", (frm.doc.app_type == "Private")); - frm.toggle_reqd("password", (frm.doc.app_type == "Private")); -}) - -frappe.ui.form.on("Shopify Settings", "refresh", function(frm){ - if(!frm.doc.__islocal && frm.doc.enable_shopify === 1){ - frm.toggle_reqd("price_list", true); - frm.toggle_reqd("warehouse", true); - frm.toggle_reqd("taxes", true); - frm.toggle_reqd("company", true); - frm.toggle_reqd("cost_center", true); - frm.toggle_reqd("cash_bank_account", true); - frm.toggle_reqd("sales_order_series", true); - frm.toggle_reqd("customer_group", true); - frm.toggle_reqd("shared_secret", true); - - frm.toggle_reqd("sales_invoice_series", frm.doc.sync_sales_invoice); - frm.toggle_reqd("delivery_note_series", frm.doc.sync_delivery_note); - - } -}) - -$.extend(erpnext_integrations.shopify_settings, { - setup_queries: function(frm) { - frm.fields_dict["warehouse"].get_query = function(doc) { - return { - filters:{ - "company": doc.company, - "is_group": "No" - } - } - } - - frm.fields_dict["taxes"].grid.get_field("tax_account").get_query = function(doc){ - return { - "query": "erpnext.controllers.queries.tax_account_query", - "filters": { - "account_type": ["Tax", "Chargeable", "Expense Account"], - "company": doc.company - } - } - } - - frm.fields_dict["cash_bank_account"].get_query = function(doc) { - return { - filters: [ - ["Account", "account_type", "in", ["Cash", "Bank"]], - ["Account", "root_type", "=", "Asset"], - ["Account", "is_group", "=",0], - ["Account", "company", "=", doc.company] - ] - } - } - - frm.fields_dict["cost_center"].get_query = function(doc) { - return { - filters:{ - "company": doc.company, - "is_group": "No" - } - } - } - - frm.fields_dict["price_list"].get_query = function() { - return { - filters:{ - "selling": 1 - } - } - } - } -}) diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json deleted file mode 100644 index 308e7d163f..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json +++ /dev/null @@ -1,353 +0,0 @@ -{ - "actions": [], - "creation": "2015-05-18 05:21:07.270859", - "doctype": "DocType", - "document_type": "System", - "engine": "InnoDB", - "field_order": [ - "status_html", - "enable_shopify", - "app_type", - "column_break_4", - "last_sync_datetime", - "section_break_2", - "shopify_url", - "api_key", - "column_break_3", - "password", - "shared_secret", - "access_token", - "section_break_38", - "webhooks", - "section_break_15", - "default_customer", - "column_break_19", - "customer_group", - "company_dependent_settings", - "company", - "cash_bank_account", - "column_break_20", - "cost_center", - "erp_settings", - "price_list", - "update_price_in_erpnext_price_list", - "column_break_26", - "warehouse", - "section_break_25", - "sales_order_series", - "column_break_27", - "sync_delivery_note", - "delivery_note_series", - "sync_sales_invoice", - "sales_invoice_series", - "section_break_22", - "html_16", - "taxes", - "syncing_details_section", - "sync_missing_orders", - "sync_based_on", - "column_break_41", - "from_date", - "to_date", - "from_order_id", - "to_order_id", - "last_order_id" - ], - "fields": [ - { - "fieldname": "status_html", - "fieldtype": "HTML", - "label": "status html", - "read_only": 1 - }, - { - "default": "0", - "fieldname": "enable_shopify", - "fieldtype": "Check", - "label": "Enable Shopify" - }, - { - "default": "Private", - "fieldname": "app_type", - "fieldtype": "Data", - "in_list_view": 1, - "label": "App Type", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "column_break_4", - "fieldtype": "Column Break" - }, - { - "fieldname": "last_sync_datetime", - "fieldtype": "Datetime", - "label": "Last Sync Datetime", - "read_only": 1 - }, - { - "fieldname": "section_break_2", - "fieldtype": "Section Break" - }, - { - "description": "eg: frappe.myshopify.com", - "fieldname": "shopify_url", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Shop URL", - "reqd": 1 - }, - { - "depends_on": "eval:doc.app_type==\"Private\"", - "fieldname": "api_key", - "fieldtype": "Data", - "label": "API Key" - }, - { - "fieldname": "column_break_3", - "fieldtype": "Column Break" - }, - { - "depends_on": "eval:doc.app_type==\"Private\"", - "fieldname": "password", - "fieldtype": "Password", - "label": "Password" - }, - { - "fieldname": "shared_secret", - "fieldtype": "Data", - "label": "Shared secret" - }, - { - "fieldname": "access_token", - "fieldtype": "Data", - "hidden": 1, - "label": "Access Token", - "read_only": 1 - }, - { - "collapsible": 1, - "fieldname": "section_break_38", - "fieldtype": "Section Break", - "label": "Webhooks Details" - }, - { - "fieldname": "webhooks", - "fieldtype": "Table", - "label": "Webhooks", - "options": "Shopify Webhook Detail", - "read_only": 1 - }, - { - "fieldname": "section_break_15", - "fieldtype": "Section Break", - "label": "Customer Settings" - }, - { - "description": "If Shopify does not have a customer in the order, then while syncing the orders, the system will consider the default customer for the order", - "fieldname": "default_customer", - "fieldtype": "Link", - "label": "Default Customer", - "options": "Customer" - }, - { - "fieldname": "column_break_19", - "fieldtype": "Column Break" - }, - { - "description": "Customer Group will set to selected group while syncing customers from Shopify", - "fieldname": "customer_group", - "fieldtype": "Link", - "label": "Customer Group", - "options": "Customer Group" - }, - { - "fieldname": "company_dependent_settings", - "fieldtype": "Section Break" - }, - { - "fieldname": "company", - "fieldtype": "Link", - "label": "For Company", - "options": "Company" - }, - { - "description": "Cash Account will used for Sales Invoice creation", - "fieldname": "cash_bank_account", - "fieldtype": "Link", - "label": "Cash/Bank Account", - "options": "Account" - }, - { - "fieldname": "column_break_20", - "fieldtype": "Column Break" - }, - { - "fieldname": "cost_center", - "fieldtype": "Link", - "label": "Cost Center", - "options": "Cost Center" - }, - { - "fieldname": "erp_settings", - "fieldtype": "Section Break" - }, - { - "fieldname": "price_list", - "fieldtype": "Link", - "label": "Price List", - "options": "Price List" - }, - { - "default": "0", - "fieldname": "update_price_in_erpnext_price_list", - "fieldtype": "Check", - "label": "Update Price from Shopify To ERPNext Price List" - }, - { - "fieldname": "column_break_26", - "fieldtype": "Column Break" - }, - { - "description": "Default Warehouse to to create Sales Order and Delivery Note", - "fieldname": "warehouse", - "fieldtype": "Link", - "label": "Warehouse", - "options": "Warehouse" - }, - { - "fieldname": "section_break_25", - "fieldtype": "Section Break" - }, - { - "fieldname": "sales_order_series", - "fieldtype": "Select", - "label": "Sales Order Series" - }, - { - "fieldname": "column_break_27", - "fieldtype": "Column Break" - }, - { - "default": "0", - "fieldname": "sync_delivery_note", - "fieldtype": "Check", - "label": "Import Delivery Notes from Shopify on Shipment" - }, - { - "depends_on": "eval:doc.sync_delivery_note==1", - "fieldname": "delivery_note_series", - "fieldtype": "Select", - "label": "Delivery Note Series" - }, - { - "default": "0", - "fieldname": "sync_sales_invoice", - "fieldtype": "Check", - "label": "Import Sales Invoice from Shopify if Payment is marked" - }, - { - "depends_on": "eval:doc.sync_sales_invoice==1", - "fieldname": "sales_invoice_series", - "fieldtype": "Select", - "label": "Sales Invoice Series" - }, - { - "fieldname": "section_break_22", - "fieldtype": "Section Break" - }, - { - "fieldname": "html_16", - "fieldtype": "HTML", - "options": "Map Shopify Taxes / Shipping Charges to ERPNext Account" - }, - { - "fieldname": "taxes", - "fieldtype": "Table", - "label": "Shopify Tax Account", - "options": "Shopify Tax Account" - }, - { - "collapsible": 1, - "fieldname": "syncing_details_section", - "fieldtype": "Section Break", - "label": "Syncing Missing Orders" - }, - { - "depends_on": "eval:doc.sync_missing_orders", - "fieldname": "last_order_id", - "fieldtype": "Data", - "label": "Last Order Id", - "read_only": 1 - }, - { - "fieldname": "column_break_41", - "fieldtype": "Column Break" - }, - { - "default": "0", - "description": "On checking this Order from the ", - "fieldname": "sync_missing_orders", - "fieldtype": "Check", - "label": "Sync Missing Old Shopify Orders" - }, - { - "depends_on": "eval:doc.sync_missing_orders", - "fieldname": "sync_based_on", - "fieldtype": "Select", - "label": "Sync Based On", - "mandatory_depends_on": "eval:doc.sync_missing_orders", - "options": "\nDate\nShopify Order Id" - }, - { - "depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders", - "fieldname": "from_date", - "fieldtype": "Date", - "label": "From Date", - "mandatory_depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders" - }, - { - "depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders", - "fieldname": "to_date", - "fieldtype": "Date", - "label": "To Date", - "mandatory_depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders" - }, - { - "depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders", - "fieldname": "from_order_id", - "fieldtype": "Data", - "label": "From Order Id", - "mandatory_depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders" - }, - { - "depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders", - "fieldname": "to_order_id", - "fieldtype": "Data", - "label": "To Order Id", - "mandatory_depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders" - } - ], - "issingle": 1, - "links": [], - "modified": "2021-03-02 17:35:41.953317", - "modified_by": "Administrator", - "module": "ERPNext Integrations", - "name": "Shopify Settings", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "print": 1, - "read": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py deleted file mode 100644 index 381c5e5dec..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -import json -from frappe import _ -from frappe.model.document import Document -from frappe.utils import get_request_session -from requests.exceptions import HTTPError -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields -from erpnext.erpnext_integrations.utils import get_webhook_address -from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log - -class ShopifySettings(Document): - def validate(self): - if self.enable_shopify == 1: - setup_custom_fields() - self.validate_access_credentials() - self.register_webhooks() - else: - self.unregister_webhooks() - - def validate_access_credentials(self): - if not (self.get_password(raise_exception=False) and self.api_key and self.shopify_url): - frappe.msgprint(_("Missing value for Password, API Key or Shopify URL"), raise_exception=frappe.ValidationError) - - def register_webhooks(self): - webhooks = ["orders/create", "orders/paid", "orders/fulfilled"] - # url = get_shopify_url('admin/webhooks.json', self) - created_webhooks = [d.method for d in self.webhooks] - url = get_shopify_url('admin/api/2021-04/webhooks.json', self) - for method in webhooks: - session = get_request_session() - try: - res = session.post(url, data=json.dumps({ - "webhook": { - "topic": method, - "address": get_webhook_address(connector_name='shopify_connection', method='store_request_data', force_https=True), - "format": "json" - } - }), headers=get_header(self)) - res.raise_for_status() - self.update_webhook_table(method, res.json()) - - except HTTPError as e: - error_message = res.json().get('errors', e) - make_shopify_log(status="Warning", exception=error_message, rollback=True) - - except Exception as e: - make_shopify_log(status="Warning", exception=e, rollback=True) - - def unregister_webhooks(self): - session = get_request_session() - deleted_webhooks = [] - - for d in self.webhooks: - url = get_shopify_url('admin/api/2021-04/webhooks/{0}.json'.format(d.webhook_id), self) - try: - res = session.delete(url, headers=get_header(self)) - res.raise_for_status() - deleted_webhooks.append(d) - - except HTTPError as e: - error_message = res.json().get('errors', e) - make_shopify_log(status="Warning", exception=error_message, rollback=True) - - except Exception as e: - frappe.log_error(message=e, title='Shopify Webhooks Issue') - - for d in deleted_webhooks: - self.remove(d) - - def update_webhook_table(self, method, res): - self.append("webhooks", { - "webhook_id": res['webhook']['id'], - "method": method - }) - -def get_shopify_url(path, settings): - if settings.app_type == "Private": - return 'https://{}:{}@{}/{}'.format(settings.api_key, settings.get_password('password'), settings.shopify_url, path) - else: - return 'https://{}/{}'.format(settings.shopify_url, path) - -def get_header(settings): - header = {'Content-Type': 'application/json'} - - return header - -@frappe.whitelist() -def get_series(): - return { - "sales_order_series" : frappe.get_meta("Sales Order").get_options("naming_series") or "SO-Shopify-", - "sales_invoice_series" : frappe.get_meta("Sales Invoice").get_options("naming_series") or "SI-Shopify-", - "delivery_note_series" : frappe.get_meta("Delivery Note").get_options("naming_series") or "DN-Shopify-" - } - -def setup_custom_fields(): - custom_fields = { - "Customer": [ - dict(fieldname='shopify_customer_id', label='Shopify Customer Id', - fieldtype='Data', insert_after='series', read_only=1, print_hide=1) - ], - "Supplier": [ - dict(fieldname='shopify_supplier_id', label='Shopify Supplier Id', - fieldtype='Data', insert_after='supplier_name', read_only=1, print_hide=1) - ], - "Address": [ - dict(fieldname='shopify_address_id', label='Shopify Address Id', - fieldtype='Data', insert_after='fax', read_only=1, print_hide=1) - ], - "Item": [ - 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='shopify_description', label='Shopify Description', - fieldtype='Text Editor', insert_after='description', read_only=1, print_hide=1) - ], - "Sales Order": [ - dict(fieldname='shopify_order_id', label='Shopify Order Id', - fieldtype='Data', insert_after='title', read_only=1, print_hide=1), - dict(fieldname='shopify_order_number', label='Shopify Order Number', - fieldtype='Data', insert_after='shopify_order_id', read_only=1, print_hide=1) - ], - "Delivery Note":[ - dict(fieldname='shopify_order_id', label='Shopify Order Id', - fieldtype='Data', insert_after='title', read_only=1, print_hide=1), - dict(fieldname='shopify_order_number', label='Shopify Order Number', - fieldtype='Data', insert_after='shopify_order_id', read_only=1, print_hide=1), - dict(fieldname='shopify_fulfillment_id', label='Shopify Fulfillment Id', - fieldtype='Data', insert_after='title', read_only=1, print_hide=1) - ], - "Sales Invoice": [ - dict(fieldname='shopify_order_id', label='Shopify Order Id', - fieldtype='Data', insert_after='title', read_only=1, print_hide=1), - dict(fieldname='shopify_order_number', label='Shopify Order Number', - fieldtype='Data', insert_after='shopify_order_id', read_only=1, print_hide=1) - ] - } - - create_custom_fields(custom_fields) diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py deleted file mode 100644 index 2af57f4c89..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py +++ /dev/null @@ -1,71 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe import _ - -def create_customer(shopify_customer, shopify_settings): - import frappe.utils.nestedset - - cust_name = (shopify_customer.get("first_name") + " " + (shopify_customer.get("last_name") \ - and shopify_customer.get("last_name") or "")) if shopify_customer.get("first_name")\ - else shopify_customer.get("email") - - try: - customer = frappe.get_doc({ - "doctype": "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": frappe.utils.nestedset.get_root_of("Territory"), - "customer_type": _("Individual") - }) - customer.flags.ignore_mandatory = True - customer.insert(ignore_permissions=True) - - if customer: - create_customer_address(customer, shopify_customer) - - frappe.db.commit() - - except Exception as e: - raise e - -def create_customer_address(customer, shopify_customer): - addresses = shopify_customer.get("addresses", []) - - if not addresses and "default_address" in shopify_customer: - addresses.append(shopify_customer["default_address"]) - - for i, address in enumerate(addresses): - address_title, address_type = get_address_title_and_type(customer.customer_name, i) - try : - frappe.get_doc({ - "doctype": "Address", - "shopify_address_id": address.get("id"), - "address_title": address_title, - "address_type": address_type, - "address_line1": address.get("address1") or "Address 1", - "address_line2": address.get("address2"), - "city": address.get("city") or "City", - "state": address.get("province"), - "pincode": address.get("zip"), - "country": address.get("country"), - "phone": address.get("phone"), - "email_id": shopify_customer.get("email"), - "links": [{ - "link_doctype": "Customer", - "link_name": customer.name - }] - }).insert(ignore_mandatory=True) - - except Exception as e: - raise e - -def get_address_title_and_type(customer_name, index): - address_type = _("Billing") - address_title = customer_name - if frappe.db.get_value("Address", "{0}-{1}".format(customer_name.strip(), address_type)): - address_title = "{0}-{1}".format(customer_name.strip(), index) - - return address_title, address_type diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py deleted file mode 100644 index 16efb6caee..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py +++ /dev/null @@ -1,309 +0,0 @@ -from __future__ import unicode_literals -import frappe -from frappe import _ -from erpnext import get_default_company -from frappe.utils import cstr, cint, get_request_session -from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import get_shopify_url, get_header - -shopify_variants_attr_list = ["option1", "option2", "option3"] - -def sync_item_from_shopify(shopify_settings, item): - url = get_shopify_url("admin/api/2021-04/products/{0}.json".format(item.get("product_id")), shopify_settings) - session = get_request_session() - - try: - res = session.get(url, headers=get_header(shopify_settings)) - res.raise_for_status() - - shopify_item = res.json()["product"] - make_item(shopify_settings.warehouse, shopify_item) - except Exception as e: - raise e - -def make_item(warehouse, shopify_item): - add_item_weight(shopify_item) - - if has_variants(shopify_item): - attributes = create_attribute(shopify_item) - create_item(shopify_item, warehouse, 1, attributes) - create_item_variants(shopify_item, warehouse, attributes, shopify_variants_attr_list) - - else: - shopify_item["variant_id"] = shopify_item['variants'][0]["id"] - create_item(shopify_item, warehouse) - -def add_item_weight(shopify_item): - shopify_item["weight"] = shopify_item['variants'][0]["weight"] - shopify_item["weight_unit"] = shopify_item['variants'][0]["weight_unit"] - -def has_variants(shopify_item): - if len(shopify_item.get("options")) >= 1 and "Default Title" not in shopify_item.get("options")[0]["values"]: - return True - return False - -def create_attribute(shopify_item): - attribute = [] - # shopify item dict - for attr in shopify_item.get('options'): - if not frappe.db.get_value("Item Attribute", attr.get("name"), "name"): - frappe.get_doc({ - "doctype": "Item Attribute", - "attribute_name": attr.get("name"), - "item_attribute_values": [ - { - "attribute_value": attr_value, - "abbr":attr_value - } - for attr_value in attr.get("values") - ] - }).insert() - attribute.append({"attribute": attr.get("name")}) - - else: - # check for attribute values - item_attr = frappe.get_doc("Item Attribute", attr.get("name")) - if not item_attr.numeric_values: - set_new_attribute_values(item_attr, attr.get("values")) - item_attr.save() - attribute.append({"attribute": attr.get("name")}) - - else: - attribute.append({ - "attribute": attr.get("name"), - "from_range": item_attr.get("from_range"), - "to_range": item_attr.get("to_range"), - "increment": item_attr.get("increment"), - "numeric_values": item_attr.get("numeric_values") - }) - - return attribute - -def set_new_attribute_values(item_attr, values): - for attr_value in values: - if not any((d.abbr.lower() == attr_value.lower() or d.attribute_value.lower() == attr_value.lower())\ - for d in item_attr.item_attribute_values): - item_attr.append("item_attribute_values", { - "attribute_value": attr_value, - "abbr": attr_value - }) - -def create_item(shopify_item, warehouse, has_variant=0, attributes=None,variant_of=None): - item_dict = { - "doctype": "Item", - "shopify_product_id": shopify_item.get("id"), - "shopify_variant_id": shopify_item.get("variant_id"), - "variant_of": variant_of, - "sync_with_shopify": 1, - "is_stock_item": 1, - "item_code": cstr(shopify_item.get("item_code")) or cstr(shopify_item.get("id")), - "item_name": shopify_item.get("title", '').strip(), - "description": shopify_item.get("body_html") or shopify_item.get("title"), - "shopify_description": shopify_item.get("body_html") or shopify_item.get("title"), - "item_group": get_item_group(shopify_item.get("product_type")), - "has_variants": has_variant, - "attributes":attributes or [], - "stock_uom": shopify_item.get("uom") or _("Nos"), - "stock_keeping_unit": shopify_item.get("sku") or get_sku(shopify_item), - "default_warehouse": warehouse, - "image": get_item_image(shopify_item), - "weight_uom": shopify_item.get("weight_unit"), - "weight_per_unit": shopify_item.get("weight"), - "default_supplier": get_supplier(shopify_item), - "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) - name = '' - - if not item_details: - new_item = frappe.get_doc(item_dict) - new_item.insert(ignore_permissions=True, ignore_mandatory=True) - name = new_item.name - - if not name: - name = item_details.name - - if not has_variant: - add_to_price_list(shopify_item, name) - - frappe.db.commit() - -def create_item_variants(shopify_item, warehouse, attributes, shopify_variants_attr_list): - template_item = frappe.db.get_value("Item", filters={"shopify_product_id": shopify_item.get("id")}, - fieldname=["name", "stock_uom"], as_dict=True) - - if template_item: - for variant in shopify_item.get("variants"): - shopify_item_variant = { - "id" : variant.get("id"), - "item_code": variant.get("id"), - "title": variant.get("title"), - "product_type": shopify_item.get("product_type"), - "sku": variant.get("sku"), - "uom": template_item.stock_uom or _("Nos"), - "item_price": variant.get("price"), - "variant_id": variant.get("id"), - "weight_unit": variant.get("weight_unit"), - "weight": variant.get("weight") - } - - for i, variant_attr in enumerate(shopify_variants_attr_list): - if variant.get(variant_attr): - attributes[i].update({"attribute_value": get_attribute_value(variant.get(variant_attr), attributes[i])}) - create_item(shopify_item_variant, warehouse, 0, attributes, template_item.name) - -def get_attribute_value(variant_attr_val, attribute): - attribute_value = frappe.db.sql("""select attribute_value from `tabItem Attribute Value` - where parent = %s and (abbr = %s or attribute_value = %s)""", (attribute["attribute"], variant_attr_val, - variant_attr_val), as_list=1) - return attribute_value[0][0] if len(attribute_value)>0 else cint(variant_attr_val) - -def get_item_group(product_type=None): - import frappe.utils.nestedset - parent_item_group = frappe.utils.nestedset.get_root_of("Item Group") - - if product_type: - if not frappe.db.get_value("Item Group", product_type, "name"): - item_group = frappe.get_doc({ - "doctype": "Item Group", - "item_group_name": product_type, - "parent_item_group": parent_item_group, - "is_group": "No" - }).insert() - return item_group.name - else: - return product_type - else: - return parent_item_group - - -def get_sku(item): - if item.get("variants"): - return item.get("variants")[0].get("sku") - return "" - -def add_to_price_list(item, name): - shopify_settings = frappe.db.get_value("Shopify Settings", None, ["price_list", "update_price_in_erpnext_price_list"], as_dict=1) - if not shopify_settings.update_price_in_erpnext_price_list: - return - - item_price_name = frappe.db.get_value("Item Price", - {"item_code": name, "price_list": shopify_settings.price_list}, "name") - - if not item_price_name: - frappe.get_doc({ - "doctype": "Item Price", - "price_list": shopify_settings.price_list, - "item_code": name, - "price_list_rate": item.get("item_price") or item.get("variants")[0].get("price") - }).insert() - else: - item_rate = frappe.get_doc("Item Price", item_price_name) - item_rate.price_list_rate = item.get("item_price") or item.get("variants")[0].get("price") - item_rate.save() - -def get_item_image(shopify_item): - if shopify_item.get("image"): - return shopify_item.get("image").get("src") - return None - -def get_supplier(shopify_item): - if shopify_item.get("vendor"): - supplier = frappe.db.sql("""select name from tabSupplier - where name = %s or shopify_supplier_id = %s """, (shopify_item.get("vendor"), - shopify_item.get("vendor").lower()), as_list=1) - - if not supplier: - supplier = frappe.get_doc({ - "doctype": "Supplier", - "supplier_name": shopify_item.get("vendor"), - "shopify_supplier_id": shopify_item.get("vendor").lower(), - "supplier_group": get_supplier_group() - }).insert() - return supplier.name - else: - return shopify_item.get("vendor") - else: - return "" - -def get_supplier_group(): - supplier_group = frappe.db.get_value("Supplier Group", _("Shopify Supplier")) - if not supplier_group: - supplier_group = frappe.get_doc({ - "doctype": "Supplier Group", - "supplier_group_name": _("Shopify Supplier") - }).insert() - return supplier_group.name - return supplier_group - -def get_item_details(shopify_item): - item_details = {} - - item_details = frappe.db.get_value("Item", {"shopify_product_id": shopify_item.get("id")}, - ["name", "stock_uom", "item_name"], as_dict=1) - - if item_details: - return item_details - - else: - item_details = frappe.db.get_value("Item", {"shopify_variant_id": shopify_item.get("id")}, - ["name", "stock_uom", "item_name"], as_dict=1) - return item_details - -def is_item_exists(shopify_item, attributes=None, variant_of=None): - if variant_of: - name = variant_of - else: - name = frappe.db.get_value("Item", {"item_name": shopify_item.get("item_name")}) - - if name: - item = frappe.get_doc("Item", name) - item.flags.ignore_mandatory=True - - if not variant_of and not item.shopify_product_id: - item.shopify_product_id = shopify_item.get("shopify_product_id") - item.shopify_variant_id = shopify_item.get("shopify_variant_id") - item.save() - return True - - if item.shopify_product_id and attributes and attributes[0].get("attribute_value"): - if not variant_of: - variant_of = frappe.db.get_value("Item", - {"shopify_product_id": item.shopify_product_id}, "variant_of") - - # create conditions for all item attributes, - # 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) - - if parent: - variant = frappe.get_doc("Item", parent[0][0]) - variant.flags.ignore_mandatory = True - - variant.shopify_product_id = shopify_item.get("shopify_product_id") - variant.shopify_variant_id = shopify_item.get("shopify_variant_id") - variant.save() - return False - - if item.shopify_product_id and item.shopify_product_id != shopify_item.get("shopify_product_id"): - return False - - return True - - else: - return False diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json b/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json deleted file mode 100644 index db6c3d5aa3..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json +++ /dev/null @@ -1,527 +0,0 @@ -[ - { - "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, - "collapsible_depends_on": null, - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Customer", - "fieldname": "shopify_customer_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "naming_series", - "label": "Shopify Customer Id", - "modified": "2016-01-15 17:25:28.991818", - "name": "Customer-shopify_customer_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Address", - "fieldname": "shopify_address_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "fax", - "label": "Shopify Address Id", - "modified": "2016-01-15 17:50:52.213743", - "name": "Address-shopify_address_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Sales Order", - "fieldname": "shopify_order_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "title", - "label": "Shopify Order Id", - "modified": "2016-01-18 09:55:50.764524", - "name": "Sales Order-shopify_order_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Item", - "fieldname": "shopify_product_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "item_code", - "label": "Shopify Product Id", - "modified": "2016-01-19 15:44:16.132952", - "name": "Item-shopify_product_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Sales Invoice", - "fieldname": "shopify_order_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "naming_series", - "label": "Shopify Order Id", - "modified": "2016-01-19 16:30:12.261797", - "name": "Sales Invoice-shopify_order_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Delivery Note", - "fieldname": "shopify_order_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "title", - "label": "Shopify Order Id", - "modified": "2016-01-19 16:30:31.201198", - "name": "Delivery Note-shopify_order_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Item", - "fieldname": "stock_keeping_unit", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "stock_uom", - "label": "Stock Keeping Unit", - "modified": "2015-11-10 09:29:10.854943", - "name": "Item-stock_keeping_unit", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "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, - "collapsible_depends_on": null, - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Item", - "fieldname": "shopify_variant_id", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "item_code", - "label": "Variant Id", - "modified": "2015-11-09 18:26:50.825858", - "name": "Item-shopify_variant_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "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, - "collapsible_depends_on": null, - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "doctype": "Custom Field", - "dt": "Delivery Note", - "fieldname": "shopify_fulfillment_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "title", - "label": "Shopify Fulfillment Id", - "modified": "2016-01-20 23:50:35.609543", - "name": "Delivery Note-shopify_fulfillment_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Supplier", - "fieldname": "shopify_supplier_id", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "supplier_name", - "label": "Shopify Supplier Id", - "modified": "2016-02-01 15:41:25.818306", - "name": "Supplier-shopify_supplier_id", - "no_copy": 1, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 1, - "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": "Item", - "fieldname": "shopify_description", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "insert_after": "section_break_11", - "label": "shopify_description", - "modified": "2016-06-15 12:15:36.325581", - "name": "Item-shopify_description", - "no_copy": 0, - "options": null, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "unique": 0, - "width": null - } -] \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/shopify_customer.json b/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/shopify_customer.json deleted file mode 100644 index e91ce9abf8..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/shopify_customer.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "customer": { - "id": 2324518599, - "email": "andrew@wyatt.co.in", - "accepts_marketing": false, - "created_at": "2016-01-20T17:18:35+05:30", - "updated_at": "2016-01-20T17:22:23+05:30", - "first_name": "Andrew", - "last_name": "Wyatt", - "orders_count": 0, - "state": "disabled", - "total_spent": "0.00", - "last_order_id": null, - "note": "", - "verified_email": true, - "multipass_identifier": null, - "tax_exempt": false, - "tags": "", - "last_order_name": null, - "default_address": { - "id": 2476804295, - "first_name": "Andrew", - "last_name": "Wyatt", - "company": "Wyatt Inc.", - "address1": "B-11, Betahouse", - "address2": "Street 11, Sector 52", - "city": "Manhattan", - "province": "New York", - "country": "United States", - "zip": "10027", - "phone": "145-112211", - "name": "Andrew Wyatt", - "province_code": "NY", - "country_code": "US", - "country_name": "United States", - "default": true - }, - "addresses": [ - { - "id": 2476804295, - "first_name": "Andrew", - "last_name": "Wyatt", - "company": "Wyatt Inc.", - "address1": "B-11, Betahouse", - "address2": "Street 11, Sector 52", - "city": "Manhattan", - "province": "New York", - "country": "United States", - "zip": "10027", - "phone": "145-112211", - "name": "Andrew Wyatt", - "province_code": "NY", - "country_code": "US", - "country_name": "United States", - "default": true - } - ] - } -} \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/shopify_item.json b/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/shopify_item.json deleted file mode 100644 index 296dede786..0000000000 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_data/shopify_item.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "product": { - "id": 4059739520, - "title": "Shopify Test Item", - "body_html": "