fix: responsive
This commit is contained in:
+40
-2
@@ -1,7 +1,18 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from shop.models import ProductVariant, Tax
|
from shop.models import ProductPrice, ProductVariant, Tax
|
||||||
|
|
||||||
|
|
||||||
|
def price_without_tax(price_with_tax, tax):
|
||||||
|
"""El staff introduce el precio con impuestos (lo que paga el cliente);
|
||||||
|
ProductPrice.price se guarda sin impuestos, que es lo que usa el resto de
|
||||||
|
la aplicación (carritos, pedidos, shop/utils.py) para calcular bases
|
||||||
|
imponibles/impuestos. ProductPrice.save() recalcula price_with_tax a
|
||||||
|
partir de este valor, así que no hace falta guardarlo aquí."""
|
||||||
|
return round(price_with_tax / (1 + Decimal(tax.value) / 100), 2)
|
||||||
|
|
||||||
|
|
||||||
class ProductInitialPriceForm(forms.Form):
|
class ProductInitialPriceForm(forms.Form):
|
||||||
@@ -12,7 +23,10 @@ class ProductInitialPriceForm(forms.Form):
|
|||||||
max_digits=11,
|
max_digits=11,
|
||||||
decimal_places=2,
|
decimal_places=2,
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.NumberInput(attrs={'class': 'input input-bordered w-full', 'step': '0.01', 'placeholder': 'Precio'}),
|
label='Precio con impuestos',
|
||||||
|
widget=forms.NumberInput(
|
||||||
|
attrs={'class': 'input input-bordered w-full', 'step': '0.01', 'placeholder': 'Precio con impuestos'}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
tax = forms.ModelChoiceField(
|
tax = forms.ModelChoiceField(
|
||||||
queryset=Tax.objects.all(),
|
queryset=Tax.objects.all(),
|
||||||
@@ -31,6 +45,30 @@ class ProductInitialPriceForm(forms.Form):
|
|||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
def get_price_without_tax(self):
|
||||||
|
return price_without_tax(self.cleaned_data['price'], self.cleaned_data['tax'])
|
||||||
|
|
||||||
|
|
||||||
|
class ProductPriceForm(forms.ModelForm):
|
||||||
|
"""El campo `price` del formulario representa el precio CON impuestos (lo
|
||||||
|
que introduce el staff); al guardar se convierte al precio sin impuestos,
|
||||||
|
que es lo que almacena ProductPrice.price."""
|
||||||
|
|
||||||
|
price = forms.DecimalField(
|
||||||
|
max_digits=11,
|
||||||
|
decimal_places=2,
|
||||||
|
label='Precio con impuestos',
|
||||||
|
widget=forms.NumberInput(attrs={'step': '0.01'}),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ProductPrice
|
||||||
|
fields = ('price', 'tax', 'current')
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
self.instance.price = price_without_tax(self.cleaned_data['price'], self.cleaned_data['tax'])
|
||||||
|
return super().save(commit=commit)
|
||||||
|
|
||||||
|
|
||||||
class ProductVariantForm(forms.ModelForm):
|
class ProductVariantForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
{% load static %}
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es" data-theme="light">
|
<html lang="es" data-theme="light">
|
||||||
<head>
|
<head>
|
||||||
@@ -9,42 +8,54 @@
|
|||||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css"/>
|
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css"/>
|
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css"/>
|
||||||
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body class="min-h-screen bg-base-200">
|
<body class="min-h-screen bg-base-200">
|
||||||
<div class="flex min-h-screen">
|
<div class="drawer lg:drawer-open">
|
||||||
<aside class="w-64 shrink-0 bg-base-100 border-r border-base-300">
|
<input id="backoffice-drawer" type="checkbox" class="drawer-toggle"/>
|
||||||
<a href="{% url 'backoffice:dashboard' %}" class="text-xl font-semibold block p-4">Backoffice</a>
|
|
||||||
<ul class="menu w-full">
|
<div class="drawer-content flex flex-col min-h-screen">
|
||||||
<li>
|
<div class="navbar bg-base-100 border-b border-base-300 lg:hidden">
|
||||||
<a href="{% url 'backoffice:product_list' %}" class="{% if section == 'products' %}menu-active{% endif %}">Productos</a>
|
<label for="backoffice-drawer" class="btn btn-square btn-ghost" aria-label="Abrir menú">☰</label>
|
||||||
</li>
|
<span class="text-lg font-semibold ml-2">Backoffice</span>
|
||||||
<li>
|
</div>
|
||||||
<a href="{% url 'backoffice:order_list' %}" class="{% if section == 'orders' %}menu-active{% endif %}">Pedidos</a>
|
|
||||||
</li>
|
<main class="flex-1 p-4 lg:p-6 overflow-x-hidden">
|
||||||
<li>
|
{% block main %}
|
||||||
<a href="{% url 'backoffice:payment_list' %}" class="{% if section == 'payments' %}menu-active{% endif %}">Pagos</a>
|
{% endblock %}
|
||||||
</li>
|
</main>
|
||||||
<li>
|
</div>
|
||||||
<a href="{% url 'backoffice:customer_list' %}" class="{% if section == 'customers' %}menu-active{% endif %}">Clientes</a>
|
|
||||||
</li>
|
<div class="drawer-side z-20">
|
||||||
<li>
|
<label for="backoffice-drawer" aria-label="Cerrar menú" class="drawer-overlay"></label>
|
||||||
<a href="{% url 'backoffice:provider_list' %}" class="{% if section == 'providers' %}menu-active{% endif %}">Proveedores</a>
|
<aside class="w-64 min-h-full bg-base-100 border-r border-base-300">
|
||||||
</li>
|
<a href="{% url 'backoffice:dashboard' %}" class="text-xl font-semibold block p-4">Backoffice</a>
|
||||||
<li>
|
<ul class="menu w-full">
|
||||||
<a href="{% url 'backoffice:tax_list' %}" class="{% if section == 'taxes' %}menu-active{% endif %}">Impuestos</a>
|
<li>
|
||||||
</li>
|
<a href="{% url 'backoffice:product_list' %}" class="{% if section == 'products' %}menu-active{% endif %}">Productos</a>
|
||||||
<li>
|
</li>
|
||||||
<a href="{% url 'backoffice:brand_settings' %}" class="{% if section == 'settings' %}menu-active{% endif %}">Marca y ajustes</a>
|
<li>
|
||||||
</li>
|
<a href="{% url 'backoffice:order_list' %}" class="{% if section == 'orders' %}menu-active{% endif %}">Pedidos</a>
|
||||||
</ul>
|
</li>
|
||||||
</aside>
|
<li>
|
||||||
<main class="flex-1 p-6">
|
<a href="{% url 'backoffice:payment_list' %}" class="{% if section == 'payments' %}menu-active{% endif %}">Pagos</a>
|
||||||
{% block main %}
|
</li>
|
||||||
{% endblock %}
|
<li>
|
||||||
</main>
|
<a href="{% url 'backoffice:customer_list' %}" class="{% if section == 'customers' %}menu-active{% endif %}">Clientes</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'backoffice:provider_list' %}" class="{% if section == 'providers' %}menu-active{% endif %}">Proveedores</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'backoffice:tax_list' %}" class="{% if section == 'taxes' %}menu-active{% endif %}">Impuestos</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'backoffice:brand_settings' %}" class="{% if section == 'settings' %}menu-active{% endif %}">Marca y ajustes</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dialog id="backoffice-modal" class="modal">
|
<dialog id="backoffice-modal" class="modal">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
{% block main %}
|
{% block main %}
|
||||||
<h1 class="text-2xl font-semibold mb-6">Backoffice</h1>
|
<h1 class="text-2xl font-semibold mb-6">Backoffice</h1>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 gap-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
||||||
{% for section in sections %}
|
{% for section in sections %}
|
||||||
<a href="{% url section.url_name %}" class="card bg-base-100 border border-base-300 shadow-sm hover:shadow-md transition-shadow">
|
<a href="{% url section.url_name %}" class="card bg-base-100 border border-base-300 shadow-sm hover:shadow-md transition-shadow">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{% block title %}{{ title }}{% endblock %}
|
{% block title %}{{ title }}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-2 mb-4">
|
||||||
<h1 class="text-2xl font-semibold">{{ title }}</h1>
|
<h1 class="text-2xl font-semibold">{{ title }}</h1>
|
||||||
{% if create_url %}
|
{% if create_url %}
|
||||||
{% if create_is_page %}
|
{% if create_is_page %}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
{% block main %}
|
{% block main %}
|
||||||
<h1 class="text-2xl font-semibold mb-4">Pedido {{ object.code }}</h1>
|
<h1 class="text-2xl font-semibold mb-4">Pedido {{ object.code }}</h1>
|
||||||
|
|
||||||
<div class="stats shadow mb-6 bg-base-100">
|
<div class="stats stats-vertical sm:stats-horizontal shadow mb-6 bg-base-100 w-full sm:w-auto">
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Cliente</div>
|
<div class="stat-title">Cliente</div>
|
||||||
<div class="stat-value text-lg">{{ object.email }}</div>
|
<div class="stat-value text-lg">{{ object.email }}</div>
|
||||||
|
|||||||
@@ -16,20 +16,20 @@
|
|||||||
{% url 'backoffice:product_inline_view' product.pk 'tags' as tags_view_url %}
|
{% url 'backoffice:product_inline_view' product.pk 'tags' as tags_view_url %}
|
||||||
{% url 'backoffice:product_inline_edit' product.pk 'tags' as tags_edit_url %}
|
{% url 'backoffice:product_inline_edit' product.pk 'tags' as tags_edit_url %}
|
||||||
|
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-2 mb-4">
|
||||||
{% include 'backoffice/products/_inline_view.html' with field_name='name' view_url=name_view_url edit_url=name_edit_url %}
|
{% include 'backoffice/products/_inline_view.html' with field_name='name' view_url=name_view_url edit_url=name_edit_url %}
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button class="btn btn-sm btn-error" hx-get="{% url 'backoffice:product_delete' product.pk %}" hx-target="#backoffice-modal-box" hx-swap="innerHTML">Borrar</button>
|
<button class="btn btn-sm btn-error" hx-get="{% url 'backoffice:product_delete' product.pk %}" hx-target="#backoffice-modal-box" hx-swap="innerHTML">Borrar</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-6 mb-6">
|
<div class="flex flex-col sm:flex-row gap-6 mb-6">
|
||||||
{% with images.first as main_image %}
|
{% with images.first as main_image %}
|
||||||
<div class="shrink-0 w-64">
|
<div class="shrink-0 w-full sm:w-64">
|
||||||
{% if main_image %}
|
{% if main_image %}
|
||||||
<img class="w-64 h-64 object-cover rounded-box border border-base-300 shadow" src="{{ main_image.l.url }}" alt="{{ product.name }}">
|
<img class="w-full h-64 sm:w-64 object-cover rounded-box border border-base-300 shadow" src="{{ main_image.l.url }}" alt="{{ product.name }}">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="w-64 h-64 rounded-box border border-base-300 border-dashed flex items-center justify-center text-sm opacity-50">
|
<div class="w-full h-64 sm:w-64 rounded-box border border-base-300 border-dashed flex items-center justify-center text-sm opacity-50">
|
||||||
Sin imagen
|
Sin imagen
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<section class="w-full">
|
<section class="w-full">
|
||||||
<div class="stats shadow bg-base-100 self-start">
|
<div class="stats stats-vertical sm:stats-horizontal shadow bg-base-100 self-start w-full sm:w-auto">
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">SKU</div>
|
<div class="stat-title">SKU</div>
|
||||||
<div class="stat-value text-lg">{{ product.sku }}</div>
|
<div class="stat-value text-lg">{{ product.sku }}</div>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
{% include 'backoffice/products/_inline_view.html' with field_name='description' view_url=description_view_url edit_url=description_edit_url %}
|
{% include 'backoffice/products/_inline_view.html' with field_name='description' view_url=description_view_url edit_url=description_edit_url %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-3 gap-4 m-4">
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 m-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-sm font-medium opacity-70 mb-1">Marca</h3>
|
<h3 class="text-sm font-medium opacity-70 mb-1">Marca</h3>
|
||||||
{% include 'backoffice/products/_inline_view.html' with field_name='brand' view_url=brand_view_url edit_url=brand_edit_url %}
|
{% include 'backoffice/products/_inline_view.html' with field_name='brand' view_url=brand_view_url edit_url=brand_edit_url %}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
{{ form.description.errors }}
|
{{ form.description.errors }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-3 gap-4 mb-6">
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-sm font-medium opacity-70 mb-1">Marca</h3>
|
<h3 class="text-sm font-medium opacity-70 mb-1">Marca</h3>
|
||||||
{% include 'backoffice/products/_combobox.html' with field_name='brand' multiple=False %}
|
{% include 'backoffice/products/_combobox.html' with field_name='brand' multiple=False %}
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4 mb-4 max-w-md">
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-4 max-w-md">
|
||||||
<div>
|
<div>
|
||||||
<label class="text-sm font-medium opacity-70 mb-1 block" for="{{ form.sku.id_for_label }}">Código de referencia</label>
|
<label class="text-sm font-medium opacity-70 mb-1 block" for="{{ form.sku.id_for_label }}">Código de referencia</label>
|
||||||
{{ form.sku }}
|
{{ form.sku }}
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
<div class="mb-6 max-w-md">
|
<div class="mb-6 max-w-md">
|
||||||
<h3 class="text-sm font-medium opacity-70 mb-1">Precio inicial (opcional)</h3>
|
<h3 class="text-sm font-medium opacity-70 mb-1">Precio inicial (opcional)</h3>
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
{{ price_form.price }}
|
{{ price_form.price }}
|
||||||
{{ price_form.price.errors }}
|
{{ price_form.price.errors }}
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ class TestBackofficeProducts(TestCase, CreateProductsMixin):
|
|||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
product = Product.objects.get(sku='NEW-3')
|
product = Product.objects.get(sku='NEW-3')
|
||||||
price = ProductPrice.objects.get(product=product)
|
price = ProductPrice.objects.get(product=product)
|
||||||
assert price.price == Decimal('12.50')
|
# 12.50 es el precio CON impuestos que introduce el staff; se guarda sin impuestos.
|
||||||
|
assert price.price == Decimal('10.33')
|
||||||
|
assert price.price_with_tax == Decimal('12.50')
|
||||||
assert price.current is True
|
assert price.current is True
|
||||||
|
|
||||||
def test_create_product_with_price_missing_tax_shows_error(self):
|
def test_create_product_with_price_missing_tax_shows_error(self):
|
||||||
@@ -123,7 +125,7 @@ class TestBackofficeProducts(TestCase, CreateProductsMixin):
|
|||||||
|
|
||||||
old_price.refresh_from_db()
|
old_price.refresh_from_db()
|
||||||
assert old_price.current is False
|
assert old_price.current is False
|
||||||
new_price = self.product.prices.get(price=Decimal('25.00'))
|
new_price = self.product.prices.get(price=Decimal('20.66'))
|
||||||
assert new_price.current is True
|
assert new_price.current is True
|
||||||
|
|
||||||
def test_create_variant_for_product(self):
|
def test_create_variant_for_product(self):
|
||||||
@@ -150,6 +152,7 @@ class TestBackofficeProducts(TestCase, CreateProductsMixin):
|
|||||||
assert not ProductVariant.objects.filter(sku='V-M2').exists()
|
assert not ProductVariant.objects.filter(sku='V-M2').exists()
|
||||||
|
|
||||||
def test_create_price_for_product(self):
|
def test_create_price_for_product(self):
|
||||||
|
# El staff introduce el precio CON impuestos; se guarda sin impuestos.
|
||||||
tax, created = Tax.objects.get_or_create(code='IVA', value=21)
|
tax, created = Tax.objects.get_or_create(code='IVA', value=21)
|
||||||
|
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
@@ -157,7 +160,9 @@ class TestBackofficeProducts(TestCase, CreateProductsMixin):
|
|||||||
{'price': '9.99', 'tax': tax.pk, 'current': 'on'},
|
{'price': '9.99', 'tax': tax.pk, 'current': 'on'},
|
||||||
)
|
)
|
||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
assert ProductPrice.objects.filter(product=self.product, price=Decimal('9.99')).exists()
|
price = ProductPrice.objects.get(product=self.product, current=True)
|
||||||
|
assert price.price == Decimal('8.26')
|
||||||
|
assert price.price_with_tax == Decimal('9.99')
|
||||||
|
|
||||||
def test_create_price_for_variant(self):
|
def test_create_price_for_variant(self):
|
||||||
tax, created = Tax.objects.get_or_create(code='IVA', value=21)
|
tax, created = Tax.objects.get_or_create(code='IVA', value=21)
|
||||||
@@ -169,7 +174,9 @@ class TestBackofficeProducts(TestCase, CreateProductsMixin):
|
|||||||
{'price': '19.99', 'tax': tax.pk, 'current': 'on'},
|
{'price': '19.99', 'tax': tax.pk, 'current': 'on'},
|
||||||
)
|
)
|
||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
assert ProductPrice.objects.filter(variant=variant, price=Decimal('19.99')).exists()
|
price = ProductPrice.objects.get(variant=variant, current=True)
|
||||||
|
assert price.price == Decimal('16.52')
|
||||||
|
assert price.price_with_tax == Decimal('19.99')
|
||||||
|
|
||||||
def create_image_file(self, name='test.webp'):
|
def create_image_file(self, name='test.webp'):
|
||||||
image = Image.new('RGB', (256, 256), '#ACACAC')
|
image = Image.new('RGB', (256, 256), '#ACACAC')
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from django.shortcuts import get_object_or_404, render
|
|||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView, View
|
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView, View
|
||||||
|
|
||||||
from backoffice.forms import ProductInitialPriceForm, ProductVariantForm
|
from backoffice.forms import ProductInitialPriceForm, ProductPriceForm, ProductVariantForm
|
||||||
from backoffice.mixins import (
|
from backoffice.mixins import (
|
||||||
BackofficeCRUDMixin,
|
BackofficeCRUDMixin,
|
||||||
BackofficeHtmxMixin,
|
BackofficeHtmxMixin,
|
||||||
@@ -109,7 +109,7 @@ class ProductCreateView(BackofficeCRUDMixin, BackofficeStyledFormMixin, CreateVi
|
|||||||
if price_form.cleaned_data.get('price') is not None:
|
if price_form.cleaned_data.get('price') is not None:
|
||||||
ProductPrice.objects.create(
|
ProductPrice.objects.create(
|
||||||
product=self.object,
|
product=self.object,
|
||||||
price=price_form.cleaned_data['price'],
|
price=price_form.get_price_without_tax(),
|
||||||
tax=price_form.cleaned_data['tax'],
|
tax=price_form.cleaned_data['tax'],
|
||||||
current=True,
|
current=True,
|
||||||
)
|
)
|
||||||
@@ -378,9 +378,9 @@ class ProductVariantDeleteView(BackofficeCRUDMixin, BackofficeModalDeleteMixin,
|
|||||||
|
|
||||||
class ProductPriceCreateView(BackofficeCRUDMixin, BackofficeModalFormMixin, CreateView):
|
class ProductPriceCreateView(BackofficeCRUDMixin, BackofficeModalFormMixin, CreateView):
|
||||||
model = ProductPrice
|
model = ProductPrice
|
||||||
|
form_class = ProductPriceForm
|
||||||
permission_required = 'shop.add_productprice'
|
permission_required = 'shop.add_productprice'
|
||||||
section = SECTION
|
section = SECTION
|
||||||
fields = ('price', 'tax', 'current')
|
|
||||||
template_name = 'backoffice/generic/form.html'
|
template_name = 'backoffice/generic/form.html'
|
||||||
fragment_template_name = FORM_FRAGMENT
|
fragment_template_name = FORM_FRAGMENT
|
||||||
|
|
||||||
@@ -408,9 +408,9 @@ class ProductPriceCreateView(BackofficeCRUDMixin, BackofficeModalFormMixin, Crea
|
|||||||
|
|
||||||
class ProductVariantPriceCreateView(BackofficeCRUDMixin, BackofficeModalFormMixin, CreateView):
|
class ProductVariantPriceCreateView(BackofficeCRUDMixin, BackofficeModalFormMixin, CreateView):
|
||||||
model = ProductPrice
|
model = ProductPrice
|
||||||
|
form_class = ProductPriceForm
|
||||||
permission_required = 'shop.add_productprice'
|
permission_required = 'shop.add_productprice'
|
||||||
section = SECTION
|
section = SECTION
|
||||||
fields = ('price', 'tax', 'current')
|
|
||||||
template_name = 'backoffice/generic/form.html'
|
template_name = 'backoffice/generic/form.html'
|
||||||
fragment_template_name = FORM_FRAGMENT
|
fragment_template_name = FORM_FRAGMENT
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user