refactor!: remove `woocommerce`
diff --git a/erpnext/erpnext_integrations/connectors/__init__.py b/erpnext/erpnext_integrations/connectors/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/erpnext_integrations/connectors/__init__.py
+++ /dev/null
diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
deleted file mode 100644
index 2b2da7b..0000000
--- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
+++ /dev/null
@@ -1,256 +0,0 @@
-import base64
-import hashlib
-import hmac
-import json
-
-import frappe
-from frappe import _
-from frappe.utils import cstr
-
-
-def verify_request():
- woocommerce_settings = frappe.get_doc("Woocommerce Settings")
- sig = base64.b64encode(
- hmac.new(
- woocommerce_settings.secret.encode("utf8"), frappe.request.data, hashlib.sha256
- ).digest()
- )
-
- if (
- frappe.request.data
- and not sig == frappe.get_request_header("X-Wc-Webhook-Signature", "").encode()
- ):
- frappe.throw(_("Unverified Webhook Data"))
- frappe.set_user(woocommerce_settings.creation_user)
-
-
-@frappe.whitelist(allow_guest=True)
-def order(*args, **kwargs):
- try:
- _order(*args, **kwargs)
- except Exception:
- error_message = (
- frappe.get_traceback() + "\n\n Request Data: \n" + json.loads(frappe.request.data).__str__()
- )
- frappe.log_error("WooCommerce Error", error_message)
- raise
-
-
-def _order(*args, **kwargs):
- woocommerce_settings = frappe.get_doc("Woocommerce Settings")
- if frappe.flags.woocomm_test_order_data:
- order = frappe.flags.woocomm_test_order_data
- event = "created"
- # Ignore the test ping issued during WooCommerce webhook configuration
- # Ref: https://github.com/woocommerce/woocommerce/issues/15642
- if frappe.request.data.decode("utf-8").startswith("webhook_id="):
- return "success"
- elif frappe.request and frappe.request.data:
- verify_request()
- try:
- order = json.loads(frappe.request.data)
- except ValueError:
- # woocommerce returns 'webhook_id=value' for the first request which is not JSON
- order = frappe.request.data
- event = frappe.get_request_header("X-Wc-Webhook-Event")
-
- else:
- return "success"
-
- if event == "created":
- sys_lang = frappe.get_single("System Settings").language or "en"
- raw_billing_data = order.get("billing")
- raw_shipping_data = order.get("shipping")
- customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name")
- link_customer_and_address(raw_billing_data, raw_shipping_data, customer_name)
- link_items(order.get("line_items"), woocommerce_settings, sys_lang)
- create_sales_order(order, woocommerce_settings, customer_name, sys_lang)
-
-
-def link_customer_and_address(raw_billing_data, raw_shipping_data, customer_name):
- customer_woo_com_email = raw_billing_data.get("email")
- customer_exists = frappe.get_value("Customer", {"woocommerce_email": customer_woo_com_email})
- if not customer_exists:
- # Create Customer
- customer = frappe.new_doc("Customer")
- else:
- # Edit Customer
- customer = frappe.get_doc("Customer", {"woocommerce_email": customer_woo_com_email})
- old_name = customer.customer_name
-
- customer.customer_name = customer_name
- customer.woocommerce_email = customer_woo_com_email
- customer.flags.ignore_mandatory = True
- customer.save()
-
- if customer_exists:
- # Fixes https://github.com/frappe/erpnext/issues/33708
- if old_name != customer_name:
- frappe.rename_doc("Customer", old_name, customer_name)
- for address_type in (
- "Billing",
- "Shipping",
- ):
- try:
- address = frappe.get_doc(
- "Address", {"woocommerce_email": customer_woo_com_email, "address_type": address_type}
- )
- rename_address(address, customer)
- except (
- frappe.DoesNotExistError,
- frappe.DuplicateEntryError,
- frappe.ValidationError,
- ):
- pass
- else:
- create_address(raw_billing_data, customer, "Billing")
- create_address(raw_shipping_data, customer, "Shipping")
- create_contact(raw_billing_data, customer)
-
-
-def create_contact(data, customer):
- email = data.get("email", None)
- phone = data.get("phone", None)
-
- if not email and not phone:
- return
-
- contact = frappe.new_doc("Contact")
- contact.first_name = data.get("first_name")
- contact.last_name = data.get("last_name")
- contact.is_primary_contact = 1
- contact.is_billing_contact = 1
-
- if phone:
- contact.add_phone(phone, is_primary_mobile_no=1, is_primary_phone=1)
-
- if email:
- contact.add_email(email, is_primary=1)
-
- contact.append("links", {"link_doctype": "Customer", "link_name": customer.name})
-
- contact.flags.ignore_mandatory = True
- contact.save()
-
-
-def create_address(raw_data, customer, address_type):
- address = frappe.new_doc("Address")
-
- address.address_line1 = raw_data.get("address_1", "Not Provided")
- address.address_line2 = raw_data.get("address_2", "Not Provided")
- address.city = raw_data.get("city", "Not Provided")
- address.woocommerce_email = customer.woocommerce_email
- address.address_type = address_type
- address.country = frappe.get_value("Country", {"code": raw_data.get("country", "IN").lower()})
- address.state = raw_data.get("state")
- address.pincode = raw_data.get("postcode")
- address.phone = raw_data.get("phone")
- address.email_id = customer.woocommerce_email
- address.append("links", {"link_doctype": "Customer", "link_name": customer.name})
-
- address.flags.ignore_mandatory = True
- address.save()
-
-
-def rename_address(address, customer):
- old_address_title = address.name
- new_address_title = customer.name + "-" + address.address_type
- address.address_title = customer.customer_name
- address.save()
-
- frappe.rename_doc("Address", old_address_title, new_address_title)
-
-
-def link_items(items_list, woocommerce_settings, sys_lang):
- for item_data in items_list:
- item_woo_com_id = cstr(item_data.get("product_id"))
-
- if not frappe.db.get_value("Item", {"woocommerce_id": item_woo_com_id}, "name"):
- # Create Item
- item = frappe.new_doc("Item")
- item.item_code = _("woocommerce - {0}", sys_lang).format(item_woo_com_id)
- item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang)
- item.item_group = _("WooCommerce Products", sys_lang)
-
- item.item_name = item_data.get("name")
- item.woocommerce_id = item_woo_com_id
- item.flags.ignore_mandatory = True
- item.save()
-
-
-def create_sales_order(order, woocommerce_settings, customer_name, sys_lang):
- new_sales_order = frappe.new_doc("Sales Order")
- new_sales_order.customer = customer_name
-
- new_sales_order.po_no = new_sales_order.woocommerce_id = order.get("id")
- new_sales_order.naming_series = woocommerce_settings.sales_order_series or "SO-WOO-"
-
- created_date = order.get("date_created").split("T")
- new_sales_order.transaction_date = created_date[0]
- delivery_after = woocommerce_settings.delivery_after_days or 7
- new_sales_order.delivery_date = frappe.utils.add_days(created_date[0], delivery_after)
-
- new_sales_order.company = woocommerce_settings.company
-
- set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang)
- new_sales_order.flags.ignore_mandatory = True
- new_sales_order.insert()
- new_sales_order.submit()
-
- frappe.db.commit()
-
-
-def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang):
- company_abbr = frappe.db.get_value("Company", woocommerce_settings.company, "abbr")
-
- default_warehouse = _("Stores - {0}", sys_lang).format(company_abbr)
- if not frappe.db.exists("Warehouse", default_warehouse) and not woocommerce_settings.warehouse:
- frappe.throw(_("Please set Warehouse in Woocommerce Settings"))
-
- for item in order.get("line_items"):
- woocomm_item_id = item.get("product_id")
- found_item = frappe.get_doc("Item", {"woocommerce_id": cstr(woocomm_item_id)})
-
- ordered_items_tax = item.get("total_tax")
-
- new_sales_order.append(
- "items",
- {
- "item_code": found_item.name,
- "item_name": found_item.item_name,
- "description": found_item.item_name,
- "delivery_date": new_sales_order.delivery_date,
- "uom": woocommerce_settings.uom or _("Nos", sys_lang),
- "qty": item.get("quantity"),
- "rate": item.get("price"),
- "warehouse": woocommerce_settings.warehouse or default_warehouse,
- },
- )
-
- add_tax_details(
- new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account
- )
-
- # shipping_details = order.get("shipping_lines") # used for detailed order
-
- add_tax_details(
- new_sales_order, order.get("shipping_tax"), "Shipping Tax", woocommerce_settings.f_n_f_account
- )
- add_tax_details(
- new_sales_order,
- order.get("shipping_total"),
- "Shipping Total",
- woocommerce_settings.f_n_f_account,
- )
-
-
-def add_tax_details(sales_order, price, desc, tax_account_head):
- sales_order.append(
- "taxes",
- {
- "charge_type": "Actual",
- "account_head": tax_account_head,
- "tax_amount": price,
- "description": desc,
- },
- )
diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/__init__.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/__init__.py
+++ /dev/null
diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py
deleted file mode 100644
index 9945823..0000000
--- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestWoocommerceSettings(unittest.TestCase):
- pass
diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.js b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.js
deleted file mode 100644
index d7a3d36..0000000
--- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Woocommerce Settings', {
- refresh (frm) {
- frm.trigger("add_button_generate_secret");
- frm.trigger("check_enabled");
- frm.set_query("tax_account", ()=>{
- return {
- "filters": {
- "company": frappe.defaults.get_default("company"),
- "is_group": 0
- }
- };
- });
- },
-
- enable_sync (frm) {
- frm.trigger("check_enabled");
- },
-
- add_button_generate_secret(frm) {
- frm.add_custom_button(__('Generate Secret'), () => {
- frappe.confirm(
- __("Apps using current key won't be able to access, are you sure?"),
- () => {
- frappe.call({
- type:"POST",
- method:"erpnext.erpnext_integrations.doctype.woocommerce_settings.woocommerce_settings.generate_secret",
- }).done(() => {
- frm.reload_doc();
- }).fail(() => {
- frappe.msgprint(__("Could not generate Secret"));
- });
- }
- );
- });
- },
-
- check_enabled (frm) {
- frm.set_df_property("woocommerce_server_url", "reqd", frm.doc.enable_sync);
- frm.set_df_property("api_consumer_key", "reqd", frm.doc.enable_sync);
- frm.set_df_property("api_consumer_secret", "reqd", frm.doc.enable_sync);
- }
-});
-
-frappe.ui.form.on("Woocommerce Settings", "onload", function () {
- frappe.call({
- method: "erpnext.erpnext_integrations.doctype.woocommerce_settings.woocommerce_settings.get_series",
- callback: function (r) {
- $.each(r.message, function (key, value) {
- set_field_options(key, value);
- });
- }
- });
-});
diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.json b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.json
deleted file mode 100644
index 956ae09..0000000
--- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
- "creation": "2018-02-12 15:10:05.495713",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "enable_sync",
- "sb_00",
- "woocommerce_server_url",
- "secret",
- "cb_00",
- "api_consumer_key",
- "api_consumer_secret",
- "sb_accounting_details",
- "tax_account",
- "column_break_10",
- "f_n_f_account",
- "defaults_section",
- "creation_user",
- "warehouse",
- "sales_order_series",
- "column_break_14",
- "company",
- "delivery_after_days",
- "uom",
- "endpoints",
- "endpoint"
- ],
- "fields": [
- {
- "default": "0",
- "fieldname": "enable_sync",
- "fieldtype": "Check",
- "label": "Enable Sync"
- },
- {
- "fieldname": "sb_00",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "woocommerce_server_url",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Woocommerce Server URL"
- },
- {
- "fieldname": "secret",
- "fieldtype": "Code",
- "label": "Secret",
- "read_only": 1
- },
- {
- "fieldname": "cb_00",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "api_consumer_key",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "API consumer key"
- },
- {
- "fieldname": "api_consumer_secret",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "API consumer secret"
- },
- {
- "fieldname": "sb_accounting_details",
- "fieldtype": "Section Break",
- "label": "Accounting Details"
- },
- {
- "fieldname": "tax_account",
- "fieldtype": "Link",
- "label": "Tax Account",
- "options": "Account",
- "reqd": 1
- },
- {
- "fieldname": "column_break_10",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "f_n_f_account",
- "fieldtype": "Link",
- "label": "Freight and Forwarding Account",
- "options": "Account",
- "reqd": 1
- },
- {
- "fieldname": "defaults_section",
- "fieldtype": "Section Break",
- "label": "Defaults"
- },
- {
- "description": "The user that will be used to create Customers, Items and Sales Orders. This user should have the relevant permissions.",
- "fieldname": "creation_user",
- "fieldtype": "Link",
- "label": "Creation User",
- "options": "User",
- "reqd": 1
- },
- {
- "description": "This warehouse will be used to create Sales Orders. The fallback warehouse is \"Stores\".",
- "fieldname": "warehouse",
- "fieldtype": "Link",
- "label": "Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "column_break_14",
- "fieldtype": "Column Break"
- },
- {
- "description": "The fallback series is \"SO-WOO-\".",
- "fieldname": "sales_order_series",
- "fieldtype": "Select",
- "label": "Sales Order Series"
- },
- {
- "description": "This is the default UOM used for items and Sales orders. The fallback UOM is \"Nos\".",
- "fieldname": "uom",
- "fieldtype": "Link",
- "label": "UOM",
- "options": "UOM"
- },
- {
- "fieldname": "endpoints",
- "fieldtype": "Section Break",
- "label": "Endpoints"
- },
- {
- "fieldname": "endpoint",
- "fieldtype": "Code",
- "label": "Endpoint",
- "read_only": 1
- },
- {
- "description": "This company will be used to create Sales Orders.",
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "reqd": 1
- },
- {
- "description": "This is the default offset (days) for the Delivery Date in Sales Orders. The fallback offset is 7 days from the order placement date.",
- "fieldname": "delivery_after_days",
- "fieldtype": "Int",
- "label": "Delivery After (Days)"
- }
- ],
- "issingle": 1,
- "modified": "2019-11-04 00:45:21.232096",
- "modified_by": "Administrator",
- "module": "ERPNext Integrations",
- "name": "Woocommerce Settings",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py
deleted file mode 100644
index 4aa98aa..0000000
--- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from urllib.parse import urlparse
-
-import frappe
-from frappe import _
-from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
-from frappe.model.document import Document
-from frappe.utils.nestedset import get_root_of
-
-
-class WoocommerceSettings(Document):
- def validate(self):
- self.validate_settings()
- self.create_delete_custom_fields()
- self.create_webhook_url()
-
- def create_delete_custom_fields(self):
- if self.enable_sync:
- create_custom_fields(
- {
- ("Customer", "Sales Order", "Item", "Address"): dict(
- fieldname="woocommerce_id",
- label="Woocommerce ID",
- fieldtype="Data",
- read_only=1,
- print_hide=1,
- ),
- ("Customer", "Address"): dict(
- fieldname="woocommerce_email",
- label="Woocommerce Email",
- fieldtype="Data",
- read_only=1,
- print_hide=1,
- ),
- }
- )
-
- if not frappe.get_value("Item Group", {"name": _("WooCommerce Products")}):
- item_group = frappe.new_doc("Item Group")
- item_group.item_group_name = _("WooCommerce Products")
- item_group.parent_item_group = get_root_of("Item Group")
- item_group.insert()
-
- def validate_settings(self):
- if self.enable_sync:
- if not self.secret:
- self.set("secret", frappe.generate_hash())
-
- if not self.woocommerce_server_url:
- frappe.throw(_("Please enter Woocommerce Server URL"))
-
- if not self.api_consumer_key:
- frappe.throw(_("Please enter API Consumer Key"))
-
- if not self.api_consumer_secret:
- frappe.throw(_("Please enter API Consumer Secret"))
-
- def create_webhook_url(self):
- endpoint = "/api/method/erpnext.erpnext_integrations.connectors.woocommerce_connection.order"
-
- try:
- url = frappe.request.url
- except RuntimeError:
- # for CI Test to work
- url = "http://localhost:8000"
-
- server_url = "{uri.scheme}://{uri.netloc}".format(uri=urlparse(url))
-
- delivery_url = server_url + endpoint
- self.endpoint = delivery_url
-
-
-@frappe.whitelist()
-def generate_secret():
- woocommerce_settings = frappe.get_doc("Woocommerce Settings")
- woocommerce_settings.secret = frappe.generate_hash()
- woocommerce_settings.save()
-
-
-@frappe.whitelist()
-def get_series():
- return {
- "sales_order_series": frappe.get_meta("Sales Order").get_options("naming_series") or "SO-WOO-",
- }