Woocommerce and some fixes

This commit is contained in:
Diego Calvo
2021-04-08 15:12:05 +02:00
parent 06bababfa6
commit 2ecab694b9
10 changed files with 1456 additions and 26 deletions

View File

@@ -1,7 +1,25 @@
from rest_framework import permissions from rest_framework import permissions
class IsCreator(permissions.BasePermission): class IsCompanyOwner(permissions.BasePermission):
"""
Grant permission if request.user.company same as obj.id
"""
def has_object_permission(self, request, view, obj):
if obj is not None:
# allow if authenticated and method is safe
if request.method in permissions.SAFE_METHODS:
return True
# admins always have permission
if request.user.is_staff is True:
return True
# permission if user is the object's creator
return obj == request.user.company
return False
class IsProductOwner(permissions.BasePermission):
""" """
Grant permission if request.user same as obj.creator Grant permission if request.user same as obj.creator
""" """
@@ -16,10 +34,9 @@ class IsCreator(permissions.BasePermission):
if request.user.is_staff is True: if request.user.is_staff is True:
return True return True
# permission if user is the object's creator # permission if user is the object's creator
return obj.creator == request.user return obj.company == request.user.company
return False return False
class IsStaff(permissions.BasePermission): class IsStaff(permissions.BasePermission):
""" """
Grant permission if request.user.is_staff is True Grant permission if request.user.is_staff is True

View File

@@ -47,6 +47,7 @@ urlpatterns = [
path('api/v1/companies/sample/', company_views.random_company_sample , name='company-sample'), path('api/v1/companies/sample/', company_views.random_company_sample , name='company-sample'),
path('api/v1/search/companies/', company_views.CompanySearchViewSet.as_view({'get': 'list'}) , name='company-search'), path('api/v1/search/companies/', company_views.CompanySearchViewSet.as_view({'get': 'list'}) , name='company-search'),
path('api/v1/purchase_email/', product_views.purchase_email, name='purchase-email'), path('api/v1/purchase_email/', product_views.purchase_email, name='purchase-email'),
path('api/v1/sync_shop/', product_views.sync_shop, name='purchase-email'),
path('api/v1/products/all_categories/', product_views.all_categories, name='all-categories'), path('api/v1/products/all_categories/', product_views.all_categories, name='all-categories'),
path('api/v1/stats/me/', stat_views.track_user, name='user-tracker'), path('api/v1/stats/me/', stat_views.track_user, name='user-tracker'),
path('api/v1/autocomplete/category-tag/', product_views.CategoryTagAutocomplete.as_view(), name='category-autocomplete'), path('api/v1/autocomplete/category-tag/', product_views.CategoryTagAutocomplete.as_view(), name='category-autocomplete'),

View File

@@ -19,7 +19,7 @@ from companies.models import Company
from companies.serializers import CompanySerializer from companies.serializers import CompanySerializer
from utils.tag_filters import CompanyTagFilter from utils.tag_filters import CompanyTagFilter
from rest_framework import filters from rest_framework import filters
from back_latienda.permissions import IsCreator, IsSiteAdmin from back_latienda.permissions import IsCompanyOwner, IsSiteAdmin
from utils import woocommerce from utils import woocommerce
@@ -27,7 +27,7 @@ from utils import woocommerce
class CompanySearchViewSet(viewsets.ModelViewSet): class CompanySearchViewSet(viewsets.ModelViewSet):
queryset = Company.objects.filter(is_validated=True).order_by('-created') queryset = Company.objects.filter(is_validated=True).order_by('-created')
serializer_class = CompanySerializer serializer_class = CompanySerializer
permission_classes = [IsAuthenticatedOrReadOnly, IsCreator] permission_classes = [IsAuthenticatedOrReadOnly, IsCompanyOwner]
filter_backends = (filters.SearchFilter, ) filter_backends = (filters.SearchFilter, )
# search_fields = ['company_name__unaccent__icontains', 'short_name__unaccent__icontains'] # search_fields = ['company_name__unaccent__icontains', 'short_name__unaccent__icontains']
search_fields = ['@company_name', '@short_name'] search_fields = ['@company_name', '@short_name']
@@ -36,7 +36,7 @@ class CompanySearchViewSet(viewsets.ModelViewSet):
class CompanyViewSet(viewsets.ModelViewSet): class CompanyViewSet(viewsets.ModelViewSet):
queryset = Company.objects.filter(is_validated=True).order_by('-created') queryset = Company.objects.filter(is_validated=True).order_by('-created')
serializer_class = CompanySerializer serializer_class = CompanySerializer
permission_classes = [IsAuthenticatedOrReadOnly, IsCreator] permission_classes = [IsAuthenticatedOrReadOnly, IsCompanyOwner]
filterset_class = CompanyTagFilter filterset_class = CompanyTagFilter
def perform_create(self, serializer): def perform_create(self, serializer):

View File

@@ -57,7 +57,7 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
notify = models.BooleanField('Notificar', default=False, null=True) notify = models.BooleanField('Notificar', default=False, null=True)
provider = models.CharField('Proveedor', max_length=1000, blank=True, null=True) # red social de registro provider = models.CharField('Proveedor', max_length=1000, blank=True, null=True) # red social de registro
email_verified = models.BooleanField('Email verificado', default=False, null=True) email_verified = models.BooleanField('Email verificado', default=False, null=True)
company = models.ForeignKey(Company, null=True, on_delete=models.DO_NOTHING, related_name='custom_user') company = models.ForeignKey(Company, null=True, blank=True, on_delete=models.DO_NOTHING, related_name='custom_user')
is_active = models.BooleanField('Activo', default=True) is_active = models.BooleanField('Activo', default=True)
is_staff = models.BooleanField('Empleado',default=False ) is_staff = models.BooleanField('Empleado',default=False )

View File

@@ -1,6 +1,6 @@
from rest_framework import viewsets from rest_framework import viewsets
from back_latienda.permissions import IsCreator, ReadOnly from back_latienda.permissions import ReadOnly
from . import models from . import models
from . import serializers from . import serializers

View File

@@ -10,9 +10,12 @@ from back_latienda.permissions import IsStaff
class HistorySyncViewSet(viewsets.ModelViewSet): class HistorySyncViewSet(viewsets.ModelViewSet):
queryset = HistorySync.objects.all() model = HistorySync
serializer_class = HistorySyncLogSerializer serializer_class = HistorySyncLogSerializer
permission_classes = [IsAuthenticated,] permission_classes = [IsAuthenticated,]
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(creator=self.request.user) serializer.save(creator=self.request.user)
def get_queryset(self):
return self.model.objects.filter(company=self.request.user.company).order_by('-created')

View File

@@ -30,8 +30,9 @@ from products.models import Product, CategoryTag
from products.serializers import ProductSerializer, TagFilterSerializer, SearchResultSerializer from products.serializers import ProductSerializer, TagFilterSerializer, SearchResultSerializer
from companies.models import Company from companies.models import Company
from stats.models import StatsLog from stats.models import StatsLog
from back_latienda.permissions import IsCreator, IsSiteAdmin, ReadOnly from back_latienda.permissions import IsProductOwner, IsSiteAdmin, ReadOnly
from .utils import extract_search_filters, ranked_product_search, product_loader, get_related_products from .utils import extract_search_filters, ranked_product_search, product_loader, get_related_products
from utils.woocommerce import migrate_shop_products
from utils.tag_serializers import TaggitSerializer from utils.tag_serializers import TaggitSerializer
from utils.tag_filters import ProductTagFilter, ProductOrderFilter from utils.tag_filters import ProductTagFilter, ProductOrderFilter
@@ -48,7 +49,7 @@ logging.basicConfig(
class ProductViewSet(viewsets.ModelViewSet): class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.filter(active=True).order_by('-created') queryset = Product.objects.filter(active=True).order_by('-created')
serializer_class = ProductSerializer serializer_class = ProductSerializer
permission_classes = [IsAuthenticatedOrReadOnly, IsCreator] permission_classes = [IsAuthenticatedOrReadOnly, IsProductOwner]
filter_backends = [DjangoFilterBackend, OrderingFilter] filter_backends = [DjangoFilterBackend, OrderingFilter]
filterset_class = ProductTagFilter filterset_class = ProductTagFilter
@@ -71,7 +72,7 @@ class MyProductsViewSet(viewsets.ModelViewSet):
""" """
model = Product model = Product
serializer_class = ProductSerializer serializer_class = ProductSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated, IsProductOwner]
def get_queryset(self): def get_queryset(self):
return self.model.objects.filter(company=self.request.user.company).order_by('-created') return self.model.objects.filter(company=self.request.user.company).order_by('-created')
@@ -403,3 +404,32 @@ def all_categories(request):
all_categories.append(instance.name) all_categories.append(instance.name)
return Response(data=all_categories) return Response(data=all_categories)
@api_view(['POST'])
@permission_classes([IsAuthenticated,])
def sync_shop(request):
print(request.data)
url = request.data.get('url')
key = request.data.get('key')
secret = request.data.get('secret')
print(f"Starting migration...")
response = migrate_shop_products(url, key, secret, request.user )
print(f"Products created: {len(response['new_products'])}")
print(response["error"])
if response["error"]:
message = render_to_string('sync_failed.html', {})
# send email to company
subject = "Estado de la sincronización"
email = EmailMessage(subject, message, to=[request.user.email])
email.content_subtype = "html"
email.send()
else:
message = render_to_string('sync_success.html', {
'new_products': len(response['new_products'])
})
# send email to company
subject = "Estado de la sincronización"
email = EmailMessage(subject, message, to=[request.user.email])
email.content_subtype = "html"
email.send()
return Response()

678
templates/sync_failed.html Normal file
View File

@@ -0,0 +1,678 @@
<!DOCTYPE html>
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
>
<head>
<title> </title>
<!--[if !mso]><!-- -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!--<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
#outlook a {
padding: 0;
}
body {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table,
td {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
p {
display: block;
margin: 13px 0;
}
</style>
<!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG />
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
<!--[if lte mso 11]>
<style type="text/css">
.mj-outlook-group-fix {
width: 100% !important;
}
</style>
<![endif]-->
<!--[if !mso]><!-->
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap"
rel="stylesheet"
type="text/css"
/>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap"
rel="stylesheet"
type="text/css"
/>
<style type="text/css">
@import url(https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap);
@import url(https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap);
</style>
<!--<![endif]-->
<style type="text/css">
@media only screen and (min-width: 480px) {
.mj-column-per-100 {
width: 100% !important;
max-width: 100%;
}
.mj-column-per-50 {
width: 50% !important;
max-width: 50%;
}
}
</style>
<style type="text/css">
@media only screen and (max-width: 480px) {
table.mj-full-width-mobile {
width: 100% !important;
}
td.mj-full-width-mobile {
width: auto !important;
}
}
</style>
</head>
<body style="background-color: #8cead8">
<div style="background-color: #8cead8">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 20px;
padding-top: 20px;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div
class="mj-column-per-100 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 10px;
padding-right: 0px;
padding-bottom: 10px;
padding-left: 0px;
word-break: break-word;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
border-collapse: collapse;
border-spacing: 0px;
"
>
<tbody>
<tr>
<td
style="
width: 250px;
"
>
<a
href="https://latienda.coop/"
target="_blank"
>
<img
alt=""
height="auto"
width="25"
align="left"
src="https://latienda.coop/_nuxt/img/latienda-logo.dea6549.png"
style="
border: none;
display: block;
outline: none;
text-decoration: none;
height: auto;
width: 100%;
font-size: 13px;
"
/>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 0px;
padding-top: 0;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div
class="mj-column-per-100 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 28px;
padding-right: 25px;
padding-bottom: 18px;
padding-left: 25px;
word-break: break-word;
"
>
<div
style="
font-family: Poppins,
Arial, sans-serif;
font-size: 20px;
font-weight: bold;
line-height: 1;
text-align: center;
color: #374493;
"
>
Se ha producido un error en la sincronización
</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 5px;
padding-top: 0;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div
class="mj-column-per-100 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-right: 0px;
padding-left: 0px;
word-break: break-word;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
border-collapse: collapse;
border-spacing: 0px;
"
>
<tbody>
<tr>
<td
style="
width: 250px;
"
></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr></tr>
<tr>
<td
align="center"
width="50"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 28px;
padding-right: 25px;
padding-bottom: 28px;
padding-left: 25px;
word-break: break-word;
"
>
<p
style="
font-family: Noto Sans,
sans-serif;
font-size: 17px;
line-height: 1.5;
text-align: center;
color: #374493;
margin: 0 50px;
"
>
Tu sincronización de productos desde tu tienda online ha finalizado con un error.
<br>
<br>
Comprueba tus credenciales y URL e inténtalo de nuevo. Si el error persiste, contacta con nosotros.
<br>
<br>
</p>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 15px;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:300px;"
>
<![endif]-->
<div
class="mj-column-per-50 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
></table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 20px;
padding-right: 25px;
padding-bottom: 20px;
padding-left: 25px;
word-break: break-word;
"
>
<div
style="
font-family: Poppins, Arial, sans-serif;
font-size: 15px;
line-height: 1;
text-align: center;
color: #374493;
"
>
2021 La Tienda.coop
</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</div>
</body>
</html>

678
templates/sync_success.html Normal file
View File

@@ -0,0 +1,678 @@
<!DOCTYPE html>
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
>
<head>
<title> </title>
<!--[if !mso]><!-- -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!--<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
#outlook a {
padding: 0;
}
body {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table,
td {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
p {
display: block;
margin: 13px 0;
}
</style>
<!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG />
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
<!--[if lte mso 11]>
<style type="text/css">
.mj-outlook-group-fix {
width: 100% !important;
}
</style>
<![endif]-->
<!--[if !mso]><!-->
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap"
rel="stylesheet"
type="text/css"
/>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap"
rel="stylesheet"
type="text/css"
/>
<style type="text/css">
@import url(https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap);
@import url(https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap);
</style>
<!--<![endif]-->
<style type="text/css">
@media only screen and (min-width: 480px) {
.mj-column-per-100 {
width: 100% !important;
max-width: 100%;
}
.mj-column-per-50 {
width: 50% !important;
max-width: 50%;
}
}
</style>
<style type="text/css">
@media only screen and (max-width: 480px) {
table.mj-full-width-mobile {
width: 100% !important;
}
td.mj-full-width-mobile {
width: auto !important;
}
}
</style>
</head>
<body style="background-color: #8cead8">
<div style="background-color: #8cead8">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 20px;
padding-top: 20px;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div
class="mj-column-per-100 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 10px;
padding-right: 0px;
padding-bottom: 10px;
padding-left: 0px;
word-break: break-word;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
border-collapse: collapse;
border-spacing: 0px;
"
>
<tbody>
<tr>
<td
style="
width: 250px;
"
>
<a
href="https://latienda.coop/"
target="_blank"
>
<img
alt=""
height="auto"
width="25"
align="left"
src="https://latienda.coop/_nuxt/img/latienda-logo.dea6549.png"
style="
border: none;
display: block;
outline: none;
text-decoration: none;
height: auto;
width: 100%;
font-size: 13px;
"
/>
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 0px;
padding-top: 0;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div
class="mj-column-per-100 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 28px;
padding-right: 25px;
padding-bottom: 18px;
padding-left: 25px;
word-break: break-word;
"
>
<div
style="
font-family: Poppins,
Arial, sans-serif;
font-size: 20px;
font-weight: bold;
line-height: 1;
text-align: center;
color: #374493;
"
>
Sincronización realizada con éxito
</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 5px;
padding-top: 0;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div
class="mj-column-per-100 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-right: 0px;
padding-left: 0px;
word-break: break-word;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
border-collapse: collapse;
border-spacing: 0px;
"
>
<tbody>
<tr>
<td
style="
width: 250px;
"
></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr></tr>
<tr>
<td
align="center"
width="50"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 28px;
padding-right: 25px;
padding-bottom: 28px;
padding-left: 25px;
word-break: break-word;
"
>
<p
style="
font-family: Noto Sans,
sans-serif;
font-size: 17px;
line-height: 1.5;
text-align: center;
color: #374493;
margin: 0 50px;
"
>
Tu sincronización de productos desde tu tienda online ha finalizado con éxito.
<br>
<br>
Se han creado {{count}} productos nuevos.
<br>
<br>
</p>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="
background: #ffffff;
background-color: #ffffff;
width: 100%;
"
>
<tbody>
<tr>
<td
style="
direction: ltr;
font-size: 0px;
padding: 20px 0;
padding-bottom: 15px;
text-align: center;
"
>
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:300px;"
>
<![endif]-->
<div
class="mj-column-per-50 mj-outlook-group-fix"
style="
font-size: 0px;
text-align: left;
direction: ltr;
display: inline-block;
vertical-align: top;
width: 100%;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
></table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div
style="
background: #ffffff;
background-color: #ffffff;
margin: 0px auto;
max-width: 600px;
"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align: top"
width="100%"
>
<tr>
<td
align="center"
style="
font-size: 0px;
padding: 10px 25px;
padding-top: 20px;
padding-right: 25px;
padding-bottom: 20px;
padding-left: 25px;
word-break: break-word;
"
>
<div
style="
font-family: Poppins, Arial, sans-serif;
font-size: 15px;
line-height: 1;
text-align: center;
color: #374493;
"
>
2021 La Tienda.coop
</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</div>
</body>
</html>

View File

@@ -65,15 +65,29 @@ def create_imported_product(info, company, history, user):
# alternative method # alternative method
serializer = ProductSerializer(data=instance_data) serializer = ProductSerializer(data=instance_data)
if serializer.is_valid(): if serializer.is_valid():
try: # try:
new = Product.objects.create(**serializer.validated_data) # new = Product.objects.create(**serializer.validated_data)
new.tags = tags # new.tags = tags
new.attributes = attributes # new.attributes = attributes
new.save() # new.save()
except Exception as e: # except Exception as e:
logging.error(f"Could not create product instance: {str(e)}") # logging.error(f"Could not create product instance: {str(e)}")
return None # return None
new, created = Product.objects.get_or_create(
company=company,
creator=user if user is not None else None,
history=history,
url=instance_data['url'],
stock=instance_data['stock'],
name=instance_data['name'],
description=instance_data['description'],
sku=instance_data['sku'],
price=instance_data['price']
)
new.tags = tags
new.attributes = attributes
new.save()
if len(info['images']) > 0: if len(info['images']) > 0:
try: try:
# get image # get image
@@ -109,11 +123,13 @@ def migrate_shop_products(url, key, secret, user=None, version="wc/v3"):
# get wcapi # get wcapi
wcapi = get_wcapi_instance(url, key, secret, version) wcapi = get_wcapi_instance(url, key, secret, version)
consumer_key = 'ck_565539bb25b472b1ff7a209eb157ca11c0a26397' consumer_key = 'ck_565539bb25b472b1ff7a209eb157ca11c0a26397'
consumer_secret = 'cs_9c1690ba5da0dd70f51d61c395628fa14d1a104c' consumer_secret = 'cs_9c1690ba5da0dd70f51d61c395628fa14d1a104c'
# get company fom url # get company fom url
company = Company.objects.filter(web_link=url).first() company = Company.objects.filter(shop_link=url).first()
if not company: if not company:
logging.error(f"Could not find Company with URL: {url}") logging.error(f"Could not find Company with URL: {url}")
@@ -122,8 +138,11 @@ def migrate_shop_products(url, key, secret, user=None, version="wc/v3"):
new_products = [] new_products = []
page = 1 page = 1
attemps = 0
error = False
# list products # list products
while True: while True:
try: try:
response = wcapi.get('products/', params={'per_page': 10, 'page': page}) response = wcapi.get('products/', params={'per_page': 10, 'page': page})
page += 1 page += 1
@@ -131,15 +150,19 @@ def migrate_shop_products(url, key, secret, user=None, version="wc/v3"):
products = response.json() products = response.json()
elif response.status_code == 401: elif response.status_code == 401:
logging.error(f"{response.status_code} [{response.url}]: {response.json()}") logging.error(f"{response.status_code} [{response.url}]: {response.json()}")
return None error = True
else: else:
logging.error(f"Could not load products from {response.url}: [{response.status_code}]") logging.error(f"Could not load products from {response.url}: [{response.status_code}]")
print(f"Could not load products fom {response.url}: [{response.status_code}]") print(f"Could not load products fom {response.url}: [{response.status_code}]")
return None error = True
except requests.exceptions.ReadTimeout as e: except requests.exceptions.ReadTimeout as e:
logging.error(f"Timeout reading backend: {str(e)}") logging.error(f"Timeout reading backend: {str(e)}")
# skip and try next # skip and try next
continue attemps += 1
if attemps>4:
break
else:
continue
# exit loop if no more products # exit loop if no more products
if not products: if not products:
break break
@@ -149,7 +172,6 @@ def migrate_shop_products(url, key, secret, user=None, version="wc/v3"):
company=company, company=company,
sync_date=datetime.datetime.now(), sync_date=datetime.datetime.now(),
) )
counter = 0 counter = 0
for product in products: for product in products:
# check if exists # check if exists
@@ -169,11 +191,12 @@ def migrate_shop_products(url, key, secret, user=None, version="wc/v3"):
# update history.quantity # update history.quantity
history.quantity = counter history.quantity = counter
history.save() history.save()
logging.info(f"Products created: {len(new_products)}") logging.info(f"Products created: {len(new_products)}")
print(f"Products created: {len(new_products)}") print(f"Products created: {len(new_products)}")
return new_products return {"new_products": new_products, "error": error}