diff --git a/modules/web_shop_shopify/CHANGELOG b/modules/web_shop_shopify/CHANGELOG index 0bb24a79cb..f23a18f157 100644 --- a/modules/web_shop_shopify/CHANGELOG +++ b/modules/web_shop_shopify/CHANGELOG @@ -1,3 +1,4 @@ +* Add routes to open Shopify objects * Add support for credit refunds Version 7.6.0 - 2025-04-28 diff --git a/modules/web_shop_shopify/doc/usage.rst b/modules/web_shop_shopify/doc/usage.rst index e60ef3799c..f3f5384e61 100644 --- a/modules/web_shop_shopify/doc/usage.rst +++ b/modules/web_shop_shopify/doc/usage.rst @@ -65,3 +65,21 @@ Options` selected with an `Attribute For each variant of a product, the value of the :guilabel:`Shopify Options` attributes must be unique. + +.. _Admin links: + +Admin Links +=========== + +The module provides links that offer direct access to the corresponding Tryton +record based on the Shopify identifier. +You can use these links to create an `admin link extension +`_. + + - ``GET`` ``//web_shop_shopify/products/`` + + - ``GET`` ``//web_shop_shopify/products//variants/`` + + - ``GET`` ``//web_shop_shopify/customers/`` + + - ``GET`` ``//web_shop_shopify/orders/`` diff --git a/modules/web_shop_shopify/routes.py b/modules/web_shop_shopify/routes.py index 876b446a62..fc338d6b33 100644 --- a/modules/web_shop_shopify/routes.py +++ b/modules/web_shop_shopify/routes.py @@ -6,7 +6,7 @@ import hmac import logging from trytond.protocols.wrappers import ( - HTTPStatus, Response, abort, with_pool, with_transaction) + HTTPStatus, Response, abort, redirect, with_pool, with_transaction) from trytond.wsgi import app logger = logging.getLogger(__name__) @@ -60,3 +60,68 @@ def order(request, pool, shop): else: logger.info("Unsupported topic '%s'", topic) return Response(status=HTTPStatus.NO_CONTENT) + + +@app.route('//web_shop_shopify/products/', methods={'GET'}) +@app.auth_required +@with_pool +@with_transaction(user='request') +def shopify_product(request, pool, id): + Template = pool.get('product.template') + try: + template, = Template.search( + [('shopify_identifiers.shopify_identifier_char', '=', id)], + limit=1) + except ValueError: + abort(HTTPStatus.NOT_FOUND) + return redirect(template.__href__) + + +@app.route( + '//web_shop_shopify' + '/products//variants/', + methods={'GET'}) +@app.auth_required +@with_pool +@with_transaction(user='request') +def shopify_product_variant(request, pool, product_id, variant_id): + Product = pool.get('product.product') + try: + product, = Product.search([ + ('template.shopify_identifiers.shopify_identifier_char', + '=', product_id), + ('shopify_identifiers.shopify_identifier_char', + '=', variant_id), + ], + limit=1) + except ValueError: + abort(HTTPStatus.NOT_FOUND) + return redirect(product.__href__) + + +@app.route('//web_shop_shopify/customers/', methods={'GET'}) +@app.auth_required +@with_pool +@with_transaction(user='request') +def shopify_customer(request, pool, id): + Party = pool.get('party.party') + try: + party, = Party.search([ + ('shopify_identifiers.shopify_identifier_char', '=', id), + ], limit=1) + except ValueError: + abort(HTTPStatus.NOT_FOUND) + return redirect(party.__href__) + + +@app.route('//web_shop_shopify/orders/', methods={'GET'}) +@app.auth_required +@with_pool +@with_transaction(user='request') +def shopify_order(request, pool, id): + Sale = pool.get('sale.sale') + try: + sale, = Sale.search([('shopify_identifier_char', '=', id)], limit=1) + except ValueError: + abort(HTTPStatus.NOT_FOUND) + return redirect(sale.__href__)