Public release from ruodoo-project: 19.0 - 2026-05-31 21:19:12 UTC
This commit is contained in:
1
premium_client/wizard/__init__.py
Normal file
1
premium_client/wizard/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import premium_order_wizard
|
||||
174
premium_client/wizard/premium_order_wizard.py
Normal file
174
premium_client/wizard/premium_order_wizard.py
Normal file
@ -0,0 +1,174 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import requests
|
||||
except Exception: # pragma: no cover
|
||||
requests = None
|
||||
|
||||
|
||||
class PremiumOrderWizard(models.TransientModel):
|
||||
_name = "premium.order.wizard"
|
||||
_description = "Премиум: заявка на сервис"
|
||||
|
||||
service_id = fields.Many2one("premium.service", string="Сервис", required=True)
|
||||
|
||||
company_name = fields.Char(string="Название компании", required=True)
|
||||
inn = fields.Char(string="ИНН") # будет браться из VAT
|
||||
email = fields.Char(string="Email", required=True)
|
||||
phone_telegram = fields.Char(string="Телефон/Телеграм")
|
||||
contact_person = fields.Char(string="Контактное лицо")
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
company = self.env.company
|
||||
res.setdefault("company_name", company.name)
|
||||
res.setdefault("inn", company.vat)
|
||||
res.setdefault("email", company.email or self.env.user.email)
|
||||
res.setdefault("phone_telegram", company.phone or company.mobile)
|
||||
res.setdefault("contact_person", self.env.user.name)
|
||||
_logger.info("Premium order wizard default values: %s", res)
|
||||
return res
|
||||
|
||||
@api.constrains("email")
|
||||
def _check_email(self):
|
||||
email_regex = r"^[\w\.-]+@[\w\.-]+\.\w+$"
|
||||
for rec in self:
|
||||
if rec.email and not re.match(email_regex, rec.email):
|
||||
raise ValidationError(_("Некорректный формат email."))
|
||||
|
||||
@api.constrains("inn")
|
||||
def _check_inn(self):
|
||||
for rec in self:
|
||||
if rec.inn and (not rec.inn.isdigit() or len(rec.inn) not in (10, 12)):
|
||||
raise ValidationError(_("ИНН должен содержать 10 или 12 цифр."))
|
||||
|
||||
@api.onchange("email")
|
||||
def _onchange_email(self):
|
||||
if self.email and not re.match(r"^[\w\.-]+@[\w\.-]+\.\w+$", self.email):
|
||||
return {
|
||||
"warning": {
|
||||
"title": _("Предупреждение"),
|
||||
"message": _("Некорректный формат email."),
|
||||
}
|
||||
}
|
||||
|
||||
@api.onchange("inn")
|
||||
def _onchange_inn(self):
|
||||
if self.inn and (not self.inn.isdigit() or len(self.inn) not in (10, 12)):
|
||||
return {
|
||||
"warning": {
|
||||
"title": _("Предупреждение"),
|
||||
"message": _("ИНН должен содержать 10 или 12 цифр."),
|
||||
}
|
||||
}
|
||||
|
||||
def _build_payload(self):
|
||||
self.ensure_one()
|
||||
service = self.service_id
|
||||
payload = {
|
||||
"service_id": service.id,
|
||||
"service_name": service.name,
|
||||
"service_category": service.category,
|
||||
"service_author_url": service.author_url,
|
||||
"service_description": (service.description or ""),
|
||||
"company_name": self.company_name,
|
||||
"inn": self.inn,
|
||||
"email": self.email,
|
||||
"phone": self.phone_telegram,
|
||||
"contact_name": self.contact_person,
|
||||
"source_db": self.env.cr.dbname,
|
||||
}
|
||||
_logger.info("Premium order payload built: %s", payload)
|
||||
return payload
|
||||
|
||||
def action_submit(self):
|
||||
self.ensure_one()
|
||||
if not self.email or not self.company_name:
|
||||
raise UserError(_("Заполните обязательные поля: Email и Название компании."))
|
||||
|
||||
if requests is None:
|
||||
raise UserError(_("Библиотека requests недоступна на сервере Odoo."))
|
||||
|
||||
icp = self.env["ir.config_parameter"].sudo()
|
||||
base_url = (icp.get_param("premium.project_api_url") or "").strip()
|
||||
token = (icp.get_param("premium.project_api_token") or "").strip()
|
||||
|
||||
_logger.info("Premium API configuration - URL: %s, Token present: %s", base_url, bool(token))
|
||||
|
||||
if not base_url:
|
||||
raise UserError(
|
||||
_("Не настроен адрес Project API (Settings → Technical → Parameters → System Parameters).")
|
||||
)
|
||||
|
||||
if base_url.endswith("/newlead/"):
|
||||
url = base_url
|
||||
else:
|
||||
url = base_url.rstrip("/") + "/newlead/"
|
||||
|
||||
_logger.info("Premium API final URL: %s", url)
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if token:
|
||||
headers["X-API-Key"] = token
|
||||
|
||||
payload = self._build_payload()
|
||||
_logger.info("Attempting to send payload to %s: %s", url, payload)
|
||||
|
||||
retries = 3
|
||||
for attempt in range(1, retries + 1):
|
||||
try:
|
||||
_logger.info("Premium order attempt %s of %s", attempt, retries)
|
||||
resp = requests.post(url, json=payload, headers=headers, timeout=15)
|
||||
_logger.info("Response status: %s, headers: %s", resp.status_code, dict(resp.headers))
|
||||
|
||||
ok = resp.status_code in (200, 201)
|
||||
try:
|
||||
body = resp.json()
|
||||
_logger.info("Response body: %s", body)
|
||||
except Exception as e:
|
||||
body = {}
|
||||
_logger.warning("Failed to parse response JSON: %s", e)
|
||||
_logger.info("Response text: %s", resp.text)
|
||||
|
||||
if ok and (body.get("ok") is True):
|
||||
_logger.info("Premium order successful, lead_id: %s", body.get("lead_id"))
|
||||
return {
|
||||
"type": "ir.actions.client",
|
||||
"tag": "display_notification",
|
||||
"params": {
|
||||
"title": _("Заявка успешно отправлена"),
|
||||
"type": "success",
|
||||
"sticky": False,
|
||||
},
|
||||
}
|
||||
else:
|
||||
_logger.error("Premium order failed: %s %s", resp.status_code, body)
|
||||
if attempt == retries:
|
||||
raise UserError(
|
||||
_("Сервис временно недоступен, пожалуйста, отправьте заявку на info@inf-centre.ru")
|
||||
)
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
_logger.warning("Connection error on attempt %s: %s", attempt, e)
|
||||
if attempt == retries:
|
||||
_logger.exception("Premium order connection exception: %s", e)
|
||||
raise UserError(
|
||||
_("Не удалось подключиться к серверу Project. Проверьте настройки подключения или отправьте заявку на info@inf-centre.ru")
|
||||
)
|
||||
time.sleep(3)
|
||||
except Exception as e:
|
||||
_logger.warning("Attempt %s failed: %s", attempt, e)
|
||||
if attempt == retries:
|
||||
_logger.exception("Premium order exception: %s", e)
|
||||
raise UserError(
|
||||
_("Сервис временно недоступен, пожалуйста, отправьте заявку на info@inf-centre.ru")
|
||||
)
|
||||
time.sleep(3)
|
||||
Reference in New Issue
Block a user