forked from uncloud/uncloud
cleanup commit, introduction of onetimeprice
This commit is contained in:
parent
686d2c2b1e
commit
f08269640d
15 changed files with 141 additions and 240 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ from .models import *
|
|||
for m in [
|
||||
Currency,
|
||||
Order,
|
||||
OneTimePrice,
|
||||
PricePerTime,
|
||||
Product,
|
||||
ProductOrder,
|
||||
|
|
|
@ -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)
|
||||
|
|
75
uncloud_v3/app/management/commands/test-data.py
Normal file
75
uncloud_v3/app/management/commands/test-data.py
Normal 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] })
|
|
@ -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')),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -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),
|
||||
]
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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),
|
||||
]
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue