Hack Bulgaria
github.com/HackBulgaria
Ivaylo Bachvarov
ivaylo@hacksoft.io
class RealEstate(models.Model):
seller = models.ForeignKey(User)
class Negotiation(models.Model):
real_estate=models.ForeignKey(RealEstate, related_name='negotiations')
buyer = models.ForeignKey(User)
class Offer(models.Model):
PENDING = 0
REJECTED = 1
ACCEPTED = 2
WITHDRAWN = 3
STATUS_CHOICES = (
(PENDING, 'Pending'),
(REJECTED, 'Rejected'),
(WITHDRAWN, 'Withdrawn'),
(ACCEPTED, 'Accepted'),
)
status = models.IntegerField(choices=STATUS_CHOICES, default=NEW)
negotiation = models.ForeignKey(Negotiation, related_name='offers')
offer_amount = models.PositiveIntegerField()
is_buyer_origin = models.BooleanField()
@api_view(['GET', 'POST'])
def offers_api(request):
if request.method == 'GET':
offers = Offer.objects.all()
serializer = OfferSerializer(snippets, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = OfferSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OffersSerializer
class NegotiationsListAPI(generics.ListCreateAPIView):
queryset = Negotiation.objects.all()
serializer_class = NegotiationSerializer
class NegotiationsListAPI(generics.ListCreateAPIView):
queryset = Negotiation.objects.all()
serializer_class = NegotiationSerializer
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class NegotiationsListAPI(generics.ListCreateAPIView):
queryset = Negotiation.objects.all()
serializer_class = NegotiationSerializer
def perform_create(self, serializer):
negotiation = serializer.save(owner=self.request.user)
# Send an email
context = {
"creator_name": self.request.full_name,
"property_address": negotiation.real_estate.address
}
send_email.delay(email=self.request.email, context=context)
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
def perform_create(self, serializer):
offer = serializer.save()
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
def perform_create(self, serializer):
negotiation = validated_data['negotiation']
if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValidationError("You can`t create new offer.\
There is an offer that is currently pending.")
offer = serializer.save()
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
Signals
# views.py
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
def perform_create(self, serializer):
negotiation = validated_data['negotiation']
if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValidationError("You can`t create new offer.\
There is an offer that is currently pending.")
serializer.save()
# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
if created:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
Clean
# views.py
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
def perform_create(self, serializer):
negotiation = validated_data['negotiation']
if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValidationError("You can`t create new offer.\
There is an offer that is currently pending.")
serializer.save()
# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
if created:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
Models
# models.py
class Offer(models.Model):
def clean(self):
if self.negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValueError("You can`t create new offer.\
There is an offer that is currently pending.")
# views.py
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
if created:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
# models.py
class Offer(models.Model):
def clean(self):
if self.negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValueError("You can`t create new offer.\
There is an offer that is currently pending.")
# views.py
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
@detail_route(methods=['post'])
def accept(self, request, pk=None):
offer = self.get_object()
serializer = AcceptfSerializer(data=request.data)
if serializer.is_valid():
offer.status = Offer.ACCPETED
offer.accepted_on = timezone.now()
user.save()
return Response(OfferSerializer(offer).data,
status=status.HTTP_200_OK)
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
if created:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
# permissions.py
class OnlySellerCanCreate(permissions.BasePermission):
def has_permission(self, request, view):
if not request.method == 'POST':
negotiation_id = request.data['negotiation']
real_estate = RealEstate.objects.get(negotiation=real_estate_id)
return self.request.user in real_estate.sellers
# models.py
class Offer(models.Model):
def clean(self):
if self.negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValueError("You can`t create new offer.\
There is an offer that is currently pending.")
# views.py
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
@detail_route(methods=['post'])
def accept(self, request, pk=None):
offer = self.get_object()
.........
# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
if created:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf',
options=options, context=offer)
Services
def create_offer(offers_amount, negotiation, user):
real_estate = RealEstate.objects.get(negotiation=negotiation)
if self.request.user not in real_estate.sellers:
raise PermissionDenied("You can create offer for this estate!")
if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValueError("You can`t create new offer.\
There is an offer that is currently pending.")
offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf', options=options, context=offer)
return offer
Services calling
# views.py
class OffersListAPI(generics.ListCreateAPIView):
queryset = Offers.objects.all()
serializer_class = OfferSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
obj = create_offer(**serializer.validated_data, user=self.request.user)
serializer = self.get_serializer(obj)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Services++
def create_offer(*, offers_amount, negotiation, user):
real_estate = RealEstate.objects.get(negotiation=negotiation)
if self.request.user not in real_estate.sellers:
raise PermissionDenied("You can create offer for this estate!")
if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValueError("You can`t create new offer.\
There is an offer that is currently pending.")
offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf', options=options, context=offer)
return offer
Services+++
def _check_if_user_is_seller(negotiation, user):
real_estate = RealEstate.objects.get(negotiation=negotiation)
if self.request.user not in real_estate.sellers:
raise PermissionDenied("You can create offer for this estate!")
def _check_for_other_pending_offers(negotiation):
if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
raise ValueError("You can`t create new offer.\
There is an offer that is currently pending.")
def _genarete_offer_pdf(offer):
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
}
pdfkit.from_file('offer.html', 'offer.pdf', options=options, context=offer)
def create_offer(*, offers_amount, negotiation, user):
_check_if_user_is_seller(negotiation, user)
_check_for_other_pending_offers(negotiation)
offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)
_generate_offer_pdf(offer)
return offer
Services+++
.......
def create_offer(*,
offers_amount: int,
negotiation: Negotiation,
user: User) -> Offer:
_check_if_user_is_seller(negotiation, user)
_check_for_other_pending_offers(negotiation)
offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)
_generate_offer_pdf(offer)
return offer
Services+++
class ServiceExceptionHandlerMixin:
expected_exceptions = {
ValidationError: serializers.ValidationError,
ValueError: serializers.ValidationError,
}
def handle_exception(self, exc):
if isinstance(exc, tuple(self.expected_exceptions.keys())):
drf_exception_class = self.expected_exceptions[exc.__class__]
drf_exception = drf_exception_class(get_error_message(exc))
return super().handle_exception(drf_exception)
return super().handle_exception(exc)
By Hack Bulgaria
Уводната лекция за курса по Програмиране 0