refactor!: remove woocommerce

This commit is contained in:
s-aga-r 2023-09-09 19:02:33 +05:30
parent e6c302a397
commit 328ba4b656
7 changed files with 0 additions and 582 deletions

View File

@ -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,
},
)

View File

@ -1,8 +0,0 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
class TestWoocommerceSettings(unittest.TestCase):
pass

View File

@ -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);
});
}
});
});

View File

@ -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
}

View File

@ -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-",
}