Merge branch 'main' into storefront-nuxt
This commit is contained in:
commit
7d0b6301ea
248 changed files with 17269 additions and 17666 deletions
|
|
@ -23,19 +23,17 @@ lint:
|
||||||
- "**/*.py"
|
- "**/*.py"
|
||||||
- "pyproject.toml"
|
- "pyproject.toml"
|
||||||
- ".pre-commit-config.yaml"
|
- ".pre-commit-config.yaml"
|
||||||
- "pyrightconfig.json"
|
|
||||||
when: on_success
|
when: on_success
|
||||||
- when: never
|
- when: never
|
||||||
|
|
||||||
typecheck:
|
typecheck:
|
||||||
stage: typecheck
|
stage: typecheck
|
||||||
script:
|
script:
|
||||||
- uv run pyright
|
- uv run ty check
|
||||||
rules:
|
rules:
|
||||||
- changes:
|
- changes:
|
||||||
- "**/*.py"
|
- "**/*.py"
|
||||||
- "pyproject.toml"
|
- "pyproject.toml"
|
||||||
- "pyrightconfig.json"
|
|
||||||
when: on_success
|
when: on_success
|
||||||
- when: never
|
- when: never
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
repos:
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
||||||
rev: v0.6.9
|
|
||||||
hooks:
|
|
||||||
- id: ruff
|
|
||||||
name: Ruff (lint & fix)
|
|
||||||
args: ["--fix", "--exit-non-zero-on-fix"]
|
|
||||||
files: "\\.(py|pyi)$"
|
|
||||||
exclude: "^storefront/"
|
|
||||||
- id: ruff-format
|
|
||||||
name: Ruff (format)
|
|
||||||
files: "\\.(py|pyi)$"
|
|
||||||
exclude: "^storefront/"
|
|
||||||
|
|
||||||
ci:
|
|
||||||
autofix_commit_msg: "chore(pre-commit): auto-fix issues"
|
|
||||||
autofix_prs: true
|
|
||||||
autoupdate_commit_msg: "chore(pre-commit): autoupdate hooks"
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: EVIBES 2025.4\n"
|
"Project-Id-Version: EVIBES 2025.4\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-12-18 17:19+0300\n"
|
"POT-Creation-Date: 2025-12-21 00:38+0300\n"
|
||||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ class Post(NiceModel):
|
||||||
verbose_name = _("post")
|
verbose_name = _("post")
|
||||||
verbose_name_plural = _("posts")
|
verbose_name_plural = _("posts")
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.file:
|
if self.file:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_("markdown files are not supported yet - use markdown content instead")
|
_("markdown files are not supported yet - use markdown content instead")
|
||||||
|
|
@ -110,7 +110,7 @@ class Post(NiceModel):
|
||||||
"a markdown file or markdown content must be provided - mutually exclusive"
|
"a markdown file or markdown content must be provided - mutually exclusive"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
super().save(**kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class PostTag(NiceModel):
|
class PostTag(NiceModel):
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ class NiceModel(Model):
|
||||||
|
|
||||||
def save(
|
def save(
|
||||||
self,
|
self,
|
||||||
*,
|
*args,
|
||||||
force_insert: bool = False,
|
force_insert: bool = False,
|
||||||
force_update: bool = False,
|
force_update: bool = False,
|
||||||
using: str | None = None,
|
using: str | None = None,
|
||||||
update_fields: Collection[str] | None = None,
|
update_fields: Collection[str] | None = None,
|
||||||
update_modified: bool = True,
|
update_modified: bool = True,
|
||||||
) -> None:
|
) -> None: # ty:ignore[invalid-method-override]
|
||||||
self.update_modified = update_modified
|
self.update_modified = update_modified
|
||||||
return super().save(
|
return super().save(
|
||||||
force_insert=force_insert,
|
force_insert=force_insert,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from typing import Any, ClassVar, Type
|
from typing import Any, Callable, ClassVar, Type
|
||||||
|
|
||||||
from constance.admin import Config
|
from constance.admin import Config
|
||||||
from constance.admin import ConstanceAdmin as BaseConstanceAdmin
|
from constance.admin import ConstanceAdmin as BaseConstanceAdmin
|
||||||
|
|
@ -145,6 +145,7 @@ class FieldsetsMixin:
|
||||||
|
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
class ActivationActionsMixin:
|
class ActivationActionsMixin:
|
||||||
|
message_user: Callable
|
||||||
actions_on_top = True
|
actions_on_top = True
|
||||||
actions_on_bottom = True
|
actions_on_bottom = True
|
||||||
actions = [
|
actions = [
|
||||||
|
|
@ -466,6 +467,7 @@ class ProductAdmin(
|
||||||
list_filter = (
|
list_filter = (
|
||||||
"is_active",
|
"is_active",
|
||||||
"is_digital",
|
"is_digital",
|
||||||
|
"is_updatable",
|
||||||
"stocks__vendor",
|
"stocks__vendor",
|
||||||
"tags__name",
|
"tags__name",
|
||||||
"created",
|
"created",
|
||||||
|
|
@ -513,6 +515,9 @@ class ProductAdmin(
|
||||||
"brand",
|
"brand",
|
||||||
"tags",
|
"tags",
|
||||||
]
|
]
|
||||||
|
additional_fields = [
|
||||||
|
"is_updatable",
|
||||||
|
]
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
return (
|
return (
|
||||||
|
|
@ -1082,10 +1087,8 @@ class ConstanceConfig:
|
||||||
_meta = Meta()
|
_meta = Meta()
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
site.unregister([Config]) # ty:ignore[invalid-argument-type]
|
||||||
site.unregister([Config])
|
site.register([ConstanceConfig], BaseConstanceAdmin) # ty:ignore[invalid-argument-type]
|
||||||
# noinspection PyTypeChecker
|
|
||||||
site.register([ConstanceConfig], BaseConstanceAdmin)
|
|
||||||
site.site_title = settings.PROJECT_NAME
|
site.site_title = settings.PROJECT_NAME
|
||||||
site.site_header = "eVibes"
|
site.site_header = "eVibes"
|
||||||
site.index_title = settings.PROJECT_NAME
|
site.index_title = settings.PROJECT_NAME
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import FileResponse
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from drf_spectacular.types import OpenApiTypes
|
||||||
from drf_spectacular.utils import OpenApiParameter, extend_schema, inline_serializer
|
from drf_spectacular.utils import OpenApiParameter, extend_schema, inline_serializer
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.fields import CharField, DictField, JSONField, ListField
|
from rest_framework.fields import CharField, DictField, JSONField, ListField
|
||||||
|
|
@ -32,6 +32,9 @@ CUSTOM_OPENAPI_SCHEMA = {
|
||||||
"OpenApi3 schema for this API. Format can be selected via content negotiation. "
|
"OpenApi3 schema for this API. Format can be selected via content negotiation. "
|
||||||
"Language can be selected with Accept-Language and query parameter both."
|
"Language can be selected with Accept-Language and query parameter both."
|
||||||
),
|
),
|
||||||
|
responses={
|
||||||
|
status.HTTP_200_OK: OpenApiTypes.OBJECT,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +179,7 @@ DOWNLOAD_DIGITAL_ASSET_SCHEMA = {
|
||||||
],
|
],
|
||||||
summary=_("download a digital asset from purchased digital order"),
|
summary=_("download a digital asset from purchased digital order"),
|
||||||
responses={
|
responses={
|
||||||
status.HTTP_200_OK: FileResponse,
|
status.HTTP_200_OK: OpenApiTypes.BINARY,
|
||||||
status.HTTP_400_BAD_REQUEST: error,
|
status.HTTP_400_BAD_REQUEST: error,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ CATEGORY_SCHEMA = {
|
||||||
name="lookup_value",
|
name="lookup_value",
|
||||||
location="path",
|
location="path",
|
||||||
description=_("Category UUID or slug"),
|
description=_("Category UUID or slug"),
|
||||||
type=str,
|
type=OpenApiTypes.STR,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
|
responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
|
||||||
|
|
@ -284,7 +284,7 @@ CATEGORY_SCHEMA = {
|
||||||
name="lookup_value",
|
name="lookup_value",
|
||||||
location="path",
|
location="path",
|
||||||
description=_("Category UUID or slug"),
|
description=_("Category UUID or slug"),
|
||||||
type=str,
|
type=OpenApiTypes.STR,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
responses={
|
responses={
|
||||||
|
|
@ -369,7 +369,7 @@ ORDER_SCHEMA = {
|
||||||
name="lookup_value",
|
name="lookup_value",
|
||||||
location="path",
|
location="path",
|
||||||
description=_("Order UUID or human-readable id"),
|
description=_("Order UUID or human-readable id"),
|
||||||
type=str,
|
type=OpenApiTypes.STR,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
|
responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
|
||||||
|
|
@ -1006,7 +1006,7 @@ BRAND_SCHEMA = {
|
||||||
name="lookup_value",
|
name="lookup_value",
|
||||||
location="path",
|
location="path",
|
||||||
description=_("Brand UUID or slug"),
|
description=_("Brand UUID or slug"),
|
||||||
type=str,
|
type=OpenApiTypes.STR,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
responses={status.HTTP_200_OK: BrandDetailSerializer(), **BASE_ERRORS},
|
responses={status.HTTP_200_OK: BrandDetailSerializer(), **BASE_ERRORS},
|
||||||
|
|
@ -1049,7 +1049,7 @@ BRAND_SCHEMA = {
|
||||||
name="lookup_value",
|
name="lookup_value",
|
||||||
location="path",
|
location="path",
|
||||||
description=_("Brand UUID or slug"),
|
description=_("Brand UUID or slug"),
|
||||||
type=str,
|
type=OpenApiTypes.STR,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
responses={status.HTTP_200_OK: SeoSnapshotSerializer(), **BASE_ERRORS},
|
responses={status.HTTP_200_OK: SeoSnapshotSerializer(), **BASE_ERRORS},
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from django_elasticsearch_dsl import fields
|
||||||
from django_elasticsearch_dsl.registries import registry
|
from django_elasticsearch_dsl.registries import registry
|
||||||
from elasticsearch import NotFoundError
|
from elasticsearch import NotFoundError
|
||||||
from elasticsearch.dsl import Q, Search
|
from elasticsearch.dsl import Q, Search
|
||||||
|
from elasticsearch.dsl.types import Hit
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
|
|
||||||
from engine.core.models import Brand, Category, Product
|
from engine.core.models import Brand, Category, Product
|
||||||
|
|
@ -199,8 +200,8 @@ def process_query(
|
||||||
minimum_should_match=1,
|
minimum_should_match=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
def build_search(idxs: list[str], size: int) -> Search:
|
def build_search(idxs: list[str], size: int) -> Search[Hit]:
|
||||||
return (
|
result: Search[Hit] = ( # ty: ignore[invalid-assignment]
|
||||||
Search(index=idxs)
|
Search(index=idxs)
|
||||||
.query(query_base)
|
.query(query_base)
|
||||||
.extra(
|
.extra(
|
||||||
|
|
@ -222,6 +223,7 @@ def process_query(
|
||||||
)
|
)
|
||||||
.extra(size=size, track_total_hits=True)
|
.extra(size=size, track_total_hits=True)
|
||||||
)
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
resp_cats = None
|
resp_cats = None
|
||||||
if "categories" in indexes:
|
if "categories" in indexes:
|
||||||
|
|
@ -289,12 +291,12 @@ def process_query(
|
||||||
]
|
]
|
||||||
for qx in product_exact_sequence:
|
for qx in product_exact_sequence:
|
||||||
try:
|
try:
|
||||||
resp_exact = (
|
search_exact = (
|
||||||
Search(index=["products"])
|
Search(index=["products"])
|
||||||
.query(qx)
|
.query(qx)
|
||||||
.extra(size=5, track_total_hits=False)
|
.extra(size=5, track_total_hits=False)
|
||||||
.execute()
|
|
||||||
)
|
)
|
||||||
|
resp_exact = search_exact.execute() # ty: ignore[possibly-missing-attribute]
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
resp_exact = None
|
resp_exact = None
|
||||||
if resp_exact is not None and getattr(resp_exact, "hits", None):
|
if resp_exact is not None and getattr(resp_exact, "hits", None):
|
||||||
|
|
@ -309,7 +311,7 @@ def process_query(
|
||||||
.extra(size=5, track_total_hits=False)
|
.extra(size=5, track_total_hits=False)
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
resp_exact = s_exact.execute()
|
resp_exact = s_exact.execute() # ty: ignore[possibly-missing-attribute]
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
resp_exact = None
|
resp_exact = None
|
||||||
if resp_exact is not None and getattr(resp_exact, "hits", None):
|
if resp_exact is not None and getattr(resp_exact, "hits", None):
|
||||||
|
|
@ -434,7 +436,7 @@ def _lang_analyzer(lang_code: str) -> str:
|
||||||
|
|
||||||
class ActiveOnlyMixin:
|
class ActiveOnlyMixin:
|
||||||
def get_queryset(self) -> QuerySet[Any]:
|
def get_queryset(self) -> QuerySet[Any]:
|
||||||
return super().get_queryset().filter(is_active=True)
|
return super().get_queryset().filter(is_active=True) # type: ignore[misc]
|
||||||
|
|
||||||
def should_index_object(self, obj) -> bool:
|
def should_index_object(self, obj) -> bool:
|
||||||
return getattr(obj, "is_active", False)
|
return getattr(obj, "is_active", False)
|
||||||
|
|
@ -665,7 +667,7 @@ def process_system_query(
|
||||||
.query(mm)
|
.query(mm)
|
||||||
.extra(size=size_per_index, track_total_hits=False)
|
.extra(size=size_per_index, track_total_hits=False)
|
||||||
)
|
)
|
||||||
resp = s.execute()
|
resp = s.execute() # ty: ignore[possibly-missing-attribute]
|
||||||
for h in resp.hits:
|
for h in resp.hits:
|
||||||
name = getattr(h, "name", None) or getattr(h, "title", None) or "N/A"
|
name = getattr(h, "name", None) or getattr(h, "title", None) or "N/A"
|
||||||
results[idx].append(
|
results[idx].append(
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ class ProductFilter(FilterSet):
|
||||||
data: dict[Any, Any] | None = None,
|
data: dict[Any, Any] | None = None,
|
||||||
queryset: QuerySet[Product] | None = None,
|
queryset: QuerySet[Product] | None = None,
|
||||||
*,
|
*,
|
||||||
request: HttpRequest | Request | Context = None,
|
request: HttpRequest | Request | Context | None = None,
|
||||||
prefix: str | None = None,
|
prefix: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(data=data, queryset=queryset, request=request, prefix=prefix)
|
super().__init__(data=data, queryset=queryset, request=request, prefix=prefix)
|
||||||
|
|
@ -516,12 +516,12 @@ class CategoryFilter(FilterSet):
|
||||||
if not value:
|
if not value:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
uuids = [
|
s_result = process_query(query=value, indexes=("categories",))
|
||||||
category.get("uuid")
|
|
||||||
for category in process_query(query=value, indexes=("categories",))[
|
if not s_result:
|
||||||
"categories"
|
raise ValueError("Search is unprocessable")
|
||||||
]
|
|
||||||
]
|
uuids = [category.get("uuid") for category in s_result.get("categories", [])]
|
||||||
|
|
||||||
return queryset.filter(uuid__in=uuids)
|
return queryset.filter(uuid__in=uuids)
|
||||||
|
|
||||||
|
|
@ -650,10 +650,11 @@ class BrandFilter(FilterSet):
|
||||||
if not value:
|
if not value:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
uuids = [
|
s_result = process_query(query=value, indexes=("brands",))
|
||||||
brand.get("uuid")
|
if not s_result:
|
||||||
for brand in process_query(query=value, indexes=("brands",))["brands"]
|
return queryset.none()
|
||||||
]
|
|
||||||
|
uuids = [brand.get("uuid") for brand in s_result.get("brands", [])]
|
||||||
|
|
||||||
return queryset.filter(uuid__in=uuids)
|
return queryset.filter(uuid__in=uuids)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from graphene import Mutation
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMutation(Mutation):
|
|
||||||
def __init__(self, *args: list[Any], **kwargs: dict[Any, Any]) -> None:
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(**kwargs: Any) -> None:
|
|
||||||
pass
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
from contextlib import suppress
|
|
||||||
|
|
||||||
from django.core.exceptions import PermissionDenied
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from graphene import UUID, Boolean, Field, InputObjectType, List, NonNull, String
|
|
||||||
|
|
||||||
from engine.core.graphene import BaseMutation
|
|
||||||
from engine.core.graphene.object_types import ProductType
|
|
||||||
from engine.core.models import (
|
|
||||||
Attribute,
|
|
||||||
AttributeGroup,
|
|
||||||
AttributeValue,
|
|
||||||
Brand,
|
|
||||||
Category,
|
|
||||||
Product,
|
|
||||||
ProductTag,
|
|
||||||
)
|
|
||||||
from engine.core.utils.messages import permission_denied_message
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_attributes(product, attributes):
|
|
||||||
for attr_input in attributes:
|
|
||||||
attribute = None
|
|
||||||
attr_uuid = attr_input.get("attribute_uuid")
|
|
||||||
if attr_uuid:
|
|
||||||
with suppress(Attribute.DoesNotExist):
|
|
||||||
attribute = Attribute.objects.get(uuid=attr_uuid)
|
|
||||||
if attribute is None:
|
|
||||||
group_name = attr_input.get("group_name")
|
|
||||||
attribute_name = attr_input.get("attribute_name")
|
|
||||||
value_type = attr_input.get("value_type") or "string"
|
|
||||||
if group_name and attribute_name:
|
|
||||||
group, _ = AttributeGroup.objects.get_or_create(name=group_name)
|
|
||||||
attribute, _ = Attribute.objects.get_or_create(
|
|
||||||
group=group,
|
|
||||||
name=attribute_name,
|
|
||||||
defaults={"value_type": value_type},
|
|
||||||
)
|
|
||||||
if attribute.value_type != value_type:
|
|
||||||
attribute.value_type = value_type
|
|
||||||
attribute.save(update_fields=["value_type"])
|
|
||||||
if attribute is not None:
|
|
||||||
AttributeValue.objects.update_or_create(
|
|
||||||
product=product,
|
|
||||||
attribute=attribute,
|
|
||||||
defaults={"value": str(attr_input.get("value", ""))},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_tags(product, tag_uuids):
|
|
||||||
tags = list(ProductTag.objects.filter(uuid__in=tag_uuids))
|
|
||||||
if tags:
|
|
||||||
product.tags.set(tags)
|
|
||||||
|
|
||||||
|
|
||||||
class AttributeInput(InputObjectType):
|
|
||||||
attribute_uuid = UUID(required=False, name="attributeUuid")
|
|
||||||
group_name = String(required=False, name="groupName")
|
|
||||||
attribute_name = String(required=False, name="attributeName")
|
|
||||||
value_type = String(required=False, name="valueType")
|
|
||||||
value = String(required=True)
|
|
||||||
|
|
||||||
|
|
||||||
class ProductInput(InputObjectType):
|
|
||||||
name = NonNull(String)
|
|
||||||
description = String(required=False)
|
|
||||||
is_digital = Boolean(required=False, name="isDigital")
|
|
||||||
partnumber = String(required=False)
|
|
||||||
sku = String(required=False)
|
|
||||||
|
|
||||||
category_uuid = NonNull(UUID, name="categoryUuid")
|
|
||||||
brand_uuid = UUID(required=False, name="brandUuid")
|
|
||||||
tag_uuids = List(UUID, required=False, name="tagUuids")
|
|
||||||
attributes = List(NonNull(AttributeInput), required=False)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
|
||||||
class CreateProduct(BaseMutation):
|
|
||||||
class Meta:
|
|
||||||
description = _("create a product")
|
|
||||||
|
|
||||||
class Arguments:
|
|
||||||
product_data = NonNull(ProductInput, name="productData")
|
|
||||||
|
|
||||||
product = Field(ProductType)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(parent, info, product_data):
|
|
||||||
user = info.context.user
|
|
||||||
if not user.has_perm("core.add_product"):
|
|
||||||
raise PermissionDenied(permission_denied_message)
|
|
||||||
category = Category.objects.get(uuid=product_data["category_uuid"])
|
|
||||||
brand = None
|
|
||||||
if product_data.get("brand_uuid"):
|
|
||||||
with suppress(Brand.DoesNotExist):
|
|
||||||
brand = Brand.objects.get(uuid=product_data["brand_uuid"])
|
|
||||||
|
|
||||||
product = Product.objects.create(
|
|
||||||
name=product_data["name"],
|
|
||||||
description=product_data.get("description"),
|
|
||||||
is_digital=product_data.get("is_digital") or False,
|
|
||||||
partnumber=product_data.get("partnumber"),
|
|
||||||
sku=product_data.get("sku") or None,
|
|
||||||
category=category,
|
|
||||||
brand=brand,
|
|
||||||
)
|
|
||||||
|
|
||||||
resolve_tags(product, product_data.get("tag_uuids", []))
|
|
||||||
|
|
||||||
resolve_attributes(product, product_data.get("attributes", []))
|
|
||||||
|
|
||||||
return CreateProduct(product=product)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
|
||||||
class UpdateProduct(BaseMutation):
|
|
||||||
class Meta:
|
|
||||||
description = _("create a product")
|
|
||||||
|
|
||||||
class Arguments:
|
|
||||||
product_uuid = UUID(required=True)
|
|
||||||
product_data = NonNull(ProductInput, name="productData")
|
|
||||||
|
|
||||||
product = Field(ProductType)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(parent, info, product_uuid, product_data):
|
|
||||||
user = info.context.user
|
|
||||||
if not user.has_perm("core.change_product"):
|
|
||||||
raise PermissionDenied(permission_denied_message)
|
|
||||||
product = Product.objects.get(uuid=product_uuid)
|
|
||||||
|
|
||||||
updates = {}
|
|
||||||
for field_in, model_field in (
|
|
||||||
("name", "name"),
|
|
||||||
("description", "description"),
|
|
||||||
("is_digital", "is_digital"),
|
|
||||||
("partnumber", "partnumber"),
|
|
||||||
("sku", "sku"),
|
|
||||||
):
|
|
||||||
if field_in in product_data and product_data[field_in] is not None:
|
|
||||||
updates[model_field] = product_data[field_in]
|
|
||||||
|
|
||||||
if product_data.get("category_uuid"):
|
|
||||||
product.category = Category.objects.get(uuid=product_data["category_uuid"])
|
|
||||||
if product_data.get("brand_uuid") is not None:
|
|
||||||
if product_data.get("brand_uuid"):
|
|
||||||
product.brand = Brand.objects.get(uuid=product_data["brand_uuid"])
|
|
||||||
else:
|
|
||||||
product.brand = None
|
|
||||||
|
|
||||||
for k, v in updates.items():
|
|
||||||
setattr(product, k, v)
|
|
||||||
product.save()
|
|
||||||
|
|
||||||
resolve_tags(product, product_data.get("tag_uuids", []))
|
|
||||||
|
|
||||||
resolve_attributes(product, product_data.get("attributes"))
|
|
||||||
|
|
||||||
return UpdateProduct(product=product)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
|
||||||
class DeleteProduct(BaseMutation):
|
|
||||||
class Meta:
|
|
||||||
description = _("create a product")
|
|
||||||
|
|
||||||
class Arguments:
|
|
||||||
product_uuid = UUID(required=True)
|
|
||||||
|
|
||||||
ok = Boolean()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mutate(parent, info, product_uuid):
|
|
||||||
user = info.context.user
|
|
||||||
if not user.has_perm("core.delete_product"):
|
|
||||||
raise PermissionDenied(permission_denied_message)
|
|
||||||
Product.objects.get(uuid=product_uuid).delete()
|
|
||||||
return DeleteProduct(ok=True)
|
|
||||||
|
|
@ -6,11 +6,10 @@ from django.core.cache import cache
|
||||||
from django.core.exceptions import BadRequest, PermissionDenied
|
from django.core.exceptions import BadRequest, PermissionDenied
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from graphene import UUID, Boolean, Field, Int, List, String
|
from graphene import UUID, Boolean, Field, Int, List, Mutation, String
|
||||||
from graphene.types.generic import GenericScalar
|
from graphene.types.generic import GenericScalar
|
||||||
|
|
||||||
from engine.core.elasticsearch import process_query
|
from engine.core.elasticsearch import process_query
|
||||||
from engine.core.graphene import BaseMutation
|
|
||||||
from engine.core.graphene.object_types import (
|
from engine.core.graphene.object_types import (
|
||||||
AddressType,
|
AddressType,
|
||||||
BulkProductInput,
|
BulkProductInput,
|
||||||
|
|
@ -32,7 +31,7 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class CacheOperator(BaseMutation):
|
class CacheOperator(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("cache I/O")
|
description = _("cache I/O")
|
||||||
|
|
||||||
|
|
@ -54,7 +53,7 @@ class CacheOperator(BaseMutation):
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class RequestCursedURL(BaseMutation):
|
class RequestCursedURL(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("request a CORSed URL")
|
description = _("request a CORSed URL")
|
||||||
|
|
||||||
|
|
@ -82,7 +81,7 @@ class RequestCursedURL(BaseMutation):
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class AddOrderProduct(BaseMutation):
|
class AddOrderProduct(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("add a product to the order")
|
description = _("add a product to the order")
|
||||||
|
|
||||||
|
|
@ -105,13 +104,13 @@ class AddOrderProduct(BaseMutation):
|
||||||
product_uuid=product_uuid, attributes=format_attributes(attributes)
|
product_uuid=product_uuid, attributes=format_attributes(attributes)
|
||||||
)
|
)
|
||||||
|
|
||||||
return AddOrderProduct(order=order)
|
return AddOrderProduct(order=order) # ty: ignore[unknown-argument]
|
||||||
except Order.DoesNotExist as dne:
|
except Order.DoesNotExist as dne:
|
||||||
raise Http404(_(f"order {order_uuid} not found")) from dne
|
raise Http404(_(f"order {order_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class RemoveOrderProduct(BaseMutation):
|
class RemoveOrderProduct(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("remove a product from the order")
|
description = _("remove a product from the order")
|
||||||
|
|
||||||
|
|
@ -134,13 +133,13 @@ class RemoveOrderProduct(BaseMutation):
|
||||||
product_uuid=product_uuid, attributes=format_attributes(attributes)
|
product_uuid=product_uuid, attributes=format_attributes(attributes)
|
||||||
)
|
)
|
||||||
|
|
||||||
return RemoveOrderProduct(order=order)
|
return RemoveOrderProduct(order=order) # ty: ignore[unknown-argument]
|
||||||
except Order.DoesNotExist as dne:
|
except Order.DoesNotExist as dne:
|
||||||
raise Http404(_(f"order {order_uuid} not found")) from dne
|
raise Http404(_(f"order {order_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class RemoveAllOrderProducts(BaseMutation):
|
class RemoveAllOrderProducts(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("remove all products from the order")
|
description = _("remove all products from the order")
|
||||||
|
|
||||||
|
|
@ -158,11 +157,11 @@ class RemoveAllOrderProducts(BaseMutation):
|
||||||
|
|
||||||
order = order.remove_all_products()
|
order = order.remove_all_products()
|
||||||
|
|
||||||
return RemoveAllOrderProducts(order=order)
|
return RemoveAllOrderProducts(order=order) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class RemoveOrderProductsOfAKind(BaseMutation):
|
class RemoveOrderProductsOfAKind(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("remove a product from the order")
|
description = _("remove a product from the order")
|
||||||
|
|
||||||
|
|
@ -181,11 +180,11 @@ class RemoveOrderProductsOfAKind(BaseMutation):
|
||||||
|
|
||||||
order = order.remove_products_of_a_kind(product_uuid=product_uuid)
|
order = order.remove_products_of_a_kind(product_uuid=product_uuid)
|
||||||
|
|
||||||
return RemoveOrderProductsOfAKind(order=order)
|
return RemoveOrderProductsOfAKind(order=order) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class BuyOrder(BaseMutation):
|
class BuyOrder(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("buy an order")
|
description = _("buy an order")
|
||||||
|
|
||||||
|
|
@ -230,7 +229,7 @@ class BuyOrder(BaseMutation):
|
||||||
elif order_hr_id:
|
elif order_hr_id:
|
||||||
order = Order.objects.get(user=user, human_readable_id=order_hr_id)
|
order = Order.objects.get(user=user, human_readable_id=order_hr_id)
|
||||||
|
|
||||||
instance = order.buy(
|
instance = order.buy( # ty: ignore[possibly-missing-attribute]
|
||||||
force_balance=force_balance,
|
force_balance=force_balance,
|
||||||
force_payment=force_payment,
|
force_payment=force_payment,
|
||||||
promocode_uuid=promocode_uuid,
|
promocode_uuid=promocode_uuid,
|
||||||
|
|
@ -241,9 +240,9 @@ class BuyOrder(BaseMutation):
|
||||||
|
|
||||||
match str(type(instance)):
|
match str(type(instance)):
|
||||||
case "<class 'engine.payments.models.Transaction'>":
|
case "<class 'engine.payments.models.Transaction'>":
|
||||||
return BuyOrder(transaction=instance)
|
return BuyOrder(transaction=instance) # ty: ignore[unknown-argument]
|
||||||
case "<class 'engine.core.models.Order'>":
|
case "<class 'engine.core.models.Order'>":
|
||||||
return BuyOrder(order=instance)
|
return BuyOrder(order=instance) # ty: ignore[unknown-argument]
|
||||||
case _:
|
case _:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
_(
|
_(
|
||||||
|
|
@ -256,7 +255,7 @@ class BuyOrder(BaseMutation):
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class BulkOrderAction(BaseMutation):
|
class BulkOrderAction(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("perform an action on a list of products in the order")
|
description = _("perform an action on a list of products in the order")
|
||||||
|
|
||||||
|
|
@ -295,20 +294,20 @@ class BulkOrderAction(BaseMutation):
|
||||||
# noinspection PyUnreachableCode
|
# noinspection PyUnreachableCode
|
||||||
match action:
|
match action:
|
||||||
case "add":
|
case "add":
|
||||||
order = order.bulk_add_products(products)
|
order = order.bulk_add_products(products) # ty: ignore[possibly-missing-attribute]
|
||||||
case "remove":
|
case "remove":
|
||||||
order = order.bulk_remove_products(products)
|
order = order.bulk_remove_products(products) # ty: ignore[possibly-missing-attribute]
|
||||||
case _:
|
case _:
|
||||||
raise BadRequest(_("action must be either add or remove"))
|
raise BadRequest(_("action must be either add or remove"))
|
||||||
|
|
||||||
return BulkOrderAction(order=order)
|
return BulkOrderAction(order=order) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
except Order.DoesNotExist as dne:
|
except Order.DoesNotExist as dne:
|
||||||
raise Http404(_(f"order {order_uuid} not found")) from dne
|
raise Http404(_(f"order {order_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class BulkWishlistAction(BaseMutation):
|
class BulkWishlistAction(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("perform an action on a list of products in the wishlist")
|
description = _("perform an action on a list of products in the wishlist")
|
||||||
|
|
||||||
|
|
@ -336,20 +335,20 @@ class BulkWishlistAction(BaseMutation):
|
||||||
# noinspection PyUnreachableCode
|
# noinspection PyUnreachableCode
|
||||||
match action:
|
match action:
|
||||||
case "add":
|
case "add":
|
||||||
wishlist = wishlist.bulk_add_products(products)
|
wishlist = wishlist.bulk_add_products(products) # ty: ignore[possibly-missing-attribute]
|
||||||
case "remove":
|
case "remove":
|
||||||
wishlist = wishlist.bulk_remove_products(products)
|
wishlist = wishlist.bulk_remove_products(products) # ty: ignore[possibly-missing-attribute]
|
||||||
case _:
|
case _:
|
||||||
raise BadRequest(_("action must be either add or remove"))
|
raise BadRequest(_("action must be either add or remove"))
|
||||||
|
|
||||||
return BulkWishlistAction(wishlist=wishlist)
|
return BulkWishlistAction(wishlist=wishlist) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
except Wishlist.DoesNotExist as dne:
|
except Wishlist.DoesNotExist as dne:
|
||||||
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class BuyUnregisteredOrder(BaseMutation):
|
class BuyUnregisteredOrder(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("purchase an order without account creation")
|
description = _("purchase an order without account creation")
|
||||||
|
|
||||||
|
|
@ -393,11 +392,11 @@ class BuyUnregisteredOrder(BaseMutation):
|
||||||
is_business=is_business,
|
is_business=is_business,
|
||||||
)
|
)
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return BuyUnregisteredOrder(transaction=transaction)
|
return BuyUnregisteredOrder(transaction=transaction) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class AddWishlistProduct(BaseMutation):
|
class AddWishlistProduct(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("add a product to the wishlist")
|
description = _("add a product to the wishlist")
|
||||||
|
|
||||||
|
|
@ -418,14 +417,14 @@ class AddWishlistProduct(BaseMutation):
|
||||||
|
|
||||||
wishlist.add_product(product_uuid=product_uuid)
|
wishlist.add_product(product_uuid=product_uuid)
|
||||||
|
|
||||||
return AddWishlistProduct(wishlist=wishlist)
|
return AddWishlistProduct(wishlist=wishlist) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
except Wishlist.DoesNotExist as dne:
|
except Wishlist.DoesNotExist as dne:
|
||||||
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class RemoveWishlistProduct(BaseMutation):
|
class RemoveWishlistProduct(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("remove a product from the wishlist")
|
description = _("remove a product from the wishlist")
|
||||||
|
|
||||||
|
|
@ -446,14 +445,14 @@ class RemoveWishlistProduct(BaseMutation):
|
||||||
|
|
||||||
wishlist.remove_product(product_uuid=product_uuid)
|
wishlist.remove_product(product_uuid=product_uuid)
|
||||||
|
|
||||||
return RemoveWishlistProduct(wishlist=wishlist)
|
return RemoveWishlistProduct(wishlist=wishlist) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
except Wishlist.DoesNotExist as dne:
|
except Wishlist.DoesNotExist as dne:
|
||||||
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class RemoveAllWishlistProducts(BaseMutation):
|
class RemoveAllWishlistProducts(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("remove all products from the wishlist")
|
description = _("remove all products from the wishlist")
|
||||||
|
|
||||||
|
|
@ -474,14 +473,14 @@ class RemoveAllWishlistProducts(BaseMutation):
|
||||||
for product in wishlist.products.all():
|
for product in wishlist.products.all():
|
||||||
wishlist.remove_product(product_uuid=product.pk)
|
wishlist.remove_product(product_uuid=product.pk)
|
||||||
|
|
||||||
return RemoveAllWishlistProducts(wishlist=wishlist)
|
return RemoveAllWishlistProducts(wishlist=wishlist) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
except Wishlist.DoesNotExist as dne:
|
except Wishlist.DoesNotExist as dne:
|
||||||
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class BuyWishlist(BaseMutation):
|
class BuyWishlist(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("buy all products from the wishlist")
|
description = _("buy all products from the wishlist")
|
||||||
|
|
||||||
|
|
@ -516,9 +515,9 @@ class BuyWishlist(BaseMutation):
|
||||||
)
|
)
|
||||||
match str(type(instance)):
|
match str(type(instance)):
|
||||||
case "<class 'engine.payments.models.Transaction'>":
|
case "<class 'engine.payments.models.Transaction'>":
|
||||||
return BuyWishlist(transaction=instance)
|
return BuyWishlist(transaction=instance) # ty: ignore[unknown-argument]
|
||||||
case "<class 'engine.core.models.Order'>":
|
case "<class 'engine.core.models.Order'>":
|
||||||
return BuyWishlist(order=instance)
|
return BuyWishlist(order=instance) # ty: ignore[unknown-argument]
|
||||||
case _:
|
case _:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
_(
|
_(
|
||||||
|
|
@ -531,7 +530,7 @@ class BuyWishlist(BaseMutation):
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class BuyProduct(BaseMutation):
|
class BuyProduct(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("buy a product")
|
description = _("buy a product")
|
||||||
|
|
||||||
|
|
@ -566,9 +565,9 @@ class BuyProduct(BaseMutation):
|
||||||
instance = order.buy(force_balance=force_balance, force_payment=force_payment)
|
instance = order.buy(force_balance=force_balance, force_payment=force_payment)
|
||||||
match str(type(instance)):
|
match str(type(instance)):
|
||||||
case "<class 'engine.payments.models.Transaction'>":
|
case "<class 'engine.payments.models.Transaction'>":
|
||||||
return BuyProduct(transaction=instance)
|
return BuyProduct(transaction=instance) # ty: ignore[unknown-argument]
|
||||||
case "<class 'engine.core.models.Order'>":
|
case "<class 'engine.core.models.Order'>":
|
||||||
return BuyProduct(order=instance)
|
return BuyProduct(order=instance) # ty: ignore[unknown-argument]
|
||||||
case _:
|
case _:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
_(f"wrong type came from order.buy() method: {type(instance)!s}")
|
_(f"wrong type came from order.buy() method: {type(instance)!s}")
|
||||||
|
|
@ -576,7 +575,7 @@ class BuyProduct(BaseMutation):
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class FeedbackProductAction(BaseMutation):
|
class FeedbackProductAction(Mutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
description = _("add or delete a feedback for orderproduct")
|
description = _("add or delete a feedback for orderproduct")
|
||||||
|
|
||||||
|
|
@ -605,13 +604,13 @@ class FeedbackProductAction(BaseMutation):
|
||||||
feedback = order_product.do_feedback(action="remove")
|
feedback = order_product.do_feedback(action="remove")
|
||||||
case _:
|
case _:
|
||||||
raise BadRequest(_("action must be either `add` or `remove`"))
|
raise BadRequest(_("action must be either `add` or `remove`"))
|
||||||
return FeedbackProductAction(feedback=feedback)
|
return FeedbackProductAction(feedback=feedback) # ty: ignore[unknown-argument]
|
||||||
except OrderProduct.DoesNotExist as dne:
|
except OrderProduct.DoesNotExist as dne:
|
||||||
raise Http404(_(f"order product {order_product_uuid} not found")) from dne
|
raise Http404(_(f"order product {order_product_uuid} not found")) from dne
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyTypeChecker
|
# noinspection PyUnusedLocal,PyTypeChecker
|
||||||
class CreateAddress(BaseMutation):
|
class CreateAddress(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
raw_data = String(
|
raw_data = String(
|
||||||
required=True, description=_("original address string provided by the user")
|
required=True, description=_("original address string provided by the user")
|
||||||
|
|
@ -624,11 +623,11 @@ class CreateAddress(BaseMutation):
|
||||||
user = info.context.user if info.context.user.is_authenticated else None
|
user = info.context.user if info.context.user.is_authenticated else None
|
||||||
|
|
||||||
address = Address.objects.create(raw_data=raw_data, user=user)
|
address = Address.objects.create(raw_data=raw_data, user=user)
|
||||||
return CreateAddress(address=address)
|
return CreateAddress(address=address) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class DeleteAddress(BaseMutation):
|
class DeleteAddress(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
uuid = UUID(required=True)
|
uuid = UUID(required=True)
|
||||||
|
|
||||||
|
|
@ -645,7 +644,7 @@ class DeleteAddress(BaseMutation):
|
||||||
):
|
):
|
||||||
address.delete()
|
address.delete()
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return DeleteAddress(success=True)
|
return DeleteAddress(success=True) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
raise PermissionDenied(permission_denied_message)
|
raise PermissionDenied(permission_denied_message)
|
||||||
|
|
||||||
|
|
@ -655,7 +654,7 @@ class DeleteAddress(BaseMutation):
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class AutocompleteAddress(BaseMutation):
|
class AutocompleteAddress(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
q = String()
|
q = String()
|
||||||
limit = Int()
|
limit = Int()
|
||||||
|
|
@ -672,11 +671,11 @@ class AutocompleteAddress(BaseMutation):
|
||||||
raise BadRequest(f"geocoding error: {e!s}") from e
|
raise BadRequest(f"geocoding error: {e!s}") from e
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return AutocompleteAddress(suggestions=suggestions)
|
return AutocompleteAddress(suggestions=suggestions) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class ContactUs(BaseMutation):
|
class ContactUs(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
email = String(required=True)
|
email = String(required=True)
|
||||||
name = String(required=True)
|
name = String(required=True)
|
||||||
|
|
@ -700,14 +699,14 @@ class ContactUs(BaseMutation):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return ContactUs(received=True)
|
return ContactUs(received=True) # ty: ignore[unknown-argument]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return ContactUs(received=False, error=str(e))
|
return ContactUs(received=False, error=str(e)) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyArgumentList PyUnusedLocal
|
# noinspection PyArgumentList PyUnusedLocal
|
||||||
class Search(BaseMutation):
|
class Search(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
query = String(required=True)
|
query = String(required=True)
|
||||||
|
|
||||||
|
|
@ -720,12 +719,15 @@ class Search(BaseMutation):
|
||||||
def mutate(parent, info, query):
|
def mutate(parent, info, query):
|
||||||
data = process_query(query=query, request=info.context)
|
data = process_query(query=query, request=info.context)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return Search(results=None) # ty: ignore[unknown-argument]
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return Search(
|
return Search( # ty: ignore[unknown-argument]
|
||||||
results=SearchResultsType(
|
results=SearchResultsType( # ty: ignore[unknown-argument]
|
||||||
products=data["products"],
|
products=data["products"], # ty: ignore[unknown-argument]
|
||||||
categories=data["categories"],
|
categories=data["categories"], # ty: ignore[unknown-argument]
|
||||||
brands=data["brands"],
|
brands=data["brands"], # ty: ignore[unknown-argument]
|
||||||
posts=data["posts"],
|
posts=data["posts"], # ty: ignore[unknown-argument]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ from graphene import (
|
||||||
)
|
)
|
||||||
from graphene.types.generic import GenericScalar
|
from graphene.types.generic import GenericScalar
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import (
|
||||||
|
DjangoFilterConnectionField, # ty:ignore[possibly-missing-import]
|
||||||
|
)
|
||||||
from mptt.querysets import TreeQuerySet
|
from mptt.querysets import TreeQuerySet
|
||||||
|
|
||||||
from engine.core.models import (
|
from engine.core.models import (
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ from django.core.exceptions import PermissionDenied
|
||||||
from django.db.models import Case, Exists, IntegerField, OuterRef, Q, Value, When
|
from django.db.models import Case, Exists, IntegerField, OuterRef, Q, Value, When
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from graphene import Field, List, ObjectType, Schema
|
from graphene import Field, List, ObjectType, Schema
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import (
|
||||||
|
DjangoFilterConnectionField, # ty:ignore[possibly-missing-import]
|
||||||
|
)
|
||||||
|
|
||||||
from engine.blog.filters import PostFilter
|
from engine.blog.filters import PostFilter
|
||||||
from engine.blog.graphene.object_types import PostType
|
from engine.blog.graphene.object_types import PostType
|
||||||
|
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -6,7 +6,7 @@ from tempfile import NamedTemporaryFile
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import polib
|
import polib
|
||||||
from django.apps import apps
|
from django.apps import AppConfig, apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class Command(BaseCommand):
|
||||||
help="Root path prefix to adjust file links",
|
help="Root path prefix to adjust file links",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args: list[Any], **options: dict[str, str | list[str]]) -> None:
|
def handle(self, *args: Any, **options: Any) -> None:
|
||||||
langs: list[str] = options.get("target_languages", [])
|
langs: list[str] = options.get("target_languages", [])
|
||||||
if "ALL" in langs:
|
if "ALL" in langs:
|
||||||
langs = list(dict(settings.LANGUAGES).keys())
|
langs = list(dict(settings.LANGUAGES).keys())
|
||||||
|
|
@ -103,7 +103,7 @@ class Command(BaseCommand):
|
||||||
apps_to_scan = set(TRANSLATABLE_APPS)
|
apps_to_scan = set(TRANSLATABLE_APPS)
|
||||||
root_path: str = options.get("root_path") or "/app/"
|
root_path: str = options.get("root_path") or "/app/"
|
||||||
|
|
||||||
configs = list(apps.get_app_configs())
|
configs: list[AppConfig | RootDirectory] = list(apps.get_app_configs())
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
configs.append(RootDirectory())
|
configs.append(RootDirectory())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,10 @@ class Command(BaseCommand):
|
||||||
help="App label for translation, e.g. core, payments. Use ALL to translate all apps.",
|
help="App label for translation, e.g. core, payments. Use ALL to translate all apps.",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None:
|
def handle(self, *args: Any, **options: Any) -> None:
|
||||||
target_langs: list[str] = options["target_languages"]
|
target_langs = options["target_languages"]
|
||||||
if "ALL" in target_langs:
|
if "ALL" in target_langs:
|
||||||
target_langs = DEEPL_TARGET_LANGUAGES_MAPPING.keys()
|
target_langs = list(DEEPL_TARGET_LANGUAGES_MAPPING.keys())
|
||||||
target_apps = set(options["target_apps"])
|
target_apps = set(options["target_apps"])
|
||||||
if "ALL" in target_apps:
|
if "ALL" in target_apps:
|
||||||
target_apps = {
|
target_apps = {
|
||||||
|
|
@ -122,10 +122,13 @@ class Command(BaseCommand):
|
||||||
raise CommandError("DEEPL_AUTH_KEY not set")
|
raise CommandError("DEEPL_AUTH_KEY not set")
|
||||||
|
|
||||||
# attempt to import readline for interactive fill
|
# attempt to import readline for interactive fill
|
||||||
|
readline: Any = None
|
||||||
try:
|
try:
|
||||||
import readline
|
import readline as readline_module
|
||||||
|
|
||||||
|
readline = readline_module
|
||||||
except ImportError:
|
except ImportError:
|
||||||
readline = None
|
pass
|
||||||
|
|
||||||
for target_lang in target_langs:
|
for target_lang in target_langs:
|
||||||
api_code = DEEPL_TARGET_LANGUAGES_MAPPING.get(target_lang)
|
api_code = DEEPL_TARGET_LANGUAGES_MAPPING.get(target_lang)
|
||||||
|
|
@ -176,16 +179,16 @@ class Command(BaseCommand):
|
||||||
if readline:
|
if readline:
|
||||||
|
|
||||||
def hook() -> None:
|
def hook() -> None:
|
||||||
readline.insert_text(default) # noqa: B023
|
readline.insert_text(default) # noqa: B023 # ty: ignore[unresolved-attribute]
|
||||||
readline.redisplay()
|
readline.redisplay() # ty: ignore[unresolved-attribute]
|
||||||
|
|
||||||
readline.set_pre_input_hook(hook)
|
readline.set_pre_input_hook(hook) # ty: ignore[unresolved-attribute]
|
||||||
|
|
||||||
prompt = f"Enter translation for '{e.msgid}': "
|
prompt = f"Enter translation for '{e.msgid}': "
|
||||||
user_in = input(prompt).strip()
|
user_in = input(prompt).strip()
|
||||||
|
|
||||||
if readline:
|
if readline:
|
||||||
readline.set_pre_input_hook(None)
|
readline.set_pre_input_hook(None) # ty: ignore[unresolved-attribute]
|
||||||
|
|
||||||
if user_in:
|
if user_in:
|
||||||
e.msgstr = user_in
|
e.msgstr = user_in
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class Command(BaseCommand):
|
||||||
help="Chunk size to delete",
|
help="Chunk size to delete",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None:
|
def handle(self, *args: Any, **options: Any) -> None:
|
||||||
size: int = options["size"]
|
size: int = options["size"]
|
||||||
while True:
|
while True:
|
||||||
batch_ids = list(
|
batch_ids = list(
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class Command(BaseCommand):
|
||||||
help="Chunk size to delete",
|
help="Chunk size to delete",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None:
|
def handle(self, *args: Any, **options: Any) -> None:
|
||||||
size: int = options["size"]
|
size: int = options["size"]
|
||||||
while True:
|
while True:
|
||||||
batch_ids = list(
|
batch_ids = list(
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class AddressManager(models.Manager):
|
||||||
if not kwargs.get("raw_data"):
|
if not kwargs.get("raw_data"):
|
||||||
raise ValueError("'raw_data' (address string) must be provided.")
|
raise ValueError("'raw_data' (address string) must be provided.")
|
||||||
|
|
||||||
params: dict[str, str | int] = {
|
params: dict[str, str | int | None] = {
|
||||||
"format": "json",
|
"format": "json",
|
||||||
"addressdetails": 1,
|
"addressdetails": 1,
|
||||||
"q": kwargs.get("raw_data"),
|
"q": kwargs.get("raw_data"),
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue