ob-dj-store 0.0.11.8__tar.gz → 0.0.11.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/PKG-INFO +1 -1
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/config/settings.py +3 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/stores/filters.py +25 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/stores/rest/serializers/serializers.py +51 -7
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/stores/urls.py +3 -3
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/stores/views.py +92 -31
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/admin.py +6 -6
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/admin_inlines.py +4 -4
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/models.py +1 -1
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/managers.py +1 -3
- ob-dj-store-0.0.11.10/ob_dj_store/core/stores/migrations/0062_auto_20230226_2005.py +43 -0
- ob-dj-store-0.0.11.10/ob_dj_store/core/stores/migrations/0063_alter_store_payment_methods.py +23 -0
- ob-dj-store-0.0.11.10/ob_dj_store/core/stores/migrations/0064_auto_20230228_1814.py +24 -0
- ob-dj-store-0.0.11.10/ob_dj_store/core/stores/migrations/0065_auto_20230228_1932.py +34 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_favorite.py +4 -1
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_order.py +2 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_payment.py +31 -11
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_product.py +3 -5
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_store.py +9 -8
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_wallet.py +41 -8
- ob-dj-store-0.0.11.10/ob_dj_store/core/stores/receivers.py +109 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/utils.py +14 -6
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/utils/helpers.py +7 -1
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/utils/utils.py +3 -2
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store.egg-info/PKG-INFO +1 -1
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store.egg-info/SOURCES.txt +4 -0
- ob-dj-store-0.0.11.8/ob_dj_store/core/stores/receivers.py +0 -55
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.github/dependabot.yml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.github/workflows/docs.yml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.github/workflows/pre-release.yml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.github/workflows/release.yml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.github/workflows/test-build.yml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.gitignore +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.isort.cfg +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/.pre-commit-config.yaml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/Dockerfile +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/MANIFEST.in +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/Makefile +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/Pipfile +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/Pipfile.lock +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/README.md +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/config/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/config/urls.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/config/wsgi.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docker-compose.env +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docker-compose.yml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/Makefile +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/make.bat +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/source/admin.rst +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/source/conf.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/source/index.rst +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/source/installation.rst +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/source/models.rst +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/docs/source/rest_endpoints.rst +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/fixtures/initial_users.yaml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/fixtures/stores.yaml +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/manage.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/stores/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/tap/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/tap/serializers.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/tap/urls.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/apis/tap/views.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/apps.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/admin.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/apps.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/managers.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/migrations/0001_initial.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/migrations/0002_auto_20220815_1610.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/migrations/0003_auto_20220818_1938.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/migrations/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/gateway/tap/utils.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0001_initial.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0002_auto_20220422_0205.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0003_openinghours.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0004_auto_20220422_2326.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0005_auto_20220425_2119.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0005_auto_20220427_1729.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0006_auto_20220428_0100.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0007_cart_cartitem_order_orderitem.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0008_order_status.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0009_auto_20220508_2142.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0010_auto_20220509_1633.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0011_favorite.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0012_auto_20220514_0633.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0013_auto_20220518_1539.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0014_auto_20220519_0018.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0015_inventory_inventoryoperations.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0016_productvariant_preparation_time.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0017_auto_20220524_0912.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0018_auto_20220524_1613.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0019_product_is_featured.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0020_orderhistory.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0021_auto_20220531_1849.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0022_order_pickup_time.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0023_feedback_feedbackattribute_feedbackconfig.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0024_auto_20220609_1552.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0025_productvariant_is_primary.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0026_auto_20220630_1913.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0027_auto_20220713_1759.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0028_phonecontact.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0029_auto_20220726_1750.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0030_category_parent.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0031_auto_20220811_1733.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0032_auto_20220812_1951.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0033_auto_20220815_0133.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0034_auto_20220815_1528.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0035_auto_20220818_1938.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0036_productattribute_is_mandatory.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0037_auto_20220825_1736.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0038_cartitem_extra_infos.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0039_auto_20220831_1521.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0040_auto_20220902_1806.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0041_auto_20220912_1506.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0042_wallet_wallettransaction.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0043_auto_20220919_1854.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0044_remove_productvariant_has_inventory.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0045_shippingmethod_type.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0046_auto_20221014_1720.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0047_auto_20221018_1433.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0048_auto_20221026_1933.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0049_auto_20221029_1524.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0050_favoriteextra.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0051_order_car_id.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0052_auto_20221129_1732.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0053_inventory_plu.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0054_auto_20221230_1501.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0055_store_image.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0056_auto_20230213_2224.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0057_auto_20230214_1724.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0058_attributechoice_is_default.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0059_auto_20230217_2006.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0060_alter_orderitem_product_variant.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/0061_auto_20230223_1435.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/migrations/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_address.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_cart.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_feedback.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/models/_inventory.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/core/stores/settings_validation.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/utils/__init__.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store/utils/model.py +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store.egg-info/dependency_links.txt +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store.egg-info/requires.txt +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/ob_dj_store.egg-info/top_level.txt +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/pytest.ini +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/setup.cfg +0 -0
- {ob-dj-store-0.0.11.8 → ob-dj-store-0.0.11.10}/setup.py +0 -0
@@ -5,10 +5,12 @@ from django.utils.timezone import now
|
|
5
5
|
from django_filters import rest_framework as filters
|
6
6
|
from rest_framework.exceptions import ValidationError
|
7
7
|
|
8
|
+
from config import settings as store_settings
|
8
9
|
from ob_dj_store.core.stores.models import (
|
9
10
|
Category,
|
10
11
|
Favorite,
|
11
12
|
Order,
|
13
|
+
PaymentMethod,
|
12
14
|
Product,
|
13
15
|
ProductVariant,
|
14
16
|
Store,
|
@@ -128,6 +130,7 @@ class CategoryFilter(filters.FilterSet):
|
|
128
130
|
is_active=True,
|
129
131
|
).distinct(),
|
130
132
|
),
|
133
|
+
"subcategories__products__images",
|
131
134
|
)
|
132
135
|
.distinct()
|
133
136
|
)
|
@@ -174,3 +177,25 @@ class FavoriteFilter(filters.FilterSet):
|
|
174
177
|
content_type=content_type,
|
175
178
|
object_id__in=products_ids,
|
176
179
|
)
|
180
|
+
|
181
|
+
|
182
|
+
class PaymentMethodFilter(filters.FilterSet):
|
183
|
+
store = filters.CharFilter(method="by_store")
|
184
|
+
is_digital = filters.BooleanFilter(method="by_digital")
|
185
|
+
|
186
|
+
class Meta:
|
187
|
+
models = PaymentMethod
|
188
|
+
|
189
|
+
def by_store(self, queryset, name, value):
|
190
|
+
return queryset.filter(stores=value)
|
191
|
+
|
192
|
+
def by_digital(self, queryset, name, value):
|
193
|
+
if value:
|
194
|
+
return queryset.filter(
|
195
|
+
payment_provider__in=[
|
196
|
+
store_settings.TAP_CREDIT_CARD,
|
197
|
+
store_settings.TAP_KNET,
|
198
|
+
store_settings.TAP_ALL,
|
199
|
+
]
|
200
|
+
)
|
201
|
+
return queryset
|
@@ -39,6 +39,7 @@ from ob_dj_store.core.stores.models import (
|
|
39
39
|
ShippingMethod,
|
40
40
|
Store,
|
41
41
|
Tax,
|
42
|
+
Wallet,
|
42
43
|
)
|
43
44
|
from ob_dj_store.core.stores.models._inventory import Inventory
|
44
45
|
from ob_dj_store.core.stores.utils import distance
|
@@ -288,7 +289,7 @@ class OrderSerializer(serializers.ModelSerializer):
|
|
288
289
|
if payment_method:
|
289
290
|
if payment_method.payment_provider == store_settings.WALLET:
|
290
291
|
try:
|
291
|
-
wallet = user.wallets.get(
|
292
|
+
wallet = user.wallets.get(currency=attrs["store"].currency)
|
292
293
|
except ObjectDoesNotExist:
|
293
294
|
raise serializers.ValidationError(
|
294
295
|
{
|
@@ -603,7 +604,9 @@ class ProductSerializer(FavoriteMixin, serializers.ModelSerializer):
|
|
603
604
|
return data
|
604
605
|
|
605
606
|
|
606
|
-
class ProductListSerializer(
|
607
|
+
class ProductListSerializer(serializers.ModelSerializer):
|
608
|
+
product_images = ProductMediaSerializer(many=True, source="images")
|
609
|
+
|
607
610
|
class Meta:
|
608
611
|
model = Product
|
609
612
|
fields = (
|
@@ -974,7 +977,11 @@ class FavoriteSerializer(serializers.ModelSerializer):
|
|
974
977
|
"extras",
|
975
978
|
"object_id",
|
976
979
|
"object_type",
|
980
|
+
"name",
|
977
981
|
)
|
982
|
+
extra_kwargs = {
|
983
|
+
"name": {"required": True},
|
984
|
+
}
|
978
985
|
|
979
986
|
def _lookup_validation(self, data):
|
980
987
|
content_type = ContentType.objects.get_for_model(type(data["content_object"]))
|
@@ -1001,6 +1008,7 @@ class FavoriteSerializer(serializers.ModelSerializer):
|
|
1001
1008
|
|
1002
1009
|
def validate(self, attrs):
|
1003
1010
|
validated_data = super().validate(attrs)
|
1011
|
+
name = validated_data["name"]
|
1004
1012
|
object_type = validated_data["object_type"]
|
1005
1013
|
if object_type not in store_settings.FAVORITE_TYPES and hasattr(
|
1006
1014
|
sys.modules[__name__], object_type
|
@@ -1035,14 +1043,50 @@ class FavoriteSerializer(serializers.ModelSerializer):
|
|
1035
1043
|
validated_data = {
|
1036
1044
|
"content_object": object_instance,
|
1037
1045
|
"extras": extras,
|
1046
|
+
"name": name,
|
1038
1047
|
}
|
1039
1048
|
self._lookup_validation(validated_data)
|
1040
1049
|
return validated_data
|
1041
1050
|
|
1042
1051
|
def create(self, validated_data):
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1052
|
+
try:
|
1053
|
+
favorite = Favorite.add_favorite(
|
1054
|
+
content_object=validated_data["content_object"],
|
1055
|
+
user=self.context["request"].user,
|
1056
|
+
name=validated_data["name"],
|
1057
|
+
extras=validated_data["extras"],
|
1058
|
+
)
|
1059
|
+
except ValidationError as e:
|
1060
|
+
raise serializers.ValidationError(detail=e.message_dict)
|
1048
1061
|
return favorite
|
1062
|
+
|
1063
|
+
|
1064
|
+
class WalletSerializer(serializers.ModelSerializer):
|
1065
|
+
class Meta:
|
1066
|
+
model = Wallet
|
1067
|
+
fields = ["id", "user", "balance", "name", "image", "image_thumbnail_medium"]
|
1068
|
+
extra_kwargs = {
|
1069
|
+
"user": {"read_only": True},
|
1070
|
+
"image_thumbnail_medium": {"read_only": True},
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
|
1074
|
+
class WalletTopUpSerializer(serializers.Serializer):
|
1075
|
+
amount = serializers.DecimalField(
|
1076
|
+
max_digits=10, decimal_places=2, min_value=1, required=True
|
1077
|
+
)
|
1078
|
+
payment_method = serializers.PrimaryKeyRelatedField(
|
1079
|
+
queryset=PaymentMethod.objects.filter(
|
1080
|
+
payment_provider__in=[
|
1081
|
+
store_settings.TAP_CREDIT_CARD,
|
1082
|
+
store_settings.TAP_KNET,
|
1083
|
+
store_settings.TAP_ALL,
|
1084
|
+
]
|
1085
|
+
),
|
1086
|
+
required=True,
|
1087
|
+
)
|
1088
|
+
|
1089
|
+
def top_up_wallet(self, wallet):
|
1090
|
+
amount = self.validated_data["amount"]
|
1091
|
+
payment_method = self.validated_data["payment_method"]
|
1092
|
+
return wallet.top_up_wallet(amount=amount, payment_method=payment_method)
|
@@ -16,6 +16,7 @@ from ob_dj_store.apis.stores.views import (
|
|
16
16
|
TaxViewSet,
|
17
17
|
TransactionsViewSet,
|
18
18
|
VariantView,
|
19
|
+
WalletViewSet,
|
19
20
|
)
|
20
21
|
|
21
22
|
app_name = "stores"
|
@@ -28,9 +29,6 @@ stores_router.register(r"order", OrderView, basename="order")
|
|
28
29
|
stores_router.register(r"product", ProductView, basename="product")
|
29
30
|
stores_router.register(r"variant", VariantView, basename="variant")
|
30
31
|
stores_router.register(r"inventory", InventoryView, basename="inventory")
|
31
|
-
stores_router.register(
|
32
|
-
r"payment-method", PaymentMethodViewSet, basename="payment-method"
|
33
|
-
)
|
34
32
|
stores_router.register(
|
35
33
|
r"shipping-method", ShippingMethodViewSet, basename="shipping-method"
|
36
34
|
)
|
@@ -40,6 +38,8 @@ router.register(r"transaction", TransactionsViewSet, basename="transaction")
|
|
40
38
|
router.register(r"cart", CartView, basename="cart")
|
41
39
|
router.register(r"cart-item", CartItemView, basename="cart-item")
|
42
40
|
router.register(r"favorite", FavoriteViewSet, basename="favorite")
|
41
|
+
router.register(r"wallet", WalletViewSet, basename="wallet")
|
42
|
+
router.register(r"payment-method", PaymentMethodViewSet, basename="payment-method")
|
43
43
|
urlpatterns = [
|
44
44
|
path(r"", include(router.urls)),
|
45
45
|
path(r"", include(stores_router.urls)),
|
@@ -26,6 +26,7 @@ from ob_dj_store.apis.stores.filters import (
|
|
26
26
|
FavoriteFilter,
|
27
27
|
InventoryFilter,
|
28
28
|
OrderFilter,
|
29
|
+
PaymentMethodFilter,
|
29
30
|
ProductFilter,
|
30
31
|
StoreFilter,
|
31
32
|
VariantFilter,
|
@@ -47,6 +48,8 @@ from ob_dj_store.apis.stores.rest.serializers.serializers import (
|
|
47
48
|
ShippingMethodSerializer,
|
48
49
|
StoreSerializer,
|
49
50
|
TaxSerializer,
|
51
|
+
WalletSerializer,
|
52
|
+
WalletTopUpSerializer,
|
50
53
|
)
|
51
54
|
from ob_dj_store.core.stores.models import (
|
52
55
|
Cart,
|
@@ -62,6 +65,7 @@ from ob_dj_store.core.stores.models import (
|
|
62
65
|
ShippingMethod,
|
63
66
|
Store,
|
64
67
|
Tax,
|
68
|
+
Wallet,
|
65
69
|
)
|
66
70
|
from ob_dj_store.core.stores.models._inventory import Inventory
|
67
71
|
|
@@ -188,29 +192,6 @@ class StoreView(
|
|
188
192
|
serializer = self.get_serializer(page, many=True)
|
189
193
|
return self.get_paginated_response(serializer.data)
|
190
194
|
|
191
|
-
@swagger_auto_schema(
|
192
|
-
operation_summary="Add or Remove Store from Favorites",
|
193
|
-
operation_description="""
|
194
|
-
Add or Remove Store from Favorites
|
195
|
-
""",
|
196
|
-
tags=[
|
197
|
-
"Store",
|
198
|
-
],
|
199
|
-
)
|
200
|
-
@action(
|
201
|
-
detail=True,
|
202
|
-
methods=["GET"],
|
203
|
-
url_path="favorite",
|
204
|
-
)
|
205
|
-
def favorite(self, request, *args, **kwargs):
|
206
|
-
instance = self.get_object()
|
207
|
-
try:
|
208
|
-
Favorite.objects.favorite_for_user(instance, request.user).delete()
|
209
|
-
except Favorite.DoesNotExist:
|
210
|
-
Favorite.add_favorite(instance, request.user)
|
211
|
-
serializer = StoreSerializer(instance=instance, context={"request": request})
|
212
|
-
return Response(serializer.data)
|
213
|
-
|
214
195
|
@swagger_auto_schema(
|
215
196
|
operation_summary="Retrieve count of store's products",
|
216
197
|
operation_description="""
|
@@ -674,6 +655,9 @@ class CategoryViewSet(
|
|
674
655
|
filterset_class = CategoryFilter
|
675
656
|
lookup_value_regex = "[0-9]+"
|
676
657
|
|
658
|
+
def get_queryset(self):
|
659
|
+
return super().get_queryset().prefetch_related("products__images")
|
660
|
+
|
677
661
|
def get_object(self):
|
678
662
|
store_id = self.request.query_params.get("store", None)
|
679
663
|
instance_pk = self.kwargs["pk"]
|
@@ -699,6 +683,7 @@ class CategoryViewSet(
|
|
699
683
|
"products",
|
700
684
|
queryset=product_queryset.distinct(),
|
701
685
|
),
|
686
|
+
"subcategories__products__images",
|
702
687
|
).get(pk=instance_pk)
|
703
688
|
except Category.DoesNotExist:
|
704
689
|
raise Http404("No Category matches the given query.")
|
@@ -800,14 +785,9 @@ class PaymentMethodViewSet(
|
|
800
785
|
permission_classes = [
|
801
786
|
permissions.IsAuthenticated,
|
802
787
|
]
|
803
|
-
queryset = PaymentMethod.objects.
|
804
|
-
|
805
|
-
|
806
|
-
try:
|
807
|
-
store = Store.objects.get(pk=self.kwargs["store_pk"])
|
808
|
-
except ObjectDoesNotExist:
|
809
|
-
raise ValidationError(_(f"Store does not Exist"))
|
810
|
-
return store.payment_methods.filter(is_active=True)
|
788
|
+
queryset = PaymentMethod.objects.filter(is_active=True)
|
789
|
+
filterset_class = PaymentMethodFilter
|
790
|
+
lookup_value_regex = "[0-9]+"
|
811
791
|
|
812
792
|
@swagger_auto_schema(
|
813
793
|
operation_summary="List Payment Methods",
|
@@ -949,3 +929,84 @@ class FavoriteViewSet(
|
|
949
929
|
)
|
950
930
|
def destroy(self, request, *args, **kwargs):
|
951
931
|
return super().destroy(request, *args, **kwargs)
|
932
|
+
|
933
|
+
|
934
|
+
class WalletViewSet(
|
935
|
+
mixins.ListModelMixin,
|
936
|
+
mixins.RetrieveModelMixin,
|
937
|
+
mixins.UpdateModelMixin,
|
938
|
+
viewsets.GenericViewSet,
|
939
|
+
):
|
940
|
+
queryset = Wallet.objects.all()
|
941
|
+
serializer_class = WalletSerializer
|
942
|
+
permission_classes = [
|
943
|
+
permissions.IsAuthenticated,
|
944
|
+
]
|
945
|
+
|
946
|
+
def get_queryset(self):
|
947
|
+
return Wallet.objects.filter(user=self.request.user)
|
948
|
+
|
949
|
+
@swagger_auto_schema(
|
950
|
+
operation_summary="Get User Wallet",
|
951
|
+
operation_description="""
|
952
|
+
Get User Wallet
|
953
|
+
""",
|
954
|
+
tags=[
|
955
|
+
"Wallet",
|
956
|
+
],
|
957
|
+
)
|
958
|
+
def retrieve(
|
959
|
+
self, request: Request, *args: typing.Any, **kwargs: typing.Any
|
960
|
+
) -> Response:
|
961
|
+
return super().retrieve(request=request, *args, **kwargs)
|
962
|
+
|
963
|
+
@swagger_auto_schema(
|
964
|
+
operation_summary="Update user wallet",
|
965
|
+
operation_description="""
|
966
|
+
Update a wallet
|
967
|
+
""",
|
968
|
+
tags=[
|
969
|
+
"Wallet",
|
970
|
+
],
|
971
|
+
)
|
972
|
+
def partial_update(self, request: Request, *args: typing.Any, **kwargs: typing.Any):
|
973
|
+
return super().partial_update(request, *args, **kwargs)
|
974
|
+
|
975
|
+
@swagger_auto_schema(
|
976
|
+
operation_summary="List User Wallets",
|
977
|
+
operation_description="""
|
978
|
+
List User Wallets
|
979
|
+
""",
|
980
|
+
tags=[
|
981
|
+
"Wallet",
|
982
|
+
],
|
983
|
+
)
|
984
|
+
def list(
|
985
|
+
self, request: Request, *args: typing.Any, **kwargs: typing.Any
|
986
|
+
) -> Response:
|
987
|
+
return super().list(request=request, *args, **kwargs)
|
988
|
+
|
989
|
+
@swagger_auto_schema(
|
990
|
+
operation_summary="top up a wallet",
|
991
|
+
operation_description="""
|
992
|
+
top up a user wallet with tap payment
|
993
|
+
""",
|
994
|
+
tags=[
|
995
|
+
"Wallet",
|
996
|
+
],
|
997
|
+
)
|
998
|
+
@action(
|
999
|
+
methods=["POST"],
|
1000
|
+
detail=True,
|
1001
|
+
url_path="top-up",
|
1002
|
+
url_name="top-up",
|
1003
|
+
serializer_class=WalletTopUpSerializer,
|
1004
|
+
)
|
1005
|
+
def top_up_wallet(
|
1006
|
+
self, request: Request, *args: typing.Any, **kwargs: typing.Any
|
1007
|
+
) -> Response:
|
1008
|
+
serializer = self.get_serializer(data=request.data)
|
1009
|
+
serializer.is_valid(raise_exception=True)
|
1010
|
+
instance = self.get_object()
|
1011
|
+
payment_url = serializer.top_up_wallet(instance)
|
1012
|
+
return Response({"payment_url": payment_url}, status=status.HTTP_200_OK)
|
@@ -104,12 +104,6 @@ class CategoryAdmin(admin.ModelAdmin):
|
|
104
104
|
"is_active",
|
105
105
|
]
|
106
106
|
|
107
|
-
def save_model(self, request, obj, form, change) -> None:
|
108
|
-
from ob_dj_store.core.stores.receivers import create_media_thumbnails
|
109
|
-
|
110
|
-
create_media_thumbnails(None, obj, None)
|
111
|
-
return super().save_model(request, obj, form, change)
|
112
|
-
|
113
107
|
|
114
108
|
class ProductVariantAdmin(admin.ModelAdmin):
|
115
109
|
inlines = [
|
@@ -122,6 +116,9 @@ class ProductVariantAdmin(admin.ModelAdmin):
|
|
122
116
|
]
|
123
117
|
search_fields = ["name", "product__name", "sku"]
|
124
118
|
|
119
|
+
def get_queryset(self, request):
|
120
|
+
return super().get_queryset(request).prefetch_related("inventories")
|
121
|
+
|
125
122
|
|
126
123
|
class ProductAdmin(admin.ModelAdmin):
|
127
124
|
list_display = ["id", "name", "category", "type", "is_active"]
|
@@ -249,6 +246,9 @@ class InventoryAdmin(admin.ModelAdmin):
|
|
249
246
|
"is_uncountable",
|
250
247
|
]
|
251
248
|
|
249
|
+
def get_queryset(self, request):
|
250
|
+
return super().get_queryset(request).prefetch_related("store")
|
251
|
+
|
252
252
|
|
253
253
|
class TaxAdmin(admin.ModelAdmin):
|
254
254
|
list_display = [
|
@@ -22,10 +22,10 @@ class InventoryInlineAdmin(admin.TabularInline):
|
|
22
22
|
extra = 1
|
23
23
|
|
24
24
|
def get_queryset(self, request):
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
"variant",
|
25
|
+
return (
|
26
|
+
super()
|
27
|
+
.get_queryset(request)
|
28
|
+
.select_related("variant", "store", "variant__product")
|
29
29
|
)
|
30
30
|
|
31
31
|
|
@@ -6,7 +6,6 @@ from django.db import models
|
|
6
6
|
from django.utils.translation import gettext_lazy as _
|
7
7
|
|
8
8
|
from config import settings
|
9
|
-
from ob_dj_store.core.stores.utils import get_country_by_currency
|
10
9
|
|
11
10
|
|
12
11
|
class ActiveMixin:
|
@@ -77,8 +76,7 @@ class PaymentManager(models.Manager):
|
|
77
76
|
return instance
|
78
77
|
elif gateway == settings.WALLET:
|
79
78
|
try:
|
80
|
-
|
81
|
-
wallet = kwargs["user"].wallets.get(country=country)
|
79
|
+
wallet = kwargs["user"].wallets.get(currency=currency)
|
82
80
|
except ObjectDoesNotExist:
|
83
81
|
raise ValidationError({"wallet": _("Wallet Not Found")})
|
84
82
|
WalletTransaction.objects.create(
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Generated by Django 3.2.8 on 2023-02-26 17:05
|
2
|
+
|
3
|
+
from django.conf import settings
|
4
|
+
from django.db import migrations, models
|
5
|
+
|
6
|
+
import ob_dj_store.core.stores.utils
|
7
|
+
|
8
|
+
|
9
|
+
class Migration(migrations.Migration):
|
10
|
+
|
11
|
+
dependencies = [
|
12
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
13
|
+
("stores", "0061_auto_20230223_1435"),
|
14
|
+
]
|
15
|
+
|
16
|
+
operations = [
|
17
|
+
migrations.AddField(
|
18
|
+
model_name="store",
|
19
|
+
name="currency",
|
20
|
+
field=models.CharField(
|
21
|
+
default="KWD",
|
22
|
+
max_length=3,
|
23
|
+
validators=[ob_dj_store.core.stores.utils.validate_currency],
|
24
|
+
),
|
25
|
+
),
|
26
|
+
migrations.AddField(
|
27
|
+
model_name="wallet",
|
28
|
+
name="currency",
|
29
|
+
field=models.CharField(
|
30
|
+
default="KWD",
|
31
|
+
max_length=3,
|
32
|
+
validators=[ob_dj_store.core.stores.utils.validate_currency],
|
33
|
+
),
|
34
|
+
),
|
35
|
+
migrations.AlterUniqueTogether(
|
36
|
+
name="wallet",
|
37
|
+
unique_together={("user", "currency")},
|
38
|
+
),
|
39
|
+
migrations.RemoveField(
|
40
|
+
model_name="wallet",
|
41
|
+
name="country",
|
42
|
+
),
|
43
|
+
]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generated by Django 3.2.8 on 2023-02-27 11:15
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
("stores", "0062_auto_20230226_2005"),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AlterField(
|
14
|
+
model_name="store",
|
15
|
+
name="payment_methods",
|
16
|
+
field=models.ManyToManyField(
|
17
|
+
blank=True,
|
18
|
+
help_text="Payment methods within the store",
|
19
|
+
related_name="stores",
|
20
|
+
to="stores.PaymentMethod",
|
21
|
+
),
|
22
|
+
),
|
23
|
+
]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Generated by Django 3.2.8 on 2023-02-28 15:14
|
2
|
+
|
3
|
+
from django.conf import settings
|
4
|
+
from django.db import migrations, models
|
5
|
+
|
6
|
+
|
7
|
+
class Migration(migrations.Migration):
|
8
|
+
|
9
|
+
dependencies = [
|
10
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
11
|
+
("stores", "0063_alter_store_payment_methods"),
|
12
|
+
]
|
13
|
+
|
14
|
+
operations = [
|
15
|
+
migrations.AddField(
|
16
|
+
model_name="favorite",
|
17
|
+
name="name",
|
18
|
+
field=models.CharField(blank=True, max_length=200, null=True),
|
19
|
+
),
|
20
|
+
migrations.AlterUniqueTogether(
|
21
|
+
name="favorite",
|
22
|
+
unique_together={("name", "user")},
|
23
|
+
),
|
24
|
+
]
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Generated by Django 3.2.8 on 2023-02-28 16:32
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
import ob_dj_store.utils.helpers
|
6
|
+
|
7
|
+
|
8
|
+
class Migration(migrations.Migration):
|
9
|
+
|
10
|
+
dependencies = [
|
11
|
+
("stores", "0064_auto_20230228_1814"),
|
12
|
+
]
|
13
|
+
|
14
|
+
operations = [
|
15
|
+
migrations.AddField(
|
16
|
+
model_name="wallet",
|
17
|
+
name="image",
|
18
|
+
field=models.ImageField(
|
19
|
+
blank=True,
|
20
|
+
null=True,
|
21
|
+
upload_to=ob_dj_store.utils.helpers.wallet_media_upload_to,
|
22
|
+
),
|
23
|
+
),
|
24
|
+
migrations.AddField(
|
25
|
+
model_name="wallet",
|
26
|
+
name="image_thumbnail_medium",
|
27
|
+
field=models.ImageField(blank=True, null=True, upload_to="wallets/"),
|
28
|
+
),
|
29
|
+
migrations.AddField(
|
30
|
+
model_name="wallet",
|
31
|
+
name="name",
|
32
|
+
field=models.CharField(blank=True, max_length=200, null=True),
|
33
|
+
),
|
34
|
+
]
|
@@ -16,6 +16,7 @@ class Favorite(DjangoModelCleanMixin, models.Model):
|
|
16
16
|
user = models.ForeignKey(
|
17
17
|
get_user_model(), related_name="favorites", on_delete=models.CASCADE
|
18
18
|
)
|
19
|
+
name = models.CharField(max_length=200, null=True, blank=True)
|
19
20
|
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
20
21
|
content_object = GenericForeignKey("content_type", "object_id")
|
21
22
|
object_id = models.PositiveIntegerField()
|
@@ -26,18 +27,20 @@ class Favorite(DjangoModelCleanMixin, models.Model):
|
|
26
27
|
class Meta:
|
27
28
|
verbose_name = _("favorite")
|
28
29
|
verbose_name_plural = _("favorites")
|
30
|
+
unique_together = (("name", "user"),)
|
29
31
|
|
30
32
|
def __str__(self):
|
31
33
|
return f"{self.user} favorites {self.content_object}"
|
32
34
|
|
33
35
|
@classmethod
|
34
|
-
def add_favorite(cls, content_object, user, extras=[]):
|
36
|
+
def add_favorite(cls, content_object, user, name, extras=[]):
|
35
37
|
content_type = ContentType.objects.get_for_model(type(content_object))
|
36
38
|
favorite = Favorite(
|
37
39
|
user=user,
|
38
40
|
content_type=content_type,
|
39
41
|
object_id=content_object.pk,
|
40
42
|
content_object=content_object,
|
43
|
+
name=name,
|
41
44
|
)
|
42
45
|
favorite.save()
|
43
46
|
for extra in extras:
|
@@ -119,6 +119,8 @@ class Order(DjangoModelCleanMixin, models.Model):
|
|
119
119
|
|
120
120
|
@property
|
121
121
|
def total_amount(self):
|
122
|
+
if self.type_of_order == Order.OrderType.WALLET.value:
|
123
|
+
return Decimal(self.extra_infos["amount"])
|
122
124
|
amount = Decimal(
|
123
125
|
sum(map(lambda item: Decimal(item.total_amount) or 0, self.items.all()))
|
124
126
|
)
|
@@ -110,17 +110,36 @@ class Payment(models.Model):
|
|
110
110
|
return f"Payment (PK={self.pk})"
|
111
111
|
|
112
112
|
def mark_paid(self):
|
113
|
+
"""
|
114
|
+
mark payment and orders as paid then perform post payment actions
|
115
|
+
if wallet fill up we add wallet transaction to the user
|
116
|
+
if physical order we decrease the quantity from inventory and delete items from cart
|
117
|
+
"""
|
118
|
+
from ob_dj_store.core.stores.models._wallet import WalletTransaction
|
119
|
+
|
113
120
|
self.status = self.PaymentStatus.SUCCESS
|
114
|
-
orders =
|
115
|
-
|
116
|
-
|
121
|
+
orders = self.orders.all()
|
122
|
+
if orders[0].type_of_order == Order.OrderType.WALLET.value:
|
123
|
+
order = orders[0]
|
124
|
+
currency = order.extra_infos["currency"]
|
125
|
+
wallet = self.user.wallets.get(currency=currency)
|
126
|
+
WalletTransaction.objects.create(
|
127
|
+
wallet=wallet,
|
128
|
+
amount=self.amount, # TODO: cunfused about how we hundle if he want to fill up other currency
|
129
|
+
type=WalletTransaction.TYPE.CREDIT,
|
130
|
+
)
|
117
131
|
order.status = Order.OrderStatus.PAID
|
118
|
-
for item in order.items.all():
|
119
|
-
if item.inventory:
|
120
|
-
item.inventory.decrease(item.quantity)
|
121
132
|
order.save()
|
122
|
-
|
123
|
-
|
133
|
+
else:
|
134
|
+
cart = self.user.cart
|
135
|
+
for order in orders:
|
136
|
+
order.status = Order.OrderStatus.PAID
|
137
|
+
for item in order.items.all():
|
138
|
+
if item.inventory:
|
139
|
+
item.inventory.decrease(item.quantity)
|
140
|
+
order.save()
|
141
|
+
items = order.store.store_items.filter(cart=cart)
|
142
|
+
items.delete()
|
124
143
|
self.payment_post_at = timezone.now()
|
125
144
|
self.save()
|
126
145
|
|
@@ -130,14 +149,15 @@ class Payment(models.Model):
|
|
130
149
|
|
131
150
|
@property
|
132
151
|
def total_payment(self):
|
152
|
+
orders = self.orders.all()
|
133
153
|
sum_orders = Decimal(
|
134
|
-
sum(map(lambda order: Decimal(order.total_amount) or 0,
|
154
|
+
sum(map(lambda order: Decimal(order.total_amount) or 0, orders))
|
135
155
|
)
|
136
156
|
if self.payment_tax.rate == Tax.Rates.PERCENTAGE:
|
137
157
|
perc = Decimal(sum_orders * self.payment_tax.value / 100)
|
138
|
-
return sum_orders + perc
|
158
|
+
return round(sum_orders + perc, 3)
|
139
159
|
|
140
|
-
return sum_orders +
|
160
|
+
return round(sum_orders + self.payment_tax.value, 3)
|
141
161
|
|
142
162
|
@property
|
143
163
|
def type_of_order(self):
|