forked from uncloud/uncloud
in between commit: html bug
- "range" is great in theory, but does not show actual nummber - "number" does not allow float Need to go back to text
This commit is contained in:
parent
8952ef0b3a
commit
1e69722f4b
9 changed files with 120 additions and 9 deletions
|
@ -26,6 +26,11 @@ machine. Use `kubectl get nodes` to verify minikube is up and running.
|
|||
complete ones
|
||||
* resources are also timeframe bound
|
||||
* name != unique (?)
|
||||
* how do we link?
|
||||
* stays towards resource
|
||||
* we only show resources which have price_per_time with one of
|
||||
our timeframes
|
||||
* And we filter out timeframes that don't have all resources
|
||||
* Can we filter drop down in admin?
|
||||
* yes: ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)¶
|
||||
* resources should have a slug
|
||||
|
@ -40,7 +45,16 @@ machine. Use `kubectl get nodes` to verify minikube is up and running.
|
|||
|
||||
* Show products [done]
|
||||
* Link to ProductOrderForm [done]
|
||||
* Find suitable timeframes for a product [done]
|
||||
* Continue to resources / add resources
|
||||
* Need to list resources
|
||||
* Need to create manytomany relations for each resource resolutling
|
||||
in ResourceOrders
|
||||
* On submit
|
||||
* List of
|
||||
* resources + values
|
||||
* Product
|
||||
* Timeframe
|
||||
* Confirm & create
|
||||
|
||||
#### 3.0.0 (2022-01-14)
|
||||
|
|
18
uncloud_v3/app/migrations/0007_timeframe_slug.py
Normal file
18
uncloud_v3/app/migrations/0007_timeframe_slug.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.0 on 2022-01-14 23:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0006_resource_slug_alter_product_slug_alter_resource_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='timeframe',
|
||||
name='slug',
|
||||
field=models.SlugField(null=True, unique=True),
|
||||
),
|
||||
]
|
18
uncloud_v3/app/migrations/0008_currency_slug.py
Normal file
18
uncloud_v3/app/migrations/0008_currency_slug.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.0 on 2022-01-14 23:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0007_timeframe_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='currency',
|
||||
name='slug',
|
||||
field=models.SlugField(null=True, unique=True),
|
||||
),
|
||||
]
|
18
uncloud_v3/app/migrations/0009_product_timeframes.py
Normal file
18
uncloud_v3/app/migrations/0009_product_timeframes.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.0 on 2022-01-14 23:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0008_currency_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='product',
|
||||
name='timeframes',
|
||||
field=models.ManyToManyField(blank=True, to='app.TimeFrame'),
|
||||
),
|
||||
]
|
|
@ -2,9 +2,10 @@ from django.db import models
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.utils import timezone
|
||||
from django.urls import reverse
|
||||
|
||||
from django.db.models import Q
|
||||
|
||||
class Currency(models.Model):
|
||||
slug = models.SlugField(null=True, unique=True)
|
||||
name = models.CharField(max_length=128, unique=True)
|
||||
short_name = models.CharField(max_length=3, unique=True)
|
||||
|
||||
|
@ -13,6 +14,7 @@ class Currency(models.Model):
|
|||
|
||||
|
||||
class TimeFrame(models.Model):
|
||||
slug = models.SlugField(null=True, unique=True)
|
||||
name = models.CharField(max_length=128, unique=True)
|
||||
seconds = models.IntegerField(null=True, blank=True)
|
||||
|
||||
|
@ -70,7 +72,7 @@ class Resource(models.Model):
|
|||
|
||||
pricing = ", ".join(pricing)
|
||||
|
||||
return f"{self.name}: {minimum}-{maximum} (+/-){self.step_size} {self.unit} ({pricing})"
|
||||
return f"{self.slug}: {minimum}-{maximum} (+/-){self.step_size} {self.unit} ({pricing})"
|
||||
|
||||
class ResourceOrder(models.Model):
|
||||
"""
|
||||
|
@ -86,13 +88,29 @@ class Product(models.Model):
|
|||
Describes a product a user can buy
|
||||
"""
|
||||
|
||||
name = models.CharField(max_length=128, unique=True)
|
||||
slug = models.SlugField(null=True, unique=True)
|
||||
name = models.CharField(max_length=128, unique=True)
|
||||
|
||||
# textconfig = models.ManyToManyField(ProductTextConfiguration)
|
||||
# textfieldconfig = models.ManyToManyField(ProductTextFieldConfiguration)
|
||||
resources = models.ManyToManyField(Resource, blank=True) # List of REQUIRED resources
|
||||
timeframes = models.ManyToManyField(TimeFrame, blank=True) # List of POSSIBLE timeframes
|
||||
|
||||
resources = models.ManyToManyField(Resource, blank=True)
|
||||
def valid_timeframes(self):
|
||||
"""
|
||||
Return all timeframes that have all resources configured
|
||||
"""
|
||||
|
||||
valid_tf = []
|
||||
|
||||
num_res = self.resources.all().count()
|
||||
|
||||
for tf in self.timeframes.all():
|
||||
# Get all distinct source for this timeframe
|
||||
res = self.resources.filter(price_per_time__timeframe=tf).distinct().count()
|
||||
|
||||
if res == num_res:
|
||||
valid_tf.append(tf)
|
||||
|
||||
return valid_tf
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('product-detail', kwargs={'slug' : self.slug})
|
||||
|
|
|
@ -7,4 +7,10 @@
|
|||
<input type="submit" value="Buy">
|
||||
</form>
|
||||
|
||||
<ul>
|
||||
{% for tf in timeframes %}
|
||||
<li><a href="{% url 'product-order-tf' object.slug tf.slug %}">{{ tf }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
HERE we show a link to <a href="{{ productorder }}">order</a>.
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
Ordering a {{ product }} instance
|
||||
Ordering a {{ product }} instance for {{ timeframe }}
|
||||
|
||||
we are here?!
|
||||
|
||||
|
||||
<form method="post" >
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{{ form.as_p }}
|
||||
{% for res in product.resources.all %}
|
||||
<li>
|
||||
{% if res.minimum_units and res.maximum_units %}
|
||||
<input type="range" id="{{res.slug}}" name="{{res.slug}}"
|
||||
min="{{ res.minimum_units }}" max="{{ res.maximum_units
|
||||
}}">
|
||||
{% else %}
|
||||
<input type="text" id="{{res.slug}}" name="{{res.slug}}">
|
||||
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
<input type="submit" value="Next">
|
||||
</form>
|
||||
|
|
|
@ -16,6 +16,7 @@ class ProductOrderView(CreateView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['product'] = get_object_or_404(Product, slug=self.kwargs['product'])
|
||||
context['timeframe'] = get_object_or_404(TimeFrame, slug=self.kwargs['timeframe'])
|
||||
print(context)
|
||||
print(self.kwargs)
|
||||
return context
|
||||
|
@ -27,6 +28,8 @@ class ProductDetailView(DetailView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['productorder'] = reverse('product-order', kwargs={'product': self.object.slug })
|
||||
context['timeframes'] = context['product'].valid_timeframes()
|
||||
print(context)
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ urlpatterns = [
|
|||
path('admin/', admin.site.urls),
|
||||
path('order', appviews.ProductSelectView.as_view()),
|
||||
path('order/<slug:product>/', appviews.ProductOrderView.as_view(), name='product-order'),
|
||||
path('order/<slug:product>/<slug:timeframe>/', appviews.ProductOrderView.as_view(), name='product-order'),
|
||||
path('order/<slug:product>/<slug:timeframe>/', appviews.ProductOrderView.as_view(), name='product-order-tf'),
|
||||
path('product/', appviews.ProductListView.as_view()),
|
||||
path('product/<slug:slug>/', appviews.ProductDetailView.as_view(), name='product-detail')
|
||||
|
||||
|
|
Loading…
Reference in a new issue