From 3fc701158528c3808a8f479846b1f033b4b8df2c Mon Sep 17 00:00:00 2001 From: fowczrek Date: Thu, 29 Dec 2022 12:54:30 +0100 Subject: [PATCH 1/9] Use replicas to fetching disount info --- saleor/discount/utils.py | 48 ++++++++++++++++++-------- saleor/graphql/discount/dataloaders.py | 12 ++++--- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/saleor/discount/utils.py b/saleor/discount/utils.py index 47b3d917e67..d1790dad324 100644 --- a/saleor/discount/utils.py +++ b/saleor/discount/utils.py @@ -14,6 +14,7 @@ cast, ) +from django.conf import settings from django.db.models import F from django.utils import timezone from prices import Money, TaxedMoney @@ -100,7 +101,7 @@ def get_product_discounts( collections: Iterable["Collection"], discounts: Iterable[DiscountInfo], channel: "Channel", - variant_id: Optional[int] = None + variant_id: Optional[int] = None, ) -> Iterator[Tuple[int, Callable]]: """Return sale ids, discount values for all discounts applicable to a product.""" product_collections = set(pc.id for pc in collections) @@ -120,7 +121,7 @@ def get_sale_id_with_min_price( collections: Iterable["Collection"], discounts: Optional[Iterable[DiscountInfo]], channel: "Channel", - variant_id: Optional[int] = None + variant_id: Optional[int] = None, ) -> Tuple[Optional[int], Money]: """Return a sale_id and minimum product's price.""" available_discounts = [ @@ -150,7 +151,7 @@ def calculate_discounted_price( collections: Iterable["Collection"], discounts: Optional[Iterable[DiscountInfo]], channel: "Channel", - variant_id: Optional[int] = None + variant_id: Optional[int] = None, ) -> Money: """Return minimum product's price of all prices with discounts applied.""" if discounts: @@ -172,7 +173,7 @@ def get_sale_id_applied_as_a_discount( collections: Iterable["Collection"], discounts: Optional[Iterable[DiscountInfo]], channel: "Channel", - variant_id: Optional[int] = None + variant_id: Optional[int] = None, ) -> Optional[int]: """Return an ID of Sale applied to product.""" if not discounts: @@ -257,11 +258,15 @@ def get_products_voucher_discount( return total_amount -def fetch_categories(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: +def fetch_categories( + sale_pks: Iterable[str], + database_connection_name: str = settings.DATABASE_CONNECTION_DEFAULT_NAME, +) -> Dict[int, Set[int]]: from ..product.models import Category categories = ( - Sale.categories.through.objects.filter(sale_id__in=sale_pks) + Sale.categories.through.objects.using(database_connection_name) + .filter(sale_id__in=sale_pks) .order_by("id") .values_list("sale_id", "category_id") ) @@ -278,9 +283,13 @@ def fetch_categories(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: return subcategory_map -def fetch_collections(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: +def fetch_collections( + sale_pks: Iterable[str], + database_connection_name: str = settings.DATABASE_CONNECTION_DEFAULT_NAME, +) -> Dict[int, Set[int]]: collections = ( - Sale.collections.through.objects.filter(sale_id__in=sale_pks) + Sale.collections.through.objects.using(database_connection_name) + .filter(sale_id__in=sale_pks) .order_by("id") .values_list("sale_id", "collection_id") ) @@ -290,9 +299,13 @@ def fetch_collections(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: return collection_map -def fetch_products(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: +def fetch_products( + sale_pks: Iterable[str], + database_connection_name: str = settings.DATABASE_CONNECTION_DEFAULT_NAME, +) -> Dict[int, Set[int]]: products = ( - Sale.products.through.objects.filter(sale_id__in=sale_pks) + Sale.products.through.objects.using(database_connection_name) + .filter(sale_id__in=sale_pks) .order_by("id") .values_list("sale_id", "product_id") ) @@ -302,9 +315,13 @@ def fetch_products(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: return product_map -def fetch_variants(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: +def fetch_variants( + sale_pks: Iterable[str], + database_connection_name: str = settings.DATABASE_CONNECTION_DEFAULT_NAME, +) -> Dict[int, Set[int]]: variants = ( - Sale.variants.through.objects.filter(sale_id__in=sale_pks) + Sale.variants.through.objects.using(database_connection_name) + .filter(sale_id__in=sale_pks) .order_by("id") .values_list("sale_id", "productvariant_id") ) @@ -316,9 +333,12 @@ def fetch_variants(sale_pks: Iterable[str]) -> Dict[int, Set[int]]: def fetch_sale_channel_listings( sale_pks: Iterable[str], + database_connection_name: str = settings.DATABASE_CONNECTION_DEFAULT_NAME, ): - channel_listings = SaleChannelListing.objects.filter(sale_id__in=sale_pks).annotate( - channel_slug=F("channel__slug") + channel_listings = ( + SaleChannelListing.objects.using(database_connection_name) + .filter(sale_id__in=sale_pks) + .annotate(channel_slug=F("channel__slug")) ) channel_listings_map: Dict[int, Dict[str, SaleChannelListing]] = defaultdict(dict) for channel_listing in channel_listings: diff --git a/saleor/graphql/discount/dataloaders.py b/saleor/graphql/discount/dataloaders.py index 8cfe2c51e7c..adde23a558e 100644 --- a/saleor/graphql/discount/dataloaders.py +++ b/saleor/graphql/discount/dataloaders.py @@ -33,11 +33,13 @@ def batch_load(self, keys): for datetime in keys } pks = {s.pk for d, ss in sales_map.items() for s in ss} - collections = fetch_collections(pks) - channel_listings = fetch_sale_channel_listings(pks) - products = fetch_products(pks) - categories = fetch_categories(pks) - variants = fetch_variants(pks) + collections = fetch_collections(pks, self.database_connection_name) + channel_listings = fetch_sale_channel_listings( + pks, self.database_connection_name + ) + products = fetch_products(pks, self.database_connection_name) + categories = fetch_categories(pks, self.database_connection_name) + variants = fetch_variants(pks, self.database_connection_name) return [ [ From 6a18e04f97b88b970cdf2cc6328c975483041519 Mon Sep 17 00:00:00 2001 From: fowczrek Date: Fri, 30 Dec 2022 12:02:55 +0100 Subject: [PATCH 2/9] Release 3.1.40 --- package-lock.json | 4 ++-- package.json | 2 +- pyproject.toml | 2 +- saleor/__init__.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c11be0698ad..951240b2c76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "saleor", - "version": "3.1.39", + "version": "3.1.40", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "saleor", - "version": "3.1.39", + "version": "3.1.40", "license": "BSD-3-Clause", "devDependencies": { "@release-it/bumper": "^3.0.1", diff --git a/package.json b/package.json index acd2feb502d..d0f2aed1d35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "saleor", - "version": "3.1.39", + "version": "3.1.40", "engines": { "node": ">=16 <17", "npm": ">=7" diff --git a/pyproject.toml b/pyproject.toml index ef9f27a9edc..493df73d47a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "saleor" -version = "3.1.39" +version = "3.1.40" description = "A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React." authors = [ "Saleor Commerce " ] license = "BSD-3-Clause" diff --git a/saleor/__init__.py b/saleor/__init__.py index e0cd32dedcf..9e37118c4d9 100644 --- a/saleor/__init__.py +++ b/saleor/__init__.py @@ -3,7 +3,7 @@ from .celeryconf import app as celery_app __all__ = ["celery_app"] -__version__ = "3.1.39" +__version__ = "3.1.40" def patched_print_object(type): From 08d73c28dad61d2707d7f1c8e76f1e20569df367 Mon Sep 17 00:00:00 2001 From: Mika <6186720+NyanKiyoshi@users.noreply.github.com> Date: Mon, 2 Jan 2023 10:45:10 +0100 Subject: [PATCH 3/9] Bump pillow to 9.4.0 (#11612) This updates `pillow` to 9.4.0 which contains two security fixes related to `ImageFont.py` Details: https://pillow.readthedocs.io/en/stable/releasenotes/9.4.0.html --- poetry.lock | 133 +++++++++++++++++++++++-------------------- requirements.txt | 2 +- requirements_dev.txt | 2 +- 3 files changed, 74 insertions(+), 63 deletions(-) diff --git a/poetry.lock b/poetry.lock index af38d806579..5744515ac8d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1645,14 +1645,14 @@ python-versions = "*" [[package]] name = "Pillow" -version = "9.3.0" +version = "9.4.0" description = "Python Imaging Library (Fork)" category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] [[package]] @@ -3821,65 +3821,69 @@ phonenumberslite = [ {file = "phonenumberslite-8.12.48.tar.gz", hash = "sha256:7cd291fa401da6a3313c3309b2dfc5c10caad4878b7b388185cebda054e3e210"}, ] Pillow = [ - {file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"}, - {file = "Pillow-9.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b90f7616ea170e92820775ed47e136208e04c967271c9ef615b6fbd08d9af0e3"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68943d632f1f9e3dce98908e873b3a090f6cba1cbb1b892a9e8d97c938871fbe"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be55f8457cd1eac957af0c3f5ece7bc3f033f89b114ef30f710882717670b2a8"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d77adcd56a42d00cc1be30843d3426aa4e660cab4a61021dc84467123f7a00c"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:829f97c8e258593b9daa80638aee3789b7df9da5cf1336035016d76f03b8860c"}, - {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:801ec82e4188e935c7f5e22e006d01611d6b41661bba9fe45b60e7ac1a8f84de"}, - {file = "Pillow-9.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:871b72c3643e516db4ecf20efe735deb27fe30ca17800e661d769faab45a18d7"}, - {file = "Pillow-9.3.0-cp310-cp310-win32.whl", hash = "sha256:655a83b0058ba47c7c52e4e2df5ecf484c1b0b0349805896dd350cbc416bdd91"}, - {file = "Pillow-9.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:9f47eabcd2ded7698106b05c2c338672d16a6f2a485e74481f524e2a23c2794b"}, - {file = "Pillow-9.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:57751894f6618fd4308ed8e0c36c333e2f5469744c34729a27532b3db106ee20"}, - {file = "Pillow-9.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7db8b751ad307d7cf238f02101e8e36a128a6cb199326e867d1398067381bff4"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3033fbe1feb1b59394615a1cafaee85e49d01b51d54de0cbf6aa8e64182518a1"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22b012ea2d065fd163ca096f4e37e47cd8b59cf4b0fd47bfca6abb93df70b34c"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a65733d103311331875c1dca05cb4606997fd33d6acfed695b1232ba1df193"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:502526a2cbfa431d9fc2a079bdd9061a2397b842bb6bc4239bb176da00993812"}, - {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:90fb88843d3902fe7c9586d439d1e8c05258f41da473952aa8b328d8b907498c"}, - {file = "Pillow-9.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:89dca0ce00a2b49024df6325925555d406b14aa3efc2f752dbb5940c52c56b11"}, - {file = "Pillow-9.3.0-cp311-cp311-win32.whl", hash = "sha256:3168434d303babf495d4ba58fc22d6604f6e2afb97adc6a423e917dab828939c"}, - {file = "Pillow-9.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:18498994b29e1cf86d505edcb7edbe814d133d2232d256db8c7a8ceb34d18cef"}, - {file = "Pillow-9.3.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:772a91fc0e03eaf922c63badeca75e91baa80fe2f5f87bdaed4280662aad25c9"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa4107d1b306cdf8953edde0534562607fe8811b6c4d9a486298ad31de733b2"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4012d06c846dc2b80651b120e2cdd787b013deb39c09f407727ba90015c684f"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77ec3e7be99629898c9a6d24a09de089fa5356ee408cdffffe62d67bb75fdd72"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:6c738585d7a9961d8c2821a1eb3dcb978d14e238be3d70f0a706f7fa9316946b"}, - {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:828989c45c245518065a110434246c44a56a8b2b2f6347d1409c787e6e4651ee"}, - {file = "Pillow-9.3.0-cp37-cp37m-win32.whl", hash = "sha256:82409ffe29d70fd733ff3c1025a602abb3e67405d41b9403b00b01debc4c9a29"}, - {file = "Pillow-9.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:41e0051336807468be450d52b8edd12ac60bebaa97fe10c8b660f116e50b30e4"}, - {file = "Pillow-9.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b03ae6f1a1878233ac620c98f3459f79fd77c7e3c2b20d460284e1fb370557d4"}, - {file = "Pillow-9.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4390e9ce199fc1951fcfa65795f239a8a4944117b5935a9317fb320e7767b40f"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40e1ce476a7804b0fb74bcfa80b0a2206ea6a882938eaba917f7a0f004b42502"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a06a052c5f37b4ed81c613a455a81f9a3a69429b4fd7bb913c3fa98abefc20"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03150abd92771742d4a8cd6f2fa6246d847dcd2e332a18d0c15cc75bf6703040"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:15c42fb9dea42465dfd902fb0ecf584b8848ceb28b41ee2b58f866411be33f07"}, - {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:51e0e543a33ed92db9f5ef69a0356e0b1a7a6b6a71b80df99f1d181ae5875636"}, - {file = "Pillow-9.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3dd6caf940756101205dffc5367babf288a30043d35f80936f9bfb37f8355b32"}, - {file = "Pillow-9.3.0-cp38-cp38-win32.whl", hash = "sha256:f1ff2ee69f10f13a9596480335f406dd1f70c3650349e2be67ca3139280cade0"}, - {file = "Pillow-9.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:276a5ca930c913f714e372b2591a22c4bd3b81a418c0f6635ba832daec1cbcfc"}, - {file = "Pillow-9.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:73bd195e43f3fadecfc50c682f5055ec32ee2c933243cafbfdec69ab1aa87cad"}, - {file = "Pillow-9.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c7c8ae3864846fc95f4611c78129301e203aaa2af813b703c55d10cc1628535"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0918e03aa0c72ea56edbb00d4d664294815aa11291a11504a377ea018330d3"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0915e734b33a474d76c28e07292f196cdf2a590a0d25bcc06e64e545f2d146c"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0372acb5d3598f36ec0914deed2a63f6bcdb7b606da04dc19a88d31bf0c05b"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ad58d27a5b0262c0c19b47d54c5802db9b34d38bbf886665b626aff83c74bacd"}, - {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:97aabc5c50312afa5e0a2b07c17d4ac5e865b250986f8afe2b02d772567a380c"}, - {file = "Pillow-9.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9aaa107275d8527e9d6e7670b64aabaaa36e5b6bd71a1015ddd21da0d4e06448"}, - {file = "Pillow-9.3.0-cp39-cp39-win32.whl", hash = "sha256:bac18ab8d2d1e6b4ce25e3424f709aceef668347db8637c2296bcf41acb7cf48"}, - {file = "Pillow-9.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:b472b5ea442148d1c3e2209f20f1e0bb0eb556538690fa70b5e1f79fa0ba8dc2"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ab388aaa3f6ce52ac1cb8e122c4bd46657c15905904b3120a6248b5b8b0bc228"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb8e7f2abee51cef77673be97760abff1674ed32847ce04b4af90f610144c7b"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca31dd6014cb8b0b2db1e46081b0ca7d936f856da3b39744aef499db5d84d02"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c7025dce65566eb6e89f56c9509d4f628fddcedb131d9465cacd3d8bac337e7e"}, - {file = "Pillow-9.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ebf2029c1f464c59b8bdbe5143c79fa2045a581ac53679733d3a91d400ff9efb"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b59430236b8e58840a0dfb4099a0e8717ffb779c952426a69ae435ca1f57210c"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12ce4932caf2ddf3e41d17fc9c02d67126935a44b86df6a206cf0d7161548627"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae5331c23ce118c53b172fa64a4c037eb83c9165aba3a7ba9ddd3ec9fa64a699"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:0b07fffc13f474264c336298d1b4ce01d9c5a011415b79d4ee5527bb69ae6f65"}, - {file = "Pillow-9.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8"}, - {file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"}, + {file = "Pillow-9.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157"}, + {file = "Pillow-9.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070"}, + {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28"}, + {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35"}, + {file = "Pillow-9.4.0-cp310-cp310-win32.whl", hash = "sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a"}, + {file = "Pillow-9.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391"}, + {file = "Pillow-9.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133"}, + {file = "Pillow-9.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d"}, + {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8"}, + {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a"}, + {file = "Pillow-9.4.0-cp311-cp311-win32.whl", hash = "sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c"}, + {file = "Pillow-9.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee"}, + {file = "Pillow-9.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5"}, + {file = "Pillow-9.4.0-cp37-cp37m-win32.whl", hash = "sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e"}, + {file = "Pillow-9.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6"}, + {file = "Pillow-9.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9"}, + {file = "Pillow-9.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b"}, + {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f"}, + {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628"}, + {file = "Pillow-9.4.0-cp38-cp38-win32.whl", hash = "sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d"}, + {file = "Pillow-9.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a"}, + {file = "Pillow-9.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569"}, + {file = "Pillow-9.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6"}, + {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2"}, + {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153"}, + {file = "Pillow-9.4.0-cp39-cp39-win32.whl", hash = "sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c"}, + {file = "Pillow-9.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9"}, + {file = "Pillow-9.4.0.tar.gz", hash = "sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e"}, ] platformdirs = [ {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, @@ -4169,6 +4173,13 @@ pyyaml = [ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, diff --git a/requirements.txt b/requirements.txt index d9533d68e6f..6c4b73b7acc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -96,7 +96,7 @@ opentracing==2.4.0 ; python_version >= "3.9" and python_version < "3.10" packaging==21.3 ; python_version >= "3.9" and python_version < "3.10" petl==1.7.8 ; python_version >= "3.9" and python_version < "3.10" phonenumberslite==8.12.48 ; python_version >= "3.9" and python_version < "3.10" -pillow==9.3.0 ; python_version >= "3.9" and python_version < "3.10" +pillow==9.4.0 ; python_version >= "3.9" and python_version < "3.10" posuto==2022.5.0 ; python_version >= "3.9" and python_version < "3.10" prices==1.1.0 ; python_version >= "3.9" and python_version < "3.10" promise==2.3 ; python_version >= "3.9" and python_version < "3.10" diff --git a/requirements_dev.txt b/requirements_dev.txt index 0684e97692a..2dc9efdf30d 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -129,7 +129,7 @@ packaging==21.3 ; python_version >= "3.9" and python_version < "3.10" pathspec==0.9.0 ; python_version >= "3.9" and python_version < "3.10" petl==1.7.8 ; python_version >= "3.9" and python_version < "3.10" phonenumberslite==8.12.48 ; python_version >= "3.9" and python_version < "3.10" -pillow==9.3.0 ; python_version >= "3.9" and python_version < "3.10" +pillow==9.4.0 ; python_version >= "3.9" and python_version < "3.10" platformdirs==2.5.2 ; python_version >= "3.9" and python_version < "3.10" pluggy==1.0.0 ; python_version >= "3.9" and python_version < "3.10" posuto==2022.5.0 ; python_version >= "3.9" and python_version < "3.10" From f56fa02eb69068323e55eeaa5638b5f58337c323 Mon Sep 17 00:00:00 2001 From: Mikail Kocak Date: Mon, 2 Jan 2023 10:46:02 +0100 Subject: [PATCH 4/9] Release 3.1.41 --- package-lock.json | 2 +- package.json | 2 +- pyproject.toml | 2 +- saleor/__init__.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 951240b2c76..cfe0aff994d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "saleor", - "version": "3.1.40", + "version": "3.1.41", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index d0f2aed1d35..2543fe0fbb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "saleor", - "version": "3.1.40", + "version": "3.1.41", "engines": { "node": ">=16 <17", "npm": ">=7" diff --git a/pyproject.toml b/pyproject.toml index 493df73d47a..42b9dc699d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "saleor" -version = "3.1.40" +version = "3.1.41" description = "A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React." authors = [ "Saleor Commerce " ] license = "BSD-3-Clause" diff --git a/saleor/__init__.py b/saleor/__init__.py index 9e37118c4d9..8659dfb834f 100644 --- a/saleor/__init__.py +++ b/saleor/__init__.py @@ -3,7 +3,7 @@ from .celeryconf import app as celery_app __all__ = ["celery_app"] -__version__ = "3.1.40" +__version__ = "3.1.41" def patched_print_object(type): From f8a823479d209eac5d2969ea4dca4c44fa9fabd0 Mon Sep 17 00:00:00 2001 From: Maciej Korycinski Date: Mon, 9 Jan 2023 16:04:39 +0100 Subject: [PATCH 5/9] Fix missing psp references for some adyen payments (#11662) --- saleor/payment/gateways/adyen/plugin.py | 1 + .../test_handle_additional_actions.py | 39 ++++++++++++++++ .../webhooks/test_handle_notifications.py | 46 +++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/saleor/payment/gateways/adyen/plugin.py b/saleor/payment/gateways/adyen/plugin.py index e5eabda9482..63d7736f674 100644 --- a/saleor/payment/gateways/adyen/plugin.py +++ b/saleor/payment/gateways/adyen/plugin.py @@ -642,6 +642,7 @@ def confirm_payment( error=None, raw_response={}, transaction_already_processed=bool(transaction_already_processed), + psp_reference=token, ) @require_active_plugin diff --git a/saleor/payment/gateways/adyen/tests/webhooks/test_handle_additional_actions.py b/saleor/payment/gateways/adyen/tests/webhooks/test_handle_additional_actions.py index 7c7af3017c1..331e6308e67 100644 --- a/saleor/payment/gateways/adyen/tests/webhooks/test_handle_additional_actions.py +++ b/saleor/payment/gateways/adyen/tests/webhooks/test_handle_additional_actions.py @@ -159,6 +159,45 @@ def test_handle_additional_actions_handles_return_urls( assert response.status_code == 302 +@mock.patch("saleor.payment.gateways.adyen.webhooks.api_call") +def test_handle_additional_actions_sets_psp_reference( + api_call_mock, payment_adyen_for_checkout, adyen_plugin +): + # given + plugin = adyen_plugin() + channel_slug = plugin.channel.slug + payment_adyen_for_checkout.to_confirm = True + payment_adyen_for_checkout.extra_data = json.dumps( + {"payment_data": "test_data", "parameters": ["payload"]} + ) + payment_adyen_for_checkout.save(update_fields=["to_confirm", "extra_data"]) + + checkout = payment_adyen_for_checkout.checkout + payment_id = graphene.Node.to_global_id("Payment", payment_adyen_for_checkout.pk) + + request_mock = mock.Mock() + request_mock.GET = { + "payment": payment_id, + "checkout": str(checkout.pk), + "payload": "test", + } + + expected_psp_reference = "psp-11111" + payment_details_mock = mock.Mock() + message = { + "pspReference": expected_psp_reference, + "resultCode": "authorised", + } + api_call_mock.return_value.message = message + + # when + handle_additional_actions(request_mock, payment_details_mock, channel_slug) + + # then + payment_adyen_for_checkout.refresh_from_db() + assert payment_adyen_for_checkout.psp_reference == expected_psp_reference + + @mock.patch("saleor.payment.gateways.adyen.webhooks.api_call") def test_handle_additional_actions_get( api_call_mock, payment_adyen_for_checkout, adyen_plugin diff --git a/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py b/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py index 8e4cbb5574b..0e238a3f20a 100644 --- a/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py +++ b/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py @@ -146,6 +146,52 @@ def test_handle_authorization_for_pending_order( assert external_events.count() == 1 +def test_handle_authorization_sets_psp_reference( + notification, + adyen_plugin, + payment_adyen_for_checkout, + address, + shipping_method, +): + # given + checkout = payment_adyen_for_checkout.checkout + checkout.shipping_address = address + checkout.shipping_method = shipping_method + checkout.billing_address = address + checkout.save() + + payment = payment_adyen_for_checkout + manager = get_plugins_manager() + lines, _ = fetch_checkout_lines(checkout) + checkout_info = fetch_checkout_info(checkout, lines, [], manager) + total = calculations.calculate_checkout_total_with_gift_cards( + manager, checkout_info, lines, address + ) + payment.is_active = True + payment.order = None + payment.total = total.gross.amount + payment.currency = total.gross.currency + payment.to_confirm = True + payment.save() + + expected_psp_reference = "psp-123" + + payment_id = graphene.Node.to_global_id("Payment", payment.pk) + notification = notification( + psp_reference=expected_psp_reference, + merchant_reference=payment_id, + value=price_to_minor_unit(payment.total, payment.currency), + ) + config = adyen_plugin().config + + # when + handle_authorization(notification, config) + + # then + payment.refresh_from_db() + assert payment.psp_reference == expected_psp_reference + + def test_handle_authorization_for_checkout( notification, adyen_plugin, From b00644399934275de6a3fb8659f7bc6da3df83ce Mon Sep 17 00:00:00 2001 From: Maciej Korycinski Date: Mon, 9 Jan 2023 16:06:16 +0100 Subject: [PATCH 6/9] Release 3.1.42 --- package-lock.json | 4 ++-- package.json | 2 +- pyproject.toml | 2 +- saleor/__init__.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfe0aff994d..f48babb7b9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "saleor", - "version": "3.1.41", + "version": "3.1.42", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "saleor", - "version": "3.1.40", + "version": "3.1.42", "license": "BSD-3-Clause", "devDependencies": { "@release-it/bumper": "^3.0.1", diff --git a/package.json b/package.json index 2543fe0fbb3..5e721a13c37 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "saleor", - "version": "3.1.41", + "version": "3.1.42", "engines": { "node": ">=16 <17", "npm": ">=7" diff --git a/pyproject.toml b/pyproject.toml index 42b9dc699d5..cb33fd3ecf4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "saleor" -version = "3.1.41" +version = "3.1.42" description = "A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React." authors = [ "Saleor Commerce " ] license = "BSD-3-Clause" diff --git a/saleor/__init__.py b/saleor/__init__.py index 8659dfb834f..cba3bc39974 100644 --- a/saleor/__init__.py +++ b/saleor/__init__.py @@ -3,7 +3,7 @@ from .celeryconf import app as celery_app __all__ = ["celery_app"] -__version__ = "3.1.41" +__version__ = "3.1.42" def patched_print_object(type): From d01e06aff41d56d8255f3b92589693bd9a371ae9 Mon Sep 17 00:00:00 2001 From: Maciej Korycinski Date: Tue, 10 Jan 2023 13:34:15 +0100 Subject: [PATCH 7/9] Workaround for failing sphinxcontrib-applehelp dependency (#11676) * Workaround for failing dependency * Add sphinxcontrib-applehelp dependency to pytest CI * replace path for flake8 in pre-commit, from gitlab to github --- .github/workflows/pytest.yml | 3 +++ .pre-commit-config.yaml | 2 +- Dockerfile | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 09d79a99fd2..3a67f26366e 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -44,8 +44,11 @@ jobs: restore-keys: | ${{ runner.os }}-pip- + # sphinxcontrib-applehelp added due to https://github.com/coddingtonbear/python-measurement/issues/75. + # To remove once the issue is resolved. - name: Install dependencies run: | + python -m pip install sphinxcontrib-applehelp==1.0.2 python -m pip install wheel python -m pip install -r requirements_dev.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a78cff36c57..a19b8c8ceac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: exclude: ^templates/templated_email/compiled/ exclude_types: [svg] - - repo: https://gitlab.com/pycqa/flake8 + - repo: https://github.com/PyCQA/flake8 rev: 3.9.2 hooks: - id: flake8 diff --git a/Dockerfile b/Dockerfile index 78e106ef1c2..29472003e6b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,8 @@ RUN apt-get -y update \ # Install Python dependencies COPY requirements_dev.txt /app/ WORKDIR /app +## sphinxcontrib-applehelp installed due to https://github.com/saleor/saleor/issues/11664 +RUN pip install sphinxcontrib-applehelp==1.0.2 RUN pip install -r requirements_dev.txt ### Final image From 36a9623d8b53177f5865d043425e1fae64b2a663 Mon Sep 17 00:00:00 2001 From: Maciej Korycinski Date: Tue, 10 Jan 2023 13:37:16 +0100 Subject: [PATCH 8/9] Release 3.1.43 --- package-lock.json | 4 ++-- package.json | 2 +- pyproject.toml | 2 +- saleor/__init__.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f48babb7b9c..f9ac7ddd4c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "saleor", - "version": "3.1.42", + "version": "3.1.43", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "saleor", - "version": "3.1.42", + "version": "3.1.43", "license": "BSD-3-Clause", "devDependencies": { "@release-it/bumper": "^3.0.1", diff --git a/package.json b/package.json index 5e721a13c37..db7545bb5cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "saleor", - "version": "3.1.42", + "version": "3.1.43", "engines": { "node": ">=16 <17", "npm": ">=7" diff --git a/pyproject.toml b/pyproject.toml index cb33fd3ecf4..111408bbd6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "saleor" -version = "3.1.42" +version = "3.1.43" description = "A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React." authors = [ "Saleor Commerce " ] license = "BSD-3-Clause" diff --git a/saleor/__init__.py b/saleor/__init__.py index cba3bc39974..de4eb69ed0a 100644 --- a/saleor/__init__.py +++ b/saleor/__init__.py @@ -3,7 +3,7 @@ from .celeryconf import app as celery_app __all__ = ["celery_app"] -__version__ = "3.1.42" +__version__ = "3.1.43" def patched_print_object(type): From 7c80fb767c0191cc1a7fafe83f6ba1008d7a558f Mon Sep 17 00:00:00 2001 From: Maciej Korycinski Date: Tue, 10 Jan 2023 15:23:14 +0100 Subject: [PATCH 9/9] Fix Adyen authorize notification handler that raises unhandled exception (#11647) * Improve Adyen authorize notification handler * Add test for out of stock after the payment --- .../webhooks/test_handle_notifications.py | 140 +++++++++++++++++- saleor/payment/gateways/adyen/webhooks.py | 77 ++++------ 2 files changed, 170 insertions(+), 47 deletions(-) diff --git a/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py b/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py index 0e238a3f20a..9f1f1b3b7d8 100644 --- a/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py +++ b/saleor/payment/gateways/adyen/tests/webhooks/test_handle_notifications.py @@ -1,8 +1,9 @@ import logging from decimal import Decimal from unittest import mock -from unittest.mock import patch +from unittest.mock import MagicMock, patch +import before_after import graphene import pytest from django.core.exceptions import ValidationError @@ -11,6 +12,7 @@ from ......checkout.fetch import fetch_checkout_info, fetch_checkout_lines from ......order import OrderEvents, OrderStatus from ......plugins.manager import get_plugins_manager +from ......warehouse.models import Stock from ..... import ChargeStatus, TransactionKind from .....utils import price_to_minor_unit from ...webhooks import ( @@ -285,6 +287,142 @@ def test_handle_authorization_for_checkout_partial_payment( assert not payment.order +@mock.patch("saleor.payment.gateways.adyen.plugin.call_refund") +def test_handle_authorization_for_checkout_out_of_stock_after_payment( + mock_refund, + notification, + adyen_plugin, + payment_adyen_for_checkout, + address, + shipping_method, +): + + refund_response = {"pspReference": "refund-psp"} + mock_refund_response = MagicMock() + mock_refund.return_value = mock_refund_response + mock_refund_response.message = refund_response + + checkout = payment_adyen_for_checkout.checkout + checkout.shipping_address = address + checkout.shipping_method = shipping_method + checkout.billing_address = address + checkout.save() + + payment = payment_adyen_for_checkout + manager = get_plugins_manager() + lines, _ = fetch_checkout_lines(checkout) + checkout_info = fetch_checkout_info(checkout, lines, [], manager) + total = calculations.calculate_checkout_total_with_gift_cards( + manager, checkout_info, lines, address + ) + payment.is_active = True + payment.order = None + payment.total = total.gross.amount + payment.currency = total.gross.currency + payment.to_confirm = True + payment.save() + + payment_id = graphene.Node.to_global_id("Payment", payment.pk) + notification = notification( + psp_reference="reference", + merchant_reference=payment_id, + value=price_to_minor_unit(payment.total, payment.currency), + ) + config = adyen_plugin(adyen_auto_capture=True).config + + # when + def call_after_finalizing_payment(*args, **kwargs): + Stock.objects.all().update(quantity=0) + + with before_after.before( + "saleor.checkout.complete_checkout._create_order", + call_after_finalizing_payment, + ): + handle_authorization(notification, config) + + # then + payment.refresh_from_db() + assert not payment.order + assert payment.checkout + assert ( + payment.transactions.filter( + kind__in=[ + TransactionKind.ACTION_TO_CONFIRM, + TransactionKind.CAPTURE, + TransactionKind.REFUND_ONGOING, + ] + ).count() + == 3 + ) + + +def test_handle_authorization_for_checkout_that_cannot_be_finalized( + notification, + adyen_plugin, + payment_adyen_for_checkout, + address, + shipping_method, +): + # given + checkout = payment_adyen_for_checkout.checkout + checkout.shipping_address = address + checkout.shipping_method = shipping_method + checkout.billing_address = address + checkout.save() + + payment = payment_adyen_for_checkout + manager = get_plugins_manager() + lines, _ = fetch_checkout_lines(checkout) + checkout_info = fetch_checkout_info(checkout, lines, [], manager) + total = calculations.calculate_checkout_total_with_gift_cards( + manager, checkout_info, lines, address + ) + payment.is_active = True + payment.order = None + payment.total = total.gross.amount + payment.currency = total.gross.currency + payment.to_confirm = True + payment.save() + + payment.transactions.create( + token="reference", + kind=TransactionKind.CAPTURE, + is_success=True, + action_required=False, + currency=payment.currency, + amount=payment.total, + gateway_response={}, + ) + payment.transactions.create( + token="refund-reference", + is_success=True, + kind=TransactionKind.REFUND_ONGOING, + action_required=False, + currency=payment.currency, + amount=payment.total, + gateway_response={}, + ) + + checkout.lines.first().delete() + + payment_id = graphene.Node.to_global_id("Payment", payment.pk) + notification = notification( + psp_reference="reference", + merchant_reference=payment_id, + value=price_to_minor_unit(payment.total, payment.currency), + ) + config = adyen_plugin(adyen_auto_capture=True).config + + # when + handle_authorization(notification, config) + + # then + payment.refresh_from_db() + assert not payment.order + assert payment.checkout + assert payment.transactions.count() == 2 + + @patch("saleor.payment.gateway.void") def test_handle_authorization_for_checkout_one_of_variants_deleted( void_mock, diff --git a/saleor/payment/gateways/adyen/webhooks.py b/saleor/payment/gateways/adyen/webhooks.py index 01f778a35eb..09073a5e1d0 100644 --- a/saleor/payment/gateways/adyen/webhooks.py +++ b/saleor/payment/gateways/adyen/webhooks.py @@ -142,7 +142,7 @@ def create_new_transaction(notification, payment, kind): amount=amount, currency=currency, error="", - raw_response={}, + raw_response=notification, psp_reference=transaction_id, ) return create_transaction( @@ -226,15 +226,10 @@ def handle_not_created_order(notification, payment, checkout, kind, manager): ChargeStatus.FULLY_CHARGED, }: return - transaction = payment.transactions.filter( - action_required=False, is_success=True, kind=kind - ).last() - if not transaction: - # If the payment is not Auth/Capture, it means that user didn't return to the - # storefront and we need to finalize the checkout asynchronously. - transaction = create_new_transaction( - notification, payment, TransactionKind.ACTION_TO_CONFIRM - ) + + transaction = create_new_transaction( + notification, payment, TransactionKind.ACTION_TO_CONFIRM + ) # Only when we confirm that notification is success we will create the order if transaction.is_success and checkout: # type: ignore @@ -301,20 +296,11 @@ def handle_authorization(notification: Dict[str, Any], gateway_config: GatewayCo try_void_or_refund_inactive_payment(payment, transaction, manager) return - if not payment.order: - handle_not_created_order(notification, payment, checkout, kind, manager) - else: - adyen_auto_capture = gateway_config.connection_params["adyen_auto_capture"] - kind = TransactionKind.AUTH - if adyen_auto_capture: - kind = TransactionKind.CAPTURE - transaction = payment.transactions.filter( - token=transaction_id, - action_required=False, - is_success=True, - kind__in=[TransactionKind.AUTH, TransactionKind.CAPTURE], - ).last() - if not transaction: + transaction = get_transaction(payment, transaction_id, kind) + if not transaction: + if not payment.order: + handle_not_created_order(notification, payment, checkout, kind, manager) + else: new_transaction = create_new_transaction(notification, payment, kind) if new_transaction.is_success: gateway_postprocess(new_transaction, payment) @@ -337,6 +323,7 @@ def handle_authorization(notification: Dict[str, Any], gateway_config: GatewayCo payment, manager, ) + reason = notification.get("reason", "-") is_success = True if notification.get("success") == "true" else False success_msg = f"Adyen: The payment {transaction_id} request was successful." @@ -413,25 +400,22 @@ def handle_capture(notification: Dict[str, Any], _gateway_config: GatewayConfig) try_void_or_refund_inactive_payment(payment, transaction, manager) return - if not payment.order: - handle_not_created_order( - notification, payment, checkout, TransactionKind.CAPTURE, manager - ) - else: - capture_transaction = payment.transactions.filter( - action_required=False, - is_success=True, - kind=TransactionKind.CAPTURE, - ).last() - new_transaction = create_new_transaction( - notification, payment, TransactionKind.CAPTURE - ) - if new_transaction.is_success and not capture_transaction: - gateway_postprocess(new_transaction, payment) - order_info = fetch_order_info(payment.order) - order_captured( - order_info, None, None, new_transaction.amount, payment, manager + transaction = get_transaction(payment, transaction_id, TransactionKind.CAPTURE) + if not transaction: + if not payment.order: + handle_not_created_order( + notification, payment, checkout, TransactionKind.CAPTURE, manager ) + else: + new_transaction = create_new_transaction( + notification, payment, TransactionKind.CAPTURE + ) + if new_transaction.is_success: + gateway_postprocess(new_transaction, payment) + order_info = fetch_order_info(payment.order) + order_captured( + order_info, None, None, new_transaction.amount, payment, manager + ) reason = notification.get("reason", "-") is_success = True if notification.get("success") == "true" else False @@ -831,10 +815,15 @@ def handle_order_closed(notification: Dict[str, Any], gateway_config: GatewayCon adyen_auto_capture = gateway_config.connection_params["adyen_auto_capture"] kind = TransactionKind.CAPTURE if adyen_auto_capture else TransactionKind.AUTH + order = None try: order = handle_not_created_order( notification, payment, checkout, kind, get_plugins_manager() ) + except Exception as e: + logger.exception("Exception during order creation", extra={"error": e}) + return + finally: if not order and adyen_partial_payments: refund_partial_payments(adyen_partial_payments, config=gateway_config) # There is a possibility that user will try once again to pay with partial @@ -846,10 +835,6 @@ def handle_order_closed(notification: Dict[str, Any], gateway_config: GatewayCon id__in=[p.id for p in adyen_partial_payments] ).update(partial=False) - except Exception as e: - logger.exception("Exception during order creation", extra={"error": e}) - return - if adyen_partial_payments: create_order_event_about_adyen_partial_payments(adyen_partial_payments, payment) else: