brotherton-erpnext/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
Nabin Hait ad16e61bc2
fix: Valid warehouse in woocommerce syncing and other small fixes (#21407)
* fix: Valid warehouse in woocommerce syncing

* fix: dmall fixes in gross & net profit report

* fix: company is required for getting party details

* fix: None issue while getting raw material rate based on last purchase rate
2020-04-25 14:52:05 +05:30

182 lines
6.7 KiB
Python

from __future__ import unicode_literals
import frappe, base64, hashlib, hmac, json
from frappe import _
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 \
frappe.get_request_header("X-Wc-Webhook-Signature") and \
not sig == bytes(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(error_message, "WooCommerce Error")
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"
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")
customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name")
link_customer_and_address(raw_billing_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, 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:
frappe.rename_doc("Customer", old_name, customer_name)
address = frappe.get_doc("Address", {"woocommerce_email": customer_woo_com_email})
else:
address = frappe.new_doc("Address")
address.address_line1 = raw_billing_data.get("address_1", "Not Provided")
address.address_line2 = raw_billing_data.get("address_2", "Not Provided")
address.city = raw_billing_data.get("city", "Not Provided")
address.woocommerce_email = customer_woo_com_email
address.address_type = "Billing"
address.country = frappe.get_value("Country", {"code": raw_billing_data.get("country", "IN").lower()})
address.state = raw_billing_data.get("state")
address.pincode = raw_billing_data.get("postcode")
address.phone = raw_billing_data.get("phone")
address.email_id = customer_woo_com_email
address.append("links", {
"link_doctype": "Customer",
"link_name": customer.customer_name
})
address.flags.ignore_mandatory = True
address = address.save()
if customer_exists:
old_address_title = address.name
new_address_title = customer.customer_name + "-billing"
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 = item_data.get("product_id")
if frappe.get_value("Item", {"woocommerce_id": item_woo_com_id}):
#Edit Item
item = frappe.get_doc("Item", {"woocommerce_id": item_woo_com_id})
else:
#Create Item
item = frappe.new_doc("Item")
item.item_name = item_data.get("name")
item.item_code = _("woocommerce - {0}", sys_lang).format(item_data.get("product_id"))
item.woocommerce_id = item_data.get("product_id")
item.item_group = _("WooCommerce Products", sys_lang)
item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang)
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):
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": woocomm_item_id})
ordered_items_tax = item.get("total_tax")
new_sales_order.append("items",{
"item_code": found_item.item_code,
"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
})