Merge branch 'develop' of ssh://gl.id-east.ru:222/gm/gm-backend into develop
This commit is contained in:
commit
bb040fffdf
|
|
@ -118,7 +118,7 @@ class GuideListCreateView(GuideBaseView, generics.ListCreateAPIView):
|
|||
|
||||
### Response
|
||||
Return paginated list of guides.
|
||||
I.e.:
|
||||
E.g.:
|
||||
```
|
||||
{
|
||||
"count": 58,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ from django.core.exceptions import ValidationError
|
|||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.db.models import Case, ExpressionWrapper, F, Prefetch, Q, Subquery, When
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
|
|
@ -679,7 +678,7 @@ class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin,
|
|||
@property
|
||||
def visible_tags_detail(self):
|
||||
"""Removes some tags from detail Establishment representation"""
|
||||
return self.visible_tags.exclude(category__index_name__in=['tag'])
|
||||
return self.visible_tags.exclude(category__index_name__in=['tag', 'shop_category'])
|
||||
|
||||
def recalculate_public_mark(self):
|
||||
fresh_review = self.reviews.published().order_by('-modified').first()
|
||||
|
|
@ -1145,7 +1144,7 @@ class EmployeeQuerySet(models.QuerySet):
|
|||
queryset=EstablishmentEmployee.objects.actual()
|
||||
.prefetch_related('establishment', 'position').order_by('-from_date'),
|
||||
to_attr='prefetched_establishment_employee'),
|
||||
'awards'
|
||||
Prefetch('awards', queryset=Award.objects.select_related('award_type'))
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from functools import lru_cache
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import F
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
|
@ -14,7 +15,8 @@ from establishment import models, serializers as model_serializers
|
|||
from establishment.models import ContactEmail, ContactPhone, EstablishmentEmployee
|
||||
from establishment.serializers.common import ContactPhonesSerializer
|
||||
from gallery.models import Image
|
||||
from location.serializers import AddressDetailSerializer, TranslatedField, AddressBaseSerializer
|
||||
from location.serializers import AddressDetailSerializer, TranslatedField
|
||||
from main import models as main_models
|
||||
from main.models import Currency
|
||||
from main.serializers import AwardSerializer
|
||||
from tag.serializers import TagBaseSerializer
|
||||
|
|
@ -22,8 +24,6 @@ from utils.decorators import with_base_attributes
|
|||
from utils.methods import string_random
|
||||
from utils.serializers import ImageBaseSerializer, ProjectModelSerializer, TimeZoneChoiceField, \
|
||||
PhoneMixinSerializer
|
||||
from main import models as main_models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
|
||||
def phones_handler(phones_list, establishment):
|
||||
|
|
@ -59,7 +59,7 @@ class EstablishmentListCreateSerializer(model_serializers.EstablishmentBaseSeria
|
|||
queryset=models.Address.objects.all(),
|
||||
write_only=True
|
||||
)
|
||||
address = AddressBaseSerializer(read_only=True, allow_null=True)
|
||||
address = AddressDetailSerializer(read_only=True, allow_null=True)
|
||||
transliterated_name = serializers.CharField(
|
||||
required=False, allow_null=True, allow_blank=True
|
||||
)
|
||||
|
|
@ -363,7 +363,10 @@ class EmployeeBackSerializers(PhoneMixinSerializer, serializers.ModelSerializer)
|
|||
@staticmethod
|
||||
@lru_cache(maxsize=32)
|
||||
def get_qs(obj):
|
||||
return obj.establishmentemployee_set.actual().annotate(
|
||||
return obj.establishmentemployee_set.actual().only(
|
||||
'establishment',
|
||||
'from_date',
|
||||
).annotate(
|
||||
public_mark=F('establishment__public_mark'),
|
||||
est_id=F('establishment__id'),
|
||||
est_slug=F('establishment__slug'),
|
||||
|
|
@ -526,10 +529,8 @@ class EstEmployeeBackSerializer(EmployeeBackSerializers):
|
|||
'toque_number',
|
||||
'available_for_events',
|
||||
'photo',
|
||||
'photo_id',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'phone': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ urlpatterns = [
|
|||
path('employees/search/', views.EmployeesListSearchViews.as_view(), name='employees-search'),
|
||||
path('employees/<int:pk>/', views.EmployeeRUDView.as_view(), name='employees-rud'),
|
||||
path('employees/<int:pk>/<int:award_id>', views.RemoveAwardView.as_view(), name='employees-award-delete'),
|
||||
path('<int:establishment_id>/employee/<int:employee_id>/position/<int:position_id>',
|
||||
path('<int:establishment_id>/employee/<int:employee_id>/position/<int:position_id>/',
|
||||
views.EstablishmentEmployeeCreateView.as_view(),
|
||||
name='employees-establishment-create'),
|
||||
path('employee/position/<int:pk>/delete/', views.EstablishmentEmployeeDeleteView.as_view(),
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP
|
|||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset() \
|
||||
.with_extended_address_related() \
|
||||
.with_certain_tag_category_related('category', 'restaurant_category') \
|
||||
.with_certain_tag_category_related('cuisine', 'restaurant_cuisine') \
|
||||
.with_certain_tag_category_related('shop_category', 'artisan_category') \
|
||||
|
|
@ -68,8 +69,28 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP
|
|||
|
||||
|
||||
class EmployeeEstablishmentPositionsView(generics.ListAPIView):
|
||||
"""Establishment by employee view."""
|
||||
|
||||
"""
|
||||
## Establishment employee positions filtered by employee identifier.
|
||||
### *GET*
|
||||
#### Description
|
||||
Return paginated list of results from an intermediate table filtered by employee
|
||||
identifier, that contains connection between employee establishment,
|
||||
employee hiring dates, position, status `'I' (Idle)`, `'A' (Accepted)`, `'D' (Declined)`.
|
||||
##### Response
|
||||
```
|
||||
{
|
||||
"count": 58,
|
||||
"next": 2,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
"""
|
||||
queryset = models.EstablishmentEmployee.objects.all()
|
||||
serializer_class = serializers.EstablishmentEmployeePositionsSerializer
|
||||
permission_classes = get_permission_classes(
|
||||
|
|
@ -84,7 +105,26 @@ class EmployeeEstablishmentPositionsView(generics.ListAPIView):
|
|||
|
||||
|
||||
class EmployeeEstablishmentsListView(generics.ListAPIView):
|
||||
"""Establishment by employee list view."""
|
||||
"""
|
||||
## Employee establishments filtered by employee identifier.
|
||||
### *GET*
|
||||
#### Description
|
||||
Return paginated list of establishments filtered by employee identifier.
|
||||
##### Response
|
||||
```
|
||||
{
|
||||
"count": 58,
|
||||
"next": 2,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
"""
|
||||
serializer_class = serializers.EstablishmentListCreateSerializer
|
||||
permission_classes = get_permission_classes(
|
||||
IsEstablishmentManager,
|
||||
|
|
@ -98,8 +138,25 @@ class EmployeeEstablishmentsListView(generics.ListAPIView):
|
|||
|
||||
|
||||
class EmployeePositionsListView(generics.ListAPIView):
|
||||
"""Establishment position by employee list view."""
|
||||
|
||||
"""
|
||||
## Paginated list of establishments filtered by employee identifier
|
||||
### *GET*
|
||||
#### Description
|
||||
Return a paginated list of establishments of an employee by employee identifier.
|
||||
##### Response
|
||||
```
|
||||
{
|
||||
"count": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
"""
|
||||
queryset = models.Establishment.objects.all()
|
||||
serializer_class = serializers.EstablishmentPositionListSerializer
|
||||
permission_classes = get_permission_classes(
|
||||
|
|
@ -500,7 +557,7 @@ class EmployeeListCreateView(generics.ListCreateAPIView):
|
|||
* position_id (`int`) - filter by employees position identifier
|
||||
* public_mark (`str`) - filter by establishment public mark
|
||||
* toque_number (`str`) - filter by establishment toque number
|
||||
* username (`str`) - filter by username or name
|
||||
* username (`str`) - filter by a username or name
|
||||
|
||||
#### Response
|
||||
```
|
||||
|
|
@ -530,17 +587,18 @@ class EmployeeListCreateView(generics.ListCreateAPIView):
|
|||
|
||||
#### Request
|
||||
Required fields:
|
||||
* available_for_events (bool) - flag that responds for availability for events
|
||||
* name (`str`) - employee name
|
||||
|
||||
Non-required fields:
|
||||
* name (`str`) - name
|
||||
* last_name (`str`) - last name
|
||||
* name (`str`) - employee name
|
||||
* last_name (`str`) - employee last name
|
||||
* user (`int`) - user identifier
|
||||
* sex (`int`) - enum: `0 (Male), 1 (Female)`
|
||||
* birth_date (`str`) - birth datetime (datetime in a format `ISO-8601`)
|
||||
* email (`str`) - email address
|
||||
* phone (`str`) - phone number in format `E164`
|
||||
* phone (`str`) - phone number in a format `E164`
|
||||
* photo_id (`int`) - photo identifier
|
||||
* available_for_events (bool) - flag that responds for availability for events
|
||||
"""
|
||||
filter_class = filters.EmployeeBackFilter
|
||||
serializer_class = serializers.EmployeeBackSerializers
|
||||
|
|
@ -550,13 +608,44 @@ class EmployeeListCreateView(generics.ListCreateAPIView):
|
|||
IsEstablishmentAdministrator,
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
if self.request.country_code:
|
||||
qs = qs.filter(establishments__address__city__country__code=self.request.country_code)
|
||||
return qs
|
||||
|
||||
|
||||
class EmployeesListSearchViews(generics.ListAPIView):
|
||||
"""Employee search view"""
|
||||
"""
|
||||
## Employee search view.
|
||||
### *GET*
|
||||
##### Description
|
||||
Return a non-paginated list of employees.
|
||||
Available filters:
|
||||
* search (`str`) - filter by name or last name with mistakes
|
||||
* position_id (`int`) - filter by employees position identifier
|
||||
* public_mark (`str`) - filter by establishment public mark
|
||||
* toque_number (`str`) - filter by establishment toque number
|
||||
* username (`str`) - filter by a username or name
|
||||
(with limitations by the minimum number of characters)
|
||||
|
||||
###### Response
|
||||
```
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
]
|
||||
```
|
||||
"""
|
||||
pagination_class = None
|
||||
queryset = models.Employee.objects.all().with_back_office_related().select_related('photo')
|
||||
filter_class = filters.EmployeeBackSearchFilter
|
||||
serializer_class = serializers.EmployeeBackSerializers
|
||||
queryset = (
|
||||
models.Employee.objects.with_back_office_related()
|
||||
.select_related('photo')
|
||||
)
|
||||
permission_classes = get_permission_classes(
|
||||
IsEstablishmentManager,
|
||||
IsEstablishmentAdministrator,
|
||||
|
|
@ -564,7 +653,47 @@ class EmployeesListSearchViews(generics.ListAPIView):
|
|||
|
||||
|
||||
class EstablishmentEmployeeListView(generics.ListCreateAPIView):
|
||||
"""Establishment emplyoees list view."""
|
||||
"""
|
||||
## Establishment employees List/Create view.
|
||||
### *GET*
|
||||
#### Description
|
||||
Returning non-paginated list of employees by establishment identifier.
|
||||
##### Response
|
||||
E.g.:
|
||||
```
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### *POST*
|
||||
#### Description
|
||||
Create a new instance of employee for establishment by establishment identifier.
|
||||
#### Request
|
||||
Required:
|
||||
* name (`str`) - employee name
|
||||
|
||||
Additional:
|
||||
* last_name (`str`) - employee last name
|
||||
* user (`int`) - user identifier
|
||||
* sex (`int`) - enum: `0 (Male), 1 (Female)`
|
||||
* birth_date (`str`) - birth datetime (datetime in a format `ISO-8601`)
|
||||
* email (`str`) - email address
|
||||
* phone (`str`) - phone number in a format `E164`
|
||||
* available_for_events (bool) - flag that responds for availability for events
|
||||
* photo_id (`int`) - photo identifier
|
||||
|
||||
#### Response
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
```
|
||||
"""
|
||||
serializer_class = serializers.EstEmployeeBackSerializer
|
||||
pagination_class = None
|
||||
permission_classes = get_permission_classes(
|
||||
|
|
@ -584,7 +713,51 @@ class EstablishmentEmployeeListView(generics.ListCreateAPIView):
|
|||
|
||||
|
||||
class EmployeeRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Employee RUD view."""
|
||||
"""
|
||||
## Employee Retrieve/Update/Destroy view
|
||||
### *GET*
|
||||
#### Description
|
||||
Retrieve a serialized object of employee.
|
||||
##### Response
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### *PUT*/*PATCH*
|
||||
#### Description
|
||||
Completely/Partially update an employee object.
|
||||
##### Request
|
||||
Available fields:
|
||||
* name (`str`) - employee name
|
||||
* last_name (`str`) - employee last name
|
||||
* sex (`enum`) - 0 (Male), 1 (Female)
|
||||
* birth_date (`str`) - datetime in a format `ISO-8601`
|
||||
* email (`str`) - employee email address
|
||||
* phone (`str`) - phone number in E164 format
|
||||
* toque_number (`int`) - employee toque number
|
||||
* available_for_events (`bool`) - flag that responds for availability for events
|
||||
* photo_id (`int`) - image identifier
|
||||
##### Response
|
||||
Return an employee serialized object
|
||||
E.g.:
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### *DELETE*
|
||||
#### Description
|
||||
Delete an instance of employee
|
||||
##### Response
|
||||
```
|
||||
No content
|
||||
```
|
||||
"""
|
||||
serializer_class = serializers.EmployeeBackSerializers
|
||||
queryset = models.Employee.objects.with_back_office_related()
|
||||
permission_classes = get_permission_classes(
|
||||
|
|
@ -594,6 +767,16 @@ class EmployeeRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
|
||||
|
||||
class RemoveAwardView(generics.DestroyAPIView):
|
||||
"""
|
||||
## Remove award view.
|
||||
### *DELETE*
|
||||
#### Description
|
||||
Remove an award from an employee by an employee identifier and an award identifier.
|
||||
##### Response
|
||||
```
|
||||
No content
|
||||
```
|
||||
"""
|
||||
lookup_field = 'pk'
|
||||
serializer_class = serializers.EmployeeBackSerializers
|
||||
queryset = models.Employee.objects.with_back_office_related()
|
||||
|
|
@ -856,6 +1039,29 @@ class EstablishmentNoteRUDView(EstablishmentMixinViews,
|
|||
|
||||
|
||||
class EstablishmentEmployeeCreateView(generics.CreateAPIView):
|
||||
"""
|
||||
## Create employee position for establishment
|
||||
### *POST*
|
||||
#### Description
|
||||
Creating position for an employee for establishment,
|
||||
by `establishment identifier`, `employee identifier` and
|
||||
`position identifier`.
|
||||
|
||||
##### Request data
|
||||
Available fields:
|
||||
* from_date - datetime (datetime in a format `ISO-8601`), by default `timezone.now()`
|
||||
* to_date - datetime (datetime in a format `ISO-8601`), by default `null`
|
||||
|
||||
##### Response data
|
||||
E.g.:
|
||||
```
|
||||
{
|
||||
"id": 47405,
|
||||
"from_date": "2020-02-06T11:01:04.961000Z",
|
||||
"to_date": "2020-02-06T11:01:04.961000Z"
|
||||
}
|
||||
```
|
||||
"""
|
||||
serializer_class = serializers.EstablishmentEmployeeCreateSerializer
|
||||
queryset = models.EstablishmentEmployee.objects.all()
|
||||
permission_classes = get_permission_classes(
|
||||
|
|
@ -865,6 +1071,18 @@ class EstablishmentEmployeeCreateView(generics.CreateAPIView):
|
|||
|
||||
|
||||
class EstablishmentEmployeeDeleteView(generics.DestroyAPIView):
|
||||
"""
|
||||
## Delete employee position for establishment
|
||||
### *DELETE*
|
||||
#### Description
|
||||
Deleting position for an employee from establishment, by `position identifier`.
|
||||
|
||||
|
||||
##### Response data
|
||||
```
|
||||
No content
|
||||
```
|
||||
"""
|
||||
queryset = EstablishmentEmployee.objects.all()
|
||||
permission_classes = get_permission_classes(
|
||||
IsEstablishmentManager,
|
||||
|
|
@ -889,7 +1107,25 @@ class EstablishmentPositionListView(generics.ListAPIView):
|
|||
|
||||
|
||||
class EstablishmentAdminView(generics.ListAPIView):
|
||||
"""Establishment admin list view."""
|
||||
"""
|
||||
## List establishment admins
|
||||
### *GET*
|
||||
#### Description
|
||||
Returning paginated list of establishment administrators by establishment slug.
|
||||
##### Response
|
||||
```
|
||||
{
|
||||
"count": 58,
|
||||
"next": 2,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
``` """
|
||||
serializer_class = serializers.EstablishmentAdminListSerializer
|
||||
permission_classes = get_permission_classes(
|
||||
IsEstablishmentManager,
|
||||
|
|
|
|||
18
apps/report/migrations/0002_report_locale.py
Normal file
18
apps/report/migrations/0002_report_locale.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.7 on 2020-02-06 13:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('report', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='report',
|
||||
name='locale',
|
||||
field=models.CharField(max_length=10, null=True, verbose_name='locale'),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,22 +1,26 @@
|
|||
from django.conf import settings
|
||||
from django.core.mail import send_mail
|
||||
from django.db import models
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.text import gettext_lazy as _
|
||||
|
||||
from report.tasks import send_report_task
|
||||
from translation.models import SiteInterfaceDictionary
|
||||
from utils.models import ProjectBaseMixin
|
||||
|
||||
|
||||
class ReportManager(models.Manager):
|
||||
"""Manager for model Report."""
|
||||
|
||||
def make(self, source: int, category, url: str, description: str):
|
||||
def make(self, source: int, category, url: str, description: str, locale: str):
|
||||
"""Make object."""
|
||||
obj = self.create(
|
||||
source=source,
|
||||
category=category,
|
||||
url=url,
|
||||
description=description
|
||||
description=description,
|
||||
locale=locale,
|
||||
)
|
||||
if settings.USE_CELERY:
|
||||
send_report_task.delay(obj.id)
|
||||
|
|
@ -60,6 +64,8 @@ class Report(ProjectBaseMixin):
|
|||
verbose_name=_('category'))
|
||||
url = models.URLField(verbose_name=_('URL'))
|
||||
description = models.TextField(verbose_name=_('description'))
|
||||
locale = models.CharField(max_length=10, null=True,
|
||||
verbose_name=_('locale'))
|
||||
|
||||
objects = ReportManager.from_queryset(ReportQuerySet)()
|
||||
|
||||
|
|
@ -70,19 +76,46 @@ class Report(ProjectBaseMixin):
|
|||
|
||||
def __str__(self):
|
||||
"""Implement `str` dunder method."""
|
||||
return f'{self.id}: {self.get_category_display()} ({self.url})'
|
||||
return f'{self.id}: {self.get_category_display()} ({self.url}, {self.locale})'
|
||||
|
||||
def get_body_email_message(self):
|
||||
@cached_property
|
||||
def support_email_note(self):
|
||||
keyword = 'support.email.note'
|
||||
default_note = (
|
||||
'You received this message because you are an '
|
||||
'administrator with privileges to manage this request.'
|
||||
)
|
||||
|
||||
note_qs = SiteInterfaceDictionary.objects.filter(keywords=keyword)
|
||||
if note_qs.exists():
|
||||
return note_qs.first().text.get(self.locale, default_note)
|
||||
return default_note
|
||||
|
||||
@cached_property
|
||||
def report_message(self):
|
||||
return render_to_string(
|
||||
template_name=settings.REPORT_TEMPLATE,
|
||||
context={
|
||||
'source_value': self.get_source_display(),
|
||||
'source_page_url': self.url,
|
||||
'source_screen_language': self.locale,
|
||||
'request_category': self.get_category_display(),
|
||||
'request_description': self.description,
|
||||
'support_email_note': self.support_email_note,
|
||||
}
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def base_template(self):
|
||||
"""Prepare the body of the email message"""
|
||||
return {
|
||||
'subject': self.get_category_display(),
|
||||
'message': str(self.description),
|
||||
'html_message': self.description,
|
||||
'subject': _('[TECH_REQUEST] A new technical request has been created.'),
|
||||
'message': self.report_message,
|
||||
'html_message': self.report_message,
|
||||
'from_email': settings.EMAIL_HOST_USER,
|
||||
'recipient_list': [settings.EMAIL_TECHNICAL_SUPPORT, ],
|
||||
}
|
||||
|
||||
def send_email(self):
|
||||
"""Send an email reset user password"""
|
||||
send_mail(**self.get_body_email_message())
|
||||
|
||||
send_mail(**self.base_template)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
"""DRF-serializers for application report."""
|
||||
from django.utils.functional import cached_property
|
||||
from rest_framework import serializers
|
||||
|
||||
from report.models import Report
|
||||
|
|
@ -18,15 +19,25 @@ class ReportBaseSerializer(serializers.ModelSerializer):
|
|||
'category_display',
|
||||
'url',
|
||||
'description',
|
||||
'locale',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'source': {'required': False},
|
||||
'category': {'write_only': True}
|
||||
'category': {'write_only': True},
|
||||
'locale': {'write_only': True}
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def locale(self) -> str:
|
||||
"""Return locale from request."""
|
||||
request = self.context.get('request')
|
||||
if hasattr(request, 'locale'):
|
||||
return request.locale
|
||||
|
||||
def validate(self, attrs):
|
||||
"""An overridden validate method."""
|
||||
attrs['source'] = self.context.get('view').get_source()
|
||||
attrs['locale'] = self.locale
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class ReportListCreateView(ReportBaseView, ListCreateAPIView):
|
|||
* category: integer (0 - Bug, 1 - Suggestion improvement)
|
||||
* url: char (URL)
|
||||
* description: text (problem description)
|
||||
I.e.:
|
||||
E.g.:
|
||||
```
|
||||
{
|
||||
"category": 1,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class ReportRetrieveView(ReportBaseView, generics.RetrieveAPIView):
|
|||
## View for retrieving serialized instance.
|
||||
### Response
|
||||
Return serialized object.
|
||||
I.e.:
|
||||
E.g.:
|
||||
```
|
||||
{
|
||||
"count": 7,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class ReportListCreateView(ReportBaseView, ListCreateAPIView):
|
|||
* category: integer (0 - Bug, 1 - Suggestion improvement)
|
||||
* url: char (URL)
|
||||
* description: text (problem description)
|
||||
I.e.:
|
||||
E.g.:
|
||||
```
|
||||
{
|
||||
"category": 1,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from django.contrib.postgres.fields.jsonb import KeyTextTransform
|
|||
from django.core.validators import FileExtensionValidator
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils import timezone
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _, get_language
|
||||
from easy_thumbnails.fields import ThumbnailerImageField
|
||||
|
|
@ -516,13 +517,13 @@ def default_menu_bool_array():
|
|||
|
||||
class PhoneModelMixin:
|
||||
"""Mixin for PhoneNumberField."""
|
||||
@property
|
||||
@cached_property
|
||||
def country_calling_code(self):
|
||||
"""Return phone code from PhonеNumberField."""
|
||||
if hasattr(self, 'phone') and self.phone:
|
||||
return f'+{self.phone.country_code}'
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def national_calling_number(self):
|
||||
"""Return phone national number from from PhonеNumberField."""
|
||||
if hasattr(self, 'phone') and (self.phone and hasattr(self.phone, 'national_number')):
|
||||
|
|
|
|||
|
|
@ -462,6 +462,7 @@ CONFIRM_EMAIL_TEMPLATE = 'authorization/confirm_email.html'
|
|||
NEWS_EMAIL_TEMPLATE = 'news/news_email.html'
|
||||
NOTIFICATION_PASSWORD_TEMPLATE = 'account/password_change_email.html'
|
||||
NOTIFICATION_SUBSCRIBE_TEMPLATE = 'notification/update_email.html'
|
||||
REPORT_TEMPLATE = 'report/tech_support_template.html'
|
||||
|
||||
|
||||
# COOKIES
|
||||
|
|
@ -568,4 +569,4 @@ COUNTRY_CALLING_CODES = {
|
|||
CALLING_CODES_ANTILLES_GUYANE_WEST_INDIES = [590, 594, 1758, 596]
|
||||
DEFAULT_CALLING_CODE_ANTILLES_GUYANE_WEST_INDIES = 590
|
||||
|
||||
EMAIL_TECHNICAL_SUPPORT = 'it-report@gaultmillau.com'
|
||||
EMAIL_TECHNICAL_SUPPORT = 'tech_requests@gaultmillau.com'
|
||||
|
|
|
|||
49
project/templates/report/tech_support_template.html
Normal file
49
project/templates/report/tech_support_template.html
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user