def unregister_webhooks(self): deleted_webhooks = [] for d in self.webhooks: with self.get_shopify_session(temp=True): if not Webhook.exists(d.webhook_id): deleted_webhooks.append(d) continue try: existing_webhooks = self.get_webhooks(d.webhook_id) except Exception as e: make_shopify_log(status="Error", exception=e, rollback=True) continue for webhook in existing_webhooks: try: webhook.destroy() except Exception as e: make_shopify_log(status="Error", exception=e, rollback=True) else: deleted_webhooks.append(d) for d in deleted_webhooks: self.remove(d)
def cancel_shopify_order(shop_name: str, order: "Order", log_id: str = str()): """ Cancel all sales documents if a Shopify order is cancelled. Args: shop_name (str): The name of the Shopify configuration for the store. order (Order): The Shopify order data. log_id (str, optional): The ID of an existing Shopify Log. Defaults to an empty string. """ frappe.set_user("Administrator") frappe.flags.log_id = log_id doctypes = ["Delivery Note", "Sales Invoice", "Sales Order"] for doctype in doctypes: doc = get_shopify_document(shop_name=shop_name, doctype=doctype, order=order) if not doc: continue # recursively cancel all Shopify documents if doc.docstatus == 1: try: # ignore document links to Shopify Payout while cancelling doc.flags.ignore_links = True doc.cancel() except Exception as e: make_shopify_log(status="Error", response_data=order.to_dict(), exception=e, rollback=True) # update the financial status in all linked Shopify Payouts payout_transactions = frappe.get_all( "Shopify Payout Transaction", filters={ frappe.scrub(doctype): doc.name, "source_order_financial_status": ["!=", order.attributes.get("financial_status")] }) for transaction in payout_transactions: frappe.db.set_value( "Shopify Payout Transaction", transaction.name, "source_order_financial_status", frappe.unscrub(order.attributes.get("financial_status")))
def create_shopify_delivery(shop_name: str, shopify_order: "Order", sales_order: "SalesOrder" = None, log_id: str = str(), rollback: bool = False): """ Create Delivery Note documents for each Shopify delivery. Args: shop_name (str): The name of the Shopify configuration for the store. shopify_order (Order): The Shopify order data. sales_order (SalesOrder, optional): The reference Sales Order document for the Shopify order. Defaults to None. log_id (str, optional): The ID of an existing Shopify Log. Defaults to an empty string. rollback (bool, optional): If an error occurs while processing the order, all transactions will be rolled back, if this field is `True`. Defaults to False. Returns: list: The list of created Delivery Note documents, if any, otherwise an empty list. """ if not shopify_order.attributes.get("fulfillments"): return [] if not sales_order: sales_order = get_shopify_document(shop_name=shop_name, doctype="Sales Order", order=shopify_order) if not sales_order or sales_order.docstatus != 1: return [] frappe.flags.log_id = log_id try: delivery_notes = create_delivery_notes(shop_name, shopify_order, sales_order) except Exception as e: make_shopify_log(status="Error", response_data=shopify_order.to_dict(), exception=e, rollback=rollback) return [] else: make_shopify_log(status="Success", response_data=shopify_order.to_dict()) return delivery_notes
def create_shopify_invoice(shop_name: str, shopify_order: "Order", sales_order: "SalesOrder", log_id: str = str()): """ Create a Sales Invoice document for a Shopify order. If the Shopify order is refunded and a submitted Sales Invoice exists, make a sales return against the invoice. Args: shop_name (str): The name of the Shopify configuration for the store. shopify_order (Order): The Shopify order data. sales_order (SalesOrder, optional): The reference Sales Order document for the Shopify order. Defaults to None. log_id (str, optional): The ID of an existing Shopify Log. Defaults to an empty string. Returns: SalesInvoice: The created Sales Invoice document, if any, otherwise None. """ if not shopify_order.attributes.get("financial_status") in [ "paid", "partially_refunded", "refunded" ]: return frappe.flags.log_id = log_id try: sales_invoice = create_sales_invoice(shop_name, shopify_order, sales_order) if sales_invoice and sales_invoice.docstatus == 1: create_sales_return( shop_name=shop_name, shopify_order_id=shopify_order.id, shopify_financial_status=shopify_order.attributes.get( "financial_status"), sales_invoice=sales_invoice) except Exception as e: make_shopify_log(status="Error", response_data=shopify_order.to_dict(), exception=e) else: make_shopify_log(status="Success", response_data=shopify_order.to_dict()) return sales_invoice
def register_webhooks(self): from shopify_integration.webhooks import get_webhook_url, SHOPIFY_WEBHOOK_TOPIC_MAPPER for topic in SHOPIFY_WEBHOOK_TOPIC_MAPPER: with self.get_shopify_session(temp=True): webhook = Webhook.create({ "topic": topic, "address": get_webhook_url(), "format": "json" }) if webhook.is_valid(): self.append("webhooks", { "webhook_id": webhook.id, "method": webhook.topic }) else: make_shopify_log(status="Error", response_data=webhook.to_dict(), exception=webhook.errors.full_messages(), rollback=True)
def sync_items_from_shopify(shop_name: str): """ For a given Shopify store, sync all active products and create Item documents for missing products. Args: shop_name (str): The name of the Shopify configuration for the store. """ frappe.set_user("Administrator") shopify_settings: "ShopifySettings" = frappe.get_doc("Shopify Settings", shop_name) try: shopify_items = shopify_settings.get_products(status="active") except Exception as e: make_shopify_log(status="Error", exception=e, rollback=True) return for shopify_item in shopify_items: shopify_item: Product make_item(shopify_settings, shopify_item)
def create_shopify_order(shop_name: str, shopify_order: "Order", log_id: str = str()): """ Create a Sales Order document for a Shopify order. Args: shop_name (str): The name of the Shopify configuration for the store. shopify_order (Order): The Shopify order data. log_id (str, optional): The ID of an existing Shopify Log. Defaults to an empty string. Returns: SalesOrder: The created Sales Order document, if any, otherwise None. """ from shopify_integration.customers import validate_customer from shopify_integration.products import validate_item frappe.flags.log_id = log_id existing_so = get_shopify_document(shop_name=shop_name, doctype="Sales Order", order=shopify_order) if existing_so: existing_so: "SalesOrder" make_shopify_log(status="Skipped", response_data=shopify_order.to_dict()) return existing_so try: validate_customer(shop_name, shopify_order) validate_item(shop_name, shopify_order) sales_order = create_sales_order(shop_name, shopify_order) except Exception as e: make_shopify_log(status="Error", response_data=shopify_order.to_dict(), exception=e) else: make_shopify_log(status="Success", response_data=shopify_order.to_dict()) return sales_order
def prepare_sales_invoice(shop_name: str, order: "Order", log_id: str = str()): """ Webhook endpoint to process invoices for Shopify orders. Args: shop_name (str): The name of the Shopify configuration for the store. order (Order): The Shopify order data. log_id (str, optional): The ID of an existing Shopify Log. Defaults to an empty string. """ from shopify_integration.orders import create_shopify_documents frappe.set_user("Administrator") frappe.flags.log_id = log_id try: sales_order = get_shopify_document(shop_name=shop_name, doctype="Sales Order", order=order) if not sales_order: create_shopify_documents(shop_name, order, log_id) sales_order = get_shopify_document(shop_name=shop_name, doctype="Sales Order", order=order) if sales_order: sales_order: "SalesOrder" create_sales_invoice(shop_name, order, sales_order) make_shopify_log(status="Success", response_data=order.to_dict()) else: make_shopify_log(status="Skipped", response_data=order.to_dict()) except Exception as e: make_shopify_log(status="Error", response_data=order.to_dict(), exception=e, rollback=True)