174 lines
7.3 KiB
Python
174 lines
7.3 KiB
Python
# -*- 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) |