Made pricing

main
Далер 1 day ago
parent 151a96dc37
commit 55fa03d250

3
.gitignore vendored

@ -0,0 +1,3 @@
*.pyc
__pycache__/*
inventory/migrations/__pycache__/0001_initial.cpython-310.pyc

@ -5,39 +5,45 @@ class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
ref_name = 'InventoryProductSerializer' # Unique ref_name for inventory
class PositionSerializer(serializers.ModelSerializer):
class Meta:
model = Position
fields = '__all__'
ref_name = 'InventoryPositionSerializer' # Unique ref_name for inventory
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = '__all__'
ref_name = 'InventoryEmployeeSerializer' # Unique ref_name for inventory
class StorageLocationSerializer(serializers.ModelSerializer):
class Meta:
model = StorageLocation
fields = '__all__'
ref_name = 'InventoryStorageLocationSerializer' # Unique ref_name for inventory
class ContractorSerializer(serializers.ModelSerializer):
class Meta:
model = Contractor
fields = '__all__'
ref_name = 'InventoryContractorSerializer' # Unique ref_name for inventory
class SupplyContractSerializer(serializers.ModelSerializer):
class Meta:
model = SupplyContract
fields = '__all__'
ref_name = 'InventorySupplyContractSerializer' # Unique ref_name for inventory
class TruckSerializer(serializers.ModelSerializer):
class Meta:
model = Truck
fields = '__all__'
fields = '__all__'
ref_name = 'InventoryTruckSerializer' # Unique ref_name for inventory

@ -1,27 +1,29 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework.permissions import AllowAny
from .views import (
ProductViewSet, EmployeeViewSet, PositionViewSet,
StorageLocationViewSet, ContractorViewSet, SupplyContractViewSet, TruckViewSet
)
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework.permissions import AllowAny
router = DefaultRouter()
router.register(r'products', ProductViewSet)
router.register(r'employees', EmployeeViewSet)
router.register(r'positions', PositionViewSet)
router.register(r'storage-locations', StorageLocationViewSet)
router.register(r'contractors', ContractorViewSet)
router.register(r'supply-contracts', SupplyContractViewSet)
router.register(r'trucks', TruckViewSet)
# Create the router for inventory-related views
router_inventory = DefaultRouter()
router_inventory.register(r'products', ProductViewSet)
router_inventory.register(r'employees', EmployeeViewSet)
router_inventory.register(r'positions', PositionViewSet)
router_inventory.register(r'storage-locations', StorageLocationViewSet)
router_inventory.register(r'contractors', ContractorViewSet)
router_inventory.register(r'supply-contracts', SupplyContractViewSet)
router_inventory.register(r'trucks', TruckViewSet)
schema_view = get_schema_view(
# Swagger schema view for inventory
schema_view_inventory = get_schema_view(
openapi.Info(
title="Store Management API",
title="Store Management API - Inventory",
default_version='v1',
description="API for managing the franchise store",
description="API for managing inventory in the franchise store",
terms_of_service="https://www.example.com/terms/",
contact=openapi.Contact(email="support@example.com"),
license=openapi.License(name="BSD License"),
@ -31,7 +33,7 @@ schema_view = get_schema_view(
)
urlpatterns = [
path('api/', include(router.urls)),
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
path('', include(router_inventory.urls)),
path('swagger/', schema_view_inventory.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui-inventory'),
path('redoc/', schema_view_inventory.with_ui('redoc', cache_timeout=0), name='schema-redoc-inventory'),
]

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

@ -0,0 +1,6 @@
from django.apps import AppConfig
class PricingConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'pricing'

@ -0,0 +1,113 @@
# Generated by Django 5.1.4 on 2025-01-08 14:02
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Discount',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('discount_percentage', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Процент скидки')),
('start_date', models.DateField(verbose_name='Дата начала')),
('end_date', models.DateField(verbose_name='Дата окончания')),
('description', models.TextField(blank=True, null=True, verbose_name='Описание акции')),
],
),
migrations.CreateModel(
name='PriceList',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('entry_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Входная цена')),
('final_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Итоговая цена')),
('date_effective', models.DateField(verbose_name='Дата вступления в силу')),
('constraint_percent_limit', models.DecimalField(decimal_places=2, default=1000, max_digits=5, verbose_name='Лимит на наценку (%)')),
('constraint_price_change', models.DecimalField(decimal_places=2, default=90, max_digits=5, verbose_name='Лимит на изменение цены (%)')),
],
),
migrations.CreateModel(
name='PriceType',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(choices=[('regular', 'Регулярная'), ('discount', 'Скидочная'), ('promotional', 'Акционная')], max_length=50, verbose_name='Тип цены')),
],
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Наименование товара')),
('manufacturer_name', models.CharField(max_length=255, verbose_name='Производитель')),
('manufacturer_country', models.CharField(max_length=255, verbose_name='Страна производителя')),
('manufacturer_code', models.CharField(blank=True, max_length=50, null=True, verbose_name='Код производителя')),
('dimensions', models.CharField(blank=True, max_length=255, null=True, verbose_name='Размеры')),
('unit_of_measure', models.CharField(max_length=50, verbose_name='Единица измерения')),
('shelf_life_days', models.IntegerField(verbose_name='Срок годности (дни)')),
('barcode', models.CharField(max_length=50, unique=True, verbose_name='Штрихкод')),
],
),
migrations.CreateModel(
name='DiscountHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('old_discount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Старая скидка')),
('new_discount', models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Новая скидка')),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Дата изменения скидки')),
('reason', models.TextField(blank=True, null=True, verbose_name='Причина изменения скидки')),
('discount', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.discount', verbose_name='Акция/Скидка')),
],
),
migrations.CreateModel(
name='PriceListWithDiscount',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('final_price_after_discount', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Итоговая цена после скидки')),
('discount', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.discount', verbose_name='Скидка')),
('price_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.pricelist', verbose_name='Прайс-лист')),
],
),
migrations.AddField(
model_name='pricelist',
name='price_type',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.pricetype', verbose_name='Тип цены'),
),
migrations.CreateModel(
name='PriceTag',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tag_image', models.ImageField(blank=True, null=True, upload_to='price_tags/', verbose_name='Изображение ценника')),
('price_effective_date', models.DateField(verbose_name='Дата вступления в силу ценника')),
('price_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.pricelist', verbose_name='Прайс-лист')),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.product', verbose_name='Товар')),
],
),
migrations.AddField(
model_name='pricelist',
name='product',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.product', verbose_name='Товар'),
),
migrations.CreateModel(
name='PriceChangeHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('old_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Старая цена')),
('new_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Новая цена')),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Дата изменения цены')),
('reason', models.TextField(blank=True, null=True, verbose_name='Причина изменения цены')),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.product', verbose_name='Товар')),
],
),
migrations.AddField(
model_name='discount',
name='product',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pricing.product', verbose_name='Товар'),
),
]

@ -0,0 +1,108 @@
from django.db import models
# Справочник товаров
class Product(models.Model):
name = models.CharField(max_length=255, verbose_name="Наименование товара")
manufacturer_name = models.CharField(max_length=255, verbose_name="Производитель")
manufacturer_country = models.CharField(max_length=255, verbose_name="Страна производителя")
manufacturer_code = models.CharField(max_length=50, verbose_name="Код производителя", blank=True, null=True)
dimensions = models.CharField(max_length=255, verbose_name="Размеры", blank=True, null=True)
unit_of_measure = models.CharField(max_length=50, verbose_name="Единица измерения")
shelf_life_days = models.IntegerField(verbose_name="Срок годности (дни)")
barcode = models.CharField(max_length=50, unique=True, verbose_name="Штрихкод")
def __str__(self):
return self.name
# Типы цен (например, регулярная, скидочная, акционная)
class PriceType(models.Model):
name = models.CharField(max_length=50, verbose_name="Тип цены", choices=[
('regular', 'Регулярная'),
('discount', 'Скидочная'),
('promotional', 'Акционная'),
])
def __str__(self):
return self.name
# Прайс-листы (со всеми ценами)
class PriceList(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
price_type = models.ForeignKey(PriceType, on_delete=models.CASCADE, verbose_name="Тип цены")
entry_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Входная цена")
final_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена")
date_effective = models.DateField(verbose_name="Дата вступления в силу")
constraint_percent_limit = models.DecimalField(max_digits=5, decimal_places=2, default=1000, verbose_name="Лимит на наценку (%)")
constraint_price_change = models.DecimalField(max_digits=5, decimal_places=2, default=90, verbose_name="Лимит на изменение цены (%)")
def save(self, *args, **kwargs):
# Логика проверки на изменение цены
if self.pk:
old_price = PriceList.objects.get(pk=self.pk).final_price
price_change_percent = abs((self.final_price - old_price) / old_price) * 100
if price_change_percent > self.constraint_price_change:
raise ValueError(f"Цена не может измениться более чем на {self.constraint_price_change}%")
super().save(*args, **kwargs)
def __str__(self):
return f"{self.product.name} - {self.price_type.name} - {self.final_price} руб."
# Скидки и акции (могут применяться к товарам)
class Discount(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
discount_percentage = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Процент скидки")
start_date = models.DateField(verbose_name="Дата начала")
end_date = models.DateField(verbose_name="Дата окончания")
description = models.TextField(verbose_name="Описание акции", blank=True, null=True)
def __str__(self):
return f"Скидка {self.discount_percentage}% на {self.product.name} с {self.start_date} по {self.end_date}"
# История изменений цен
class PriceChangeHistory(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
old_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Старая цена")
new_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Новая цена")
change_date = models.DateTimeField(auto_now_add=True, verbose_name="Дата изменения цены")
reason = models.TextField(verbose_name="Причина изменения цены", blank=True, null=True)
def __str__(self):
return f"{self.product.name} - изменение цены с {self.old_price} на {self.new_price} - {self.change_date}"
# Пример использования ценников для печати
class PriceTag(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
price_list = models.ForeignKey(PriceList, on_delete=models.CASCADE, verbose_name="Прайс-лист")
tag_image = models.ImageField(upload_to='price_tags/', verbose_name="Изображение ценника", blank=True, null=True)
price_effective_date = models.DateField(verbose_name="Дата вступления в силу ценника")
def __str__(self):
return f"Ценник для {self.product.name} - {self.price_effective_date}"
# Связь с историей акций
class DiscountHistory(models.Model):
discount = models.ForeignKey(Discount, on_delete=models.CASCADE, verbose_name="Акция/Скидка")
old_discount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Старая скидка")
new_discount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Новая скидка")
change_date = models.DateTimeField(auto_now_add=True, verbose_name="Дата изменения скидки")
reason = models.TextField(verbose_name="Причина изменения скидки", blank=True, null=True)
def __str__(self):
return f"Изменение скидки с {self.old_discount}% на {self.new_discount}% для {self.discount.product.name}"
# Пример применения скидки к прайс-листу
class PriceListWithDiscount(models.Model):
price_list = models.ForeignKey(PriceList, on_delete=models.CASCADE, verbose_name="Прайс-лист")
discount = models.ForeignKey(Discount, on_delete=models.CASCADE, verbose_name="Скидка")
final_price_after_discount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена после скидки")
def __str__(self):
return f"{self.price_list.product.name} - {self.final_price_after_discount} руб. (с учетом скидки)"

@ -0,0 +1,80 @@
from rest_framework import serializers
from .models import Product, PriceType, PriceList, Discount, PriceChangeHistory, PriceTag, DiscountHistory, PriceListWithDiscount
# Сериализатор для модели Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'manufacturer_name', 'manufacturer_country', 'manufacturer_code', 'dimensions', 'unit_of_measure', 'shelf_life_days', 'barcode']
ref_name = 'PricingProductSerializer' # Unique ref_name for pricing
# Сериализатор для модели PriceType
class PriceTypeSerializer(serializers.ModelSerializer):
class Meta:
model = PriceType
fields = ['id', 'name']
ref_name = 'PricingPriceTypeSerializer' # Unique ref_name for pricing
# Сериализатор для модели PriceList
class PriceListSerializer(serializers.ModelSerializer):
product = ProductSerializer() # Вложенный сериализатор для связи с продуктом
price_type = PriceTypeSerializer() # Вложенный сериализатор для связи с типом цены
class Meta:
model = PriceList
fields = ['id', 'product', 'price_type', 'entry_price', 'final_price', 'date_effective', 'constraint_percent_limit', 'constraint_price_change']
ref_name = 'PricingPriceListSerializer' # Unique ref_name for pricing
# Сериализатор для модели Discount
class DiscountSerializer(serializers.ModelSerializer):
product = ProductSerializer() # Вложенный сериализатор для связи с продуктом
class Meta:
model = Discount
fields = ['id', 'product', 'discount_percentage', 'start_date', 'end_date', 'description']
ref_name = 'PricingDiscountSerializer' # Unique ref_name for pricing
# Сериализатор для модели PriceChangeHistory
class PriceChangeHistorySerializer(serializers.ModelSerializer):
product = ProductSerializer() # Вложенный сериализатор для связи с продуктом
class Meta:
model = PriceChangeHistory
fields = ['id', 'product', 'old_price', 'new_price', 'change_date', 'reason']
ref_name = 'PricingPriceChangeHistorySerializer' # Unique ref_name for pricing
# Сериализатор для модели PriceTag
class PriceTagSerializer(serializers.ModelSerializer):
product = ProductSerializer() # Вложенный сериализатор для связи с продуктом
price_list = PriceListSerializer() # Вложенный сериализатор для связи с прайс-листом
class Meta:
model = PriceTag
fields = ['id', 'product', 'price_list', 'tag_image', 'price_effective_date']
ref_name = 'PricingPriceTagSerializer' # Unique ref_name for pricing
# Сериализатор для модели DiscountHistory
class DiscountHistorySerializer(serializers.ModelSerializer):
discount = DiscountSerializer() # Вложенный сериализатор для связи с акцией
class Meta:
model = DiscountHistory
fields = ['id', 'discount', 'old_discount', 'new_discount', 'change_date', 'reason']
ref_name = 'PricingDiscountHistorySerializer' # Unique ref_name for pricing
# Сериализатор для модели PriceListWithDiscount
class PriceListWithDiscountSerializer(serializers.ModelSerializer):
price_list = PriceListSerializer() # Вложенный сериализатор для связи с прайс-листом
discount = DiscountSerializer() # Вложенный сериализатор для связи с скидкой
class Meta:
model = PriceListWithDiscount
fields = ['id', 'price_list', 'discount', 'final_price_after_discount']
ref_name = 'PricingPriceListWithDiscountSerializer' # Unique ref_name for pricing

@ -0,0 +1,46 @@
from rest_framework.test import APITestCase
from rest_framework import status
from .models import Product
from django.urls import reverse
class ProductAPITest(APITestCase):
def setUp(self):
# Создание тестового продукта
self.product_data = {
'name': 'Test Product',
'manufacturer_name': 'Test Manufacturer',
'manufacturer_country': 'Test Country',
'unit_of_measure': 'pcs',
'shelf_life_days': 365,
'barcode': '123456789012',
}
self.product = Product.objects.create(**self.product_data)
self.url = reverse('product-list') # Замени на свой URL
def test_create_product(self):
"""Test creating a new product"""
response = self.client.post(self.url, self.product_data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Product.objects.count(), 2)
self.assertEqual(Product.objects.latest('id').name, self.product_data['name'])
def test_get_product(self):
"""Test retrieving a product"""
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1) # Только один продукт в базе
def test_update_product(self):
"""Test updating a product"""
updated_data = {'name': 'Updated Product'}
response = self.client.put(reverse('product-detail', args=[self.product.id]), updated_data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.product.refresh_from_db()
self.assertEqual(self.product.name, 'Updated Product')
def test_delete_product(self):
"""Test deleting a product"""
response = self.client.delete(reverse('product-detail', args=[self.product.id]))
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(Product.objects.count(), 0) # Продукт должен быть удален

@ -0,0 +1,39 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework.permissions import AllowAny
from .views import (
PriceTypeViewSet, PriceListViewSet, DiscountViewSet,
PriceChangeHistoryViewSet, PriceTagViewSet, DiscountHistoryViewSet, PriceListWithDiscountViewSet
)
# Create the router for pricing-related views
router_pricing = DefaultRouter()
router_pricing.register(r'price-types', PriceTypeViewSet)
router_pricing.register(r'price-lists', PriceListViewSet)
router_pricing.register(r'discounts', DiscountViewSet)
router_pricing.register(r'price-change-history', PriceChangeHistoryViewSet)
router_pricing.register(r'price-tags', PriceTagViewSet)
router_pricing.register(r'discount-history', DiscountHistoryViewSet)
router_pricing.register(r'price-lists-with-discounts', PriceListWithDiscountViewSet)
# Swagger schema view for pricing
schema_view_pricing = get_schema_view(
openapi.Info(
title="Store Management API - Pricing",
default_version='v1',
description="API for managing pricing in the franchise store",
terms_of_service="https://www.example.com/terms/",
contact=openapi.Contact(email="support@example.com"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=(AllowAny,),
)
urlpatterns = [
path('', include(router_pricing.urls)),
path('swagger/', schema_view_pricing.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui-pricing'),
path('redoc/', schema_view_pricing.with_ui('redoc', cache_timeout=0), name='schema-redoc-pricing'),
]

@ -0,0 +1,46 @@
from rest_framework import viewsets
from .models import Product, PriceType, PriceList, Discount, PriceChangeHistory, PriceTag, DiscountHistory, PriceListWithDiscount
from .serializers import (
ProductSerializer, PriceTypeSerializer, PriceListSerializer, DiscountSerializer,
PriceChangeHistorySerializer, PriceTagSerializer, DiscountHistorySerializer, PriceListWithDiscountSerializer
)
# ViewSet для модели Product
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# ViewSet для модели PriceType
class PriceTypeViewSet(viewsets.ModelViewSet):
queryset = PriceType.objects.all()
serializer_class = PriceTypeSerializer
# ViewSet для модели PriceList
class PriceListViewSet(viewsets.ModelViewSet):
queryset = PriceList.objects.all()
serializer_class = PriceListSerializer
# ViewSet для модели Discount
class DiscountViewSet(viewsets.ModelViewSet):
queryset = Discount.objects.all()
serializer_class = DiscountSerializer
# ViewSet для модели PriceChangeHistory
class PriceChangeHistoryViewSet(viewsets.ModelViewSet):
queryset = PriceChangeHistory.objects.all()
serializer_class = PriceChangeHistorySerializer
# ViewSet для модели PriceTag
class PriceTagViewSet(viewsets.ModelViewSet):
queryset = PriceTag.objects.all()
serializer_class = PriceTagSerializer
# ViewSet для модели DiscountHistory
class DiscountHistoryViewSet(viewsets.ModelViewSet):
queryset = DiscountHistory.objects.all()
serializer_class = DiscountHistorySerializer
# ViewSet для модели PriceListWithDiscount
class PriceListWithDiscountViewSet(viewsets.ModelViewSet):
queryset = PriceListWithDiscount.objects.all()
serializer_class = PriceListWithDiscountSerializer

@ -56,6 +56,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'rest_framework',
'inventory',
'pricing',
]
ROOT_URLCONF = 'urls'

@ -3,5 +3,6 @@ from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('inventory.urls')),
]
path('api/inventory/', include('inventory.urls')), # Inventory URLs
path('api/pricing/', include('pricing.urls')), # Pricing URLs
]

Loading…
Cancel
Save