From 27eb3aa6805942c29dcbfefcc659026062e5f61b Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 3 Nov 2020 16:04:57 +0100 Subject: [PATCH 1/2] lingo: add backends and regies in site import/export (#46895) --- combo/apps/lingo/models.py | 68 +++++++++++++++++++++++++++++++++++++ combo/data/utils.py | 10 ++++++ tests/test_import_export.py | 36 ++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/combo/apps/lingo/models.py b/combo/apps/lingo/models.py index c57a0646..04c543cc 100644 --- a/combo/apps/lingo/models.py +++ b/combo/apps/lingo/models.py @@ -29,6 +29,7 @@ from requests import RequestException from django import template from django.conf import settings +from django.core import serializers from django.db import models from django.forms import models as model_forms, Select from django.utils.translation import ugettext_lazy as _ @@ -93,6 +94,11 @@ def build_remote_item(data, regie): reference_id=data.get('reference_id')) +class PaymentBackendManager(models.Manager): + def get_by_natural_key(self, slug): + return self.get(slug=slug) + + @python_2_unicode_compatible class PaymentBackend(models.Model): label = models.CharField(verbose_name=_('Label'), max_length=64) @@ -103,6 +109,8 @@ class PaymentBackend(models.Model): verbose_name=_('Payment Service'), max_length=64, choices=SERVICES) service_options = JSONField(blank=True, verbose_name=_('Payment Service Options')) + objects = PaymentBackendManager() + def __str__(self): return self.label @@ -119,6 +127,37 @@ class PaymentBackend(models.Model): options = {} return eopayment.Payment(self.service, options) + def natural_key(self): + return (self.slug,) + + @classmethod + def export_all_for_json(cls): + return [x.get_as_serialized_object() for x in cls.objects.all()] + + def get_as_serialized_object(self): + serialized_backend = json.loads( + serializers.serialize('json', [self], use_natural_primary_keys=True) + )[0] + del serialized_backend['model'] + return serialized_backend + + @classmethod + def load_serialized_objects(cls, json_site): + for json_backend in json_site: + cls.load_serialized_object(json_backend) + + @classmethod + def load_serialized_object(cls, json_backend): + json_backend['model'] = str(cls._meta) + try: + backend = cls.objects.get_by_natural_key(json_backend['fields']['slug']) + json_backend['pk'] = backend.pk + except cls.DoesNotExist: + pass + + backend = next(serializers.deserialize('json', json.dumps([json_backend]), ignorenonexistent=True)) + backend.save() + class RegieException(Exception): pass @@ -373,6 +412,35 @@ class Regie(models.Model): message.attach('%s.pdf' % invoice.id, invoice_pdf.content, 'application/pdf') message.send() + @classmethod + def export_all_for_json(cls): + return [x.get_as_serialized_object() for x in cls.objects.all()] + + def get_as_serialized_object(self): + serialized_regie = serializers.serialize( + 'json', [self], use_natural_primary_keys=True, use_natural_foreign_keys=True + ) + serialized_regie = json.loads(serialized_regie)[0] + del serialized_regie['model'] + return serialized_regie + + @classmethod + def load_serialized_objects(cls, json_site): + for json_regie in json_site: + cls.load_serialized_object(json_regie) + + @classmethod + def load_serialized_object(cls, json_regie): + json_regie['model'] = str(cls._meta) + try: + regie = cls.objects.get(slug=json_regie['fields']['slug']) + json_regie['pk'] = regie.pk + except cls.DoesNotExist: + pass + + regie = next(serializers.deserialize('json', json.dumps([json_regie]), ignorenonexistent=True)) + regie.save() + class BasketItem(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True) diff --git a/combo/data/utils.py b/combo/data/utils.py index aab319e1..9bb0094a 100644 --- a/combo/data/utils.py +++ b/combo/data/utils.py @@ -31,6 +31,7 @@ from combo.apps.assets.utils import untar_assets_files from combo.apps.assets.utils import tar_assets_files from combo.apps.maps.models import MapLayer from combo.apps.pwa.models import PwaSettings, PwaNavigationEntry +from combo.apps.lingo.models import PaymentBackend, Regie from .models import Page @@ -54,6 +55,10 @@ def export_site(): 'pwa': { 'settings': PwaSettings.export_for_json(), 'navigation': PwaNavigationEntry.export_all_for_json(), + }, + 'payment': { + 'backends': PaymentBackend.export_all_for_json(), + 'regies': Regie.export_all_for_json(), } } @@ -88,6 +93,8 @@ def import_site(data, if_empty=False, clean=False, request=None): Page.objects.all().delete() PwaSettings.objects.all().delete() PwaNavigationEntry.objects.all().delete() + PaymentBackend.objects.all().delete() + Regie.objects.all().delete() try: MapLayer.load_serialized_objects(data.get('map-layers') or []) @@ -97,6 +104,9 @@ def import_site(data, if_empty=False, clean=False, request=None): if data.get('pwa'): PwaSettings.load_serialized_settings(data['pwa'].get('settings')) PwaNavigationEntry.load_serialized_objects(data['pwa'].get('navigation')) + if data.get('payment'): + PaymentBackend.load_serialized_objects(data['payment'].get('backends')) + Regie.load_serialized_objects(data['payment'].get('regies')) except DeserializationError as e: message = str(e) if not message.startswith('Page matching query does not exist.'): diff --git a/tests/test_import_export.py b/tests/test_import_export.py index 69fbd046..a9b9e4c3 100644 --- a/tests/test_import_export.py +++ b/tests/test_import_export.py @@ -19,6 +19,7 @@ from django.utils.six import BytesIO, StringIO from combo.apps.assets.models import Asset from combo.apps.assets.utils import clean_assets_files from combo.apps.gallery.models import Image, GalleryCell +from combo.apps.lingo.models import PaymentBackend, Regie from combo.apps.maps.models import MapLayer, Map, MapLayerOptions from combo.apps.pwa.models import PwaSettings, PwaNavigationEntry from combo.data.models import Page, TextCell @@ -421,3 +422,38 @@ def test_import_export_tar(tmpdir, some_assets): tarfile.open(filename, 'w').close() # empty tar file with pytest.raises(CommandError, match=r'TAR file should provide _site.json file'): call_command('import_site', filename) + + +def test_import_export_payment(app): + backend = PaymentBackend.objects.create(label='Test', slug='test', service_options={'test': True}) + Regie.objects.create(label='Test regie', slug='test-regie', payment_backend=backend) + Regie.objects.create(label='Test regie 2', slug='test-regie-2', payment_backend=backend) + + output = get_output_of_command('export_site') + payload = json.loads(output) + assert len(payload['payment']['backends']) == 1 + assert len(payload['payment']['regies']) == 2 + + import_site(payload) + assert PaymentBackend.objects.count() == 1 + assert Regie.objects.count() == 2 + + PaymentBackend.objects.all().delete() + Regie.objects.all().delete() + import_site(payload) + + backend = PaymentBackend.objects.get(slug='test') + assert backend.label == 'Test' + assert backend.service_options == {'test': True} + + assert Regie.objects.count() == 2 + regie = Regie.objects.first() + assert regie.payment_backend == backend + + import_site(data={}, clean=True) + assert PaymentBackend.objects.count() == 0 + assert Regie.objects.count() == 0 + + empty_output = get_output_of_command('export_site') + assert len(json.loads(empty_output)['payment']['backends']) == 0 + assert len(json.loads(empty_output)['payment']['regies']) == 0 -- 2.20.1