added report app
This commit is contained in:
parent
ab3666b03d
commit
8eb07205e1
0
apps/report/__init__.py
Normal file
0
apps/report/__init__.py
Normal file
8
apps/report/admin.py
Normal file
8
apps/report/admin.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from report.models import Report
|
||||
|
||||
|
||||
@admin.register(Report)
|
||||
class ReportAdmin(admin.ModelAdmin):
|
||||
"""Report admin model."""
|
||||
8
apps/report/apps.py
Normal file
8
apps/report/apps.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.text import gettext_lazy as _
|
||||
|
||||
|
||||
class ReportConfig(AppConfig):
|
||||
name = 'report'
|
||||
verbose_name = _('Report')
|
||||
|
||||
26
apps/report/filters.py
Normal file
26
apps/report/filters.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
"""Filters for application report."""
|
||||
from django_filters import rest_framework as filters
|
||||
|
||||
from report.models import Report
|
||||
|
||||
|
||||
class ReportFilterSet(filters.FilterSet):
|
||||
"""Report filter set."""
|
||||
source = filters.ChoiceFilter(
|
||||
choices=Report.SOURCE_CHOICES,
|
||||
help_text='Filter allow filtering QuerySet by a field - source.'
|
||||
'Choices - 0 (Back office), 1 (Web), 2 (Mobile)'
|
||||
)
|
||||
category = filters.ChoiceFilter(
|
||||
choices=Report.CATEGORY_CHOICES,
|
||||
help_text='Filter allow filtering QuerySet by a field - category.'
|
||||
'Choices - 0 (Bug), 1 (Suggestion/improvement)'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = Report
|
||||
fields = (
|
||||
'source',
|
||||
'category',
|
||||
)
|
||||
31
apps/report/migrations/0001_initial.py
Normal file
31
apps/report/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 2.2.7 on 2020-02-05 12:16
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Report',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
|
||||
('source', models.PositiveSmallIntegerField(choices=[(0, 'Back office'), (1, 'Web'), (2, 'Mobile')], verbose_name='source')),
|
||||
('category', models.PositiveSmallIntegerField(choices=[(0, 'Bug'), (1, 'Suggestion/improvement')], verbose_name='category')),
|
||||
('url', models.URLField(verbose_name='URL')),
|
||||
('description', models.TextField(verbose_name='description')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Report',
|
||||
'verbose_name_plural': 'Reports',
|
||||
},
|
||||
),
|
||||
]
|
||||
0
apps/report/migrations/__init__.py
Normal file
0
apps/report/migrations/__init__.py
Normal file
84
apps/report/models.py
Normal file
84
apps/report/models.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
from django.conf import settings
|
||||
from django.core.mail import send_mail
|
||||
from django.db import models
|
||||
from django.utils.text import gettext_lazy as _
|
||||
|
||||
from report.tasks import send_report_task
|
||||
from utils.models import ProjectBaseMixin
|
||||
|
||||
|
||||
class ReportManager(models.Manager):
|
||||
"""Manager for model Report."""
|
||||
|
||||
def make(self, source: int, category, url: str, description: str):
|
||||
"""Make object."""
|
||||
obj = self.create(
|
||||
source=source,
|
||||
category=category,
|
||||
url=url,
|
||||
description=description
|
||||
)
|
||||
if settings.USE_CELERY:
|
||||
send_report_task.delay(obj.id)
|
||||
else:
|
||||
send_report_task(obj.id)
|
||||
return obj
|
||||
|
||||
|
||||
class ReportQuerySet(models.QuerySet):
|
||||
"""QuerySet for model Report."""
|
||||
|
||||
def by_source(self, source: int):
|
||||
"""Return QuerySet filtered by a source."""
|
||||
return self.filter(source=source)
|
||||
|
||||
|
||||
class Report(ProjectBaseMixin):
|
||||
"""Report model."""
|
||||
|
||||
BACK_OFFICE = 0
|
||||
WEB = 1
|
||||
MOBILE = 2
|
||||
|
||||
SOURCE_CHOICES = (
|
||||
(BACK_OFFICE, _('Back office')),
|
||||
(WEB, _('Web')),
|
||||
(MOBILE, _('Mobile')),
|
||||
)
|
||||
|
||||
BUG = 0
|
||||
SUGGESTION_IMPROVEMENT = 1
|
||||
|
||||
CATEGORY_CHOICES = (
|
||||
(BUG, _('Bug')),
|
||||
(SUGGESTION_IMPROVEMENT, _('Suggestion/improvement')),
|
||||
)
|
||||
|
||||
source = models.PositiveSmallIntegerField(choices=SOURCE_CHOICES,
|
||||
verbose_name=_('source'))
|
||||
category = models.PositiveSmallIntegerField(choices=CATEGORY_CHOICES,
|
||||
verbose_name=_('category'))
|
||||
url = models.URLField(verbose_name=_('URL'))
|
||||
description = models.TextField(verbose_name=_('description'))
|
||||
|
||||
objects = ReportManager.from_queryset(ReportQuerySet)()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
verbose_name = _('Report')
|
||||
verbose_name_plural = _('Reports')
|
||||
|
||||
def get_body_email_message(self):
|
||||
"""Prepare the body of the email message"""
|
||||
return {
|
||||
'subject': self.get_category_display(),
|
||||
'message': str(self.description),
|
||||
'html_message': self.description,
|
||||
'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())
|
||||
|
||||
34
apps/report/serializers.py
Normal file
34
apps/report/serializers.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
"""DRF-serializers for application report."""
|
||||
from rest_framework import serializers
|
||||
|
||||
from report.models import Report
|
||||
|
||||
|
||||
class ReportBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model Report."""
|
||||
|
||||
category_display = serializers.CharField(source='get_category_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = Report
|
||||
fields = [
|
||||
'id',
|
||||
'category',
|
||||
'category_display',
|
||||
'url',
|
||||
'description',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'source': {'required': False},
|
||||
'category': {'write_only': True}
|
||||
}
|
||||
|
||||
def validate(self, attrs):
|
||||
"""An overridden validate method."""
|
||||
attrs['source'] = self.context.get('view').get_source()
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
"""An overridden create method."""
|
||||
return self.Meta.model.objects.make(**validated_data)
|
||||
18
apps/report/tasks.py
Normal file
18
apps/report/tasks.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
"""Report app tasks."""
|
||||
import logging
|
||||
|
||||
from celery import shared_task
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@shared_task
|
||||
def send_report_task(report_id: int):
|
||||
from report.models import Report
|
||||
|
||||
report_qs = Report.objects.filter(id=report_id)
|
||||
if report_qs.exists():
|
||||
report = report_qs.first()
|
||||
report.send_email()
|
||||
else:
|
||||
logger.error(f'Error sending report {report_id}')
|
||||
1
apps/report/tests.py
Normal file
1
apps/report/tests.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Create your tests here.
|
||||
0
apps/report/urls/__init__.py
Normal file
0
apps/report/urls/__init__.py
Normal file
10
apps/report/urls/back.py
Normal file
10
apps/report/urls/back.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
"""Back office URL patterns for application report."""
|
||||
from django.urls import path
|
||||
|
||||
from report.views import back as views
|
||||
|
||||
app_name = 'report'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.ReportListCreateView.as_view(), name='report-list-create'),
|
||||
]
|
||||
9
apps/report/urls/common.py
Normal file
9
apps/report/urls/common.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
"""Common URL patterns for application report."""
|
||||
from django.urls import path
|
||||
|
||||
from report.views import common as views
|
||||
|
||||
app_name = 'report'
|
||||
urlpatterns = [
|
||||
path('<int:pk>/', views.ReportRetrieveView.as_view(), name='report-retrieve')
|
||||
]
|
||||
5
apps/report/urls/mobile.py
Normal file
5
apps/report/urls/mobile.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
"""Mobile URL patterns for application report."""
|
||||
|
||||
app_name = 'report'
|
||||
|
||||
urlpatterns = []
|
||||
11
apps/report/urls/web.py
Normal file
11
apps/report/urls/web.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
"""Web URL patterns for application report."""
|
||||
from django.urls import path
|
||||
|
||||
from report.urls.common import urlpatterns as common_urlpatterns
|
||||
from report.views import web as views
|
||||
|
||||
app_name = 'report'
|
||||
|
||||
urlpatterns = common_urlpatterns + [
|
||||
path('', views.ReportListCreateView.as_view(), name='report-list-create'),
|
||||
]
|
||||
0
apps/report/views/__init__.py
Normal file
0
apps/report/views/__init__.py
Normal file
39
apps/report/views/back.py
Normal file
39
apps/report/views/back.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
"""Views for application report."""
|
||||
from rest_framework.generics import ListCreateAPIView
|
||||
|
||||
from report.models import Report
|
||||
from report.views.common import ReportBaseView
|
||||
|
||||
|
||||
class ReportListCreateView(ReportBaseView, ListCreateAPIView):
|
||||
"""
|
||||
## View for getting list of reports or create a new one.
|
||||
### POST-request data
|
||||
Request data attributes:
|
||||
* category: integer (0 - Bug, 1 - Suggestion improvement)
|
||||
* url: char (URL)
|
||||
* description: text (problem description)
|
||||
I.e.:
|
||||
```
|
||||
{
|
||||
"category": 1,
|
||||
"url": "http://google.com",
|
||||
"description": "Description"
|
||||
}
|
||||
```
|
||||
|
||||
### Response
|
||||
*GET*
|
||||
Return paginated list of reports.
|
||||
|
||||
*POST*
|
||||
Creates a new report, and returns a serialized object.
|
||||
|
||||
### Description
|
||||
Method that allows getting list of reports or create a new one and return serialized object.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_source():
|
||||
"""Return a source for view."""
|
||||
return Report.BACK_OFFICE
|
||||
58
apps/report/views/common.py
Normal file
58
apps/report/views/common.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
"""Common views for application report."""
|
||||
from rest_framework import generics
|
||||
|
||||
from report.filters import ReportFilterSet
|
||||
from report.models import Report
|
||||
from report.serializers import ReportBaseSerializer
|
||||
from utils.methods import get_permission_classes
|
||||
from utils.permissions import (
|
||||
IsEstablishmentManager, IsContentPageManager, IsReviewManager,
|
||||
IsModerator, IsRestaurantInspector, IsArtisanInspector,
|
||||
IsWineryWineInspector, IsDistilleryLiquorInspector, IsProducerFoodInspector,
|
||||
IsEstablishmentAdministrator
|
||||
)
|
||||
|
||||
|
||||
class ReportBaseView(generics.GenericAPIView):
|
||||
"""
|
||||
## Report base view.
|
||||
"""
|
||||
queryset = Report.objects.all()
|
||||
serializer_class = ReportBaseSerializer
|
||||
filter_class = ReportFilterSet
|
||||
permission_classes = get_permission_classes(
|
||||
IsEstablishmentManager, IsContentPageManager, IsReviewManager,
|
||||
IsModerator, IsRestaurantInspector, IsArtisanInspector,
|
||||
IsWineryWineInspector, IsDistilleryLiquorInspector, IsProducerFoodInspector,
|
||||
IsEstablishmentAdministrator
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_source():
|
||||
"""Return a source for view."""
|
||||
return NotImplementedError('You must implement "get_source" method')
|
||||
|
||||
|
||||
class ReportRetrieveView(ReportBaseView, generics.RetrieveAPIView):
|
||||
"""
|
||||
## View for retrieving serialized instance.
|
||||
### Response
|
||||
Return serialized object.
|
||||
I.e.:
|
||||
```
|
||||
{
|
||||
"count": 7,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
Method that allows retrieving serialized report object.
|
||||
"""
|
||||
39
apps/report/views/web.py
Normal file
39
apps/report/views/web.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
"""Views for application report."""
|
||||
from rest_framework.generics import ListCreateAPIView
|
||||
|
||||
from report.models import Report
|
||||
from report.views.common import ReportBaseView
|
||||
|
||||
|
||||
class ReportListCreateView(ReportBaseView, ListCreateAPIView):
|
||||
"""
|
||||
## View for getting list of reports or create a new one.
|
||||
### POST-request data
|
||||
Request data attributes:
|
||||
* category: integer (0 - Bug, 1 - Suggestion improvement)
|
||||
* url: char (URL)
|
||||
* description: text (problem description)
|
||||
I.e.:
|
||||
```
|
||||
{
|
||||
"category": 1,
|
||||
"url": "http://google.com",
|
||||
"description": "Description"
|
||||
}
|
||||
```
|
||||
|
||||
### Response
|
||||
*GET*
|
||||
Return paginated list of reports.
|
||||
|
||||
*POST*
|
||||
Creates a new report, and returns a serialized object.
|
||||
|
||||
### Description
|
||||
Method that allows getting list of reports or create a new one and return serialized object.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_source():
|
||||
"""Return a source for view."""
|
||||
return Report.WEB
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
"""Translation app models."""
|
||||
from django.apps import apps
|
||||
from django.contrib.postgres.fields import JSONField
|
||||
from django.contrib.postgres.indexes import GinIndex
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.apps import apps
|
||||
|
||||
from utils.models import ProjectBaseMixin, LocaleManagerMixin
|
||||
|
||||
|
||||
class LanguageQuerySet(models.QuerySet):
|
||||
"""QuerySet for model Language"""
|
||||
|
||||
|
|
@ -55,7 +57,7 @@ class SiteInterfaceDictionaryManager(LocaleManagerMixin):
|
|||
Tag = apps.get_model('tag', 'Tag')
|
||||
"""Creates or updates translation for EXISTING in DB Tag"""
|
||||
if not tag.pk or not isinstance(tag, Tag):
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError()
|
||||
if tag.translation:
|
||||
tag.translation.text = translations
|
||||
tag.translation.page = 'tag'
|
||||
|
|
@ -74,7 +76,7 @@ class SiteInterfaceDictionaryManager(LocaleManagerMixin):
|
|||
"""Creates or updates translation for EXISTING in DB TagCategory"""
|
||||
TagCategory = apps.get_model('tag', 'TagCategory')
|
||||
if not tag_category.pk or not isinstance(tag_category, TagCategory):
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError()
|
||||
if tag_category.translation:
|
||||
tag_category.translation.text = translations
|
||||
tag_category.translation.page = 'tag'
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class OAuthProjectMixin:
|
|||
|
||||
def get_source(self):
|
||||
"""Method to get of platform"""
|
||||
return NotImplementedError
|
||||
return NotImplementedError()
|
||||
|
||||
|
||||
class BaseAttributes(ProjectBaseMixin):
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ PROJECT_APPS = [
|
|||
'favorites.apps.FavoritesConfig',
|
||||
'rating.apps.RatingConfig',
|
||||
'tag.apps.TagConfig',
|
||||
'report.apps.ReportConfig',
|
||||
]
|
||||
|
||||
EXTERNAL_APPS = [
|
||||
|
|
@ -566,3 +567,5 @@ 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'
|
||||
|
|
|
|||
|
|
@ -123,3 +123,5 @@ EMAIL_PORT = 587
|
|||
|
||||
# ADD TRANSFER TO INSTALLED APPS
|
||||
INSTALLED_APPS.append('transfer.apps.TransferConfig')
|
||||
|
||||
EMAIL_TECHNICAL_SUPPORT = 'a.feteleu@spider.ru'
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ urlpatterns = [
|
|||
namespace='advertisement')),
|
||||
path('main/', include('main.urls.back')),
|
||||
path('partner/', include('partner.urls.back')),
|
||||
path('report/', include('report.urls.back')),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -36,5 +36,5 @@ urlpatterns = [
|
|||
path('favorites/', include('favorites.urls')),
|
||||
path('timetables/', include('timetable.urls.web')),
|
||||
path('products/', include('product.urls.web')),
|
||||
|
||||
path('report/', include('report.urls.web')),
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user