cleanup commit, introduction of onetimeprice

This commit is contained in:
Nico Schottelius 2022-01-30 10:11:22 +01:00
parent 686d2c2b1e
commit f08269640d
15 changed files with 141 additions and 240 deletions

View File

@ -57,11 +57,8 @@ machine. Use `kubectl get nodes` to verify minikube is up and running.
in ResourceOrders1
* Need to pass in the price for the selected timeframe [done]
* On submit
* List of
* resources + values
* Product
* Timeframe
* Confirm & create
* Create ProductOrder
* Create ResourceOrder(s)
#### 3.0.0 (2022-01-14)

View File

@ -6,6 +6,7 @@ from .models import *
for m in [
Currency,
Order,
OneTimePrice,
PricePerTime,
Product,
ProductOrder,

View File

@ -1,8 +1,8 @@
from django import forms
class ProductOrderForm(forms.Form):
product = forms.SlugField(required=True)
timeframe = forms.SlugField(required=True)
product = forms.SlugField(required=True, disabled=True)
timeframe = forms.SlugField(required=True, disabled=True)
def __init__(self, resources, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@ -0,0 +1,75 @@
from django.core.management.base import BaseCommand
from app.models import *
class Command(BaseCommand):
help = 'Add test data'
# def add_arguments(self, parser):
#parser.add_argument('--username', type=str, required=True)
def handle(self, *args, **options):
currency, created = Currency.objects.get_or_create(defaults=
{
"slug": "CHF",
"name": "Swiss Franc",
"short_name": "CHF"
})
for timeframe in [ (3600, "1 hour", "1-hour"),
(86400, "1 day", "1-day"),
(7*86400, "7 days", "7-days"),
(30*86400, "30 days", "30-days"),
(365*86400, "365 days", "365 days") ]:
TimeFrame.objects.get_or_create(slug=timeframe[2],
defaults=
{
"name": timeframe[1],
"seconds": timeframe[0]
})
for ppt in [
("1-day", 1, currency),
("1-day", 2, currency),
("30-days", 10, currency), # Nextcloud
("30-days", 15, currency), # Gitea
("30-days", 35, currency), # Matrix
("30-days", 29, currency),
("30-days", 55, currency) ]:
tf = TimeFrame.objects.get(slug=ppt[0])
PricePerTime.objects.get_or_create(timeframe=tf,
value=ppt[1],
defaults=
{
"currency": currency
})
for res in [
("cpu-1", "CPU", "Core(s)", None, None),
("cpu-min-max", "CPU", "Core(s)", 1, 20),
("ram-1", "RAM", "GB", None, None),
("ram-min-max", "RAM", "GB", 1, 200),
("matrix-maintenance", "Matrix Maintenance Fee", "", 1, 1),
("nextcloud-maintenance", "Nextcloud Maintenance Fee", "", 1, 1),
("gitea-maintenance", "Gitea Maintenance Fee", "", 1, 1),
]:
Resource.objects.get_or_create(slug=res[0],
defaults=
{
"name": res[1],
"unit": res[2],
"minimum_units": res[3],
"maximum_units": res[4]
})
# Link to PPT -- later
# for ppt_res in res[5]:
# ppt = PricePerTime.objects.get(
for product in [
("matrix", "Matrix"),
("nextcloud", "Nextcloud"),
("gitea", "Gitea") ]:
Product.objects.get_or_create(slug=product[0],
defaults = { "name": product[1] })

View File

@ -1,4 +1,4 @@
# Generated by Django 4.0 on 2022-01-02 19:50
# Generated by Django 4.0 on 2022-01-16 16:44
from django.db import migrations, models
import django.db.models.deletion
@ -18,6 +18,7 @@ class Migration(migrations.Migration):
name='Currency',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(null=True, unique=True)),
('name', models.CharField(max_length=128, unique=True)),
('short_name', models.CharField(max_length=3, unique=True)),
],
@ -26,7 +27,7 @@ class Migration(migrations.Migration):
name='PricePerTime',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('price', models.FloatField()),
('value', models.FloatField()),
('currency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.currency')),
],
),
@ -34,6 +35,7 @@ class Migration(migrations.Migration):
name='Product',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(null=True, unique=True)),
('name', models.CharField(max_length=128, unique=True)),
],
),
@ -41,8 +43,9 @@ class Migration(migrations.Migration):
name='Resource',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128, unique=True)),
('unit', models.CharField(max_length=128, unique=True)),
('slug', models.SlugField(null=True, unique=True)),
('name', models.CharField(max_length=128)),
('unit', models.CharField(max_length=128)),
('minimum_units', models.FloatField(blank=True, null=True)),
('maximum_units', models.FloatField(blank=True, null=True)),
('step_size', models.FloatField(default=1)),
@ -53,6 +56,7 @@ class Migration(migrations.Migration):
name='TimeFrame',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(null=True, unique=True)),
('name', models.CharField(max_length=128, unique=True)),
('seconds', models.IntegerField(blank=True, null=True)),
],
@ -63,7 +67,6 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.FloatField()),
('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.resource')),
('timeframe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.timeframe')),
],
),
migrations.CreateModel(
@ -72,12 +75,18 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.product')),
('resources', models.ManyToManyField(to='app.ResourceOrder')),
('timeframe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.timeframe')),
],
),
migrations.AddField(
model_name='product',
name='resources',
field=models.ManyToManyField(to='app.Resource'),
field=models.ManyToManyField(blank=True, to='app.Resource'),
),
migrations.AddField(
model_name='product',
name='timeframes',
field=models.ManyToManyField(blank=True, to='app.TimeFrame'),
),
migrations.AddField(
model_name='pricepertime',
@ -95,4 +104,12 @@ class Migration(migrations.Migration):
('product', models.ManyToManyField(blank=True, to='app.ProductOrder')),
],
),
migrations.CreateModel(
name='OneTimePrice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.FloatField()),
('currency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.currency')),
],
),
]

View File

@ -1,28 +0,0 @@
# Generated by Django 4.0 on 2022-01-02 19:53
from django.db import migrations
def gen_timeframes(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
TimeFrame = apps.get_model('app', 'TimeFrame')
for timeframe in [ (3600, "1 hour"),
(86400, "1 day"),
(7*86400, "7 days"),
(30*86400, "30 days"),
(365*86400, "365 days") ]:
tf = TimeFrame(name=timeframe[1],
seconds=timeframe[0])
tf.save()
class Migration(migrations.Migration):
dependencies = [
('app', '0001_initial'),
]
operations = [
migrations.RunPython(gen_timeframes),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 4.0 on 2022-01-02 20:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0002_auto_20220102_1953'),
]
operations = [
migrations.AlterField(
model_name='product',
name='resources',
field=models.ManyToManyField(blank=True, to='app.Resource'),
),
migrations.AlterField(
model_name='resource',
name='unit',
field=models.CharField(max_length=128),
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 4.0 on 2022-01-02 20:20
from django.db import migrations
def gen_currencies(apps, schema_editor):
Currency = apps.get_model('app', 'Currency')
Currency.objects.get_or_create(name="Swiss Franc",
short_name="CHF")
class Migration(migrations.Migration):
dependencies = [
('app', '0003_alter_product_resources_alter_resource_unit'),
]
operations = [
migrations.RunPython(gen_currencies),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 4.0 on 2022-01-14 22:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0004_auto_20220102_2020'),
]
operations = [
migrations.AddField(
model_name='product',
name='slug',
field=models.SlugField(null=True),
),
]

View File

@ -1,28 +0,0 @@
# Generated by Django 4.0 on 2022-01-14 23:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0005_product_slug'),
]
operations = [
migrations.AddField(
model_name='resource',
name='slug',
field=models.SlugField(null=True, unique=True),
),
migrations.AlterField(
model_name='product',
name='slug',
field=models.SlugField(null=True, unique=True),
),
migrations.AlterField(
model_name='resource',
name='name',
field=models.CharField(max_length=128),
),
]

View File

@ -1,18 +0,0 @@
# 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),
),
]

View File

@ -1,18 +0,0 @@
# 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),
),
]

View File

@ -1,18 +0,0 @@
# 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'),
),
]

View File

@ -12,7 +12,6 @@ class Currency(models.Model):
def __str__(self):
return f"{self.name} ({self.short_name})"
class TimeFrame(models.Model):
slug = models.SlugField(null=True, unique=True)
name = models.CharField(max_length=128, unique=True)
@ -38,13 +37,20 @@ class TimeFrame(models.Model):
#return "{} ({})".format(self.name, self.secs_to_name(self.seconds))
return f"{self.name}"
class PricePerTime(models.Model):
timeframe = models.ForeignKey(TimeFrame, on_delete=models.CASCADE)
price = models.FloatField()
class OneTimePrice(models.Model):
value = models.FloatField()
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
def __str__(self):
return f"{self.price} {self.currency.short_name}/{self.timeframe}"
return f"{self.value} {self.currency.short_name}"
class PricePerTime(models.Model):
timeframe = models.ForeignKey(TimeFrame, on_delete=models.CASCADE)
value = models.FloatField()
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
def __str__(self):
return f"{self.value}{self.currency.short_name}/{self.timeframe}"
class Resource(models.Model):
slug = models.SlugField(null=True, unique=True) # primary identifier
@ -52,7 +58,7 @@ class Resource(models.Model):
unit = models.CharField(max_length=128) # Count, GB
minimum_units = models.FloatField(null=True, blank=True) # might have min
maximum_units = models.FloatField(null=True, blank=True) # might have max
step_size = models.FloatField(default=1) # might/must step size
step_size = models.FloatField(default=1) # step size
price_per_time = models.ManyToManyField(PricePerTime, blank=True)
@ -66,11 +72,7 @@ class Resource(models.Model):
else:
maximum = "No maximum"
pricing = []
for price in self.price_per_time.all():
pricing.append(f"{price.price}{price.currency.short_name}/{price.timeframe}")
pricing = ", ".join(pricing)
pricing = ", ".join([str(x) for x in self.price_per_time.all()])
return f"{self.slug}: {minimum}-{maximum} (+/-){self.step_size} {self.unit} ({pricing})"
@ -113,14 +115,11 @@ class Product(models.Model):
class ResourceOrder(models.Model):
"""
Resources that have been ordered
The timeframe should be in the ProductOrder, as it needs to be consistent
for all ordered resources
We need to record the selected value *and* potentially the
calculated price
"""
timeframe = models.ForeignKey(TimeFrame, on_delete=models.CASCADE)
value = models.FloatField()
resource = models.ForeignKey(Resource, on_delete=models.CASCADE)
@ -130,8 +129,13 @@ class ProductOrder(models.Model):
Describes a product a user bought
"""
product = models.ForeignKey(Product, on_delete=models.CASCADE)
timeframe = models.ForeignKey(TimeFrame, on_delete=models.CASCADE)
resources = models.ManyToManyField(ResourceOrder)
def __str__(self):
return f"Order of {self.product} / {self.timeframe}"
class Order(models.Model):
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, editable=False)

View File

@ -6,68 +6,45 @@ from django.views.generic.base import TemplateView
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from django.http import HttpResponse
from .models import *
from .forms import *
#class ProductOrderView(CreateView):
class ProductOrderView(FormView):
form_class = ProductOrderForm
template_name = 'app/productorder_form.html'
success_url = '/'
success_url = '/order/matrix/30-days/'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
# print(self)
# print(self.request)
print(self.kwargs)
#context = self.get_context_data(**kwargs)
#kwargs['resources'] = self.request['object'].resources.all()
# Set the product so the form can retrieve the resources
product = get_object_or_404(Product, slug=self.kwargs['product'])
kwargs['resources'] = product.resources.all()
return kwargs
def get_initial(self):
initial = super().get_initial()
initial['product'] = self.kwargs['product']
initial['timeframe'] = self.kwargs['timeframe']
return initial
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'])
# context['form'] = ProductOrderForm(
# context['product'].resources.all(),
# initial={'product': context['product'].slug,
# 'timeframe': context['timeframe'].slug}
# )
return context
# v2
# def post(self, request, *args, **kwargs):
# context = self.get_context_data()
# if context["form"].is_valid():
# print("form good")
# else:
# print("form not good")
# print(context["form"].errors)
# return HttpResponse("All good")
# v1
# 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'])
# res_price = []
# for res in context['product'].resources.all():
# price = res.price_per_time.filter(timeframe=context['timeframe'])[0].price
# currency = res.price_per_time.filter(timeframe=context['timeframe'])[0].currency
# res_price.append((res, price, currency))
# context['res_price'] = res_price
# print(context)
# print(self.kwargs)
# return context
def form_valid(self, form):
print("We got a valid form, let's create the order")
for f in form.fields:
print(f)
print(form.cleaned_data)
product = get_object_or_404(Product, slug=form.cleaned_data['product'])
tf = get_object_or_404(TimeFrame, slug=form.cleaned_data['timeframe'])
po = ProductOrder(product=product, timeframe=tf)
print(po)
return super().form_valid(form)
class ProductDetailView(DetailView):