From 7a04f15aab055d696d31708d9b81edab07f360b1 Mon Sep 17 00:00:00 2001 From: phzhik Date: Thu, 6 Jul 2023 15:49:34 +0400 Subject: [PATCH] + get_barcode CDEK API * Upload payment_proof & cheque_photo to docs --- cdek/api.py | 47 ++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + store/models.py | 10 ++++++++++ store/serializers.py | 4 ++-- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/cdek/api.py b/cdek/api.py index d2ac0b1..a064fa5 100644 --- a/cdek/api.py +++ b/cdek/api.py @@ -1,9 +1,12 @@ import http import os +from time import sleep +from typing import Optional from urllib.parse import urljoin import requests from django.conf import settings +from django.core.files.base import ContentFile from requests import Request os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'poizonstore.settings') @@ -13,6 +16,7 @@ class CDEKClient: AUTH_ENDPOINT = 'oauth/token' ORDER_INFO_ENDPOINT = 'orders' CALCULATOR_TARIFF_ENDPOINT = 'calculator/tariff' + BARCODE_ENDPOINT = 'print/barcodes' MAX_RETRIES = 2 @@ -63,6 +67,49 @@ class CDEKClient: def calculate_tariff(self, data): return self.request('POST', self.CALCULATOR_TARIFF_ENDPOINT, json=data) + def generate_barcode(self, cdek_number, format="A6") -> Optional[str]: + request_data = { + "orders": [{"cdek_number": cdek_number}], + "copy_count": 1, + "format": format + } + + r = self.request('POST', self.BARCODE_ENDPOINT, json=request_data) + if not r: + return None + + resp_data = r.json() + if 'entity' not in resp_data: + return None + + barcode_uuid = resp_data['entity']['uuid'] + return barcode_uuid + + def get_barcode_url(self, uuid) -> Optional[str]: + if not uuid: + return None + + r = self.request('GET', f'{self.BARCODE_ENDPOINT}/{uuid}') + if not r: + return None + + resp_data = r.json() + if 'entity' not in resp_data: + return None + + url = resp_data['entity'].get('url') + return url + + def get_barcode_file(self, cdek_number): + uuid = self.generate_barcode(cdek_number) + sleep(2) # Sometimes url are not yet created, so be prepared for this + url = self.get_barcode_url(uuid) + if not url: + return None + + r = self.request('GET', url) + return ContentFile(r.content) if r and r.content else None + client = CDEKClient(settings.CDEK_CLIENT_ID, settings.CDEK_CLIENT_SECRET) client.authorize() diff --git a/requirements.txt b/requirements.txt index 343ea5c..9725903 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,7 @@ Django==4.2.2 django-filter==23.2 djangorestframework==3.14.0 +drf-extra-fields==3.5.0 Pillow==9.5.0 # Misc diff --git a/store/models.py b/store/models.py index 2286b3e..457453c 100644 --- a/store/models.py +++ b/store/models.py @@ -220,6 +220,8 @@ class Checklist(models.Model): CDEK = "cdek" COMPLETED = "completed" + PDF_AVAILABLE_STATUSES = (RUSSIA, CDEK, COMPLETED) + CHOICES = ( (DRAFT, 'Черновик'), (NEW, 'Новый заказ'), @@ -291,6 +293,7 @@ class Checklist(models.Model): # trackid poizon_tracking = models.CharField('Трек-номер Poizon', max_length=100, null=True, blank=True) cdek_tracking = models.CharField('Трек-номер СДЭК', max_length=100, null=True, blank=True) + cdek_barcode_pdf = models.FileField('Штрих-код СДЭК в PDF', upload_to='docs', null=True, blank=True) objects = ChecklistQuerySet.as_manager() @@ -358,6 +361,13 @@ class Checklist(models.Model): if old_obj and self.status != old_obj.status: self.status_updated_at = timezone.now() + # Try to get CDEK barcode PDF + if not self.cdek_barcode_pdf and self.cdek_tracking and self.status in Checklist.Status.PDF_AVAILABLE_STATUSES: + from store.views import CDEKAPI + pdf_file = CDEKAPI.client.get_barcode_file(self.cdek_tracking) + if pdf_file: + self.cdek_barcode_pdf.save(f'{self.id}_barcode.pdf', pdf_file) + # Create preview image if self.images.exists() and not self.preview_image: # Render preview image diff --git a/store/serializers.py b/store/serializers.py index 4af0e6d..310e7c6 100644 --- a/store/serializers.py +++ b/store/serializers.py @@ -135,7 +135,7 @@ class ChecklistSerializer(serializers.ModelSerializer): 'buyername', 'buyerphone', 'tg', 'receivername', 'reveiverphone', 'paymenttype', 'paymentproovement', 'checkphoto', - 'trackid', 'cdek_tracking', 'delivery', + 'trackid', 'cdek_tracking', 'cdek_barcode_pdf', 'delivery', 'startDate', 'currentDate', ) @@ -188,4 +188,4 @@ class PromocodeSerializer(serializers.ModelSerializer): class Meta: model = Promocode - fields = ('name', 'discount', 'freedelivery', 'nocomission') + fields = ('id', 'name', 'discount', 'freedelivery', 'nocomission')