diff --git a/sps_integration/sps_integration/constants.py b/sps_integration/sps_integration/constants.py index 078e97d..eab8bd7 100644 --- a/sps_integration/sps_integration/constants.py +++ b/sps_integration/sps_integration/constants.py @@ -1,7 +1,7 @@ import frappe SALES_ORDER_ACKNOWLEDGEMENT_URL = "https://api.spscommerce.com/transactions/v5/" -SPS_SO_URL = "https://api.spscommerce.com/transactions/v5/data/out/" +# SPS_SO_URL = "https://api.spscommerce.com/transactions/v5/data/out/" BASE_AUTH_URL = "https://auth.spscommerce.com" def AUTHORIZATION_URL( audience: str, diff --git a/sps_integration/sps_integration/custom/sps_integration_settings.json b/sps_integration/sps_integration/custom/sps_integration_settings.json index 3f2c48a..50a47b9 100644 --- a/sps_integration/sps_integration/custom/sps_integration_settings.json +++ b/sps_integration/sps_integration/custom/sps_integration_settings.json @@ -1,5 +1,129 @@ { "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-04-03 23:32:49.326476", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "SPS Integration Settings", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "custom_order_acknowledgement_url", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 25, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "custom_get_sales_order_url", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Order Acknowledgement URL", + "length": 0, + "mandatory_depends_on": null, + "modified": "2025-04-03 23:32:49.326476", + "modified_by": "Administrator", + "module": null, + "name": "SPS Integration Settings-custom_order_acknowledgement_url", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-04-03 23:32:49.039907", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "SPS Integration Settings", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "custom_get_sales_order_url", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 24, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "days", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Get Sales Order URL", + "length": 0, + "mandatory_depends_on": null, + "modified": "2025-04-03 23:32:49.039907", + "modified_by": "Administrator", + "module": null, + "name": "SPS Integration Settings-custom_get_sales_order_url", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null + }, { "_assign": null, "_comments": null, @@ -25,7 +149,7 @@ "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 15, + "idx": 17, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_global_search": 0, @@ -87,7 +211,7 @@ "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 14, + "idx": 16, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_global_search": 0, @@ -149,14 +273,14 @@ "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 13, + "idx": 14, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_global_search": 0, "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "insert_after": "expires_on", + "insert_after": "default_tab", "is_system_generated": 0, "is_virtual": 0, "label": "Defaults", @@ -196,7 +320,7 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-02-02 20:31:11.118583", + "creation": "2025-04-03 23:32:48.857025", "default_value": null, "doc_type": "SPS Integration Settings", "docstatus": 0, @@ -204,7 +328,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-02-02 20:31:11.118583", + "modified": "2025-04-03 23:32:48.857025", "modified_by": "Administrator", "module": null, "name": "SPS Integration Settings-main-field_order", @@ -212,7 +336,7 @@ "property": "field_order", "property_type": "Data", "row_name": null, - "value": "[\"settings_name\", \"authenticate\", \"refresh_access_token\", \"redirect_uri\", \"sps_api_uri\", \"enabled\", \"column_break_ynjw\", \"client_secret\", \"client_id\", \"state\", \"access_token\", \"refresh_token\", \"expires_on\", \"defaults_tab\", \"default_uom\", \"default_item_group\"]" + "value": "[\"settings_name\", \"authenticate\", \"refresh_access_token\", \"redirect_uri\", \"sps_api_uri\", \"enabled\", \"column_break_ynjw\", \"client_secret\", \"client_id\", \"state\", \"access_token\", \"refresh_token\", \"expires_on\", \"default_tab\", \"custom_defaults\", \"custom_default_uom\", \"custom_default_item_group\", \"default_uom\", \"default_item_group\", \"marketplace\", \"column_break_rxhv\", \"customer_type\", \"shipping_category\", \"days\", \"get_sales_order_url\", \"order_acknowledgement_url\", \"order_syncing_tab\", \"sync_start_date\", \"sync_orders\", \"section_break_lafq\", \"sync_duration\"]" } ], "sync_on_migrate": 1 diff --git a/sps_integration/sps_integration/order_acknowledgement.py b/sps_integration/sps_integration/order_acknowledgement.py index 85f20bb..140d6aa 100644 --- a/sps_integration/sps_integration/order_acknowledgement.py +++ b/sps_integration/sps_integration/order_acknowledgement.py @@ -1,194 +1,4 @@ -# import frappe -# import requests -# from .constants import SALES_ORDER_ACKNOWLEDGEMENT_URL - -# def format_sales_order_ack(data: dict) -> dict: -# """ -# Format sales order acknowledgement. - -# Args: -# data (dict): Sales order payload. - -# Returns: -# dict: A formatted sales order acknowledgement. -# """ -# try: -# order_header = data.get("Header", {}).get("OrderHeader", {}) -# line_item = data.get("LineItem", []) - -# if not order_header or not line_item: -# frappe.log_error(title="Invalid Order Payload", message=str(data)) -# print("Invalid order payload received.") -# return {} - -# acknowledgement_payload = { -# "Header": { -# "OrderHeader": { -# "TradingPartnerId": order_header.get("TradingPartnerId", ""), -# "PurchaseOrderNumber": order_header.get("PurchaseOrderNumber"), -# "TsetPurposeCode": "00", -# "AcknowledgementType": "AK", -# "AcknowledgementNumber": "", -# "AcknowledgementDate": order_header.get("PurchaseOrderDate"), -# }, -# "Dates": [ -# { -# "DateTimeQualifier": "064", -# "Date": order_header.get("PurchaseOrderDate") -# } -# ] -# }, -# "LineItem": [ -# { -# "OrderLine": { -# "LineSequenceNumber": item.get("OrderLine", {}).get("LineSequenceNumber"), -# "VendorPartNumber": item.get("OrderLine", {}).get("VendorPartNumber"), -# "ConsumerPackageCode": item.get("OrderLine", {}).get("ConsumerPackageCode"), -# "OrderQty": item.get("OrderLine", {}).get("OrderQty"), -# "OrderQtyUOM": item.get("OrderLine", {}).get("OrderQtyUOM"), -# "PurchasePrice": item.get("OrderLine", {}).get("PurchasePrice"), -# }, -# "LineItemAcknowledgement": [ -# { -# "ItemStatusCode": "IA", -# "ItemScheduleQty": item.get("OrderLine", {}).get("OrderQty"), -# "ItemScheduleUOM": item.get("OrderLine", {}).get("OrderQtyUOM"), -# "ItemScheduleQualifier": "", -# "ItemScheduleDate": order_header.get("PurchaseOrderDate"), -# } -# ] -# } -# for item in line_item -# ] -# } - -# print("Formatted Sales Order Acknowledgement Payload:", acknowledgement_payload) -# return acknowledgement_payload - -# except Exception as e: -# frappe.log_error(title="SO ACK Payload Formatting Error", message=str(e)) -# print(f"Error formatting payload: {str(e)}") -# return {} - -# def sales_order_acknowledgement(data: dict): -# """Send Sales Order Acknowledgement.""" -# try: -# print("Fetching SPS Integration Settings...") -# doc = frappe.get_doc("SPS Integration Settings", "Develop") -# access_token = doc.get_password("access_token") - -# headers = { -# "Content-Type": "application/json; charset=utf-8", -# "Authorization": f"Bearer {access_token}" -# } - -# formatted_data = format_sales_order_ack(data) - -# if not formatted_data: -# print("Error: No data to send in Sales Order Acknowledgement.") -# return - -# print("Sending Sales Order Acknowledgement...") -# response = requests.post(url=SALES_ORDER_ACKNOWLEDGEMENT_URL, headers=headers, json=formatted_data) - -# print(f"Response Status Code: {response.status_code}") - -# if response.status_code in [200, 201]: -# response_json = response.json() -# frappe.log_error(title="SO Acknowledgement Success", message=str(response_json)) -# print("Sales Order Acknowledgement Successful:", response_json) -# else: -# frappe.log_error(title="SO Acknowledgement Failure", message=response.text) -# print("Sales Order Acknowledgement Failed:", response.text) - -# except Exception as e: -# frappe.log_error(title="SO Acknowledgement Error", message=str(e)) -# print(f"Error in Sales Order Acknowledgement: {str(e)}") - - - -# data = { -# "Meta" : { -# "OrderManagement" : "SA" -# }, -# "Header" : { -# "OrderHeader" : { -# "TradingPartnerId" : "0RXALLALPHARDGO", -# "PurchaseOrderNumber" : "WGE680227-29", -# "TsetPurposeCode" : "00", -# "PrimaryPOTypeCode" : "SA", -# "PurchaseOrderDate" : "2025-02-10", -# "Vendor" : "ALPHAR" -# }, -# "Dates" : [ { -# "DateTimeQualifier" : "010", -# "Date" : "2025-02-28" -# }, { -# "DateTimeQualifier" : "001", -# "Date" : "2025-03-30" -# } ], -# "Contacts" : [ { -# "ContactTypeCode" : "BD", -# "ContactName" : "XAX XAX" -# } ], -# "Address" : [ { -# "AddressTypeCode" : "BT", -# "LocationCodeQualifier" : "92", -# "AddressLocationNumber" : "00", -# "AddressName" : "Worldwide Golf Enterprises", -# "Address1" : "1430 Village Way", -# "Address2" : "Suite J", -# "City" : "Santa Ana", -# "State" : "CA", -# "PostalCode" : "92705" -# }, { -# "AddressTypeCode" : "ST", -# "LocationCodeQualifier" : "92", -# "AddressLocationNumber" : "29", -# "AddressName" : "ROGER DUNN", -# "Address1" : "11849 Foothill Blvd. Ste. D", -# "City" : "RANCHO CUCAMONGA", -# "State" : "CA", -# "PostalCode" : "91730", -# "Country" : "US" -# } ], -# "Notes" : [ { -# "Note" : "https://commerce.spscommerce.com/fulfillment/redirect/?searchType=exact&documentType=Order&keyword=WGE680227-29" -# }, { -# "Note" : "https: //commerce.spscommerce.com/fulfillment-monitor" -# } ] -# }, -# "LineItem" : [ { -# "OrderLine" : { -# "LineSequenceNumber" : "1", -# "VendorPartNumber" : "CYBERE-BL", -# "ConsumerPackageCode" : "849650001612", -# "OrderQty" : 1.0, -# "OrderQtyUOM" : "EA", -# "PurchasePrice" : 949.0 -# }, -# "ProductOrItemDescription" : [ { -# "ProductCharacteristicCode" : "08", -# "ProductDescription" : "CYBERCART" -# } ] -# } ], -# "Summary" : { -# "TotalAmount" : 949.0 -# } -# } - - -import frappe import requests -import json - -# SPS Commerce API URL (Updated) -SPS_API_URL = "https://api.spscommerce.com/transactions/v5/data/testin/" - - - - - import json import frappe from datetime import datetime, timedelta @@ -299,13 +109,13 @@ def sales_order_acknowledgement(data: dict): return # Debugging prints - print("Final JSON Payload:", json.dumps(formatted_data, indent=2)) - print(f"Request URL: {SPS_API_URL}") - print(f"Headers: {headers}") - print(f"Sending Request to SPS Commerce...") + # print("Final JSON Payload:", json.dumps(formatted_data, indent=2)) + # print(f"Request URL: {SPS_API_URL}") + # print(f"Headers: {headers}") + # print(f"Sending Request to SPS Commerce...") # Corrected API request (Using json= instead of data=) - response = requests.post(url=SPS_API_URL, headers=headers, data=json.dumps(formatted_data)) + response = requests.post(url=doc.custom_order_acknowledgement_url, headers=headers, data=json.dumps(formatted_data)) print(f"Response Status Code: {response.status_code}") print(f"Response Headers: {response.headers}") diff --git a/sps_integration/sps_integration/order_sync.py b/sps_integration/sps_integration/order_sync.py index c703aeb..068631c 100644 --- a/sps_integration/sps_integration/order_sync.py +++ b/sps_integration/sps_integration/order_sync.py @@ -8,7 +8,7 @@ from .orders_utills import (check_customer_if_exists, create_customer_if_not_exists) # from .order_acknowledgement import get_sales_order_pyload from .validate_creds import validate_api_user -from .constants import SPS_SO_URL +# from .constants import SPS_SO_URL import requests from frappe.utils import get_datetime, now_datetime from .oauth import refresh_access_token @@ -115,12 +115,13 @@ def get_sps_sales_order(doc: str): response = requests.get(url=so_url, headers=headers) if response.status_code == 200: - create_sps_sales_order( + sales_order = create_sps_sales_order( data=response.json(), setting_doc=doc, path=path ) - sales_order_acknowledgement(data=response.json()) + if frappe.db.exists("Sales Order", {"name": sales_order, "docstatus":1}): + sales_order_acknowledgement(data=response.json()) else: failed_requests.append(so_url) except requests.RequestException as e: @@ -153,7 +154,7 @@ def retrieve_sps_order_urls(setting_doc_name: str) -> None: "Authorization": f"Bearer {access_token}", "Content-Type": "application/json" } - response = requests.get(url=SPS_SO_URL, + response = requests.get(url=setting_doc.custom_get_sales_order_url, headers=headers ) if response.status_code == 200: @@ -182,7 +183,7 @@ def create_sps_sales_order(data: dict, setting_doc: str, path: str) -> None: data (dict): Sales order payload. setting_doc (str): SPS Integration Settings document. """ - print("Initializing Sales Order creation...") + # print("Initializing Sales Order creation...") # Extract order details order_header = data.get("Header", {}).get("OrderHeader", {}) @@ -209,9 +210,9 @@ def create_sps_sales_order(data: dict, setting_doc: str, path: str) -> None: # Check and create contact if not exists contact_name = check_and_create_contact(data, setting_doc) - print("") - if contact_name: - print(f"Contact verified/created: {contact_name}") + # print("") + # if contact_name: + # print(f"Contact verified/created: {contact_name}") # Create addresses if not exists billing_address, shipping_address = create_address_contact(data, customer_name) @@ -227,11 +228,11 @@ def create_sps_sales_order(data: dict, setting_doc: str, path: str) -> None: if not marketplace_data: frappe.log_error("SPS Order Error", "No wholesale marketplace found.") - print("No wholesale marketplace found. Aborting order creation.") + # print("No wholesale marketplace found. Aborting order creation.") return marketplace_name, series_name = marketplace_data[0] - print(f"Marketplace found: {marketplace_name}, Series: {series_name}") + # print(f"Marketplace found: {marketplace_name}, Series: {series_name}") # Create Sales Order sales_order = frappe.new_doc("Sales Order") @@ -249,7 +250,7 @@ def create_sps_sales_order(data: dict, setting_doc: str, path: str) -> None: if contact_name: sales_order.contact_person = contact_name - print(f"Created Sales Order Document: {sales_order.customer}") + # print(f"Created Sales Order Document: {sales_order.customer}") # Adding items to the sales order for item in data.get("LineItem", []): @@ -265,17 +266,17 @@ def create_sps_sales_order(data: dict, setting_doc: str, path: str) -> None: item_row = create_sps_sales_order_item_row(sku, quantity, amount, uom, description, setting_doc) sales_order.append("items", item_row) - print(f"Added item: {sku}, Quantity: {quantity}, Amount: {amount}") + # print(f"Added item: {sku}, Quantity: {quantity}, Amount: {amount}") try: - print("Saving and submitting Sales Order...") - print(sales_order.__dict__) # Debugging + # print("Saving and submitting Sales Order...") + # print(sales_order.__dict__) # Debugging sales_order.save() sales_order.submit() frappe.db.commit() - - print(f"Sales order successfully created and submitted: {sales_order.name}") + return sales_order.name + # print(f"Sales order successfully created and submitted: {sales_order.name}") except Exception as e: error_msg = frappe.get_traceback() @@ -283,81 +284,8 @@ def create_sps_sales_order(data: dict, setting_doc: str, path: str) -> None: title="Sales Order Creation Error", message=f"Marketplace: SPS\n\nTraceback:\n{error_msg}", ) - print(f"Error while creating sales order: {e}") - -data = { - "Meta" : { - "OrderManagement" : "SA" - }, - "Header" : { - "OrderHeader" : { - "TradingPartnerId" : "0RXALLALPHARDGO", - "PurchaseOrderNumber" : "WGE686124-176", - "TsetPurposeCode" : "00", - "PrimaryPOTypeCode" : "SA", - "PurchaseOrderDate" : "2025-02-27", - "Vendor" : "ALPHAR" - }, - "Dates" : [ { - "DateTimeQualifier" : "010", - "Date" : "2025-02-27" - }, { - "DateTimeQualifier" : "001", - "Date" : "2025-03-27" - } ], - "Contacts" : [ { - "ContactTypeCode" : "BD", - "ContactName" : "Roland Anderson" - } ], - "Address" : [ { - "AddressTypeCode" : "BT", - "LocationCodeQualifier" : "92", - "AddressLocationNumber" : "00", - "AddressName" : "Worldwide Golf Enterprises", - "Address1" : "1430 Village Way", - "Address2" : "Suite J", - "City" : "Santa Ana", - "State" : "CA", - "PostalCode" : "92705" - }, { - "AddressTypeCode" : "ST", - "LocationCodeQualifier" : "92", - "AddressLocationNumber" : "176", - "AddressName" : "GOLF & SKI WAREHOUSE", - "Address1" : "290 PLAINFIELD ROAD", - "City" : "WEST LEBANON", - "State" : "NH", - "PostalCode" : "03784", - "Country" : "US" - } ], - "Notes" : [ { - "Note" : "https://commerce.spscommerce.com/fulfillment/redirect/?searchType=exact&documentType=Order&keyword=WGE686124-176" - }, { - "Note" : "https: //commerce.spscommerce.com/fulfillment-monitor" - } ] - }, - "LineItem" : [ { - "OrderLine" : { - "LineSequenceNumber" : "1", - "VendorPartNumber" : "CYBERE-BL", - "ConsumerPackageCode" : "849650001612", - "OrderQty" : 6.0, - "OrderQtyUOM" : "EA", - "PurchasePrice" : 949.0 - }, - "ProductOrItemDescription" : [ { - "ProductCharacteristicCode" : "08", - "ProductDescription" : "CYBERCART" - } ] - } ], - "Summary" : { - "TotalAmount" : 5694.0 - } -} - -# Trigger the order processing -create_sps_sales_order(data, setting_doc="Develop", path="") -# from sps_integration.sps_integration import order_sync + # print(f"Error while creating sales order: {e}") +