Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2da58f2
Port metadata import to v14.
batonac Mar 23, 2023
586eded
Port metadata import to v14.
batonac Mar 23, 2023
6604ea1
Co-authored-by: Kevin Shenk <kevin@avu.nu>
batonac Mar 28, 2023
41318a0
Cleanup Code
batonac Mar 28, 2023
56406e6
Reformat tab size.
batonac Mar 28, 2023
0cf39cb
Make requested changes to pull request.
batonac Mar 29, 2023
58dc49b
Remove Create/Update Custom Fields Button, validate custom field not …
batonac Apr 6, 2023
70c1220
Adjust new JS for custom field validation before delete per deepsourc…
batonac Apr 6, 2023
e5f9a8e
Fix bug so that unedited new custom fields can be deleted.
batonac Apr 6, 2023
9565db8
Fix bug on deleting empty custom fields.
batonac Apr 6, 2023
9a2dd8c
fix: format files
Apr 17, 2023
8b19d54
fix: add tab breaks
Apr 17, 2023
1b55e54
remove mandatory field
batonac May 11, 2023
6683a8b
Merge pull request #1 from Alchez/metadataimport-v14
batonac May 11, 2023
9c6e7d8
drop section break custom field option
batonac May 11, 2023
0886ddf
refactor: address updating
batonac Jul 26, 2024
0fd20a0
refactor: remove amazon_customer
batonac Jul 26, 2024
21bf1cb
refactor: create or update address
batonac Jul 29, 2024
95bf7c1
feat: add or update address
batonac Jul 29, 2024
d37d759
feat: order status
batonac Sep 10, 2024
95ccf23
fix: cancelation procedure
batonac Jan 27, 2025
2be2927
feat: update code
batonac May 2, 2025
de90070
fix: missing customer email handling
batonac May 6, 2025
911073b
feat: add custom check fields
batonac May 16, 2025
b816277
feat: cancel the order explicitly
batonac May 16, 2025
6173167
fix: fix the customer matching code
batonac Jul 14, 2025
5ef2506
fix: type annotations
batonac Oct 27, 2025
7fb2c80
chore: type annotations
batonac Feb 5, 2026
9e07d85
chore: pylance issues
batonac Feb 5, 2026
7a312ac
feat: enhance logging in order processing and validation
batonac Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions shipstation_integration/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ def list_orders(

if not last_order_datetime:
# Get data for the last day, Shipstation API behaves oddly when it's a shorter period
last_order_datetime = datetime.datetime.utcnow() - datetime.timedelta(hours=24)

last_order_datetime = datetime.datetime.utcnow() - datetime.timedelta(hours=sss_doc.get("hours_to_fetch", 24))
store: "ShipstationStore"
for store in sss_doc.shipstation_stores:
if not store.enable_orders:
Expand All @@ -70,7 +69,6 @@ def list_orders(
for order in orders:
if validate_order(sss_doc, order, store):
should_create_order = True

process_order_hook = frappe.get_hooks("process_shipstation_order")
if process_order_hook:
should_create_order = frappe.get_attr(process_order_hook[0])(order, store)
Expand Down Expand Up @@ -177,9 +175,7 @@ def create_erpnext_order(order: "ShipStationOrder", store: "ShipstationStore") -
settings = frappe.get_doc("Shipstation Settings", store.parent)
item_code = create_item(item, settings=settings, store=store)
item_notes = get_item_notes(item)
so.append(
"items",
{
item_dict = {
"item_code": item_code,
"qty": item.quantity,
"uom": frappe.db.get_single_value("Stock Settings", "stock_uom"),
Expand All @@ -188,8 +184,26 @@ def create_erpnext_order(order: "ShipStationOrder", store: "ShipstationStore") -
"warehouse": store.warehouse,
"shipstation_order_item_id": item.order_item_id,
"shipstation_item_notes": item_notes,
},
)
}

options_import = frappe.get_all("Shipstation Option",
filters=dict(parent=store.parent),
fields=["shipstation_option_name", "item_field"])

for option in item.options:
# check to see if the option is in the Options Import table
option_import = next((x for x in options_import if x.shipstation_option_name == option.name), None)
if option_import:
if option_import.item_field:
item_dict[option_import.item_field] = option.value
else:
# if the option name is not in the Options Import table, add it
settings.append("shipstation_options", {
"shipstation_option_name": option.name
})
settings.save()

so.append("items", item_dict)

if not so.get("items"):
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{
"actions": [],
"creation": "2023-03-22 09:59:42.179486",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"label",
"fieldtype",
"fieldname",
"length",
"mandatory",
"hidden",
"read_only",
"reqd",
"column_break_oh9el",
"options",
"default",
"fetch_from",
"fetch_if_empty"
],
"fields": [
{
"bold": 1,
"fieldname": "label",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Label",
"reqd": 1
},
{
"default": "0",
"fieldname": "mandatory",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Mandatory"
},
{
"default": "0",
"fieldname": "hidden",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Hidden"
},
{
"default": "0",
"fieldname": "read_only",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Read Only"
},
{
"fieldname": "options",
"fieldtype": "Small Text",
"label": "Options"
},
{
"fieldname": "column_break_oh9el",
"fieldtype": "Column Break"
},
{
"fieldname": "default",
"fieldtype": "Small Text",
"label": "Default"
},
{
"fieldname": "fetch_from",
"fieldtype": "Small Text",
"label": "Fetch From"
},
{
"default": "0",
"fieldname": "fetch_if_empty",
"fieldtype": "Check",
"label": "Fetch If Empty"
},
{
"bold": 1,
"default": "Data",
"fieldname": "fieldtype",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"options": "\nCheck\nData\nLink\nSection Break\nSelect\nSmall Text\nText",
Comment thread
Alchez marked this conversation as resolved.
Outdated
"reqd": 1
},
{
"bold": 1,
"fieldname": "fieldname",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Name",
"reqd": 1
},
{
"fieldname": "length",
"fieldtype": "Data",
"label": "Length"
},
{
"default": "0",
"fieldname": "reqd",
"fieldtype": "Check",
"label": "Reqd"
Comment thread
Alchez marked this conversation as resolved.
Outdated
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-03-28 09:05:26.518578",
"modified_by": "Administrator",
"module": "Shipstation Integration",
"name": "Shipstation Item Custom Field",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2023, Parsimony LLC and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class ShipstationItemCustomField(Document):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-03-22 09:21:18.362079",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"shipstation_option_name",
"column_break_lcx0j",
"item_field"
],
"fields": [
{
"fieldname": "item_field",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Item Field"
},
{
"fieldname": "column_break_lcx0j",
"fieldtype": "Column Break"
},
{
"bold": 1,
"fieldname": "shipstation_option_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Shipstation Option Name"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-03-28 16:46:54.820883",
"modified_by": "Administrator",
"module": "Shipstation Integration",
"name": "Shipstation Option",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2023, Parsimony LLC and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class ShipstationOption(Document):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,41 @@ function company_query(frm, cdt, cdn) {
};
}

function set_item_field_options(frm) {
let options_arr = [];
// delete the "Sales Order Item" doctype meta from locals, to force a reload of the field list
delete locals.DocType['Sales Order Item'];
Comment thread
Alchez marked this conversation as resolved.
Outdated
// loads the "Sales Order Item" doctype meta into locals
frappe.model.with_doctype("Sales Order Item", () => {
const fieldlist = frappe.get_meta("Sales Order Item").fields;
Comment thread
Alchez marked this conversation as resolved.
Outdated
// This filters for "Data", "Text", "Small Text", "Link", and "Select."
const filtered_fieldlist = fieldlist.filter((field) => {
return ["Data", "Text", "Small Text", "Link", "Select"].includes(field.fieldtype);
});
// This maps fieldname and value.
options_arr = filtered_fieldlist.map((field) => {
return { value: field.fieldname, label: field.label };
});
// This alphanumerically sorts the array by label.
options_arr = options_arr.sort((a, b) => {
return a.label.localeCompare(b.label);
});
// This updates the individual row's "item_field" field.
frm.fields_dict.shipstation_options.grid.update_docfield_property("item_field", "options", options_arr);
});
};

async function update_order_item_custom_fields_on_remove(frm) {
const opts = {
doc: frm.doc,
method: "update_order_item_custom_fields",
args: { removed_item_custom_fields: locals.removed_item_custom_fields },
freeze: true,
};
await frm.call(opts);
set_item_field_options(frm);
};

frappe.ui.form.on("Shipstation Settings", {
setup: (frm) => {
frm.set_query("shipstation_warehouses", {
Expand All @@ -24,17 +59,23 @@ frappe.ui.form.on("Shipstation Settings", {
frm.set_query(
"shipping_income_account",
"shipstation_stores",
company_query
company_query,
);
frm.set_query(
"shipping_expense_account",
"shipstation_stores",
company_query
company_query,
);
set_item_field_options(frm);
},

on_update: (frm) => {
update_order_item_custom_fields_on_remove(frm);
},

after_save: (frm) => {
frm.trigger("toggle_mandatory_table_fields");
update_order_item_custom_fields_on_remove(frm);
},

refresh: (frm) => {
Expand All @@ -44,9 +85,9 @@ frappe.ui.form.on("Shipstation Settings", {
wrapper.html(
frappe.render_template("carriers", {
carriers: frm.doc.__onload.carriers,
})
}),
);
}
};
},

update_carriers_and_stores: (frm) => {
Expand Down Expand Up @@ -141,3 +182,19 @@ frappe.ui.form.on("Shipstation Settings", {
);
},
});

frappe.ui.form.on("Shipstation Item Custom Field", {
before_item_custom_fields_remove: (frm, cdt, cdn) => {
const deleted_row = frappe.get_doc(cdt, cdn);
// Check if there are rows in the shipstation options table that have the deleted fieldname in their "item_field" field.
const deleted_row_in_use = frm.doc.shipstation_options.find((row) => {
return row.item_field === deleted_row.fieldname;
}) !== undefined;
if (deleted_row_in_use && deleted_row.fieldname) {
frappe.throw(__(`Cannot delete field ${deleted_row.label} because it is in use.`));
} else {
locals.removed_item_custom_fields = locals.removed_item_custom_fields || [];
locals.removed_item_custom_fields.push(deleted_row.fieldname);
};
},
});
Loading