Merge branch 'develop' of https://github.com/frappe/erpnext into sa-vat-report
This commit is contained in:
commit
346bde875c
@ -1545,6 +1545,7 @@
|
|||||||
"fieldname": "consolidated_invoice",
|
"fieldname": "consolidated_invoice",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Consolidated Sales Invoice",
|
"label": "Consolidated Sales Invoice",
|
||||||
|
"no_copy": 1,
|
||||||
"options": "Sales Invoice",
|
"options": "Sales Invoice",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
@ -1552,7 +1553,7 @@
|
|||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-02-01 15:03:33.800707",
|
"modified": "2021-07-29 13:37:20.636171",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Invoice",
|
"name": "POS Invoice",
|
||||||
|
@ -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)
|
|
||||||
|
|
@ -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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
|
|
||||||
}
|
|
@ -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})
|
|
@ -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"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()
|
|
||||||
]);
|
|
||||||
|
|
||||||
});
|
|
@ -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
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@ -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
|
|
||||||
}
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
||||||
}
|
|
||||||
]
|
|
@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
{
|
|
||||||
"product": {
|
|
||||||
"id": 4059739520,
|
|
||||||
"title": "Shopify Test Item",
|
|
||||||
"body_html": "<div>Hold back Spin Medallion-Set of 2</div>\n<div></div>\n<div>Finish: Plated/ Powder Coated</div>\n<div>Material: Iron</div>\n<div>Color Finish: Satin Silver, Brown Oil Rubbed, Roman Bronze</div>\n<div>Qty: 1 Set</div>",
|
|
||||||
"vendor": "Boa casa",
|
|
||||||
"product_type": "Curtain Accessories",
|
|
||||||
"created_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"handle": "1001624-01",
|
|
||||||
"updated_at": "2016-01-20T17:26:44+05:30",
|
|
||||||
"published_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"template_suffix": null,
|
|
||||||
"published_scope": "global",
|
|
||||||
"tags": "Category_Curtain Accessories, Type_Holdback",
|
|
||||||
"variants": [{
|
|
||||||
"id": 13917612359,
|
|
||||||
"product_id": 4059739520,
|
|
||||||
"title": "Test BALCK Item",
|
|
||||||
"price": "499.00",
|
|
||||||
"sku": "",
|
|
||||||
"position": 1,
|
|
||||||
"grams": 0,
|
|
||||||
"inventory_policy": "continue",
|
|
||||||
"compare_at_price": null,
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"inventory_management": "shopify",
|
|
||||||
"option1": "BLACK",
|
|
||||||
"option2": null,
|
|
||||||
"option3": null,
|
|
||||||
"created_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"updated_at": "2016-01-20T17:26:44+05:30",
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"barcode": "",
|
|
||||||
"inventory_quantity": -1,
|
|
||||||
"old_inventory_quantity": -1,
|
|
||||||
"image_id": 8539321735,
|
|
||||||
"weight": 0,
|
|
||||||
"weight_unit": "kg"
|
|
||||||
}, {
|
|
||||||
"id": 13917612423,
|
|
||||||
"product_id": 4059739520,
|
|
||||||
"title": "Test BLUE Item",
|
|
||||||
"price": "499.00",
|
|
||||||
"sku": "",
|
|
||||||
"position": 2,
|
|
||||||
"grams": 0,
|
|
||||||
"inventory_policy": "continue",
|
|
||||||
"compare_at_price": null,
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"inventory_management": "shopify",
|
|
||||||
"option1": "BLUE",
|
|
||||||
"option2": null,
|
|
||||||
"option3": null,
|
|
||||||
"created_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"updated_at": "2016-01-20T17:26:44+05:30",
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"barcode": "",
|
|
||||||
"inventory_quantity": -1,
|
|
||||||
"old_inventory_quantity": -1,
|
|
||||||
"image_id": null,
|
|
||||||
"weight": 0,
|
|
||||||
"weight_unit": "kg"
|
|
||||||
}, {
|
|
||||||
"id": 13917612487,
|
|
||||||
"product_id": 4059739520,
|
|
||||||
"title": "Test White Item",
|
|
||||||
"price": "499.00",
|
|
||||||
"sku": "",
|
|
||||||
"position": 3,
|
|
||||||
"grams": 0,
|
|
||||||
"inventory_policy": "continue",
|
|
||||||
"compare_at_price": null,
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"inventory_management": "shopify",
|
|
||||||
"option1": "White",
|
|
||||||
"option2": null,
|
|
||||||
"option3": null,
|
|
||||||
"created_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"updated_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"barcode": "",
|
|
||||||
"inventory_quantity": 0,
|
|
||||||
"old_inventory_quantity": 0,
|
|
||||||
"image_id": null,
|
|
||||||
"weight": 0,
|
|
||||||
"weight_unit": "kg"
|
|
||||||
}],
|
|
||||||
"options": [{
|
|
||||||
"id": 4985027399,
|
|
||||||
"product_id": 4059739520,
|
|
||||||
"name": "Colour",
|
|
||||||
"position": 1,
|
|
||||||
"values": [
|
|
||||||
"BLACK",
|
|
||||||
"BLUE",
|
|
||||||
"White"
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
"images": [{
|
|
||||||
"id": 8539321735,
|
|
||||||
"product_id": 4059739520,
|
|
||||||
"position": 1,
|
|
||||||
"created_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"updated_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"src": "https://cdn.shopify.com/s/files/1/1123/0654/products/2015-12-17_6.png?v=1453117597",
|
|
||||||
"variant_ids": [
|
|
||||||
13917612359
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
"image": {
|
|
||||||
"id": 8539321735,
|
|
||||||
"product_id": 4059739520,
|
|
||||||
"position": 1,
|
|
||||||
"created_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"updated_at": "2016-01-18T17:16:37+05:30",
|
|
||||||
"src": "https://cdn.shopify.com/s/files/1/1123/0654/products/2015-12-17_6.png?v=1453117597",
|
|
||||||
"variant_ids": [
|
|
||||||
13917612359
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,270 +0,0 @@
|
|||||||
{
|
|
||||||
"order": {
|
|
||||||
"id": 2414345735,
|
|
||||||
"email": "andrew@wyatt.co.in",
|
|
||||||
"closed_at": null,
|
|
||||||
"created_at": "2016-01-20T17:26:39+05:30",
|
|
||||||
"updated_at": "2016-01-20T17:27:15+05:30",
|
|
||||||
"number": 5,
|
|
||||||
"note": "",
|
|
||||||
"token": "660fed25987517b733644a8c9ec7c8e0",
|
|
||||||
"gateway": "manual",
|
|
||||||
"test": false,
|
|
||||||
"total_price": "1018.00",
|
|
||||||
"subtotal_price": "998.00",
|
|
||||||
"total_weight": 0,
|
|
||||||
"total_tax": "0.00",
|
|
||||||
"taxes_included": false,
|
|
||||||
"currency": "INR",
|
|
||||||
"financial_status": "paid",
|
|
||||||
"confirmed": true,
|
|
||||||
"total_discounts": "0.00",
|
|
||||||
"total_line_items_price": "998.00",
|
|
||||||
"cart_token": null,
|
|
||||||
"buyer_accepts_marketing": false,
|
|
||||||
"name": "#1005",
|
|
||||||
"referring_site": null,
|
|
||||||
"landing_site": null,
|
|
||||||
"cancelled_at": null,
|
|
||||||
"cancel_reason": null,
|
|
||||||
"total_price_usd": "15.02",
|
|
||||||
"checkout_token": null,
|
|
||||||
"reference": null,
|
|
||||||
"user_id": 55391175,
|
|
||||||
"location_id": null,
|
|
||||||
"source_identifier": null,
|
|
||||||
"source_url": null,
|
|
||||||
"processed_at": "2016-01-20T17:26:39+05:30",
|
|
||||||
"device_id": null,
|
|
||||||
"browser_ip": null,
|
|
||||||
"landing_site_ref": null,
|
|
||||||
"order_number": 1005,
|
|
||||||
"discount_codes": [],
|
|
||||||
"note_attributes": [],
|
|
||||||
"payment_gateway_names": [
|
|
||||||
"manual"
|
|
||||||
],
|
|
||||||
"processing_method": "manual",
|
|
||||||
"checkout_id": null,
|
|
||||||
"source_name": "shopify_draft_order",
|
|
||||||
"fulfillment_status": "fulfilled",
|
|
||||||
"tax_lines": [],
|
|
||||||
"tags": "",
|
|
||||||
"contact_email": "andrew@wyatt.co.in",
|
|
||||||
"line_items": [
|
|
||||||
{
|
|
||||||
"id": 4125768135,
|
|
||||||
"variant_id": 13917612359,
|
|
||||||
"title": "Shopify Test Item",
|
|
||||||
"quantity": 1,
|
|
||||||
"price": "499.00",
|
|
||||||
"grams": 0,
|
|
||||||
"sku": "",
|
|
||||||
"variant_title": "Roman BALCK 1",
|
|
||||||
"vendor": "Boa casa",
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"product_id": 4059739527,
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"gift_card": false,
|
|
||||||
"name": "Roman BALCK 1",
|
|
||||||
"variant_inventory_management": "shopify",
|
|
||||||
"properties": [],
|
|
||||||
"product_exists": true,
|
|
||||||
"fulfillable_quantity": 0,
|
|
||||||
"total_discount": "0.00",
|
|
||||||
"fulfillment_status": "fulfilled",
|
|
||||||
"tax_lines": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4125768199,
|
|
||||||
"variant_id": 13917612423,
|
|
||||||
"title": "Shopify Test Item",
|
|
||||||
"quantity": 1,
|
|
||||||
"price": "499.00",
|
|
||||||
"grams": 0,
|
|
||||||
"sku": "",
|
|
||||||
"variant_title": "Satin BLUE 1",
|
|
||||||
"vendor": "Boa casa",
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"product_id": 4059739527,
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"gift_card": false,
|
|
||||||
"name": "Satin BLUE 1",
|
|
||||||
"variant_inventory_management": "shopify",
|
|
||||||
"properties": [],
|
|
||||||
"product_exists": true,
|
|
||||||
"fulfillable_quantity": 0,
|
|
||||||
"total_discount": "0.00",
|
|
||||||
"fulfillment_status": "fulfilled",
|
|
||||||
"tax_lines": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"shipping_lines": [
|
|
||||||
{
|
|
||||||
"id": 2108906247,
|
|
||||||
"title": "International Shipping",
|
|
||||||
"price": "20.00",
|
|
||||||
"code": "International Shipping",
|
|
||||||
"source": "shopify",
|
|
||||||
"phone": null,
|
|
||||||
"tax_lines": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"billing_address": {
|
|
||||||
"first_name": "Andrew",
|
|
||||||
"address1": "B-11, Betahouse",
|
|
||||||
"phone": "145-112211",
|
|
||||||
"city": "Manhattan",
|
|
||||||
"zip": "10027",
|
|
||||||
"province": "New York",
|
|
||||||
"country": "United States",
|
|
||||||
"last_name": "Wyatt",
|
|
||||||
"address2": "Street 11, Sector 52",
|
|
||||||
"company": "Wyatt Inc.",
|
|
||||||
"latitude": 40.8138912,
|
|
||||||
"longitude": -73.96243270000001,
|
|
||||||
"name": "Andrew Wyatt",
|
|
||||||
"country_code": "US",
|
|
||||||
"province_code": "NY"
|
|
||||||
},
|
|
||||||
"shipping_address": {
|
|
||||||
"first_name": "Andrew",
|
|
||||||
"address1": "B-11, Betahouse",
|
|
||||||
"phone": "145-112211",
|
|
||||||
"city": "Manhattan",
|
|
||||||
"zip": "10027",
|
|
||||||
"province": "New York",
|
|
||||||
"country": "United States",
|
|
||||||
"last_name": "Wyatt",
|
|
||||||
"address2": "Street 11, Sector 52",
|
|
||||||
"company": "Wyatt Inc.",
|
|
||||||
"latitude": 40.8138912,
|
|
||||||
"longitude": -73.96243270000001,
|
|
||||||
"name": "Andrew Wyatt",
|
|
||||||
"country_code": "US",
|
|
||||||
"province_code": "NY"
|
|
||||||
},
|
|
||||||
"fulfillments": [
|
|
||||||
{
|
|
||||||
"id": 1849629255,
|
|
||||||
"order_id": 2414345735,
|
|
||||||
"status": "success",
|
|
||||||
"created_at": "2016-01-20T17:27:15+05:30",
|
|
||||||
"service": "manual",
|
|
||||||
"updated_at": "2016-01-20T17:27:15+05:30",
|
|
||||||
"tracking_company": null,
|
|
||||||
"tracking_number": null,
|
|
||||||
"tracking_numbers": [],
|
|
||||||
"tracking_url": null,
|
|
||||||
"tracking_urls": [],
|
|
||||||
"receipt": {},
|
|
||||||
"line_items": [
|
|
||||||
{
|
|
||||||
"id": 4125768199,
|
|
||||||
"variant_id": 13917612423,
|
|
||||||
"title": "1001624/01",
|
|
||||||
"quantity": 1,
|
|
||||||
"price": "499.00",
|
|
||||||
"grams": 0,
|
|
||||||
"sku": "",
|
|
||||||
"variant_title": "Satin Silver",
|
|
||||||
"vendor": "Boa casa",
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"product_id": 4059739527,
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"gift_card": false,
|
|
||||||
"name": "1001624/01 - Satin Silver",
|
|
||||||
"variant_inventory_management": "shopify",
|
|
||||||
"properties": [],
|
|
||||||
"product_exists": true,
|
|
||||||
"fulfillable_quantity": 0,
|
|
||||||
"total_discount": "0.00",
|
|
||||||
"fulfillment_status": "fulfilled",
|
|
||||||
"tax_lines": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1849628167,
|
|
||||||
"order_id": 2414345735,
|
|
||||||
"status": "success",
|
|
||||||
"created_at": "2016-01-20T17:26:58+05:30",
|
|
||||||
"service": "manual",
|
|
||||||
"updated_at": "2016-01-20T17:26:58+05:30",
|
|
||||||
"tracking_company": null,
|
|
||||||
"tracking_number": null,
|
|
||||||
"tracking_numbers": [],
|
|
||||||
"tracking_url": null,
|
|
||||||
"tracking_urls": [],
|
|
||||||
"receipt": {},
|
|
||||||
"line_items": [
|
|
||||||
{
|
|
||||||
"id": 4125768135,
|
|
||||||
"variant_id": 13917612359,
|
|
||||||
"title": "1001624/01",
|
|
||||||
"quantity": 1,
|
|
||||||
"price": "499.00",
|
|
||||||
"grams": 0,
|
|
||||||
"sku": "",
|
|
||||||
"variant_title": "Roman Bronze",
|
|
||||||
"vendor": "Boa casa",
|
|
||||||
"fulfillment_service": "manual",
|
|
||||||
"product_id": 4059739527,
|
|
||||||
"requires_shipping": true,
|
|
||||||
"taxable": true,
|
|
||||||
"gift_card": false,
|
|
||||||
"name": "1001624/01 - Roman Bronze",
|
|
||||||
"variant_inventory_management": "shopify",
|
|
||||||
"properties": [],
|
|
||||||
"product_exists": true,
|
|
||||||
"fulfillable_quantity": 0,
|
|
||||||
"total_discount": "0.00",
|
|
||||||
"fulfillment_status": "fulfilled",
|
|
||||||
"tax_lines": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"refunds": [],
|
|
||||||
"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:26:39+05:30",
|
|
||||||
"first_name": "Andrew",
|
|
||||||
"last_name": "Wyatt",
|
|
||||||
"orders_count": 1,
|
|
||||||
"state": "disabled",
|
|
||||||
"total_spent": "1018.00",
|
|
||||||
"last_order_id": 2414345735,
|
|
||||||
"note": "",
|
|
||||||
"verified_email": true,
|
|
||||||
"multipass_identifier": null,
|
|
||||||
"tax_exempt": false,
|
|
||||||
"tags": "",
|
|
||||||
"last_order_name": "#1005",
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 Settings", function (assert) {
|
|
||||||
let done = assert.async();
|
|
||||||
|
|
||||||
// number of asserts
|
|
||||||
assert.expect(1);
|
|
||||||
|
|
||||||
frappe.run_serially([
|
|
||||||
// insert a new Shopify Settings
|
|
||||||
() => frappe.tests.make('Shopify Settings', [
|
|
||||||
// values to be set
|
|
||||||
{key: 'value'}
|
|
||||||
]),
|
|
||||||
() => {
|
|
||||||
assert.equal(cur_frm.doc.key, 'value');
|
|
||||||
},
|
|
||||||
() => done()
|
|
||||||
]);
|
|
||||||
|
|
||||||
});
|
|
@ -1,107 +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, os, json
|
|
||||||
from frappe.utils import cstr, cint
|
|
||||||
from erpnext.erpnext_integrations.connectors.shopify_connection import create_order
|
|
||||||
from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import make_item
|
|
||||||
from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer
|
|
||||||
from frappe.core.doctype.data_import.data_import import import_doc
|
|
||||||
|
|
||||||
|
|
||||||
class ShopifySettings(unittest.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
frappe.set_user("Administrator")
|
|
||||||
|
|
||||||
cls.allow_negative_stock = cint(frappe.db.get_value('Stock Settings', None, 'allow_negative_stock'))
|
|
||||||
if not cls.allow_negative_stock:
|
|
||||||
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 1)
|
|
||||||
|
|
||||||
# use the fixture data
|
|
||||||
import_doc(path=frappe.get_app_path("erpnext", "erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json"))
|
|
||||||
|
|
||||||
frappe.reload_doctype("Customer")
|
|
||||||
frappe.reload_doctype("Sales Order")
|
|
||||||
frappe.reload_doctype("Delivery Note")
|
|
||||||
frappe.reload_doctype("Sales Invoice")
|
|
||||||
|
|
||||||
cls.setup_shopify()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
if not cls.allow_negative_stock:
|
|
||||||
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setup_shopify(cls):
|
|
||||||
shopify_settings = frappe.get_doc("Shopify Settings")
|
|
||||||
shopify_settings.taxes = []
|
|
||||||
|
|
||||||
shopify_settings.update({
|
|
||||||
"app_type": "Private",
|
|
||||||
"shopify_url": "test.myshopify.com",
|
|
||||||
"api_key": "17702c7c4452b9c5d235240b6e7a39da",
|
|
||||||
"password": "17702c7c4452b9c5d235240b6e7a39da",
|
|
||||||
"shared_secret": "17702c7c4452b9c5d235240b6e7a39da",
|
|
||||||
"price_list": "_Test Price List",
|
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
|
||||||
"cash_bank_account": "Cash - _TC",
|
|
||||||
"account": "Cash - _TC",
|
|
||||||
"customer_group": "_Test Customer Group",
|
|
||||||
"cost_center": "Main - _TC",
|
|
||||||
"taxes": [
|
|
||||||
{
|
|
||||||
"shopify_tax": "International Shipping",
|
|
||||||
"tax_account":"Legal Expenses - _TC"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"enable_shopify": 0,
|
|
||||||
"sales_order_series": "SO-",
|
|
||||||
"sync_sales_invoice": 1,
|
|
||||||
"sales_invoice_series": "SINV-",
|
|
||||||
"sync_delivery_note": 1,
|
|
||||||
"delivery_note_series": "DN-"
|
|
||||||
}).save(ignore_permissions=True)
|
|
||||||
|
|
||||||
cls.shopify_settings = shopify_settings
|
|
||||||
|
|
||||||
def test_order(self):
|
|
||||||
# Create Customer
|
|
||||||
with open (os.path.join(os.path.dirname(__file__), "test_data", "shopify_customer.json")) as shopify_customer:
|
|
||||||
shopify_customer = json.load(shopify_customer)
|
|
||||||
create_customer(shopify_customer.get("customer"), self.shopify_settings)
|
|
||||||
|
|
||||||
# Create Item
|
|
||||||
with open (os.path.join(os.path.dirname(__file__), "test_data", "shopify_item.json")) as shopify_item:
|
|
||||||
shopify_item = json.load(shopify_item)
|
|
||||||
make_item("_Test Warehouse - _TC", shopify_item.get("product"))
|
|
||||||
|
|
||||||
# Create Order
|
|
||||||
with open (os.path.join(os.path.dirname(__file__), "test_data", "shopify_order.json")) as shopify_order:
|
|
||||||
shopify_order = json.load(shopify_order)
|
|
||||||
|
|
||||||
create_order(shopify_order.get("order"), self.shopify_settings, False, company="_Test Company")
|
|
||||||
|
|
||||||
sales_order = frappe.get_doc("Sales Order", {"shopify_order_id": cstr(shopify_order.get("order").get("id"))})
|
|
||||||
|
|
||||||
self.assertEqual(cstr(shopify_order.get("order").get("id")), sales_order.shopify_order_id)
|
|
||||||
|
|
||||||
# Check for customer
|
|
||||||
shopify_order_customer_id = cstr(shopify_order.get("order").get("customer").get("id"))
|
|
||||||
sales_order_customer_id = frappe.get_value("Customer", sales_order.customer, "shopify_customer_id")
|
|
||||||
|
|
||||||
self.assertEqual(shopify_order_customer_id, sales_order_customer_id)
|
|
||||||
|
|
||||||
# Check sales invoice
|
|
||||||
sales_invoice = frappe.get_doc("Sales Invoice", {"shopify_order_id": sales_order.shopify_order_id})
|
|
||||||
self.assertEqual(sales_invoice.rounded_total, sales_order.rounded_total)
|
|
||||||
|
|
||||||
# Check delivery note
|
|
||||||
delivery_note_count = frappe.db.sql("""select count(*) from `tabDelivery Note`
|
|
||||||
where shopify_order_id = %s""", sales_order.shopify_order_id)[0][0]
|
|
||||||
|
|
||||||
self.assertEqual(delivery_note_count, len(shopify_order.get("order").get("fulfillments")))
|
|
@ -1,133 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2015-10-05 16:55:20.455371",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 0,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "shopify_tax",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Shopify Tax/Shipping Title",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"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": "column_break_2",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"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,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"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": "tax_account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "ERPNext Account",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Account",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"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": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-04-09 11:36:49.272815",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "ERPNext Integrations",
|
|
||||||
"name": "Shopify Tax Account",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0
|
|
||||||
}
|
|
@ -1,10 +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
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
class ShopifyTaxAccount(Document):
|
|
||||||
pass
|
|
@ -1,103 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-04-10 17:06:22.697427",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 0,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "webhook_id",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Webhook ID",
|
|
||||||
"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": "method",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-04-11 12:43:09.456449",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "ERPNext Integrations",
|
|
||||||
"name": "Shopify Webhook Detail",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
class ShopifyWebhookDetail(Document):
|
|
||||||
pass
|
|
@ -40,16 +40,6 @@
|
|||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Shopify Settings",
|
|
||||||
"link_to": "Shopify Settings",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
@ -113,4 +103,4 @@
|
|||||||
"pin_to_bottom": 0,
|
"pin_to_bottom": 0,
|
||||||
"pin_to_top": 0,
|
"pin_to_top": 0,
|
||||||
"shortcuts": []
|
"shortcuts": []
|
||||||
}
|
}
|
||||||
|
@ -30,16 +30,6 @@
|
|||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Shopify Settings",
|
|
||||||
"link_to": "Shopify Settings",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"dependencies": "",
|
"dependencies": "",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -79,4 +69,4 @@
|
|||||||
"pin_to_bottom": 0,
|
"pin_to_bottom": 0,
|
||||||
"pin_to_top": 0,
|
"pin_to_top": 0,
|
||||||
"shortcuts": []
|
"shortcuts": []
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,6 @@ scheduler_events = {
|
|||||||
"erpnext.projects.doctype.project.project.hourly_reminder",
|
"erpnext.projects.doctype.project.project.hourly_reminder",
|
||||||
"erpnext.projects.doctype.project.project.collect_project_status",
|
"erpnext.projects.doctype.project.project.collect_project_status",
|
||||||
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
|
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
|
||||||
"erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
|
|
||||||
"erpnext.support.doctype.service_level_agreement.service_level_agreement.set_service_level_agreement_variance"
|
"erpnext.support.doctype.service_level_agreement.service_level_agreement.set_service_level_agreement_variance"
|
||||||
],
|
],
|
||||||
"hourly_long": [
|
"hourly_long": [
|
||||||
|
@ -45,7 +45,6 @@ erpnext.patches.v11_0.make_location_from_warehouse
|
|||||||
erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
|
erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
|
||||||
erpnext.patches.v11_0.check_buying_selling_in_currency_exchange
|
erpnext.patches.v11_0.check_buying_selling_in_currency_exchange
|
||||||
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 #19-06-2019
|
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 #19-06-2019
|
||||||
erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07
|
|
||||||
erpnext.patches.v11_0.rename_overproduction_percent_field
|
erpnext.patches.v11_0.rename_overproduction_percent_field
|
||||||
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
|
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
|
||||||
erpnext.patches.v11_0.inter_state_field_for_gst
|
erpnext.patches.v11_0.inter_state_field_for_gst
|
||||||
@ -143,7 +142,6 @@ erpnext.patches.v12_0.add_variant_of_in_item_attribute_table
|
|||||||
erpnext.patches.v12_0.rename_bank_account_field_in_journal_entry_account
|
erpnext.patches.v12_0.rename_bank_account_field_in_journal_entry_account
|
||||||
erpnext.patches.v12_0.create_default_energy_point_rules
|
erpnext.patches.v12_0.create_default_energy_point_rules
|
||||||
erpnext.patches.v12_0.set_produced_qty_field_in_sales_order_for_work_order
|
erpnext.patches.v12_0.set_produced_qty_field_in_sales_order_for_work_order
|
||||||
erpnext.patches.v12_0.set_default_shopify_app_type
|
|
||||||
erpnext.patches.v12_0.set_cwip_and_delete_asset_settings
|
erpnext.patches.v12_0.set_cwip_and_delete_asset_settings
|
||||||
erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes
|
erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes
|
||||||
erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
|
erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
|
||||||
@ -244,7 +242,6 @@ erpnext.patches.v13_0.updates_for_multi_currency_payroll
|
|||||||
erpnext.patches.v13_0.update_reason_for_resignation_in_employee
|
erpnext.patches.v13_0.update_reason_for_resignation_in_employee
|
||||||
execute:frappe.delete_doc("Report", "Quoted Item Comparison")
|
execute:frappe.delete_doc("Report", "Quoted Item Comparison")
|
||||||
erpnext.patches.v13_0.update_member_email_address
|
erpnext.patches.v13_0.update_member_email_address
|
||||||
erpnext.patches.v13_0.update_custom_fields_for_shopify
|
|
||||||
erpnext.patches.v13_0.updates_for_multi_currency_payroll
|
erpnext.patches.v13_0.updates_for_multi_currency_payroll
|
||||||
erpnext.patches.v13_0.create_leave_policy_assignment_based_on_employee_current_leave_policy
|
erpnext.patches.v13_0.create_leave_policy_assignment_based_on_employee_current_leave_policy
|
||||||
erpnext.patches.v13_0.update_pos_closing_entry_in_merge_log
|
erpnext.patches.v13_0.update_pos_closing_entry_in_merge_log
|
||||||
@ -300,3 +297,4 @@ erpnext.patches.v13_0.update_amt_in_work_order_required_items
|
|||||||
erpnext.patches.v13_0.update_export_type_for_gst
|
erpnext.patches.v13_0.update_export_type_for_gst
|
||||||
erpnext.patches.v13_0.update_tds_check_field #3
|
erpnext.patches.v13_0.update_tds_check_field #3
|
||||||
erpnext.patches.v13_0.add_custom_field_for_south_africa
|
erpnext.patches.v13_0.add_custom_field_for_south_africa
|
||||||
|
erpnext.patches.v13_0.shopify_deprecation_warning
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.installer import remove_from_installed_apps
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_settings')
|
|
||||||
frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_tax_account')
|
|
||||||
frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_log')
|
|
||||||
frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_webhook_detail')
|
|
||||||
|
|
||||||
if 'erpnext_shopify' in frappe.get_installed_apps():
|
|
||||||
remove_from_installed_apps('erpnext_shopify')
|
|
||||||
|
|
||||||
frappe.delete_doc("Module Def", 'erpnext_shopify')
|
|
||||||
|
|
||||||
frappe.db.commit()
|
|
||||||
|
|
||||||
frappe.db.sql("truncate `tabShopify Log`")
|
|
||||||
|
|
||||||
setup_app_type()
|
|
||||||
else:
|
|
||||||
disable_shopify()
|
|
||||||
|
|
||||||
def setup_app_type():
|
|
||||||
try:
|
|
||||||
shopify_settings = frappe.get_doc("Shopify Settings")
|
|
||||||
shopify_settings.app_type = 'Private'
|
|
||||||
shopify_settings.update_price_in_erpnext_price_list = 0 if getattr(shopify_settings, 'push_prices_to_shopify', None) else 1
|
|
||||||
shopify_settings.flags.ignore_mandatory = True
|
|
||||||
shopify_settings.ignore_permissions = True
|
|
||||||
shopify_settings.save()
|
|
||||||
except Exception:
|
|
||||||
frappe.db.set_value("Shopify Settings", None, "enable_shopify", 0)
|
|
||||||
frappe.log_error(frappe.get_traceback())
|
|
||||||
|
|
||||||
def disable_shopify():
|
|
||||||
# due to frappe.db.set_value wrongly written and enable_shopify being default 1
|
|
||||||
# Shopify Settings isn't properly configured and leads to error
|
|
||||||
shopify = frappe.get_doc('Shopify Settings')
|
|
||||||
|
|
||||||
if shopify.app_type == "Public" or shopify.app_type == None or \
|
|
||||||
(shopify.enable_shopify and not (shopify.shopify_url or shopify.api_key)):
|
|
||||||
frappe.db.set_value("Shopify Settings", None, "enable_shopify", 0)
|
|
@ -1,6 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
frappe.reload_doc('erpnext_integrations', 'doctype', 'shopify_settings')
|
|
||||||
frappe.db.set_value('Shopify Settings', None, 'app_type', 'Private')
|
|
@ -30,19 +30,20 @@ def execute():
|
|||||||
return
|
return
|
||||||
|
|
||||||
repost_stock_entries = []
|
repost_stock_entries = []
|
||||||
|
|
||||||
stock_entries = frappe.db.sql_list('''
|
stock_entries = frappe.db.sql_list('''
|
||||||
SELECT
|
SELECT
|
||||||
se.name
|
se.name
|
||||||
FROM
|
FROM
|
||||||
`tabStock Entry` se
|
`tabStock Entry` se
|
||||||
WHERE
|
WHERE
|
||||||
se.purpose = 'Manufacture' and se.docstatus < 2 and se.work_order in {work_orders}
|
se.purpose = 'Manufacture' and se.docstatus < 2 and se.work_order in %s
|
||||||
and not exists(
|
and not exists(
|
||||||
select name from `tabStock Entry Detail` sed where sed.parent = se.name and sed.is_finished_item = 1
|
select name from `tabStock Entry Detail` sed where sed.parent = se.name and sed.is_finished_item = 1
|
||||||
)
|
)
|
||||||
Order BY
|
ORDER BY
|
||||||
se.posting_date, se.posting_time
|
se.posting_date, se.posting_time
|
||||||
'''.format(work_orders=tuple(work_orders)))
|
''', (work_orders,))
|
||||||
|
|
||||||
if stock_entries:
|
if stock_entries:
|
||||||
print('Length of stock entries', len(stock_entries))
|
print('Length of stock entries', len(stock_entries))
|
||||||
|
10
erpnext/patches/v13_0/shopify_deprecation_warning.py
Normal file
10
erpnext/patches/v13_0/shopify_deprecation_warning.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import click
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
|
||||||
|
click.secho(
|
||||||
|
"Shopify Integration is moved to a separate app and will be removed from ERPNext in version-14.\n"
|
||||||
|
"Please install the app to continue using the integration: https://github.com/frappe/ecommerce_integrations",
|
||||||
|
fg="yellow",
|
||||||
|
)
|
@ -1,10 +0,0 @@
|
|||||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# MIT License. See license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import setup_custom_fields
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
if frappe.db.get_single_value('Shopify Settings', 'enable_shopify'):
|
|
||||||
setup_custom_fields()
|
|
@ -969,7 +969,7 @@ class GSPConnector():
|
|||||||
"attached_to_doctype": doctype,
|
"attached_to_doctype": doctype,
|
||||||
"attached_to_name": docname,
|
"attached_to_name": docname,
|
||||||
"attached_to_field": "qrcode_image",
|
"attached_to_field": "qrcode_image",
|
||||||
"is_private": 1,
|
"is_private": 0,
|
||||||
"content": qr_image.getvalue()})
|
"content": qr_image.getvalue()})
|
||||||
_file.save()
|
_file.save()
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
|
@ -564,7 +564,6 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
)
|
)
|
||||||
|
|
||||||
set_dynamic_rate_header_width();
|
set_dynamic_rate_header_width();
|
||||||
this.scroll_to_item($item_to_update);
|
|
||||||
|
|
||||||
function set_dynamic_rate_header_width() {
|
function set_dynamic_rate_header_width() {
|
||||||
const rate_cols = Array.from(me.$cart_items_wrapper.find(".item-rate-amount"));
|
const rate_cols = Array.from(me.$cart_items_wrapper.find(".item-rate-amount"));
|
||||||
@ -639,12 +638,6 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
$($img).parent().replaceWith(`<div class="item-image item-abbr">${item_abbr}</div>`);
|
$($img).parent().replaceWith(`<div class="item-image item-abbr">${item_abbr}</div>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
scroll_to_item($item) {
|
|
||||||
if ($item.length === 0) return;
|
|
||||||
const scrollTop = $item.offset().top - this.$cart_items_wrapper.offset().top + this.$cart_items_wrapper.scrollTop();
|
|
||||||
this.$cart_items_wrapper.animate({ scrollTop });
|
|
||||||
}
|
|
||||||
|
|
||||||
update_selector_value_in_cart_item(selector, value, item) {
|
update_selector_value_in_cart_item(selector, value, item) {
|
||||||
const $item_to_update = this.get_cart_item(item);
|
const $item_to_update = this.get_cart_item(item);
|
||||||
$item_to_update.attr(`data-${selector}`, escape(value));
|
$item_to_update.attr(`data-${selector}`, escape(value));
|
||||||
|
@ -29,13 +29,50 @@ frappe.ui.form.on('Repost Item Valuation', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.trigger('setup_realtime_progress');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setup_realtime_progress: function(frm) {
|
||||||
|
frappe.realtime.on('item_reposting_progress', data => {
|
||||||
|
if (frm.doc.name !== data.name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frm.doc.status == 'In Progress') {
|
||||||
|
frm.doc.current_index = data.current_index;
|
||||||
|
frm.doc.items_to_be_repost = data.items_to_be_repost;
|
||||||
|
|
||||||
|
frm.dashboard.reset();
|
||||||
|
frm.trigger('show_reposting_progress');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (frm.doc.status == "Failed" && frm.doc.docstatus==1) {
|
if (frm.doc.status == "Failed" && frm.doc.docstatus==1) {
|
||||||
frm.add_custom_button(__('Restart'), function () {
|
frm.add_custom_button(__('Restart'), function () {
|
||||||
frm.trigger("restart_reposting");
|
frm.trigger("restart_reposting");
|
||||||
}).addClass("btn-primary");
|
}).addClass("btn-primary");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.trigger('show_reposting_progress');
|
||||||
|
},
|
||||||
|
|
||||||
|
show_reposting_progress: function(frm) {
|
||||||
|
var bars = [];
|
||||||
|
|
||||||
|
let total_count = frm.doc.items_to_be_repost ? JSON.parse(frm.doc.items_to_be_repost).length : 0;
|
||||||
|
let progress = flt(cint(frm.doc.current_index) / total_count * 100, 2) || 0.5;
|
||||||
|
var title = __('Reposting Completed {0}%', [progress]);
|
||||||
|
|
||||||
|
bars.push({
|
||||||
|
'title': title,
|
||||||
|
'width': progress + '%',
|
||||||
|
'progress_class': 'progress-bar-success'
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.dashboard.add_progress(__('Reposting Progress'), bars);
|
||||||
},
|
},
|
||||||
|
|
||||||
restart_reposting: function(frm) {
|
restart_reposting: function(frm) {
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
"allow_zero_rate",
|
"allow_zero_rate",
|
||||||
"amended_from",
|
"amended_from",
|
||||||
"error_section",
|
"error_section",
|
||||||
"error_log"
|
"error_log",
|
||||||
|
"items_to_be_repost",
|
||||||
|
"distinct_item_and_warehouse",
|
||||||
|
"current_index"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -142,12 +145,39 @@
|
|||||||
"fieldname": "allow_zero_rate",
|
"fieldname": "allow_zero_rate",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Allow Zero Rate"
|
"label": "Allow Zero Rate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "items_to_be_repost",
|
||||||
|
"fieldtype": "Code",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Items to Be Repost",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "distinct_item_and_warehouse",
|
||||||
|
"fieldtype": "Code",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Distinct Item and Warehouse",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "current_index",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Current Index",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-12-10 07:52:12.476589",
|
"modified": "2021-07-22 18:59:43.057878",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Repost Item Valuation",
|
"name": "Repost Item Valuation",
|
||||||
|
@ -81,7 +81,7 @@ def repost(doc):
|
|||||||
def repost_sl_entries(doc):
|
def repost_sl_entries(doc):
|
||||||
if doc.based_on == 'Transaction':
|
if doc.based_on == 'Transaction':
|
||||||
repost_future_sle(voucher_type=doc.voucher_type, voucher_no=doc.voucher_no,
|
repost_future_sle(voucher_type=doc.voucher_type, voucher_no=doc.voucher_no,
|
||||||
allow_negative_stock=doc.allow_negative_stock, via_landed_cost_voucher=doc.via_landed_cost_voucher)
|
allow_negative_stock=doc.allow_negative_stock, via_landed_cost_voucher=doc.via_landed_cost_voucher, doc=doc)
|
||||||
else:
|
else:
|
||||||
repost_future_sle(args=[frappe._dict({
|
repost_future_sle(args=[frappe._dict({
|
||||||
"item_code": doc.item_code,
|
"item_code": doc.item_code,
|
||||||
|
@ -312,8 +312,8 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
"transaction_date": args.get("transaction_date"),
|
"transaction_date": args.get("transaction_date"),
|
||||||
"against_blanket_order": args.get("against_blanket_order"),
|
"against_blanket_order": args.get("against_blanket_order"),
|
||||||
"bom_no": item.get("default_bom"),
|
"bom_no": item.get("default_bom"),
|
||||||
"weight_per_unit": args.get("weight_per_unit") or item.get("weight_per_unit"),
|
"weight_per_unit": item.get("weight_per_unit"),
|
||||||
"weight_uom": args.get("weight_uom") or item.get("weight_uom")
|
"weight_uom": item.get("weight_uom")
|
||||||
})
|
})
|
||||||
|
|
||||||
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
||||||
|
@ -16,8 +16,6 @@ def execute(filters=None):
|
|||||||
is_reposting_item_valuation_in_progress()
|
is_reposting_item_valuation_in_progress()
|
||||||
if not filters: filters = {}
|
if not filters: filters = {}
|
||||||
|
|
||||||
validate_filters(filters)
|
|
||||||
|
|
||||||
from_date = filters.get('from_date')
|
from_date = filters.get('from_date')
|
||||||
to_date = filters.get('to_date')
|
to_date = filters.get('to_date')
|
||||||
|
|
||||||
@ -295,12 +293,6 @@ def get_item_reorder_details(items):
|
|||||||
|
|
||||||
return dict((d.parent + d.warehouse, d) for d in item_reorder_details)
|
return dict((d.parent + d.warehouse, d) for d in item_reorder_details)
|
||||||
|
|
||||||
def validate_filters(filters):
|
|
||||||
if not (filters.get("item_code") or filters.get("warehouse")):
|
|
||||||
sle_count = flt(frappe.db.sql("""select count(name) from `tabStock Ledger Entry`""")[0][0])
|
|
||||||
if sle_count > 500000:
|
|
||||||
frappe.throw(_("Please set filter based on Item or Warehouse due to a large amount of entries."))
|
|
||||||
|
|
||||||
def get_variants_attributes():
|
def get_variants_attributes():
|
||||||
'''Return all item variant attributes.'''
|
'''Return all item variant attributes.'''
|
||||||
return [i.name for i in frappe.get_all('Item Attribute')]
|
return [i.name for i in frappe.get_all('Item Attribute')]
|
||||||
|
@ -127,30 +127,26 @@ def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False):
|
|||||||
sle.submit()
|
sle.submit()
|
||||||
return sle
|
return sle
|
||||||
|
|
||||||
def repost_future_sle(args=None, voucher_type=None, voucher_no=None, allow_negative_stock=None, via_landed_cost_voucher=False):
|
def repost_future_sle(args=None, voucher_type=None, voucher_no=None, allow_negative_stock=None, via_landed_cost_voucher=False, doc=None):
|
||||||
if not args and voucher_type and voucher_no:
|
if not args and voucher_type and voucher_no:
|
||||||
args = get_args_for_voucher(voucher_type, voucher_no)
|
args = get_items_to_be_repost(voucher_type, voucher_no, doc)
|
||||||
|
|
||||||
distinct_item_warehouses = {}
|
distinct_item_warehouses = get_distinct_item_warehouse(args, doc)
|
||||||
for i, d in enumerate(args):
|
|
||||||
distinct_item_warehouses.setdefault((d.item_code, d.warehouse), frappe._dict({
|
|
||||||
"reposting_status": False,
|
|
||||||
"sle": d,
|
|
||||||
"args_idx": i
|
|
||||||
}))
|
|
||||||
|
|
||||||
i = 0
|
i = get_current_index(doc) or 0
|
||||||
while i < len(args):
|
while i < len(args):
|
||||||
|
validate_item_warehouse(args[i])
|
||||||
|
|
||||||
obj = update_entries_after({
|
obj = update_entries_after({
|
||||||
"item_code": args[i].item_code,
|
'item_code': args[i].get('item_code'),
|
||||||
"warehouse": args[i].warehouse,
|
'warehouse': args[i].get('warehouse'),
|
||||||
"posting_date": args[i].posting_date,
|
'posting_date': args[i].get('posting_date'),
|
||||||
"posting_time": args[i].posting_time,
|
'posting_time': args[i].get('posting_time'),
|
||||||
"creation": args[i].get("creation"),
|
'creation': args[i].get('creation'),
|
||||||
"distinct_item_warehouses": distinct_item_warehouses
|
'distinct_item_warehouses': distinct_item_warehouses
|
||||||
}, allow_negative_stock=allow_negative_stock, via_landed_cost_voucher=via_landed_cost_voucher)
|
}, allow_negative_stock=allow_negative_stock, via_landed_cost_voucher=via_landed_cost_voucher)
|
||||||
|
|
||||||
distinct_item_warehouses[(args[i].item_code, args[i].warehouse)].reposting_status = True
|
distinct_item_warehouses[(args[i].get('item_code'), args[i].get('warehouse'))].reposting_status = True
|
||||||
|
|
||||||
if obj.new_items_found:
|
if obj.new_items_found:
|
||||||
for item_wh, data in iteritems(distinct_item_warehouses):
|
for item_wh, data in iteritems(distinct_item_warehouses):
|
||||||
@ -159,11 +155,41 @@ def repost_future_sle(args=None, voucher_type=None, voucher_no=None, allow_negat
|
|||||||
args.append(data.sle)
|
args.append(data.sle)
|
||||||
elif data.sle_changed and not data.reposting_status:
|
elif data.sle_changed and not data.reposting_status:
|
||||||
args[data.args_idx] = data.sle
|
args[data.args_idx] = data.sle
|
||||||
|
|
||||||
data.sle_changed = False
|
data.sle_changed = False
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
def get_args_for_voucher(voucher_type, voucher_no):
|
if doc and i % 2 == 0:
|
||||||
|
update_args_in_repost_item_valuation(doc, i, args, distinct_item_warehouses)
|
||||||
|
|
||||||
|
if doc and args:
|
||||||
|
update_args_in_repost_item_valuation(doc, i, args, distinct_item_warehouses)
|
||||||
|
|
||||||
|
def validate_item_warehouse(args):
|
||||||
|
for field in ['item_code', 'warehouse', 'posting_date', 'posting_time']:
|
||||||
|
if not args.get(field):
|
||||||
|
validation_msg = f'The field {frappe.unscrub(args.get(field))} is required for the reposting'
|
||||||
|
frappe.throw(_(validation_msg))
|
||||||
|
|
||||||
|
def update_args_in_repost_item_valuation(doc, index, args, distinct_item_warehouses):
|
||||||
|
frappe.db.set_value(doc.doctype, doc.name, {
|
||||||
|
'items_to_be_repost': json.dumps(args, default=str),
|
||||||
|
'distinct_item_and_warehouse': json.dumps({str(k): v for k,v in distinct_item_warehouses.items()}, default=str),
|
||||||
|
'current_index': index
|
||||||
|
})
|
||||||
|
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
frappe.publish_realtime('item_reposting_progress', {
|
||||||
|
'name': doc.name,
|
||||||
|
'items_to_be_repost': json.dumps(args, default=str),
|
||||||
|
'current_index': index
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_items_to_be_repost(voucher_type, voucher_no, doc=None):
|
||||||
|
if doc and doc.items_to_be_repost:
|
||||||
|
return json.loads(doc.items_to_be_repost) or []
|
||||||
|
|
||||||
return frappe.db.get_all("Stock Ledger Entry",
|
return frappe.db.get_all("Stock Ledger Entry",
|
||||||
filters={"voucher_type": voucher_type, "voucher_no": voucher_no},
|
filters={"voucher_type": voucher_type, "voucher_no": voucher_no},
|
||||||
fields=["item_code", "warehouse", "posting_date", "posting_time", "creation"],
|
fields=["item_code", "warehouse", "posting_date", "posting_time", "creation"],
|
||||||
@ -171,6 +197,25 @@ def get_args_for_voucher(voucher_type, voucher_no):
|
|||||||
group_by="item_code, warehouse"
|
group_by="item_code, warehouse"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_distinct_item_warehouse(args=None, doc=None):
|
||||||
|
distinct_item_warehouses = {}
|
||||||
|
if doc and doc.distinct_item_and_warehouse:
|
||||||
|
distinct_item_warehouses = json.loads(doc.distinct_item_and_warehouse)
|
||||||
|
distinct_item_warehouses = {frappe.safe_eval(k): frappe._dict(v) for k, v in distinct_item_warehouses.items()}
|
||||||
|
else:
|
||||||
|
for i, d in enumerate(args):
|
||||||
|
distinct_item_warehouses.setdefault((d.item_code, d.warehouse), frappe._dict({
|
||||||
|
"reposting_status": False,
|
||||||
|
"sle": d,
|
||||||
|
"args_idx": i
|
||||||
|
}))
|
||||||
|
|
||||||
|
return distinct_item_warehouses
|
||||||
|
|
||||||
|
def get_current_index(doc=None):
|
||||||
|
if doc and doc.current_index:
|
||||||
|
return doc.current_index
|
||||||
|
|
||||||
class update_entries_after(object):
|
class update_entries_after(object):
|
||||||
"""
|
"""
|
||||||
update valution rate and qty after transaction
|
update valution rate and qty after transaction
|
||||||
|
Loading…
x
Reference in New Issue
Block a user