Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
alex 2019-11-01 10:48:56 +03:00
commit 383032b2af
24 changed files with 537 additions and 79 deletions

View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.4 on 2019-10-25 16:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('booking', '0002_auto_20191003_1601'),
]
operations = [
migrations.AddField(
model_name='booking',
name='amount',
field=models.CharField(default=None, max_length=30, null=True, verbose_name='prepayment price'),
),
migrations.AddField(
model_name='booking',
name='stripe_key',
field=models.TextField(default=None, null=True, verbose_name='stripe service payment key'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.4 on 2019-10-25 16:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('booking', '0003_auto_20191025_1613'),
]
operations = [
migrations.AddField(
model_name='booking',
name='stripe_token',
field=models.TextField(default=None, null=True, verbose_name='stripe service pre-payed booking token'),
),
]

View File

@ -24,6 +24,9 @@ class Booking(ProjectBaseMixin):
pending_booking_id = models.TextField(verbose_name=_('external service pending booking'), default=None)
booking_id = models.TextField(verbose_name=_('external service booking id'), default=None, null=True,
db_index=True, )
stripe_key = models.TextField(null=True, default=None, verbose_name=_('stripe service payment key'))
stripe_token = models.TextField(null=True, default=None, verbose_name=_('stripe service pre-payed booking token'))
amount = models.CharField(null=True, default=None, verbose_name=_('prepayment price'), max_length=30)
user = models.ForeignKey(
'account.User', verbose_name=_('booking owner'), null=True,
related_name='bookings',

View File

@ -1,10 +1,13 @@
from abc import ABC, abstractmethod
import json
from abc import ABC, abstractmethod
import requests
from django.conf import settings
from rest_framework import status
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, status
from rest_framework.response import Response
import booking.models.models as models
from rest_framework import serializers
class AbstractBookingService(ABC):
@ -24,8 +27,12 @@ class AbstractBookingService(ABC):
self.url = settings.LASTABLE_SERVICE
@staticmethod
def get_certain_keys(d: dict, keys_to_preserve: set) -> dict:
def get_certain_keys(d: dict, keys_to_preserve: set, required=True) -> dict:
""" Helper """
if required:
diff = keys_to_preserve - d.keys()
if diff:
raise serializers.ValidationError({field: _(f'This field is required') for field in diff})
return {key: d[key] for key in d.keys() & keys_to_preserve}
@abstractmethod
@ -66,22 +73,22 @@ class GuestonlineService(AbstractBookingService):
def get_common_headers(self):
return {'X-Token': self.token, 'Content-type': 'application/json', 'Accept': 'application/json'}
def check_whether_booking_available(self, restaurant_id, date: str):
super().check_whether_booking_available(restaurant_id, date)
url = f'{self.url}v1/runtime_services'
params = {'restaurant_id': restaurant_id, 'date': date, 'expands[]': 'table_availabilities'}
def check_whether_booking_available(self, restaurant_id, *args, **kwargs):
url = f'{self.url}v1/periods'
params = {'restaurant_id': restaurant_id, **kwargs}
r = requests.get(url, headers=self.get_common_headers(), params=params)
if not status.is_success(r.status_code):
return False
response = json.loads(r.content)['runtime_services']
keys_to_preserve = {'left_seats', 'table_availabilities', 'closed', 'start_time', 'end_time', 'last_booking'}
response = map(lambda x: self.get_certain_keys(x, keys_to_preserve), response)
self.response = response
self.response = r.json()
return True
def commit_booking(self, payload):
def commit_booking(self, payload, stripe_token = None):
url = f'{self.url}v1/pending_bookings/{payload}/commit'
r = requests.put(url, headers=self.get_common_headers())
if stripe_token:
r = requests.put(url, headers=self.get_common_headers(),
data=json.dumps({'stripe_token': stripe_token}))
else:
r = requests.put(url, headers=self.get_common_headers())
self.response = json.loads(r.content)
if status.is_success(r.status_code) and self.response is None:
raise serializers.ValidationError(detail='Booking already committed.')
@ -93,8 +100,13 @@ class GuestonlineService(AbstractBookingService):
payload['lastname'] = payload.pop('last_name')
payload['firstname'] = payload.pop('first_name')
payload['mobile_phone'] = payload.pop('phone')
payload['user_locale'] = payload.pop('country_code')
headers = self.get_common_headers()
r = requests.put(url, headers=headers, data=json.dumps({'contact_info': payload}))
response = r.json()
self.response = response.get('prepayment')
if not status.is_success(r.status_code):
return Response(status=r.status_code, data=response)
return status.is_success(r.status_code)
def create_booking(self, payload):
@ -103,7 +115,10 @@ class GuestonlineService(AbstractBookingService):
payload['persons'] = payload.pop('booked_persons_number')
payload['date'] = payload.pop('booking_date')
r = requests.post(url, headers=self.get_common_headers(), data=json.dumps(payload))
return json.loads(r.content)['id'] if status.is_success(r.status_code) else False
if status.is_success(r.status_code):
return json.loads(r.content)['id']
else:
return Response(status=r.status_code, data=r.json())
def cancel_booking(self, payload):
url = f'{self.url}v1/pending_bookings/{payload}'

View File

@ -42,13 +42,29 @@ class PendingBookingSerializer(serializers.ModelSerializer):
'user',
)
class CommitBookingSerializer(serializers.ModelSerializer):
class Meta:
model = models.Booking
fields = (
'stripe_token',
)
def update(self, instance, validated_data):
"""Override update method"""
# Update user password from instance
service = instance.get_service_by_type(instance.type)
service.commit_booking(instance.pending_booking_id, validated_data.get('stripe_token'))
instance.stripe_token = validated_data.get('stripe_token')
instance.save()
return instance
class UpdateBookingSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()
class Meta:
model = models.Booking
fields = ('booking_id', 'id')
fields = ('booking_id', 'id', 'stripe_key', 'amount')
class GetBookingSerializer(serializers.ModelSerializer):

View File

@ -8,6 +8,7 @@ urlpatterns = [
path('<int:establishment_id>/check/', views.CheckWhetherBookingAvailable.as_view(), name='booking-check'),
path('<int:establishment_id>/create/', views.CreatePendingBooking.as_view(), name='create-pending-booking'),
path('<int:pk>/', views.UpdatePendingBooking.as_view(), name='update-pending-booking'),
path('<int:pk>/commit/', views.CommitPendingBooking.as_view(), name='update-pending-booking'),
path('<int:pk>/cancel/', views.CancelBooking.as_view(), name='cancel-existing-booking'),
path('last/', views.LastBooking.as_view(), name='last_booking-for-authorizer-user'),
path('retrieve/<int:pk>/', views.GetBookingById.as_view(), name='retrieves-booking-by-id'),

View File

@ -1,11 +1,13 @@
from rest_framework import generics, permissions, status, serializers
from django.shortcuts import get_object_or_404
from establishment.models import Establishment
from booking.models.models import Booking, GuestonlineService, LastableService
from rest_framework import generics, permissions, status, serializers
from rest_framework.response import Response
from booking.serializers.web import (PendingBookingSerializer,
UpdateBookingSerializer, GetBookingSerializer, CheckBookingSerializer)
from booking.models.models import Booking, GuestonlineService, LastableService
from booking.serializers.web import (PendingBookingSerializer, UpdateBookingSerializer, GetBookingSerializer,
CheckBookingSerializer, CommitBookingSerializer)
from establishment.models import Establishment
from notification.models import Subscriber
from utils.methods import get_user_ip
class CheckWhetherBookingAvailable(generics.GenericAPIView):
@ -28,7 +30,9 @@ class CheckWhetherBookingAvailable(generics.GenericAPIView):
service = l_service
service.service_id = establishment.lastable_id
elif (not establishment.guestonline_id is None) and g_service \
.check_whether_booking_available(establishment.guestonline_id, date):
.check_whether_booking_available(establishment.guestonline_id,
**g_service.get_certain_keys(request.query_params,
{'date', 'persons'})):
is_booking_available = True
service = g_service
service.service_id = establishment.guestonline_id
@ -61,7 +65,9 @@ class CreatePendingBooking(generics.CreateAPIView):
}
data['pending_booking_id'] = service.create_booking(
service.get_certain_keys(data.copy(), service_to_keys[data.get('type')]))
if not data['pending_booking_id']:
if isinstance(data['pending_booking_id'], Response):
return data['pending_booking_id']
elif not data['pending_booking_id']:
return Response(status=status.HTTP_403_FORBIDDEN, data='Unable to create booking')
data['booking_id'] = data['pending_booking_id'] if data.get('type') == Booking.LASTABLE else None
serializer = self.get_serializer(data=data)
@ -70,6 +76,13 @@ class CreatePendingBooking(generics.CreateAPIView):
return Response(status=status.HTTP_201_CREATED, data=serializer.data)
class CommitPendingBooking(generics.UpdateAPIView):
""" Commit pending booking """
queryset = Booking.objects.all()
permission_classes = (permissions.AllowAny,)
serializer_class = CommitBookingSerializer
class UpdatePendingBooking(generics.UpdateAPIView):
""" Update pending booking with contacts """
queryset = Booking.objects.all()
@ -81,9 +94,29 @@ class UpdatePendingBooking(generics.UpdateAPIView):
data = request.data.copy()
service = Booking.get_service_by_type(instance.type)
data['pending_booking_id'] = instance.pending_booking_id
service.update_booking(service.get_certain_keys(data, {
'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id',
r = service.update_booking(service.get_certain_keys(data, {
'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id', 'note',
}))
if isinstance(r, Response):
return r
if data.get('newsletter'):
Subscriber.objects.make_subscriber(email=data['email'], country_code=data['country_code'],
locale=request.locale, ip_address=get_user_ip(request),
user=request.user)
if service.response:
# если есть предоплата, возвращаем фронту страйп-ключ для совершения оплаты и цену
amount = service.response.get('amount')
stripe_key = service.response.get('stripe_key')
data = {
'id': instance.pk,
'amount': amount,
'stripe_key': stripe_key,
'type': instance.type,
}
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
serializer.update(instance, data)
return Response(status=status.HTTP_200_OK, data=data)
service.commit_booking(data['pending_booking_id'])
data = {
'booking_id': service.response.get('id'),

View File

View File

@ -0,0 +1,164 @@
from django.core.management.base import BaseCommand
from establishment.models import Establishment
from location.models import Country, Language
from transfer.models import Collections
from collection.models import Collection
from news.models import News
class Command(BaseCommand):
help = 'Import collection'
def handle(self, *args, **kwargs):
raw_qs = Collections.objects.raw('''
select
distinct
a.id,
a.collection_id,
-- a.establishment_id,
a.title,
a.tag_name,
a.slug,
-- a.attachment_file_name,
-- a.attachment_content_type,
-- a.attachment_file_size,
-- a.attachment_suffix_url,
-- active as is_publish,
a.country_code,
-- a.geometries,
a.description,
min(a.start) AS start
from
(
select distinct
c.id,
c.id as collection_id,
m.establishment_id,
c.title, c.tag_name,
c.slug, c.attachment_file_name,
c.attachment_content_type, c.attachment_file_size,
c.attachment_suffix_url,
active,
s.country_code_2 as country_code,
c.geometries,
c.title as description,
m.created_at as start
from collections as c
join metadata m on m.value = c.tag_name
join establishments e on e.id = m.establishment_id
join sites s on s.id = c.site_id
where m.`key` = 'collection'
union
select distinct
c.id,
c.id as collection_id,
m.establishment_id,
c.title, c.tag_name,
c.slug, c.attachment_file_name,
c.attachment_content_type, c.attachment_file_size,
c.attachment_suffix_url,
active,
s.country_code_2 as country_code,
c.geometries,
c.title as description,
m.created_at as start
from collections as c
join metadata m on m.value = c.slug
join establishments e on e.id = m.establishment_id
join sites s on s.id = c.site_id
where m.`key` = 'collection'
) a
group by
a.id,
a.collection_id,
-- a.establishment_id,
a.title,
a.tag_name,
a.slug,
-- a.attachment_file_name,
-- a.attachment_content_type,
-- a.attachment_file_size,
-- a.attachment_suffix_url,
-- active as is_publish,
a.country_code,
a.description
''')
objects = []
queryset = [vars(query) for query in raw_qs]
for obj in queryset:
# establishment = Establishment.objects.filter(old_id=obj['establishment_id']).first()
lang = Language.objects.filter(locale=obj['country_code'])
country = Country.objects.filter(languages__in=lang).first()
if country:
objects.append(
Collection(name={"en-GB": obj['title']}, collection_type=Collection.ORDINARY,
country=country,
description=obj['description'],
slug=obj['slug'], old_id=obj['collection_id'],
start=obj['start']
)
)
Collection.objects.bulk_create(objects)
raw_qs = Collections.objects.raw('''
select
distinct
a.id,
a.collection_id,
a.establishment_id
from
(
select distinct
c.id,
c.id as collection_id,
m.establishment_id,
c.title, c.tag_name,
c.slug, c.attachment_file_name,
c.attachment_content_type, c.attachment_file_size,
c.attachment_suffix_url,
active,
s.country_code_2 as country_code,
c.geometries,
c.title as description,
m.created_at as start
from collections as c
join metadata m on m.value = c.tag_name
join establishments e on e.id = m.establishment_id
join sites s on s.id = c.site_id
where m.`key` = 'collection'
union
select distinct
c.id,
c.id as collection_id,
m.establishment_id,
c.title, c.tag_name,
c.slug, c.attachment_file_name,
c.attachment_content_type, c.attachment_file_size,
c.attachment_suffix_url,
active,
s.country_code_2 as country_code,
c.geometries,
c.title as description,
m.created_at as start
from collections as c
join metadata m on m.value = c.slug
join establishments e on e.id = m.establishment_id
join sites s on s.id = c.site_id
where m.`key` = 'collection'
) a
''')
queryset = [vars(query) for query in raw_qs]
for obj in queryset:
print('COLLECT_ID: {}'.format(obj['collection_id']))
est = Establishment.objects.filter(old_id=obj['establishment_id'])
if est.exists():
inst = est.first()
collect = Collection.objects.filter(old_id=obj['collection_id'])
for c in collect:
inst.collections.add(c)
inst.save()

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.4 on 2019-10-31 13:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('collection', '0016_auto_20191024_1334'),
]
operations = [
migrations.AddField(
model_name='collection',
name='old_id',
field=models.IntegerField(blank=True, null=True),
),
]

View File

@ -76,6 +76,7 @@ class Collection(ProjectBaseMixin, CollectionDateMixin,
slug = models.SlugField(max_length=50, unique=True,
verbose_name=_('Collection slug'), editable=True, null=True)
old_id=models.IntegerField(null=True, blank=True)
objects = CollectionQuerySet.as_manager()
class Meta:

View File

@ -27,22 +27,7 @@ card = {
# "country": "Country",
}
},
"Guide": {
# как работать с ForeignKey на самого себя(self), поле "parent"
"data_type": "objects",
"dependencies": ("Collection", "self"),
"fields": {
"Guides": {
# нету аналогов для полей start и end
"name": "title"
}
},
"relations": {
# аналалог для поля "collection" не найдено
# "parent": "Guide",
# "collection": "Collection"
}
}
}
used_apps = ("location", )

View File

@ -15,6 +15,13 @@ class Country(TranslatedFieldsMixin, SVGImageMixin, ProjectBaseMixin):
STR_FIELD_NAME = 'name'
TWENTEEN_HOURS_FORMAT_COUNTRIES = [
'ca', # Canada
'au', # Australia
'us', # USA
'nz', # New Zeland
]
name = TJSONField(null=True, blank=True, default=None,
verbose_name=_('Name'), help_text='{"en-GB":"some text"}')
code = models.CharField(max_length=255, unique=True, verbose_name=_('Code'))
@ -23,6 +30,10 @@ class Country(TranslatedFieldsMixin, SVGImageMixin, ProjectBaseMixin):
languages = models.ManyToManyField(Language, verbose_name=_('Languages'))
old_id = models.IntegerField(null=True, blank=True, default=None)
@property
def time_format(self):
return 'hh:mmA' if self.code.lower() in self.TWENTEEN_HOURS_FORMAT_COUNTRIES else 'hh:mm'
@property
def country_id(self):
return self.id

View File

@ -8,11 +8,13 @@ from pprint import pprint
def transfer_countries():
queryset = Cities.objects.raw("""SELECT cities.id, cities.country_code_2
FROM cities WHERE
country_code_2 IS NOT NULL AND
country_code_2 != ""
GROUP BY cities.country_code_2""")
queryset = Cities.objects.raw("""
SELECT cities.id, cities.country_code_2
FROM cities
WHERE country_code_2 IS NOT NULL AND
country_code_2 != ""
GROUP BY cities.id, cities.country_code_2
""")
queryset = [vars(query) for query in queryset]
@ -24,16 +26,24 @@ def transfer_countries():
def transfer_regions():
regions_without_subregion_queryset = Cities.objects.raw("""SELECT cities.id, cities.region_code,
cities.country_code_2, cities.subregion_code
FROM cities WHERE
(subregion_code IS NULL OR
subregion_code = "") AND
region_code IS NOT NULL AND
region_code != "" AND
country_code_2 IS NOT NULL AND
country_code_2 != ""
GROUP BY region_code""")
regions_without_subregion_queryset = Cities.objects.raw("""
SELECT cities.id,
cities.region_code,
cities.country_code_2,
cities.subregion_code
FROM cities
WHERE (subregion_code IS NULL
OR subregion_code = ""
)
AND region_code IS NOT NULL
AND region_code != ""
AND country_code_2 IS NOT NULL
AND country_code_2 != ""
GROUP BY cities.id,
cities.region_code,
cities.country_code_2,
cities.subregion_code
""")
regions_without_subregion_queryset = [vars(query) for query in regions_without_subregion_queryset]
@ -43,25 +53,34 @@ def transfer_regions():
else:
pprint(f"Parent regions serializer errors: {serialized_without_subregion.errors}")
regions_with_subregion_queryset = Cities.objects.raw("""SELECT cities.id, cities.region_code,
cities.country_code_2, cities.subregion_code
FROM cities WHERE
subregion_code IS NOT NULL AND
subregion_code != "" AND
region_code IS NOT NULL AND
region_code != "" AND
country_code_2 IS NOT NULL AND
country_code_2 != ""
AND cities.subregion_code in (
SELECT region_code FROM cities WHERE
(subregion_code IS NULL OR
subregion_code = "") AND
region_code IS NOT NULL AND
region_code != "" AND
country_code_2 IS NOT NULL AND
country_code_2 != ""
)
GROUP BY region_code""")
regions_with_subregion_queryset = Cities.objects.raw("""
SELECT
cities.id,
cities.region_code,
cities.country_code_2,
cities.subregion_code
FROM cities
WHERE subregion_code IS NOT NULL AND
subregion_code != "" AND
region_code IS NOT NULL AND
region_code != "" AND
country_code_2 IS NOT NULL AND
country_code_2 != ""
AND cities.subregion_code in
(
SELECT region_code FROM cities WHERE
(subregion_code IS NULL OR
subregion_code = "") AND
region_code IS NOT NULL AND
region_code != "" AND
country_code_2 IS NOT NULL AND
country_code_2 != ""
)
GROUP BY cities.id,
cities.region_code,
cities.country_code_2,
cities.subregion_code
""")
regions_with_subregion_queryset = [vars(query) for query in regions_with_subregion_queryset]

View File

@ -64,6 +64,7 @@ class SiteSettingsSerializer(serializers.ModelSerializer):
country_code = serializers.CharField(source='subdomain', read_only=True)
country_name = serializers.CharField(source='country.name_translated', read_only=True)
time_format = serializers.CharField(source='country.time_format', read_only=True)
class Meta:
"""Meta class."""
@ -71,6 +72,7 @@ class SiteSettingsSerializer(serializers.ModelSerializer):
model = models.SiteSettings
fields = (
'country_code',
'time_format',
'subdomain',
'pinterest_page_url',
'twitter_page_url',
@ -81,7 +83,7 @@ class SiteSettingsSerializer(serializers.ModelSerializer):
'ad_config',
'published_features',
'currency',
'country_name'
'country_name',
)

View File

@ -0,0 +1,29 @@
# Generated by Django 2.2.4 on 2019-10-30 13:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('product', '0002_product_slug'),
]
operations = [
migrations.AddField(
model_name='product',
name='old_id',
field=models.IntegerField(blank=True, null=True, verbose_name='Product old id'),
),
migrations.AddField(
model_name='product',
name='old_id_establishment',
field=models.IntegerField(blank=True, null=True, verbose_name='Establishment old id'),
),
migrations.AlterField(
model_name='product',
name='establishment',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='products', to='establishment.Establishment', verbose_name='establishment'),
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 2.2.4 on 2019-10-31 09:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('product', '0003_auto_20191030_1315'),
]
operations = [
migrations.RemoveField(
model_name='product',
name='old_id_establishment',
),
migrations.AlterField(
model_name='product',
name='establishment',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='products', to='establishment.Establishment', verbose_name='establishment'),
),
migrations.AlterField(
model_name='product',
name='old_id',
field=models.IntegerField(blank=True, null=True),
),
migrations.AlterField(
model_name='productsubtype',
name='index_name',
field=models.CharField(choices=[('rum', 'Rum'), ('other', 'Other'), ('extra brut', 'extra brut'), ('brut', 'brut'), ('brut nature', 'brut nature'), ('demi-sec', 'demi-sec'), ('Extra Dry', 'Extra Dry'), ('dosage zero', 'dosage zero'), ('sec', 'sec'), ('doux', 'doux'), ('moelleux', 'moelleux')], db_index=True, max_length=50, unique=True, verbose_name='Index name'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-10-31 09:29
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('product', '0004_auto_20191031_0923'),
]
operations = [
migrations.AlterField(
model_name='product',
name='characteristics',
field=django.contrib.postgres.fields.jsonb.JSONField(null=True, verbose_name='Characteristics'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-10-31 09:30
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('product', '0005_auto_20191031_0929'),
]
operations = [
migrations.AlterField(
model_name='product',
name='establishment',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='products', to='establishment.Establishment', verbose_name='establishment'),
),
]

View File

@ -0,0 +1,29 @@
# Generated by Django 2.2.4 on 2019-10-31 14:08
import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('product', '0006_auto_20191031_0930'),
]
operations = [
migrations.RemoveField(
model_name='product',
name='old_id',
),
migrations.AlterField(
model_name='product',
name='characteristics',
field=django.contrib.postgres.fields.jsonb.JSONField(verbose_name='Characteristics', null=True),
),
migrations.AlterField(
model_name='product',
name='establishment',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='products', to='establishment.Establishment', verbose_name='establishment'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-10-31 14:10
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('product', '0007_auto_20191031_1408'),
]
operations = [
migrations.AlterField(
model_name='product',
name='characteristics',
field=django.contrib.postgres.fields.jsonb.JSONField(null=True, verbose_name='Characteristics'),
),
]

View File

@ -138,7 +138,8 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
help_text='{"en-GB":"some text"}')
description = TJSONField(_('Description'), null=True, blank=True,
default=None, help_text='{"en-GB":"some text"}')
characteristics = JSONField(_('Characteristics'))
#TODO set null=False
characteristics = JSONField(_('Characteristics'), null=True)
country = models.ManyToManyField('location.Country',
verbose_name=_('Country'))
available = models.BooleanField(_('Available'), default=True)

View File

@ -71,7 +71,7 @@ class RegionSerializer(serializers.ModelSerializer):
print(data)
if "subregion_code" in data and data["subregion_code"] is not None and data["subregion_code"].strip() != "":
try:
parent_region = Region.objects.get(code=str(data['region_code']))
parent_region = Region.objects.filter(code=str(data['region_code'])).first()
except Exception as e:
raise ValueError(f"Parent region error with {data}: {e}")