diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index a715c9d7..00000000
--- a/.dockerignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.git
-.env
diff --git a/.gitignore b/.gitignore
index a41d813d..2d923e99 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,3 @@ secret-key
!.gitkeep
*.orig
.vscode/settings.json
-2024-*
-2025-*
-2023-*
diff --git a/Changelog b/Changelog
index 9e420c87..5700852e 100644
--- a/Changelog
+++ b/Changelog
@@ -1,46 +1,3 @@
-3.4: 2022-04-14
- * 11566: Fix for ungleich.ch product section alignment
-3.2: 2021-02-07
- * 8816: Update order confirmation text to better prepared for payment dispute
- * supportticket#22990: Fix: can't add a deleted card
-3.1: 2021-01-11
- * 8781: Fix error is setting a default card (MR!746)
-3.0: 2021-01-07
- * 8393: Implement SCA for stripe payments (MR!745)
- * 8691: Implment check_vm_templates management command (MR!744)
-2.14: 2020-12-07
- * 8692: Create a script that fixes django db for the order after celery error (MR!743)
-2.13: 2020-12-02
- * 8654: Fix 500 error on invoices list for the user contact+devuanhosting.com@virus.media (MR!742)
- * 8593: Escape user's ssh key in xml-rpc call to create VM (MR!741)
-2.12.1: 2020-07-21
- * 8307: Introduce "Exclude vat calculations" for Generic Products (MR!740)
- * Change DE VAT rate to 16% from 19% (MR!739)
-2.12: 2020-06-23
- * 7894: Show one time payment invoices (MR!738)
-2.11: 2020-06-11
- * Bugfix: Correct the wrong constant name (caused payment to go thru and showing error and VMs not instantiated)
-2.10.8: 2020-06-10
- * #8102: Refactor MAX_TIME_TO_WAIT_FOR_VM_TERMINATE to increase time to poll whether VM has been terminated or not (MR!737)
-2.10.7: 2020-05-25
- * Bugfix: Handle VM templates deleted in OpenNebula but VM instances still existing (MR!736)
- Notes for deployment:
- When deploying define a UPDATED_TEMPLATES string represented dictionary value in .env
-```
- # Represents Template Ids that were
- # deleted and the new template Id to look for the template
- # definition
- UPDATED_TEMPLATES="{1: 100}"
-```
-2.10.6: 2020-03-25
- * Bugfix: Handle Nonetype for discount's name (MR!735)
-2.10.5: 2020-03-17
- * Introduce base price for VMs and let admins add stripe_coupon_id (MR!730)
- Notes for deployment:
- 1. Add env variable `VM_BASE_PRICE`
- 2. Migrate datacenterlight app. This introduces the stripe_coupon_code field in the VMPricing.
- 3. Create a coupon in stripe with the desired value and note down the stripe's coupon id
- 4. Update the discount amount and set the corresponding coupon id in the admin
2.10.3b: 2020-03-05
* #7773: Use username for communicating with opennebula all the time
2.10.2b: 2020-02-25
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 4c1a9a66..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,32 +0,0 @@
-# FROM python:3.10.0-alpine3.15
-FROM python:3.5-alpine3.12
-
-WORKDIR /usr/src/app
-
-RUN apk add --update --no-cache \
- git \
- build-base \
- openldap-dev \
- python3-dev \
- postgresql-dev \
- jpeg-dev \
- libxml2-dev \
- libxslt-dev \
- libmemcached-dev \
- zlib-dev \
- && rm -rf /var/cache/apk/*
-
-## For alpine 3.15 replace postgresql-dev with libpq-dev
-
-# FIX https://github.com/python-ldap/python-ldap/issues/432
-RUN echo 'INPUT ( libldap.so )' > /usr/lib/libldap_r.so
-
-COPY requirements.txt ./
-
-# Pillow seems to need LIBRARY_PATH set as follows: (see: https://github.com/python-pillow/Pillow/issues/1763#issuecomment-222383534)
-RUN LIBRARY_PATH=/lib:/usr/lib /bin/sh -c "pip install --no-cache-dir -r requirements.txt"
-
-COPY ./ .
-COPY entrypoint.sh /
-
-ENTRYPOINT ["/entrypoint.sh" ]
diff --git a/Makefile b/Makefile
index 68ff014e..67c0c15b 100644
--- a/Makefile
+++ b/Makefile
@@ -14,12 +14,6 @@ help:
@echo ' make rsync_upload '
@echo ' make install_debian_packages '
-buildimage:
- docker build -t dynamicweb:$$(git describe) .
-
-releaseimage: buildimage
- ./release.sh
-
collectstatic:
$(PY?) $(BASEDIR)/manage.py collectstatic
diff --git a/alplora/views.py b/alplora/views.py
index d628cffc..0a10b4e0 100644
--- a/alplora/views.py
+++ b/alplora/views.py
@@ -31,10 +31,9 @@ class ContactView(FormView):
return context
def form_valid(self, form):
- print("alplora contactusform")
- #form.save()
- #form.send_email(email_to='info@alplora.ch')
- #messages.add_message(self.request, messages.SUCCESS, self.success_message)
+ form.save()
+ form.send_email(email_to='info@alplora.ch')
+ messages.add_message(self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'alplora/contact_success.html', {})
diff --git a/build-image.sh b/build-image.sh
deleted file mode 100755
index 64a67fd6..00000000
--- a/build-image.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-if [ $# -lt 1 ]; then
- echo "$0 imageversion [push]"
- echo "Version could be: $(git describe --always)"
- echo "If push is specified, also push to our harbor"
- exit 1
-fi
-
-tagprefix=harbor.k8s.ungleich.ch/ungleich-public/dynamicweb
-version=$1; shift
-
-tag=${tagprefix}:${version}
-
-set -ex
-
-docker build -t "${tag}" .
-
-push=$1; shift
-
-if [ "$push" ]; then
- docker push "${tag}"
-fi
diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py
index 52b4f19f..c3ec974f 100644
--- a/datacenterlight/cms_plugins.py
+++ b/datacenterlight/cms_plugins.py
@@ -1,6 +1,5 @@
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
-from django.conf import settings
from .cms_models import (
DCLBannerItemPluginModel, DCLBannerListPluginModel, DCLContactPluginModel,
@@ -101,7 +100,6 @@ class DCLCalculatorPlugin(CMSPluginBase):
vm_type=instance.vm_type
).order_by('name')
context['instance'] = instance
- context['vm_base_price'] = settings.VM_BASE_PRICE
context['min_ram'] = 0.5 if instance.enable_512mb_ram else 1
return context
diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po
index cd7fab99..1a1a2a26 100644
--- a/datacenterlight/locale/de/LC_MESSAGES/django.po
+++ b/datacenterlight/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-02-07 11:10+0000\n"
+"POT-Creation-Date: 2020-02-01 09:42+0000\n"
"PO-Revision-Date: 2018-03-30 23:22+0000\n"
"Last-Translator: b'Anonymous User '\n"
"Language-Team: LANGUAGE \n"
@@ -144,8 +144,8 @@ msgid ""
"the heart of Switzerland."
msgstr "Bei uns findest Du die günstiges VMs aus der Schweiz."
-msgid "Try now, order a VM. VM price starts from only 11.5 CHF per month."
-msgstr "Unser Angebot beginnt bei 11.5 CHF pro Monat. Probier's jetzt aus!"
+msgid "Try now, order a VM. VM price starts from only 10.5 CHF per month."
+msgstr "Unser Angebot beginnt bei 10.5 CHF pro Monat. Probier's jetzt aus!"
msgid "ORDER VM"
msgstr "VM BESTELLEN"
@@ -415,9 +415,8 @@ msgstr "Deine MwSt-Nummer wurde überprüft"
msgid ""
"Your VAT number is under validation. VAT will be adjusted, once the "
"validation is complete."
-msgstr ""
-"Deine MwSt-Nummer wird derzeit validiert. Die MwSt. wird angepasst, sobald "
-"die Validierung abgeschlossen ist."
+msgstr "Deine MwSt-Nummer wird derzeit validiert. Die MwSt. wird angepasst, "
+"sobald die Validierung abgeschlossen ist."
msgid "Payment method"
msgstr "Bezahlmethode"
@@ -431,6 +430,18 @@ msgstr "Bestellungsübersicht"
msgid "Product"
msgstr "Produkt"
+msgid "Price"
+msgstr "Preise"
+
+msgid "VAT for"
+msgstr "MwSt für"
+
+msgid "Total Amount"
+msgstr "Gesamtsumme"
+
+msgid "Amount"
+msgstr "Betrag"
+
msgid "Description"
msgstr "Beschreibung"
@@ -443,51 +454,42 @@ msgstr "Preis ohne MwSt."
msgid "Pre VAT"
msgstr "Exkl. MwSt."
-msgid "VAT for"
-msgstr "MwSt für"
-
msgid "Your Price in Total"
msgstr "Dein Gesamtpreis"
-#, python-format
msgid ""
-" By clicking \"Place order\" you agree to our Terms of Service and "
-"this plan will charge your credit card account with %(total_price)s CHF/year"
+"By clicking \"Place order\" this plan will charge your credit card account "
+"with %(total_price)s CHF/year"
msgstr ""
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(total_price)s CHF/Jahr belastet."
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(total_price)s "
+"CHF pro Jahr belastet"
#, python-format
msgid ""
-"\n"
-" By clicking \"Place order\" you agree to "
-"our Terms "
-"of Service and this plan will charge your credit card account with "
-"%(total_price)s CHF/month"
+"By clicking \"Place order\" this plan will charge your credit card account "
+"with %(total_price)s CHF/month"
msgstr ""
-"\n"
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(total_price)s CHF/Monat belastet."
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(total_price)s "
+"CHF pro Monat belastet"
+
+#, fuzzy, python-format
+#| msgid ""
+#| "By clicking \"Place order\" this payment will charge your credit card "
+#| "account with a one time amount of %(total_price)s CHF"
+msgid ""
+"By clicking \"Place order\" this payment will charge your credit card "
+"account with a one time amount of %(total_price)s CHF"
+msgstr ""
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
+"%(vm_total_price)s CHF pro Monat belastet"
#, python-format
msgid ""
-"By clicking \"Place order\" you agree to our Terms of Service and "
-"this plan will charge your credit card account with %(total_price)s CHF"
+"By clicking \"Place order\" this plan will charge your credit card account "
+"with %(vm_total_price)s CHF/month"
msgstr ""
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(total_price)s CHF belastet."
-
-#, python-format
-msgid ""
-"By clicking \"Place order\" you agree to our Terms of Service and "
-"this plan will charge your credit card account with %(vm_total_price)s CHF/"
-"month"
-msgstr ""
-"Indem Du auf \"Bestellung aufgeben\" klickst, erklärst Du dich mit unseren Nutzungsbedingungen einverstanden und Dein Kreditkartenkonto wird mit %(vm_total_price)s CHF/Monat belastet"
+"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
+"%(vm_total_price)s CHF pro Monat belastet"
msgid "Place order"
msgstr "Bestellen"
@@ -606,22 +608,16 @@ msgid "Incorrect pricing name. Please contact support{support_email}"
msgstr ""
"Ungültige Preisbezeichnung. Bitte kontaktiere den Support{support_email}"
+#, python-brace-format
+msgid "{user} does not have permission to access the card"
+msgstr "{user} hat keine Erlaubnis auf diese Karte zuzugreifen"
+
+msgid "An error occurred. Details: {}"
+msgstr "Ein Fehler ist aufgetreten. Details: {}"
+
msgid "Confirm Order"
msgstr "Bestellung Bestätigen"
-#, fuzzy
-#| msgid "Thank you!"
-msgid "Thank you !"
-msgstr "Vielen Dank!"
-
-msgid "Your product will be provisioned as soon as we receive the payment."
-msgstr ""
-
-#, python-brace-format
-msgid "An error occurred while associating the card. Details: {details}"
-msgstr ""
-"Beim Verbinden der Karte ist ein Fehler aufgetreten. Details: {details}"
-
msgid "Error."
msgstr ""
@@ -632,21 +628,10 @@ msgstr ""
"Es ist ein Fehler bei der Zahlung betreten. Du wirst nach dem Schliessen vom "
"Popup zur Bezahlseite weitergeleitet."
-msgid "Thank you for the order."
-msgstr "Danke für Deine Bestellung."
-
-msgid ""
-"Your product will be provisioned as soon as we receive a payment "
-"confirmation from Stripe. We will send you a confirmation email. You can "
-"always contact us at support@datacenterlight.ch"
+#, python-brace-format
+msgid "An error occurred while associating the card. Details: {details}"
msgstr ""
-
-msgid ""
-"Your VM will be up and running in a few moments. We will send you a "
-"confirmation email as soon as it is ready."
-msgstr ""
-"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
-"auf sie zugreifen kannst."
+"Beim Verbinden der Karte ist ein Fehler aufgetreten. Details: {details}"
msgid " This is a monthly recurring plan."
msgstr "Dies ist ein monatlich wiederkehrender Plan."
@@ -686,40 +671,15 @@ msgstr ""
"Du wirst bald eine Bestätigungs-E-Mail über die Zahlung erhalten. Du kannst "
"jederzeit unter info@ungleich.ch kontaktieren."
-#, python-format
-#~ msgid ""
-#~ "By clicking \"Place order\" this plan will charge your credit card "
-#~ "account with %(total_price)s CHF/month"
-#~ msgstr ""
-#~ "Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
-#~ "%(total_price)s CHF pro Monat belastet"
+msgid "Thank you for the order."
+msgstr "Danke für Deine Bestellung."
-#, fuzzy, python-format
-#~| msgid ""
-#~| "By clicking \"Place order\" this payment will charge your credit card "
-#~| "account with a one time amount of %(total_price)s CHF"
-#~ msgid ""
-#~ "By clicking \"Place order\" this payment will charge your credit card "
-#~ "account with a one time amount of %(total_price)s CHF"
-#~ msgstr ""
-#~ "Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
-#~ "%(vm_total_price)s CHF pro Monat belastet"
-
-#, python-brace-format
-#~ msgid "{user} does not have permission to access the card"
-#~ msgstr "{user} hat keine Erlaubnis auf diese Karte zuzugreifen"
-
-#~ msgid "An error occurred. Details: {}"
-#~ msgstr "Ein Fehler ist aufgetreten. Details: {}"
-
-#~ msgid "Price"
-#~ msgstr "Preise"
-
-#~ msgid "Total Amount"
-#~ msgstr "Gesamtsumme"
-
-#~ msgid "Amount"
-#~ msgstr "Betrag"
+msgid ""
+"Your VM will be up and running in a few moments. We will send you a "
+"confirmation email as soon as it is ready."
+msgstr ""
+"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
+"auf sie zugreifen kannst."
#~ msgid "Subtotal"
#~ msgstr "Zwischensumme"
@@ -786,6 +746,9 @@ msgstr ""
#~ "Wir werden dann sobald als möglich Ihren Beta-Zugang erstellen und Sie "
#~ "daraufhin kontaktieren.Bis dahin bitten wir Sie um etwas Geduld."
+#~ msgid "Thank you!"
+#~ msgstr "Vielen Dank!"
+
#~ msgid "Thank you for order! Our team will contact you via email"
#~ msgstr ""
#~ "Vielen Dank für die Bestellung. Unser Team setzt sich sobald wie möglich "
diff --git a/datacenterlight/management/commands/check_vm_templates.py b/datacenterlight/management/commands/check_vm_templates.py
deleted file mode 100644
index d30e5b0d..00000000
--- a/datacenterlight/management/commands/check_vm_templates.py
+++ /dev/null
@@ -1,80 +0,0 @@
-from django.core.management.base import BaseCommand
-from opennebula_api.models import OpenNebulaManager
-from datacenterlight.models import VMTemplate
-from datacenterlight.cms_models import DCLCalculatorPluginModel
-from membership.models import CustomUser
-from utils.tasks import send_plain_email_task
-from django.conf import settings
-from time import sleep
-import datetime
-import json
-import logging
-import os
-
-logger = logging.getLogger(__name__)
-
-
-class Command(BaseCommand):
- help = '''Checks all VM templates to find if they can be instantiated'''
-
- def add_arguments(self, parser):
- parser.add_argument('user_email', type=str)
-
- def handle(self, *args, **options):
- result_dict = {}
- error_dict = {}
- user_email = options['user_email'] if 'user_email' in options else ""
-
- if user_email:
- cu = CustomUser.objects.get(email=user_email)
- specs = {'cpu': 1, 'memory': 1, 'disk_size': 10}
- manager = OpenNebulaManager(email=user_email, password=cu.password)
- pub_keys = [settings.TEST_MANAGE_SSH_KEY_PUBKEY]
- PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))
- if not os.path.exists("%s/outputs" % PROJECT_PATH):
- os.mkdir("%s/outputs" % PROJECT_PATH)
- public_templates_plugin = DCLCalculatorPluginModel.objects.filter(cmsplugin_ptr_id=23356).first()
- ipv6_templates_plugin = DCLCalculatorPluginModel.objects.filter(cmsplugin_ptr_id=21943).first()
- templates = public_templates_plugin.vm_templates_to_show + ipv6_templates_plugin.vm_templates_to_show
- vm_templates = VMTemplate.objects.filter(opennebula_vm_template_id__in=templates)
- for vm_template in vm_templates:
- vm_name = 'test-%s-%s' % (vm_template.vm_type, vm_template.name)
- vm_id = manager.create_vm(
- template_id=vm_template.opennebula_vm_template_id,
- specs=specs,
- ssh_key='\n'.join(pub_keys),
- vm_name=vm_name
- )
- if vm_id and vm_id > 0:
- result_dict[vm_name] = "%s OK, created VM %s" % (
- '%s %s %s' % (vm_template.opennebula_vm_template_id,
- vm_template.name, vm_template.vm_type),
- vm_id
- )
- self.stdout.write(self.style.SUCCESS(result_dict[vm_name]))
- manager.delete_vm(vm_id)
- else:
- result_dict[vm_name] = '''Error creating VM %s, template_id
- %s %s''' % (vm_name,
- vm_template.opennebula_vm_template_id,
- vm_template.vm_type)
- error_dict[vm_name] = result_dict[vm_name]
- self.stdout.write(self.style.ERROR(result_dict[vm_name]))
- sleep(1)
- date_str = datetime.datetime.strftime(
- datetime.datetime.now(), '%Y%m%d%H%M%S'
- )
- with open("%s/outputs/check_vm_templates_%s.txt" %
- (PROJECT_PATH, date_str),
- 'w',
- encoding='utf-8') as f:
- f.write(json.dumps(result_dict))
- if error_dict:
- email_data = {
- 'subject': 'Check VM Templates ERROR',
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': [settings.ADMIN_EMAIL],
- 'body': json.dumps(error_dict),
- }
- send_plain_email_task.delay(email_data)
- self.stdout.write(self.style.SUCCESS("Done"))
diff --git a/datacenterlight/management/commands/fix_generic_stripe_plan_product_names.py b/datacenterlight/management/commands/fix_generic_stripe_plan_product_names.py
deleted file mode 100644
index 2773009d..00000000
--- a/datacenterlight/management/commands/fix_generic_stripe_plan_product_names.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from django.core.management.base import BaseCommand
-from datacenterlight.tasks import handle_metadata_and_emails
-from datacenterlight.models import StripePlan
-from opennebula_api.models import OpenNebulaManager
-from membership.models import CustomUser
-from hosting.models import GenericProduct
-import logging
-import json
-import sys
-import stripe
-
-logger = logging.getLogger(__name__)
-
-
-class Command(BaseCommand):
- help = '''Stripe plans created before version 3.4 saved the plan name like generic-{subscription_id}-amount. This
- command aims at replacing this with the actual product name
- '''
-
- def handle(self, *args, **options):
- cnt = 0
- self.stdout.write(
- self.style.SUCCESS(
- 'In Fix generic stripe plan product names'
- )
- )
- plans_to_change = StripePlan.objects.filter(stripe_plan_id__startswith='generic')
- for plan in plans_to_change:
- response = input("Press 'y' to continue: ")
-
- # Check if the user entered 'y'
- if response.lower() == 'y':
- plan_name = plan.stripe_plan_id
- first_index_hyphen = plan_name.index("-") + 1
- product_id = plan_name[
- first_index_hyphen:(plan_name[first_index_hyphen:].index("-")) + first_index_hyphen]
- gp = GenericProduct.objects.get(id=product_id)
- if gp:
- cnt += 1
- # update stripe
- sp = stripe.Plan.retrieve(plan_name)
- pr = stripe.Product.retrieve(sp.product)
- pr.name = gp.product_name
- pr.save()
- # update local
- spl = StripePlan.objects.get(stripe_plan_id=plan_name)
- spl.stripe_plan_name = gp.product_name
- spl.save()
- print("%s. %s => %s" % (cnt, plan_name, gp.product_name))
- else:
- print("Invalid input. Please try again.")
- sys.exit()
-
- print("Done")
\ No newline at end of file
diff --git a/datacenterlight/management/commands/fix_vm_after_celery_error.py b/datacenterlight/management/commands/fix_vm_after_celery_error.py
deleted file mode 100644
index 0cfdb423..00000000
--- a/datacenterlight/management/commands/fix_vm_after_celery_error.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from django.core.management.base import BaseCommand
-from datacenterlight.tasks import handle_metadata_and_emails
-from opennebula_api.models import OpenNebulaManager
-from membership.models import CustomUser
-import logging
-import json
-
-logger = logging.getLogger(__name__)
-
-
-class Command(BaseCommand):
- help = '''Updates the DB after manual creation of VM'''
-
- def add_arguments(self, parser):
- parser.add_argument('vm_id', type=int)
- parser.add_argument('order_id', type=int)
- parser.add_argument('user', type=str)
- parser.add_argument('specs', type=str)
- parser.add_argument('template', type=str)
-
- def handle(self, *args, **options):
- vm_id = options['vm_id']
- order_id = options['order_id']
- user_str = options['user']
- specs_str = options['specs']
- template_str = options['template']
-
- json_acceptable_string = user_str.replace("'", "\"")
- user_dict = json.loads(json_acceptable_string)
-
- json_acceptable_string = specs_str.replace("'", "\"")
- specs = json.loads(json_acceptable_string)
-
- json_acceptable_string = template_str.replace("'", "\"")
- template = json.loads(json_acceptable_string)
- if vm_id <= 0:
- self.stdout.write(self.style.ERROR(
- 'vm_id can\'t be less than or 0. Given: %s' % vm_id))
- return
- if vm_id <= 0:
- self.stdout.write(self.style.ERROR(
- 'order_id can\'t be less than or 0. Given: %s' % vm_id))
- return
- if specs_str is None or specs_str == "":
- self.stdout.write(
- self.style.ERROR('specs can\'t be empty or None'))
- return
-
- user = {
- 'name': user_dict['name'],
- 'email': user_dict['email'],
- 'username': user_dict['username'],
- 'pass': user_dict['pass'],
- 'request_scheme': user_dict['request_scheme'],
- 'request_host': user_dict['request_host'],
- 'language': user_dict['language'],
- }
- cu = CustomUser.objects.get(username=user.get('username'))
- # Create OpenNebulaManager
- self.stdout.write(
- self.style.SUCCESS(
- 'Connecting using %s' % (cu.username)
- )
- )
- manager = OpenNebulaManager(email=cu.username, password=cu.password)
- handle_metadata_and_emails(order_id, vm_id, manager, user, specs,
- template)
- self.stdout.write(
- self.style.SUCCESS(
- 'Done handling metadata and emails for %s %s %s' % (
- order_id,
- vm_id,
- str(user)
- )
- )
- )
diff --git a/datacenterlight/migrations/0031_vmpricing_stripe_coupon_id.py b/datacenterlight/migrations/0031_vmpricing_stripe_coupon_id.py
deleted file mode 100644
index d2e45871..00000000
--- a/datacenterlight/migrations/0031_vmpricing_stripe_coupon_id.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by Django 1.9.4 on 2020-02-04 03:16
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('datacenterlight', '0030_dclnavbarpluginmodel_show_non_transparent_navbar_always'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='vmpricing',
- name='stripe_coupon_id',
- field=models.CharField(blank=True, max_length=255, null=True),
- ),
- ]
diff --git a/datacenterlight/models.py b/datacenterlight/models.py
index 64d785a2..6410254b 100644
--- a/datacenterlight/models.py
+++ b/datacenterlight/models.py
@@ -54,7 +54,6 @@ class VMPricing(models.Model):
discount_amount = models.DecimalField(
max_digits=6, decimal_places=2, default=0
)
- stripe_coupon_id = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
display_str = self.name + ' => ' + ' - '.join([
diff --git a/datacenterlight/static/datacenterlight/js/main.js b/datacenterlight/static/datacenterlight/js/main.js
index c6869cda..8fea438a 100644
--- a/datacenterlight/static/datacenterlight/js/main.js
+++ b/datacenterlight/static/datacenterlight/js/main.js
@@ -225,8 +225,8 @@
}
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
(cardPricing['ram'].value * window.ramUnitPrice) +
- (cardPricing['storage'].value * window.ssdUnitPrice) +
- window.vmBasePrice - window.discountAmount;
+ (cardPricing['storage'].value * window.ssdUnitPrice) -
+ window.discountAmount;
total = parseFloat(total.toFixed(2));
$("#total").text(total);
}
diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index 899b506f..f080da90 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -56,6 +56,11 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
"Running create_vm_task on {}".format(current_task.request.hostname))
vm_id = None
try:
+ final_price = (
+ specs.get('total_price') if 'total_price' in specs
+ else specs.get('price')
+ )
+
if 'pass' in user:
on_user = user.get('username')
on_pass = user.get('pass')
@@ -87,8 +92,107 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
if vm_id is None:
raise Exception("Could not create VM")
- handle_metadata_and_emails(order_id, vm_id, manager, user, specs,
- template)
+ # Update HostingOrder with the created vm_id
+ hosting_order = HostingOrder.objects.filter(id=order_id).first()
+ error_msg = None
+
+ try:
+ hosting_order.vm_id = vm_id
+ hosting_order.save()
+ logger.debug(
+ "Updated hosting_order {} with vm_id={}".format(
+ hosting_order.id, vm_id
+ )
+ )
+ except Exception as ex:
+ error_msg = (
+ "HostingOrder with id {order_id} not found. This means that "
+ "the hosting order was not created and/or it is/was not "
+ "associated with VM with id {vm_id}. Details {details}".format(
+ order_id=order_id, vm_id=vm_id, details=str(ex)
+ )
+ )
+ logger.error(error_msg)
+
+ stripe_utils = StripeUtils()
+ result = stripe_utils.set_subscription_metadata(
+ subscription_id=hosting_order.subscription_id,
+ metadata={"VM_ID": str(vm_id)}
+ )
+
+ if result.get('error') is not None:
+ emsg = "Could not update subscription metadata for {sub}".format(
+ sub=hosting_order.subscription_id
+ )
+ logger.error(emsg)
+ if error_msg:
+ error_msg += ". " + emsg
+ else:
+ error_msg = emsg
+
+ vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
+
+ context = {
+ 'name': user.get('name'),
+ 'email': user.get('email'),
+ 'cores': specs.get('cpu'),
+ 'memory': specs.get('memory'),
+ 'storage': specs.get('disk_size'),
+ 'price': final_price,
+ 'template': template.get('name'),
+ 'vm_name': vm.get('name'),
+ 'vm_id': vm['vm_id'],
+ 'order_id': order_id
+ }
+
+ if error_msg:
+ context['errors'] = error_msg
+ if 'pricing_name' in specs:
+ context['pricing'] = str(VMPricing.get_vm_pricing_by_name(
+ name=specs['pricing_name']
+ ))
+ email_data = {
+ 'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
+ 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
+ 'to': ['info@ungleich.ch'],
+ 'body': "\n".join(
+ ["%s=%s" % (k, v) for (k, v) in context.items()]),
+ 'reply_to': [context['email']],
+ }
+ email = EmailMessage(**email_data)
+ email.send()
+
+ if 'pass' in user:
+ lang = 'en-us'
+ if user.get('language') is not None:
+ logger.debug(
+ "Language is set to {}".format(user.get('language')))
+ lang = user.get('language')
+ translation.activate(lang)
+ # Send notification to the user as soon as VM has been booked
+ context = {
+ 'base_url': "{0}://{1}".format(user.get('request_scheme'),
+ user.get('request_host')),
+ 'order_url': reverse('hosting:invoices'),
+ 'page_header': _(
+ 'Your New VM %(vm_name)s at Data Center Light') % {
+ 'vm_name': vm.get('name')},
+ 'vm_name': vm.get('name')
+ }
+ email_data = {
+ 'subject': context.get('page_header'),
+ 'to': user.get('email'),
+ 'context': context,
+ 'template_name': 'new_booked_vm',
+ 'template_path': 'hosting/emails/',
+ 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
+ }
+ email = BaseEmail(**email_data)
+ email.send()
+
+ logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
+ if vm_id > 0:
+ get_or_create_vm_detail(custom_user, manager, vm_id)
except Exception as e:
logger.error(str(e))
try:
@@ -110,127 +214,3 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id):
return
return vm_id
-
-
-def handle_metadata_and_emails(order_id, vm_id, manager, user, specs,
- template):
- """
- Handle's setting up of the metadata in Stripe and database and sending of
- emails to the user after VM creation
-
- :param order_id: the hosting order id
- :param vm_id: the id of the vm created
- :param manager: the OpenNebula Manager instance
- :param user: the user's dict passed to the celery task
- :param specs: the specification's dict passed to the celery task
- :param template: the template dict passed to the celery task
-
- :return:
- """
-
- custom_user = CustomUser.objects.get(email=user.get('email'))
- final_price = (
- specs.get('total_price') if 'total_price' in specs
- else specs.get('price')
- )
- # Update HostingOrder with the created vm_id
- hosting_order = HostingOrder.objects.filter(id=order_id).first()
- error_msg = None
-
- try:
- hosting_order.vm_id = vm_id
- hosting_order.save()
- logger.debug(
- "Updated hosting_order {} with vm_id={}".format(
- hosting_order.id, vm_id
- )
- )
- except Exception as ex:
- error_msg = (
- "HostingOrder with id {order_id} not found. This means that "
- "the hosting order was not created and/or it is/was not "
- "associated with VM with id {vm_id}. Details {details}".format(
- order_id=order_id, vm_id=vm_id, details=str(ex)
- )
- )
- logger.error(error_msg)
-
- stripe_utils = StripeUtils()
- result = stripe_utils.set_subscription_metadata(
- subscription_id=hosting_order.subscription_id,
- metadata={"VM_ID": str(vm_id)}
- )
-
- if result.get('error') is not None:
- emsg = "Could not update subscription metadata for {sub}".format(
- sub=hosting_order.subscription_id
- )
- logger.error(emsg)
- if error_msg:
- error_msg += ". " + emsg
- else:
- error_msg = emsg
-
- vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
-
- context = {
- 'name': user.get('name'),
- 'email': user.get('email'),
- 'cores': specs.get('cpu'),
- 'memory': specs.get('memory'),
- 'storage': specs.get('disk_size'),
- 'price': final_price,
- 'template': template.get('name'),
- 'vm_name': vm.get('name'),
- 'vm_id': vm['vm_id'],
- 'order_id': order_id
- }
-
- if error_msg:
- context['errors'] = error_msg
- if 'pricing_name' in specs:
- context['pricing'] = str(VMPricing.get_vm_pricing_by_name(
- name=specs['pricing_name']
- ))
- email_data = {
- 'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': ['dcl-orders@ungleich.ch'],
- 'body': "\n".join(
- ["%s=%s" % (k, v) for (k, v) in context.items()]),
- 'reply_to': [context['email']],
- }
- email = EmailMessage(**email_data)
- email.send()
-
- if 'pass' in user:
- lang = 'en-us'
- if user.get('language') is not None:
- logger.debug(
- "Language is set to {}".format(user.get('language')))
- lang = user.get('language')
- translation.activate(lang)
- # Send notification to the user as soon as VM has been booked
- context = {
- 'base_url': "{0}://{1}".format(user.get('request_scheme'),
- user.get('request_host')),
- 'order_url': reverse('hosting:invoices'),
- 'page_header': _(
- 'Your New VM %(vm_name)s at Data Center Light') % {
- 'vm_name': vm.get('name')},
- 'vm_name': vm.get('name')
- }
- email_data = {
- 'subject': context.get('page_header'),
- 'to': user.get('email'),
- 'context': context,
- 'template_name': 'new_booked_vm',
- 'template_path': 'hosting/emails/',
- 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
- }
- email = BaseEmail(**email_data)
- email.send()
-
- logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
- if vm_id > 0:
- get_or_create_vm_detail(custom_user, manager, vm_id)
diff --git a/datacenterlight/templates/datacenterlight/cms/calculator.html b/datacenterlight/templates/datacenterlight/cms/calculator.html
index 20a6664a..7b123a72 100644
--- a/datacenterlight/templates/datacenterlight/cms/calculator.html
+++ b/datacenterlight/templates/datacenterlight/cms/calculator.html
@@ -1,5 +1,5 @@
- {% include "datacenterlight/includes/_calculator_form.html" with vm_pricing=instance.pricing vm_base_price=vm_base_price %}
+ {% include "datacenterlight/includes/_calculator_form.html" with vm_pricing=instance.pricing %}
\ No newline at end of file
diff --git a/datacenterlight/templates/datacenterlight/emails/welcome_user.html b/datacenterlight/templates/datacenterlight/emails/welcome_user.html
index 2044b2ee..25185618 100644
--- a/datacenterlight/templates/datacenterlight/emails/welcome_user.html
+++ b/datacenterlight/templates/datacenterlight/emails/welcome_user.html
@@ -28,7 +28,7 @@
{% blocktrans %}Thanks for joining us! We provide the most affordable virtual machines from the heart of Switzerland.{% endblocktrans %}
- {% blocktrans %}Try now, order a VM. VM price starts from only 11.5 CHF per month.{% endblocktrans %}
+ {% blocktrans %}Try now, order a VM. VM price starts from only 10.5 CHF per month.{% endblocktrans %}
diff --git a/datacenterlight/templates/datacenterlight/emails/welcome_user.txt b/datacenterlight/templates/datacenterlight/emails/welcome_user.txt
index 06e8aa33..772e51a5 100644
--- a/datacenterlight/templates/datacenterlight/emails/welcome_user.txt
+++ b/datacenterlight/templates/datacenterlight/emails/welcome_user.txt
@@ -3,7 +3,7 @@
{% trans "Welcome to Data Center Light!" %}
{% blocktrans %}Thanks for joining us! We provide the most affordable virtual machines from the heart of Switzerland.{% endblocktrans %}
-{% blocktrans %}Try now, order a VM. VM price starts from only 11.5 CHF per month.{% endblocktrans %}
+{% blocktrans %}Try now, order a VM. VM price starts from only 10.5 CHF per month.{% endblocktrans %}
{{ base_url }}{% url 'hosting:create_virtual_machine' %}
diff --git a/datacenterlight/templates/datacenterlight/includes/_calculator_form.html b/datacenterlight/templates/datacenterlight/includes/_calculator_form.html
index 2c2b51dd..f64a9500 100644
--- a/datacenterlight/templates/datacenterlight/includes/_calculator_form.html
+++ b/datacenterlight/templates/datacenterlight/includes/_calculator_form.html
@@ -9,7 +9,6 @@
window.ssdUnitPrice = {{vm_pricing.ssd_unit_price|default:0}};
window.hddUnitPrice = {{vm_pricing.hdd_unit_price|default:0}};
window.discountAmount = {{vm_pricing.discount_amount|default:0}};
- window.vmBasePrice = {{vm_base_price|default:0}};
window.minRam = {{min_ram}};
window.minRamErr = '{% blocktrans with min_ram=min_ram %}Please enter a value in range {{min_ram}} - 200.{% endblocktrans %}';
diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html
index 1f7a3cda..02bce0ed 100644
--- a/datacenterlight/templates/datacenterlight/order_detail.html
+++ b/datacenterlight/templates/datacenterlight/order_detail.html
@@ -2,14 +2,6 @@
{% load staticfiles bootstrap3 i18n custom_tags humanize %}
{% block content %}
-
{% if messages %}
@@ -111,61 +103,58 @@
{% endif %}
- {% if generic_payment_details.exclude_vat_calculations %}
- {% else %}
-
-
+
+
+
+
+
+ {% trans "Price Before VAT" %}
+ {{generic_payment_details.amount_before_vat|floatformat:2|intcomma}} CHF
+
+
+
+
+
+
+
+
+
+
+
+
{% trans "Pre VAT" %}
+
+
+
{% trans "VAT for" %} {{generic_payment_details.vat_country}} ({{generic_payment_details.vat_rate}}%)
+
-
-
- {% trans "Price Before VAT" %}
- {{generic_payment_details.amount_before_vat|floatformat:2|intcomma}} CHF
-
@@ -278,16 +267,15 @@
{% if generic_payment_details %}
{% if generic_payment_details.recurring %}
{% if generic_payment_details.recurring_interval == 'year' %}
-
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %} By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ total_price }} CHF/year{% endblocktrans %}.
+
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{total_price}} CHF/year{% endblocktrans %}.
{% else %}
-
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}
- By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ total_price }} CHF/month{% endblocktrans %}.
+
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{total_price}} CHF/month{% endblocktrans %}.
{% endif %}
{% else %}
-
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ total_price }} CHF{% endblocktrans %}.
+
{% blocktrans with total_price=generic_payment_details.amount|floatformat:2|intcomma %}By clicking "Place order" this payment will charge your credit card account with a one time amount of {{total_price}} CHF{% endblocktrans %}.
{% endif %}
{% else %}
-
{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ vm_total_price }} CHF/month{% endblocktrans %}.
+
{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{vm_total_price}} CHF/month{% endblocktrans %}.
{% endif %}
@@ -330,14 +318,5 @@
{%endblock%}
diff --git a/datacenterlight/templatetags/custom_tags.py b/datacenterlight/templatetags/custom_tags.py
index fc39eec7..0cb18e5b 100644
--- a/datacenterlight/templatetags/custom_tags.py
+++ b/datacenterlight/templatetags/custom_tags.py
@@ -6,7 +6,7 @@ from django.core.urlresolvers import resolve, reverse
from django.utils.safestring import mark_safe
from django.utils.translation import activate, get_language, ugettext_lazy as _
-from hosting.models import GenericProduct, HostingOrder
+from hosting.models import GenericProduct
from utils.hosting_utils import get_ip_addresses
logger = logging.getLogger(__name__)
@@ -63,42 +63,6 @@ def escaped_line_break(value):
return value.replace("\\n", "\n")
-@register.filter('get_line_item_from_hosting_order_charge')
-def get_line_item_from_hosting_order_charge(hosting_order_id):
- """
- Returns ready-to-use "html" line item to be shown for a charge in the
- invoice list page
-
- :param hosting_order_id: the HostingOrder id
- :return:
- """
- try:
- print("Hositng order id = %s" % hosting_order_id)
- hosting_order = HostingOrder.objects.get(id = hosting_order_id)
- if hosting_order.stripe_charge_id:
- return mark_safe("""
-
{% blocktrans with vm_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ vm_price }} CHF/month.{% endblocktrans %}.
+
{% blocktrans with vm_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{ vm_price }} CHF/month{% endblocktrans %}.
diff --git a/hosting/urls.py b/hosting/urls.py
index e34d27d6..5b2b87b0 100644
--- a/hosting/urls.py
+++ b/hosting/urls.py
@@ -51,7 +51,7 @@ urlpatterns = [
name='choice_ssh_keys'),
url(r'delete_ssh_key/(?P\d+)/?$', SSHKeyDeleteView.as_view(),
name='delete_ssh_key'),
- url(r'delete_card/(?P[\w\-]+)/$', SettingsView.as_view(),
+ url(r'delete_card/(?P\d+)/?$', SettingsView.as_view(),
name='delete_card'),
url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(),
name='create_ssh_key'),
diff --git a/hosting/views.py b/hosting/views.py
index c2470707..8dd01906 100644
--- a/hosting/views.py
+++ b/hosting/views.py
@@ -1,7 +1,6 @@
import logging
import uuid
from datetime import datetime
-from urllib.parse import quote
from time import sleep
import stripe
@@ -14,7 +13,6 @@ from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.urlresolvers import reverse_lazy, reverse
-from django.db.models import Q
from django.http import (
Http404, HttpResponseRedirect, HttpResponse, JsonResponse
)
@@ -554,31 +552,20 @@ class SettingsView(LoginRequiredMixin, FormView):
Check if the user already saved contact details. If so, then show
the form populated with those details, to let user change them.
"""
- username = self.request.GET.get('username')
- if self.request.user.is_admin and username:
- user = CustomUser.objects.get(username=username)
- else:
- user = self.request.user
return form_class(
- instance=user.billing_addresses.first(),
+ instance=self.request.user.billing_addresses.first(),
**self.get_form_kwargs())
def get_context_data(self, **kwargs):
context = super(SettingsView, self).get_context_data(**kwargs)
# Get user
- username = self.request.GET.get('username')
- if self.request.user.is_admin and username:
- user = CustomUser.objects.get(username=username)
- else:
- user = self.request.user
+ user = self.request.user
stripe_customer = None
if hasattr(user, 'stripecustomer'):
stripe_customer = user.stripecustomer
- stripe_utils = StripeUtils()
- cards_list_request = stripe_utils.get_available_payment_methods(
- stripe_customer
+ cards_list = UserCardDetail.get_all_cards_list(
+ stripe_customer=stripe_customer
)
- cards_list = cards_list_request.get('response_object')
context.update({
'cards_list': cards_list,
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
@@ -589,38 +576,48 @@ class SettingsView(LoginRequiredMixin, FormView):
def post(self, request, *args, **kwargs):
if 'card' in request.POST and request.POST['card'] is not '':
card_id = escape(request.POST['card'])
+ user_card_detail = UserCardDetail.objects.get(id=card_id)
UserCardDetail.set_default_card(
stripe_api_cus_id=request.user.stripecustomer.stripe_id,
- stripe_source_id=card_id
+ stripe_source_id=user_card_detail.card_id
)
- stripe_utils = StripeUtils()
- card_details = stripe_utils.get_cards_details_from_payment_method(
- card_id
- )
- if not card_details.get('response_object'):
- logger.debug("Could not find card %s in stripe" % card_id)
- messages.add_message(request, messages.ERROR,
- _("Could not set a default card."))
- return HttpResponseRedirect(reverse_lazy('hosting:settings'))
- card_details_response = card_details['response_object']
msg = _(
("Your {brand} card ending in {last4} set as "
"default card").format(
- brand=card_details_response['brand'],
- last4=card_details_response['last4']
+ brand=user_card_detail.brand,
+ last4=user_card_detail.last4
)
)
messages.add_message(request, messages.SUCCESS, msg)
return HttpResponseRedirect(reverse_lazy('hosting:settings'))
if 'delete_card' in request.POST:
- card = self.kwargs.get('pk')
- stripe_utils = StripeUtils()
- stripe_utils.dissociate_customer_card(
- request.user.stripecustomer.stripe_id,
- card
- )
- msg = _("Card deassociation successful")
- messages.add_message(request, messages.SUCCESS, msg)
+ try:
+ card = UserCardDetail.objects.get(pk=self.kwargs.get('pk'))
+ if (request.user.has_perm(self.permission_required[0], card)
+ and
+ request.user
+ .stripecustomer
+ .usercarddetail_set
+ .count() > 1):
+ if card.card_id is not None:
+ stripe_utils = StripeUtils()
+ stripe_utils.dissociate_customer_card(
+ request.user.stripecustomer.stripe_id,
+ card.card_id
+ )
+ if card.preferred:
+ UserCardDetail.set_default_card_from_stripe(
+ request.user.stripecustomer.stripe_id
+ )
+ card.delete()
+ msg = _("Card deassociation successful")
+ messages.add_message(request, messages.SUCCESS, msg)
+ else:
+ msg = _("You are not permitted to do this operation")
+ messages.add_message(request, messages.ERROR, msg)
+ except UserCardDetail.DoesNotExist:
+ msg = _("The selected card does not exist")
+ messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(reverse_lazy('hosting:settings'))
form = self.get_form()
if form.is_valid():
@@ -695,49 +692,51 @@ class SettingsView(LoginRequiredMixin, FormView):
msg = _("Billing address updated successfully")
messages.add_message(request, messages.SUCCESS, msg)
else:
- id_payment_method = request.POST.get('id_payment_method', None)
+ token = form.cleaned_data.get('token')
stripe_utils = StripeUtils()
- card_details = stripe_utils.get_cards_details_from_payment_method(
- id_payment_method
+ card_details = stripe_utils.get_cards_details_from_token(
+ token
)
if not card_details.get('response_object'):
form.add_error("__all__", card_details.get('error'))
return self.render_to_response(self.get_context_data())
stripe_customer = StripeCustomer.get_or_create(
- email=request.user.email, id_payment_method=id_payment_method
+ email=request.user.email, token=token
)
card = card_details['response_object']
- acc_result = stripe_utils.associate_customer_card(
- request.user.stripecustomer.stripe_id,
- id_payment_method,
- set_as_default=True
- )
- if acc_result['response_object'] is None:
- msg = _(
- 'An error occurred while associating the card.'
- ' Details: {details}'.format(
- details=acc_result['error']
- )
- )
+ if UserCardDetail.get_user_card_details(stripe_customer, card):
+ msg = _('You seem to have already added this card')
messages.add_message(request, messages.ERROR, msg)
- return self.render_to_response(self.get_context_data())
- preferred = False
- if stripe_customer.usercarddetail_set.count() == 0:
- preferred = True
- UserCardDetail.create(
- stripe_customer=stripe_customer,
- last4=card['last4'],
- brand=card['brand'],
- fingerprint=card['fingerprint'],
- exp_month=card['exp_month'],
- exp_year=card['exp_year'],
- card_id=card['card_id'],
- preferred=preferred
- )
- msg = _(
- "Successfully associated the card with your account"
- )
- messages.add_message(request, messages.SUCCESS, msg)
+ else:
+ acc_result = stripe_utils.associate_customer_card(
+ request.user.stripecustomer.stripe_id, token
+ )
+ if acc_result['response_object'] is None:
+ msg = _(
+ 'An error occurred while associating the card.'
+ ' Details: {details}'.format(
+ details=acc_result['error']
+ )
+ )
+ messages.add_message(request, messages.ERROR, msg)
+ return self.render_to_response(self.get_context_data())
+ preferred = False
+ if stripe_customer.usercarddetail_set.count() == 0:
+ preferred = True
+ UserCardDetail.create(
+ stripe_customer=stripe_customer,
+ last4=card['last4'],
+ brand=card['brand'],
+ fingerprint=card['fingerprint'],
+ exp_month=card['exp_month'],
+ exp_year=card['exp_year'],
+ card_id=card['card_id'],
+ preferred=preferred
+ )
+ msg = _(
+ "Successfully associated the card with your account"
+ )
+ messages.add_message(request, messages.SUCCESS, msg)
return self.render_to_response(self.get_context_data())
else:
billing_address_data = form.cleaned_data
@@ -810,7 +809,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
card_id = form.cleaned_data.get('card')
customer = owner.stripecustomer
try:
- user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
+ user_card_detail = UserCardDetail.objects.get(id=card_id)
if not request.user.has_perm(
'view_usercarddetail', user_card_detail
):
@@ -1014,7 +1013,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
context['cc_exp_month'] = card_details_response['exp_month']
else:
card_id = self.request.session.get('card_id')
- card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
+ card_detail = UserCardDetail.objects.get(id=card_id)
context['cc_last4'] = card_detail.last4
context['cc_brand'] = card_detail.brand
context['cc_exp_year'] = card_detail.exp_year
@@ -1078,13 +1077,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
billing_address_data = request.session.get('billing_address_data')
vm_template_id = template.get('id', 1)
stripe_api_cus_id = request.user.stripecustomer.stripe_id
- logger.debug("template=%s specs=%s stripe_customer_id=%s "
- "billing_address_data=%s vm_template_id=%s "
- "stripe_api_cus_id=%s" % (
- template, specs, stripe_customer_id, billing_address_data,
- vm_template_id, stripe_api_cus_id)
- )
- if 'id_payment_method' in self.request.session:
+ if 'token' in self.request.session:
card_details = stripe_utils.get_cards_details_from_token(
request.session['token']
)
@@ -1101,7 +1094,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
)
if not ucd:
acc_result = stripe_utils.associate_customer_card(
- stripe_api_cus_id, request.session['id_payment_method'],
+ stripe_api_cus_id, request.session['token'],
set_as_default=True
)
if acc_result['response_object'] is None:
@@ -1128,7 +1121,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
return JsonResponse(response)
else:
card_id = request.session.get('card_id')
- user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
+ user_card_detail = UserCardDetail.objects.get(id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,
@@ -1192,31 +1185,10 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
subscription_result = stripe_utils.subscribe_customer_to_plan(
stripe_api_cus_id,
[{"plan": stripe_plan.get('response_object').stripe_plan_id}],
- coupon=(discount['stripe_coupon_id']
- if 'name' in discount and
- discount['name'] is not None and
- 'ipv6' in discount['name'].lower() and
- discount['stripe_coupon_id']
- else ""),
+ coupon='ipv6-discount-8chf' if 'name' in discount and 'ipv6' in discount['name'].lower() else "",
tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [],
- default_payment_method=request.session['id_payment_method']
)
stripe_subscription_obj = subscription_result.get('response_object')
- latest_invoice = stripe.Invoice.retrieve(stripe_subscription_obj.latest_invoice)
- ret = stripe.PaymentIntent.confirm(
- latest_invoice.payment_intent
- )
- if ret.status == 'requires_source_action' or ret.status == 'requires_action':
- pi = stripe.PaymentIntent.retrieve(
- latest_invoice.payment_intent
- )
- context = {
- 'sid': stripe_subscription_obj.id,
- 'payment_intent_secret': pi.client_secret,
- 'STRIPE_PUBLISHABLE_KEY': settings.STRIPE_API_PUBLIC_KEY,
- 'showSCA': True
- }
- return JsonResponse(context)
# Check if the subscription was approved and is active
if (stripe_subscription_obj is None or
stripe_subscription_obj.status != 'active'):
@@ -1310,11 +1282,10 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
page = self.request.GET.get('page', 1)
context = super(InvoiceListView, self).get_context_data(**kwargs)
invs_page = None
- invs_page_charges = None
if ('user_email' in self.request.GET
and self.request.user.email == settings.ADMIN_EMAIL):
user_email = self.request.GET['user_email']
- context['user_email'] = '%s' % quote(user_email)
+ context['user_email'] = user_email
logger.debug(
"user_email = {}".format(user_email)
)
@@ -1324,8 +1295,7 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
logger.debug("User does not exist")
cu = self.request.user
invs = stripe.Invoice.list(customer=cu.stripecustomer.stripe_id,
- count=100,
- status='paid')
+ count=100)
paginator = Paginator(invs.data, 10)
try:
invs_page = paginator.page(page)
@@ -1333,21 +1303,6 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
invs_page = paginator.page(1)
except EmptyPage:
invs_page = paginator.page(paginator.num_pages)
- hosting_orders = HostingOrder.objects.filter(
- customer=cu.stripecustomer).filter(
- Q(subscription_id=None) | Q(subscription_id='')
- ).order_by('-created_at')
- stripe_chgs = []
- for ho in hosting_orders:
- stripe_chgs.append({ho: stripe.Charge.retrieve(ho.stripe_charge_id)})
-
- paginator_charges = Paginator(stripe_chgs, 10)
- try:
- invs_page_charges = paginator_charges.page(page)
- except PageNotAnInteger:
- invs_page_charges = paginator_charges.page(1)
- except EmptyPage:
- invs_page_charges = paginator_charges.page(paginator_charges.num_pages)
else:
try:
invs = stripe.Invoice.list(
@@ -1361,27 +1316,10 @@ class InvoiceListView(LoginRequiredMixin, TemplateView):
invs_page = paginator.page(1)
except EmptyPage:
invs_page = paginator.page(paginator.num_pages)
- hosting_orders = HostingOrder.objects.filter(
- customer=self.request.user.stripecustomer).filter(
- Q(subscription_id=None) | Q(subscription_id='')
- ).order_by('-created_at')
- stripe_chgs = []
- for ho in hosting_orders:
- stripe_chgs.append(
- {ho: stripe.Charge.retrieve(ho.stripe_charge_id)})
- paginator_charges = Paginator(stripe_chgs, 10)
- try:
- invs_page_charges = paginator_charges.page(page)
- except PageNotAnInteger:
- invs_page_charges = paginator_charges.page(1)
- except EmptyPage:
- invs_page_charges = paginator_charges.page(
- paginator_charges.num_pages)
except Exception as ex:
logger.error(str(ex))
invs_page = None
context["invs"] = invs_page
- context["invs_charge"] = invs_page_charges
return context
@method_decorator(decorators)
@@ -1544,12 +1482,7 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
ordering = '-id'
def get_queryset(self):
- username = self.request.GET.get('username')
- if self.request.user.is_admin and username:
- user = CustomUser.objects.get(username=username)
- else:
- user = self.request.user
- owner = user
+ owner = self.request.user
manager = OpenNebulaManager(email=owner.username,
password=owner.password)
try:
@@ -1708,11 +1641,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
login_url = reverse_lazy('hosting:login')
def get_object(self):
- username = self.request.GET.get('username')
- if self.request.user.is_admin and username:
- owner = CustomUser.objects.get(username=username)
- else:
- owner = self.request.user
+ owner = self.request.user
vm = None
manager = OpenNebulaManager(
email=owner.username,
@@ -1768,10 +1697,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
subscription=hosting_order.subscription_id,
count=1
)
- if stripe_obj.data:
- inv_url = stripe_obj.data[0].hosted_invoice_url
- else:
- inv_url = ''
+ inv_url = stripe_obj.data[0].hosted_invoice_url
elif hosting_order.stripe_charge_id:
stripe_obj = stripe.Charge.retrieve(
hosting_order.stripe_charge_id
@@ -1852,7 +1778,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
)
response['text'] = str(_('Error terminating VM')) + str(vm.id)
else:
- for t in range(settings.MAX_TIME_TO_WAIT_FOR_VM_TERMINATE):
+ for t in range(15):
try:
manager.get_vm(vm.id)
except WrongIdError:
@@ -1875,10 +1801,6 @@ class VirtualMachineView(LoginRequiredMixin, View):
)
break
else:
- logger.debug(
- 'Sleeping 2 seconds for terminate action on VM %s' %
- vm.id
- )
sleep(2)
if not response['status']:
response['text'] = str(_("VM terminate action timed out. "
@@ -1932,7 +1854,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
'subject': ("Deleted " if response['status']
else "ERROR deleting ") + admin_msg_sub,
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': ['dcl-orders@ungleich.ch'],
+ 'to': ['info@ungleich.ch'],
'body': "\n".join(
["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]),
}
diff --git a/hosting/migrations/0063_auto_20201223_0612.py b/membership/migrations/0012_auto_20200306_1016.py
similarity index 50%
rename from hosting/migrations/0063_auto_20201223_0612.py
rename to membership/migrations/0012_auto_20200306_1016.py
index eb4ca9d4..f38f0780 100644
--- a/hosting/migrations/0063_auto_20201223_0612.py
+++ b/membership/migrations/0012_auto_20200306_1016.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Generated by Django 1.9.4 on 2020-12-23 06:12
+# Generated by Django 1.9.4 on 2020-03-06 10:16
from __future__ import unicode_literals
from django.db import migrations, models
@@ -8,13 +8,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('hosting', '0062_incompletesubscriptions'),
+ ('membership', '0011_auto_20191218_1050'),
]
operations = [
migrations.AlterField(
- model_name='incompletesubscriptions',
- name='completed_at',
- field=models.DateTimeField(null=True),
+ model_name='customuser',
+ name='username',
+ field=models.CharField(max_length=120, null=True, unique=True),
),
]
diff --git a/membership/models.py b/membership/models.py
index 81054fb9..b572833d 100644
--- a/membership/models.py
+++ b/membership/models.py
@@ -77,28 +77,59 @@ def get_first_and_last_name(full_name):
return first_name, last_name
+def limit_username_length(username):
+ """
+ Limit the length of username before the addition of random numbers to
+ 18 characters
+
+ :param username: the username to limit
+ :return:
+ """
+ if len(username) > settings.MAX_USERNAME_LENGTH:
+ username = username[(len(username) - settings.MAX_USERNAME_LENGTH):]
+ return username.strip()
+
+
def assign_username(user):
if not user.username:
ldap_manager = LdapManager()
# Try to come up with a username
first_name, last_name = get_first_and_last_name(user.name)
- user.username = unicodedata.normalize('NFKD', first_name + last_name)
+ user.username = unicodedata.normalize(
+ 'NFKD', first_name + last_name
+ ).encode('ascii', 'ignore').decode('ascii', 'ignore')
user.username = "".join([char for char in user.username if char.isalnum()]).lower()
+ if user.username.strip() == "":
+ try:
+ # the inferred username from name is empty, hence attempt
+ # inferring a username from email
+ logger.debug("Inferred username from name is empty. So, "
+ "inferring from email now.")
+ user.username = user.email[0:user.email.index("@")]
+ user.username = "".join(
+ [char for char in user.username if char.isalnum()]
+ ).lower()
+ except Exception as ex:
+ logger.debug("Exception %s" % str(ex))
+ user.username = get_random_string(
+ allowed_chars='abcdefghijklmnopqrstuvwxyz'
+ )
exist = True
+ user_username = limit_username_length(user.username)
while exist:
# Check if it exists
- exist, entries = ldap_manager.check_user_exists(user.username)
+ exist, entries = ldap_manager.check_user_exists(user_username)
if exist:
# If username exists in ldap, come up with a new user name and check it again
- user.username = user.username + str(random.randint(0, 2 ** 10))
+ user.username = user_username + str(random.randint(0, 2 ** 10))
else:
# If username does not exists in ldap, try to save it in database
try:
user.save()
except IntegrityError:
# If username exists in database then come up with a new username
- user.username = user.username + str(random.randint(0, 2 ** 10))
+ user.username = user_username + str(random.randint(0, 2 ** 10))
exist = True
@@ -116,7 +147,7 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
site = models.ForeignKey(Site, default=1)
name = models.CharField(max_length=50, validators=[validate_name])
email = models.EmailField(unique=True)
- username = models.CharField(max_length=60, unique=True, null=True)
+ username = models.CharField(max_length=120, unique=True, null=True)
validated = models.IntegerField(choices=VALIDATED_CHOICES, default=0)
in_ldap = models.BooleanField(default=False)
# By default, we initialize the validation_slug with appropriate value
@@ -277,7 +308,7 @@ class StripeCustomer(models.Model):
return "%s - %s" % (self.stripe_id, self.user.email)
@classmethod
- def create_stripe_api_customer(cls, email=None, id_payment_method=None,
+ def create_stripe_api_customer(cls, email=None, token=None,
customer_name=None):
"""
This method creates a Stripe API customer with the given
@@ -288,8 +319,7 @@ class StripeCustomer(models.Model):
stripe user.
"""
stripe_utils = StripeUtils()
- stripe_data = stripe_utils.create_customer(
- id_payment_method, email, customer_name)
+ stripe_data = stripe_utils.create_customer(token, email, customer_name)
if stripe_data.get('response_object'):
stripe_cus_id = stripe_data.get('response_object').get('id')
return stripe_cus_id
@@ -297,7 +327,7 @@ class StripeCustomer(models.Model):
return None
@classmethod
- def get_or_create(cls, email=None, token=None, id_payment_method=None):
+ def get_or_create(cls, email=None, token=None):
"""
Check if there is a registered stripe customer with that email
or create a new one
diff --git a/opennebula_api/models.py b/opennebula_api/models.py
index 2f76f423..19e3e4f7 100644
--- a/opennebula_api/models.py
+++ b/opennebula_api/models.py
@@ -154,8 +154,6 @@ class OpenNebulaManager():
protocol=settings.OPENNEBULA_PROTOCOL)
)
raise ConnectionRefusedError
- except Exception as ex:
- logger.error(str(ex))
def _get_user_pool(self):
try:
@@ -429,12 +427,8 @@ class OpenNebulaManager():
template_id = int(template_id)
try:
template_pool = self._get_template_pool()
- if template_id in settings.UPDATED_TEMPLATES_DICT.keys():
- template_id = settings.UPDATED_TEMPLATES_DICT[template_id]
return template_pool.get_by_id(template_id)
- except Exception as ex:
- logger.debug("Template Id we are looking for : %s" % template_id)
- logger.error(str(ex))
+ except:
raise ConnectionRefusedError
def create_template(self, name, cores, memory, disk_size, core_price,
diff --git a/release.sh b/release.sh
deleted file mode 100755
index 535cc7d4..00000000
--- a/release.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-# Nico Schottelius, 2021-12-17
-
-current=$(git describe --dirty)
-last_tag=$(git describe --tags --abbrev=0)
-registry=harbor.ungleich.svc.p10.k8s.ooo/ungleich-public
-image_url=$registry/dynamicweb:${current}
-
-if echo $current | grep -q -e 'dirty$'; then
- echo Refusing to release a dirty tree build
- exit 1
-fi
-
-if [ "$current" != "$last_tag" ]; then
- echo "Last tag ($last_tag) is not current version ($current)"
- echo "Only release proper versions"
- exit 1
-fi
-
-docker tag dynamicweb:${current} ${image_url}
-docker push ${image_url}
diff --git a/requirements.txt b/requirements.txt
index 73cdf987..e7769a7e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -83,7 +83,7 @@ stripe==2.41.0
wheel==0.29.0
django-admin-honeypot==1.0.0
coverage==4.3.4
-git+https://github.com/ungleich/python-oca.git#egg=oca
+git+https://github.com/ungleich/python-oca.git#egg=python-oca
djangorestframework==3.6.3
flake8==3.3.0
python-memcached==1.58
diff --git a/templates/gdpr/gdpr_banner.html b/templates/gdpr/gdpr_banner.html
index f927f8ee..7e9f5c7f 100644
--- a/templates/gdpr/gdpr_banner.html
+++ b/templates/gdpr/gdpr_banner.html
@@ -134,6 +134,8 @@
digitalglarus.ch
hack4lgarus.ch
ipv6onlyhosting.com
+ ipv6onlyhosting.ch
+ ipv6onlyhosting.net
django-hosting.ch
rails-hosting.ch
node-hosting.ch
diff --git a/ungleich_page/templates/ungleich_page/ungleich/section_products.html b/ungleich_page/templates/ungleich_page/ungleich/section_products.html
index e3d0dc73..9cdc94c8 100644
--- a/ungleich_page/templates/ungleich_page/ungleich/section_products.html
+++ b/ungleich_page/templates/ungleich_page/ungleich/section_products.html
@@ -19,15 +19,13 @@
+
\ No newline at end of file
diff --git a/ungleich_page/views.py b/ungleich_page/views.py
index 01d1138d..e5a99d8d 100644
--- a/ungleich_page/views.py
+++ b/ungleich_page/views.py
@@ -25,10 +25,9 @@ class ContactView(FormView):
success_message = _('Message Successfully Sent')
def form_valid(self, form):
- print("ungleich_page contactusform")
- #form.save()
- #form.send_email()
- #messages.add_message(self.request, messages.SUCCESS, self.success_message)
+ form.save()
+ form.send_email()
+ messages.add_message(self.request, messages.SUCCESS, self.success_message)
return super(ContactView, self).form_valid(form)
def get_context_data(self, **kwargs):
diff --git a/utils/fields.py b/utils/fields.py
index ca1115de..48a606cc 100644
--- a/utils/fields.py
+++ b/utils/fields.py
@@ -1,8 +1,7 @@
from django.utils.translation import ugettext as _
from django.db import models
-# Old: http://xml.coverpages.org/country3166.html
-# 2023-12-29: Updated list of countries from https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
+# http://xml.coverpages.org/country3166.html
COUNTRIES = (
('AD', _('Andorra')),
('AE', _('United Arab Emirates')),
@@ -11,6 +10,7 @@ COUNTRIES = (
('AI', _('Anguilla')),
('AL', _('Albania')),
('AM', _('Armenia')),
+ ('AN', _('Netherlands Antilles')),
('AO', _('Angola')),
('AQ', _('Antarctica')),
('AR', _('Argentina')),
@@ -18,7 +18,6 @@ COUNTRIES = (
('AT', _('Austria')),
('AU', _('Australia')),
('AW', _('Aruba')),
- ('AX', _('Aland Islands')),
('AZ', _('Azerbaijan')),
('BA', _('Bosnia and Herzegovina')),
('BB', _('Barbados')),
@@ -29,13 +28,11 @@ COUNTRIES = (
('BH', _('Bahrain')),
('BI', _('Burundi')),
('BJ', _('Benin')),
- ('BL', _('St. Barts')),
('BM', _('Bermuda')),
- ('BN', _('Brunei')),
+ ('BN', _('Brunei Darussalam')),
('BO', _('Bolivia')),
- ('BQ', _('Caribbean Netherlands')),
('BR', _('Brazil')),
- ('BS', _('Bahamas')),
+ ('BS', _('Bahama')),
('BT', _('Bhutan')),
('BV', _('Bouvet Island')),
('BW', _('Botswana')),
@@ -43,12 +40,11 @@ COUNTRIES = (
('BZ', _('Belize')),
('CA', _('Canada')),
('CC', _('Cocos (Keeling) Islands')),
- ('CD', _('Congo - Kinshasa')),
('CF', _('Central African Republic')),
- ('CG', _('Congo - Brazzaville')),
+ ('CG', _('Congo')),
('CH', _('Switzerland')),
('CI', _('Ivory Coast')),
- ('CK', _('Cook Islands')),
+ ('CK', _('Cook Iislands')),
('CL', _('Chile')),
('CM', _('Cameroon')),
('CN', _('China')),
@@ -56,10 +52,9 @@ COUNTRIES = (
('CR', _('Costa Rica')),
('CU', _('Cuba')),
('CV', _('Cape Verde')),
- ('CW', _('Curacao')),
('CX', _('Christmas Island')),
('CY', _('Cyprus')),
- ('CZ', _('Czechia')),
+ ('CZ', _('Czech Republic')),
('DE', _('Germany')),
('DJ', _('Djibouti')),
('DK', _('Denmark')),
@@ -75,16 +70,16 @@ COUNTRIES = (
('ET', _('Ethiopia')),
('FI', _('Finland')),
('FJ', _('Fiji')),
- ('FK', _('Falkland Islands')),
+ ('FK', _('Falkland Islands (Malvinas)')),
('FM', _('Micronesia')),
('FO', _('Faroe Islands')),
('FR', _('France')),
+ ('FX', _('France, Metropolitan')),
('GA', _('Gabon')),
- ('GB', _('United Kingdom')),
+ ('GB', _('United Kingdom (Great Britain)')),
('GD', _('Grenada')),
('GE', _('Georgia')),
('GF', _('French Guiana')),
- ('GG', _('Guernsey')),
('GH', _('Ghana')),
('GI', _('Gibraltar')),
('GL', _('Greenland')),
@@ -98,7 +93,7 @@ COUNTRIES = (
('GU', _('Guam')),
('GW', _('Guinea-Bissau')),
('GY', _('Guyana')),
- ('HK', _('Hong Kong SAR China')),
+ ('HK', _('Hong Kong')),
('HM', _('Heard & McDonald Islands')),
('HN', _('Honduras')),
('HR', _('Croatia')),
@@ -107,14 +102,12 @@ COUNTRIES = (
('ID', _('Indonesia')),
('IE', _('Ireland')),
('IL', _('Israel')),
- ('IM', _('Isle of Man')),
('IN', _('India')),
('IO', _('British Indian Ocean Territory')),
('IQ', _('Iraq')),
- ('IR', _('Iran')),
+ ('IR', _('Islamic Republic of Iran')),
('IS', _('Iceland')),
('IT', _('Italy')),
- ('JE', _('Jersey')),
('JM', _('Jamaica')),
('JO', _('Jordan')),
('JP', _('Japan')),
@@ -124,14 +117,14 @@ COUNTRIES = (
('KI', _('Kiribati')),
('KM', _('Comoros')),
('KN', _('St. Kitts and Nevis')),
- ('KP', _('North Korea')),
- ('KR', _('South Korea')),
+ ('KP', _('Korea, Democratic People\'s Republic of')),
+ ('KR', _('Korea, Republic of')),
('KW', _('Kuwait')),
('KY', _('Cayman Islands')),
('KZ', _('Kazakhstan')),
- ('LA', _('Laos')),
+ ('LA', _('Lao People\'s Democratic Republic')),
('LB', _('Lebanon')),
- ('LC', _('St. Lucia')),
+ ('LC', _('Saint Lucia')),
('LI', _('Liechtenstein')),
('LK', _('Sri Lanka')),
('LR', _('Liberia')),
@@ -139,23 +132,20 @@ COUNTRIES = (
('LT', _('Lithuania')),
('LU', _('Luxembourg')),
('LV', _('Latvia')),
- ('LY', _('Libya')),
+ ('LY', _('Libyan Arab Jamahiriya')),
('MA', _('Morocco')),
('MC', _('Monaco')),
- ('MD', _('Moldova')),
- ('ME', _('Montenegro')),
- ('MF', _('St. Martin')),
+ ('MD', _('Moldova, Republic of')),
('MG', _('Madagascar')),
('MH', _('Marshall Islands')),
- ('MK', _('North Macedonia')),
('ML', _('Mali')),
- ('MM', _('Myanmar (Burma)')),
('MN', _('Mongolia')),
- ('MO', _('Macao SAR China')),
+ ('MM', _('Myanmar')),
+ ('MO', _('Macau')),
('MP', _('Northern Mariana Islands')),
('MQ', _('Martinique')),
('MR', _('Mauritania')),
- ('MS', _('Montserrat')),
+ ('MS', _('Monserrat')),
('MT', _('Malta')),
('MU', _('Mauritius')),
('MV', _('Maldives')),
@@ -184,17 +174,15 @@ COUNTRIES = (
('PK', _('Pakistan')),
('PL', _('Poland')),
('PM', _('St. Pierre & Miquelon')),
- ('PN', _('Pitcairn Islands')),
+ ('PN', _('Pitcairn')),
('PR', _('Puerto Rico')),
- ('PS', _('Palestinian Territories')),
('PT', _('Portugal')),
('PW', _('Palau')),
('PY', _('Paraguay')),
('QA', _('Qatar')),
('RE', _('Reunion')),
('RO', _('Romania')),
- ('RS', _('Serbia')),
- ('RU', _('Russia')),
+ ('RU', _('Russian Federation')),
('RW', _('Rwanda')),
('SA', _('Saudi Arabia')),
('SB', _('Solomon Islands')),
@@ -204,19 +192,17 @@ COUNTRIES = (
('SG', _('Singapore')),
('SH', _('St. Helena')),
('SI', _('Slovenia')),
- ('SJ', _('Svalbard and Jan Mayen')),
+ ('SJ', _('Svalbard & Jan Mayen Islands')),
('SK', _('Slovakia')),
('SL', _('Sierra Leone')),
('SM', _('San Marino')),
('SN', _('Senegal')),
('SO', _('Somalia')),
('SR', _('Suriname')),
- ('SS', _('South Sudan')),
('ST', _('Sao Tome & Principe')),
('SV', _('El Salvador')),
- ('SX', _('Sint Maarten')),
- ('SY', _('Syria')),
- ('SZ', _('Eswatini')),
+ ('SY', _('Syrian Arab Republic')),
+ ('SZ', _('Swaziland')),
('TC', _('Turks & Caicos Islands')),
('TD', _('Chad')),
('TF', _('French Southern Territories')),
@@ -224,34 +210,36 @@ COUNTRIES = (
('TH', _('Thailand')),
('TJ', _('Tajikistan')),
('TK', _('Tokelau')),
- ('TL', _('Timor-Leste')),
('TM', _('Turkmenistan')),
('TN', _('Tunisia')),
('TO', _('Tonga')),
+ ('TP', _('East Timor')),
('TR', _('Turkey')),
('TT', _('Trinidad & Tobago')),
('TV', _('Tuvalu')),
- ('TW', _('Taiwan')),
- ('TZ', _('Tanzania')),
+ ('TW', _('Taiwan, Province of China')),
+ ('TZ', _('Tanzania, United Republic of')),
('UA', _('Ukraine')),
('UG', _('Uganda')),
- ('UM', _('U.S. Outlying Islands')),
- ('US', _('United States')),
+ ('UM', _('United States Minor Outlying Islands')),
+ ('US', _('United States of America')),
('UY', _('Uruguay')),
('UZ', _('Uzbekistan')),
- ('VA', _('Vatican City')),
- ('VC', _('St. Vincent & Grenadines')),
+ ('VA', _('Vatican City State (Holy See)')),
+ ('VC', _('St. Vincent & the Grenadines')),
('VE', _('Venezuela')),
('VG', _('British Virgin Islands')),
- ('VI', _('U.S. Virgin Islands')),
- ('VN', _('Vietnam')),
+ ('VI', _('United States Virgin Islands')),
+ ('VN', _('Viet Nam')),
('VU', _('Vanuatu')),
- ('WF', _('Wallis & Futuna')),
+ ('WF', _('Wallis & Futuna Islands')),
('WS', _('Samoa')),
('YE', _('Yemen')),
('YT', _('Mayotte')),
+ ('YU', _('Yugoslavia')),
('ZA', _('South Africa')),
('ZM', _('Zambia')),
+ ('ZR', _('Zaire')),
('ZW', _('Zimbabwe')),
)
diff --git a/utils/forms.py b/utils/forms.py
index 3cc57578..f35c90f4 100644
--- a/utils/forms.py
+++ b/utils/forms.py
@@ -4,8 +4,6 @@ from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
-from django_recaptcha.fields import ReCaptchaField
-
from membership.models import CustomUser
from .models import ContactMessage, BillingAddress, UserBillingAddress
@@ -190,7 +188,6 @@ class UserBillingAddressForm(forms.ModelForm):
class ContactUsForm(forms.ModelForm):
error_css_class = 'autofocus'
- captcha = ReCaptchaField()
class Meta:
model = ContactMessage
@@ -209,12 +206,11 @@ class ContactUsForm(forms.ModelForm):
}
def send_email(self, email_to='info@digitalglarus.ch'):
- pass
- #text_content = render_to_string(
- # 'emails/contact.txt', {'data': self.cleaned_data})
- #html_content = render_to_string(
- # 'emails/contact.html', {'data': self.cleaned_data})
- #email = EmailMultiAlternatives('Subject', text_content)
- #email.attach_alternative(html_content, "text/html")
- #email.to = [email_to]
- #email.send()
+ text_content = render_to_string(
+ 'emails/contact.txt', {'data': self.cleaned_data})
+ html_content = render_to_string(
+ 'emails/contact.html', {'data': self.cleaned_data})
+ email = EmailMultiAlternatives('Subject', text_content)
+ email.attach_alternative(html_content, "text/html")
+ email.to = [email_to]
+ email.send()
diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py
index b9e2eb8a..7bff9a89 100644
--- a/utils/hosting_utils.py
+++ b/utils/hosting_utils.py
@@ -3,8 +3,6 @@ import logging
import math
import subprocess
-from django.conf import settings
-
from oca.pool import WrongIdError
from datacenterlight.models import VMPricing
@@ -81,8 +79,7 @@ def get_vm_price(cpu, memory, disk_size, hdd_size=0, pricing_name='default'):
price = ((decimal.Decimal(cpu) * pricing.cores_unit_price) +
(decimal.Decimal(memory) * pricing.ram_unit_price) +
(decimal.Decimal(disk_size) * pricing.ssd_unit_price) +
- (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) +
- decimal.Decimal(settings.VM_BASE_PRICE))
+ (decimal.Decimal(hdd_size) * pricing.hdd_unit_price))
cents = decimal.Decimal('.01')
price = price.quantize(cents, decimal.ROUND_HALF_UP)
return round(float(price), 2)
@@ -105,8 +102,7 @@ def get_vm_price_for_given_vat(cpu, memory, ssd_size, hdd_size=0,
(decimal.Decimal(cpu) * pricing.cores_unit_price) +
(decimal.Decimal(memory) * pricing.ram_unit_price) +
(decimal.Decimal(ssd_size) * pricing.ssd_unit_price) +
- (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) +
- decimal.Decimal(settings.VM_BASE_PRICE)
+ (decimal.Decimal(hdd_size) * pricing.hdd_unit_price)
)
discount_name = pricing.discount_name
@@ -122,8 +118,7 @@ def get_vm_price_for_given_vat(cpu, memory, ssd_size, hdd_size=0,
discount = {
'name': discount_name,
'amount': discount_amount,
- 'amount_with_vat': round(float(discount_amount_with_vat), 2),
- 'stripe_coupon_id': pricing.stripe_coupon_id
+ 'amount_with_vat': round(float(discount_amount_with_vat), 2)
}
return (round(float(price), 2), round(float(vat), 2),
round(float(vat_percent), 2), discount)
@@ -159,8 +154,7 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0,
(decimal.Decimal(cpu) * pricing.cores_unit_price) +
(decimal.Decimal(memory) * pricing.ram_unit_price) +
(decimal.Decimal(ssd_size) * pricing.ssd_unit_price) +
- (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) +
- decimal.Decimal(settings.VM_BASE_PRICE)
+ (decimal.Decimal(hdd_size) * pricing.hdd_unit_price)
)
if pricing.vat_inclusive:
vat = decimal.Decimal(0)
@@ -174,8 +168,7 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0,
vat = vat.quantize(cents, decimal.ROUND_HALF_UP)
discount = {
'name': pricing.discount_name,
- 'amount': round(float(pricing.discount_amount), 2),
- 'stripe_coupon_id': pricing.stripe_coupon_id
+ 'amount': round(float(pricing.discount_amount), 2)
}
return (round(float(price), 2), round(float(vat), 2),
round(float(vat_percent), 2), discount)
@@ -222,6 +215,11 @@ def get_ip_addresses(vm_id):
return "--"
+def round_up(n, decimals=0):
+ multiplier = 10 ** decimals
+ return math.ceil(n * multiplier) / multiplier
+
+
class HostingUtils:
@staticmethod
def clear_items_from_list(from_list, items_list):
diff --git a/utils/ldap_manager.py b/utils/ldap_manager.py
index d40e931f..8c555224 100644
--- a/utils/ldap_manager.py
+++ b/utils/ldap_manager.py
@@ -3,7 +3,6 @@ import hashlib
import random
import ldap3
import logging
-import unicodedata
from django.conf import settings
@@ -102,7 +101,7 @@ class LdapManager:
"uidNumber": [str(uidNumber)],
"gidNumber": [str(settings.LDAP_CUSTOMER_GROUP_ID)],
"loginShell": ["/bin/bash"],
- "homeDirectory": ["/home/{}".format(unicodedata.normalize('NFKD', user).encode('ascii','ignore'))],
+ "homeDirectory": ["/home/{}".format(user).encode("utf-8")],
"mail": email.encode("utf-8"),
"userPassword": [self._ssha_password(
password.encode("utf-8")
@@ -267,7 +266,7 @@ class LdapManager:
logger.error(
"Error reading int value from {}. {}"
"Returning default value {} instead".format(
- settings.LDAP_MAX_UID_FILE_PATH,
+ settings.LDAP_MAX_UID_PATH,
str(ve),
settings.LDAP_DEFAULT_START_UID
)
diff --git a/utils/stripe_utils.py b/utils/stripe_utils.py
index 875a174e..ade06dd3 100644
--- a/utils/stripe_utils.py
+++ b/utils/stripe_utils.py
@@ -34,7 +34,6 @@ def handleStripeError(f):
logger.error(str(e))
return response
except stripe.error.RateLimitError as e:
- logger.error(str(e))
response.update(
{'error': "Too many requests made to the API too quickly"})
return response
@@ -70,7 +69,7 @@ class StripeUtils(object):
CURRENCY = 'chf'
INTERVAL = 'month'
SUCCEEDED_STATUS = 'succeeded'
- RESOURCE_ALREADY_EXISTS_ERROR_CODE = 'resource_already_exists'
+ STRIPE_PLAN_ALREADY_EXISTS = 'Plan already exists'
STRIPE_NO_SUCH_PLAN = 'No such plan'
PLAN_EXISTS_ERROR_MSG = 'Plan {} exists already.\nCreating a local StripePlan now.'
PLAN_DOES_NOT_EXIST_ERROR_MSG = 'Plan {} does not exist.'
@@ -83,31 +82,20 @@ class StripeUtils(object):
customer.save()
@handleStripeError
- def associate_customer_card(self, stripe_customer_id, id_payment_method,
+ def associate_customer_card(self, stripe_customer_id, token,
set_as_default=False):
customer = stripe.Customer.retrieve(stripe_customer_id)
- stripe.PaymentMethod.attach(
- id_payment_method,
- customer=stripe_customer_id,
- )
+ card = customer.sources.create(source=token)
if set_as_default:
- customer.invoice_settings.default_payment_method = id_payment_method
+ customer.default_source = card.id
customer.save()
return True
@handleStripeError
def dissociate_customer_card(self, stripe_customer_id, card_id):
customer = stripe.Customer.retrieve(stripe_customer_id)
- if card_id.startswith("pm"):
- logger.debug("PaymentMethod %s detached %s" % (card_id,
- stripe_customer_id))
- pm = stripe.PaymentMethod.retrieve(card_id)
- stripe.PaymentMethod.detach(card_id)
- pm.delete()
- else:
- logger.debug("card %s detached %s" % (card_id, stripe_customer_id))
- card = customer.sources.retrieve(card_id)
- card.delete()
+ card = customer.sources.retrieve(card_id)
+ card.delete()
@handleStripeError
def update_customer_card(self, customer_id, token):
@@ -199,24 +187,6 @@ class StripeUtils(object):
}
return card_details
- @handleStripeError
- def get_cards_details_from_payment_method(self, payment_method_id):
- payment_method = stripe.PaymentMethod.retrieve(payment_method_id)
- # payment_method does not always seem to have a card with id
- # if that is the case, fallback to payment_method_id for card_id
- card_id = payment_method_id
- if hasattr(payment_method.card, 'id'):
- card_id = payment_method.card.id
- card_details = {
- 'last4': payment_method.card.last4,
- 'brand': payment_method.card.brand,
- 'exp_month': payment_method.card.exp_month,
- 'exp_year': payment_method.card.exp_year,
- 'fingerprint': payment_method.card.fingerprint,
- 'card_id': card_id
- }
- return card_details
-
def check_customer(self, stripe_cus_api_id, user, token):
try:
customer = stripe.Customer.retrieve(stripe_cus_api_id)
@@ -236,11 +206,11 @@ class StripeUtils(object):
return customer
@handleStripeError
- def create_customer(self, id_payment_method, email, name=None):
+ def create_customer(self, token, email, name=None):
if name is None or name.strip() == "":
name = email
customer = self.stripe.Customer.create(
- payment_method=id_payment_method,
+ source=token,
description=name,
email=email
)
@@ -297,17 +267,11 @@ class StripeUtils(object):
stripe_plan_db_obj = StripePlan.objects.create(
stripe_plan_id=stripe_plan_id)
except stripe.error.InvalidRequestError as e:
- logger.error(str(e))
- logger.error("error_code = %s" % str(e.__dict__))
- if self.RESOURCE_ALREADY_EXISTS_ERROR_CODE in e.error.code:
+ if self.STRIPE_PLAN_ALREADY_EXISTS in str(e):
logger.debug(
self.PLAN_EXISTS_ERROR_MSG.format(stripe_plan_id))
- stripe_plan_db_obj, c = StripePlan.objects.get_or_create(
+ stripe_plan_db_obj = StripePlan.objects.create(
stripe_plan_id=stripe_plan_id)
- if c:
- logger.debug("Created stripe plan %s" % stripe_plan_id)
- else:
- logger.debug("Plan %s exists already" % stripe_plan_id)
return stripe_plan_db_obj
@handleStripeError
@@ -336,14 +300,10 @@ class StripeUtils(object):
@handleStripeError
def subscribe_customer_to_plan(self, customer, plans, trial_end=None,
- coupon="", tax_rates=list(),
- default_payment_method=""):
+ coupon="", tax_rates=list()):
"""
Subscribes the given customer to the list of given plans
- :param default_payment_method:
- :param tax_rates:
- :param coupon:
:param customer: The stripe customer identifier
:param plans: A list of stripe plans.
:param trial_end: An integer representing when the Stripe subscription
@@ -357,17 +317,12 @@ class StripeUtils(object):
]
:return: The subscription StripeObject
"""
- logger.debug("Subscribing %s to plan %s : coupon = %s" % (
- customer, str(plans), str(coupon)
- ))
+
subscription_result = self.stripe.Subscription.create(
customer=customer, items=plans, trial_end=trial_end,
coupon=coupon,
default_tax_rates=tax_rates,
- payment_behavior='allow_incomplete',
- default_payment_method=default_payment_method
)
- logger.debug("Done subscribing")
return subscription_result
@handleStripeError
@@ -525,49 +480,7 @@ class StripeUtils(object):
)
return tax_id_obj
- @handleStripeError
- def get_payment_intent(self, amount, customer):
- """ Create a stripe PaymentIntent of the given amount and return it
- :param amount: the amount of payment_intent
- :return:
- """
- payment_intent_obj = stripe.PaymentIntent.create(
- amount=amount,
- currency='chf',
- customer=customer,
- setup_future_usage='off_session'
- )
- return payment_intent_obj
-
- @handleStripeError
- def get_available_payment_methods(self, customer):
- """ Retrieves all payment methods of the given customer
- :param customer: StripeCustomer object
- :return: a list of available payment methods
- """
- return_list = []
- if customer is None:
- return return_list
- cu = stripe.Customer.retrieve(customer.stripe_id)
- pms = stripe.PaymentMethod.list(
- customer=customer.stripe_id,
- type="card",
- )
- default_source = None
- if cu.default_source:
- default_source = cu.default_source
- else:
- default_source = cu.invoice_settings.default_payment_method
- for pm in pms.data:
- return_list.append({
- 'last4': pm.card.last4, 'brand': pm.card.brand, 'id': pm.id,
- 'exp_year': pm.card.exp_year,
- 'exp_month': '{:02d}'.format(pm.card.exp_month),
- 'preferred': pm.id == default_source
- })
- return return_list
-
def compare_vat_numbers(self, vat1, vat2):
_vat1 = vat1.replace(" ", "").replace(".", "").replace("-","")
_vat2 = vat2.replace(" ", "").replace(".", "").replace("-","")
- return True if _vat1 == _vat2 else False
+ return True if _vat1 == _vat2 else False
\ No newline at end of file
diff --git a/vat_rates.csv b/vat_rates.csv
index 72870530..17bdb997 100644
--- a/vat_rates.csv
+++ b/vat_rates.csv
@@ -321,4 +321,5 @@ IM",GBP,0.1,standard,
2019-12-17,,IS,EUR,0.24,standard,Iceland standard VAT (added manually)
2019-12-17,,FX,EUR,0.20,standard,France metropolitan standard VAT (added manually)
2020-01-04,,CY,EUR,0.19,standard,Cyprus standard VAT (added manually)
+2019-01-04,,IL,EUR,0.23,standard,Ireland standard VAT (added manually)
2019-01-04,,LI,EUR,0.077,standard,Liechtenstein standard VAT (added manually)
diff --git a/webhook/views.py b/webhook/views.py
index 0a96d0b6..516d1afc 100644
--- a/webhook/views.py
+++ b/webhook/views.py
@@ -1,17 +1,14 @@
import datetime
import logging
-import json
-import stripe
+import stripe
# Create your views here.
from django.conf import settings
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
-from datacenterlight.views import do_provisioning, do_provisioning_generic
from membership.models import StripeCustomer
-from hosting.models import IncompleteSubscriptions, IncompletePaymentIntents
from utils.models import BillingAddress, UserBillingAddress
from utils.tasks import send_plain_email_task
@@ -114,193 +111,8 @@ def handle_webhook(request):
'to': settings.DCL_ERROR_EMAILS_TO_LIST,
'body': "Response = %s" % str(tax_id_obj),
}
+
send_plain_email_task.delay(email_data)
- elif event.type == 'invoice.paid':
- #More info: https://stripe.com/docs/billing/migration/strong-customer-authentication#scenario-1-handling-fulfillment
- invoice_obj = event.data.object
- logger.debug("Webhook Event: invoice.paid")
- logger.debug("invoice_obj %s " % str(invoice_obj))
- logger.debug("invoice_obj.paid = %s %s" % (invoice_obj.paid, type(invoice_obj.paid)))
- logger.debug("invoice_obj.billing_reason = %s %s" % (invoice_obj.billing_reason, type(invoice_obj.billing_reason)))
- # We should check for billing_reason == "subscription_create" but we
- # check for "subscription_update"
- # because we are using older api.
- # See https://stripe.com/docs/upgrades?since=2015-07-13
-
- # The billing_reason attribute of the invoice object now can take the
- # value of subscription_create, indicating that it is the first
- # invoice of a subscription. For older API versions,
- # billing_reason=subscription_create is represented as
- # subscription_update.
-
- if (invoice_obj.paid and
- invoice_obj.billing_reason == "subscription_update"):
- logger.debug("""invoice_obj.paid and
- invoice_obj.billing_reason == subscription_update""")
- logger.debug("Start provisioning")
- try:
- logger.debug("Looking for subscription %s" %
- invoice_obj.subscription)
- stripe_subscription_obj = stripe.Subscription.retrieve(
- invoice_obj.subscription)
- try:
- incomplete_sub = IncompleteSubscriptions.objects.get(
- subscription_id=invoice_obj.subscription)
- request = ""
- soc = ""
- card_details_response = ""
- gp_details = ""
- template = ""
- specs = ""
- billing_address_data = ""
- if incomplete_sub.request:
- request = json.loads(incomplete_sub.request)
- if incomplete_sub.specs:
- specs = json.loads(incomplete_sub.specs)
- if incomplete_sub.stripe_onetime_charge:
- soc = json.loads(incomplete_sub.stripe_onetime_charge)
- if incomplete_sub.gp_details:
- gp_details = json.loads(incomplete_sub.gp_details)
- if incomplete_sub.card_details_response:
- card_details_response = json.loads(
- incomplete_sub.card_details_response)
- if incomplete_sub.template:
- template = json.loads(
- incomplete_sub.template)
- if incomplete_sub.billing_address_data:
- billing_address_data = json.loads(
- incomplete_sub.billing_address_data)
- logger.debug("*******")
- logger.debug(str(incomplete_sub))
- logger.debug("*******")
- logger.debug("1*******")
- logger.debug(request)
- logger.debug("2*******")
- logger.debug(card_details_response)
- logger.debug("3*******")
- logger.debug(soc)
- logger.debug("4*******")
- logger.debug(gp_details)
- logger.debug("5*******")
- logger.debug(template)
- logger.debug("6*******")
- do_provisioning(
- request=request,
- stripe_api_cus_id=incomplete_sub.stripe_api_cus_id,
- card_details_response=card_details_response,
- stripe_subscription_obj=stripe_subscription_obj,
- stripe_onetime_charge=soc,
- gp_details=gp_details,
- specs=specs,
- vm_template_id=incomplete_sub.vm_template_id,
- template=template,
- billing_address_data=billing_address_data,
- real_request=None
- )
- except IncompleteSubscriptions.DoesNotExist as ex:
- logger.error(str(ex))
- except IncompleteSubscriptions.MultipleObjectsReturned as ex:
- logger.error(str(ex))
- email_data = {
- 'subject': "IncompleteSubscriptions error",
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': settings.DCL_ERROR_EMAILS_TO_LIST,
- 'body': "Response = %s" % str(ex),
- }
- send_plain_email_task.delay(email_data)
- except Exception as ex:
- logger.error(str(ex))
- email_data = {
- 'subject': "invoice.paid Webhook error",
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': settings.DCL_ERROR_EMAILS_TO_LIST,
- 'body': "Response = %s" % str(ex),
- }
- send_plain_email_task.delay(email_data)
- elif event.type == 'invoice.payment_failed':
- invoice_obj = event.data.object
- logger.debug("Webhook Event: invoice.payment_failed")
- logger.debug("invoice_obj %s " % str(invoice_obj))
- if (invoice_obj.payment_failed and
- invoice_obj.billing_reason == "subscription_update"):
- logger.debug("Payment failed, inform the users")
- elif event.type == 'payment_intent.succeeded':
- payment_intent_obj = event.data.object
- logger.debug("Webhook Event: payment_intent.succeeded")
- logger.debug("payment_intent_obj %s " % str(payment_intent_obj))
- try:
- logger.debug("Looking for IncompletePaymentIntents %s " %
- payment_intent_obj.id)
- incomplete_pm = IncompletePaymentIntents.objects.get(
- payment_intent_id=payment_intent_obj.id)
- logger.debug("incomplete_pm = %s" % str(incomplete_pm.__dict__))
- request = ""
- soc = ""
- card_details_response = ""
- gp_details = ""
- template = ""
- billing_address_data = ""
- if incomplete_pm.request:
- request = json.loads(incomplete_pm.request)
- logger.debug("request = %s" % str(request))
- if incomplete_pm.stripe_charge_id:
- soc = incomplete_pm.stripe_charge_id
- logger.debug("stripe_onetime_charge = %s" % str(soc))
- if incomplete_pm.gp_details:
- gp_details = json.loads(incomplete_pm.gp_details)
- logger.debug("gp_details = %s" % str(gp_details))
- if incomplete_pm.card_details_response:
- card_details_response = json.loads(
- incomplete_pm.card_details_response)
- logger.debug("card_details_response = %s" % str(card_details_response))
- if incomplete_pm.billing_address_data:
- billing_address_data = json.loads(
- incomplete_pm.billing_address_data)
- logger.debug("billing_address_data = %s" % str(billing_address_data))
- logger.debug("1*******")
- logger.debug(request)
- logger.debug("2*******")
- logger.debug(card_details_response)
- logger.debug("3*******")
- logger.debug(soc)
- logger.debug("4*******")
- logger.debug(gp_details)
- logger.debug("5*******")
- logger.debug(template)
- logger.debug("6*******")
- logger.debug(billing_address_data)
- incomplete_pm.completed_at = datetime.datetime.now()
- charges = ""
- if len(payment_intent_obj.charges.data) > 0:
- for d in payment_intent_obj.charges.data:
- if charges == "":
- charges = "%s" % d.id
- else:
- charges = "%s,%s" % (charges, d.id)
- logger.debug("Charge ids = %s" % charges)
- incomplete_pm.stripe_charge_id=charges
- do_provisioning_generic(
- request=request,
- stripe_api_cus_id=incomplete_pm.stripe_api_cus_id,
- card_details_response=card_details_response,
- stripe_subscription_id=None,
- stripe_charge_id=charges,
- gp_details=gp_details,
- billing_address_data=billing_address_data
- )
- incomplete_pm.save()
- except IncompletePaymentIntents.DoesNotExist as ex:
- logger.error(str(ex))
- except (IncompletePaymentIntents.MultipleObjectsReturned,
- Exception) as ex:
- logger.error(str(ex))
- email_data = {
- 'subject': "IncompletePaymentIntents error",
- 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
- 'to': settings.DCL_ERROR_EMAILS_TO_LIST,
- 'body': "Response = %s" % str(ex),
- }
- send_plain_email_task.delay(email_data)
else:
logger.error("Unhandled event : " + event.type)
return HttpResponse(status=200)