diff --git a/river/migrations/0005_auto_20191020_1027.py b/river/migrations/0005_auto_20191020_1027.py new file mode 100644 index 0000000..6e98188 --- /dev/null +++ b/river/migrations/0005_auto_20191020_1027.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.24 on 2019-10-20 15:27 +from __future__ import unicode_literals + +from django.db import migrations, models +from django.db.models import Case, When, Value + + +def migrate_status(apps, schema_editor): + from river.models import PENDING, APPROVED + TransitionApproval = apps.get_model('river', 'TransitionApproval') + TransitionApproval.objects.update(status2=Case( + When(status=0, then=Value(PENDING)), + When(status=1, then=Value(APPROVED)) + )) + + +def reverse_migrate_status(apps, schema_editor): + from river.models import PENDING, APPROVED + TransitionApproval = apps.get_model('river', 'TransitionApproval') + TransitionApproval.objects.update(status=Case( + When(status2=PENDING, then=Value(0)), + When(status2=APPROVED, then=Value(1)), + )) + + +class Migration(migrations.Migration): + dependencies = [ + ('river', '0004_auto_20191016_1731'), + ] + + operations = [ + migrations.AddField( + model_name='transitionapproval', + name='status2', + field=models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved')], default='pending', max_length=100, verbose_name='Status'), + ), + migrations.RunPython(migrate_status, reverse_code=reverse_migrate_status), + migrations.RemoveField( + model_name='transitionapproval', + name='status', + ), + migrations.RenameField('transitionapproval', 'status2', 'status'), + ] diff --git a/river/models/transitionapproval.py b/river/models/transitionapproval.py index 4d6244c..28b6818 100644 --- a/river/models/transitionapproval.py +++ b/river/models/transitionapproval.py @@ -19,8 +19,8 @@ __author__ = 'ahmetdal' -PENDING = 0 -APPROVED = 1 +PENDING = "pending" +APPROVED = "approved" STATUSES = [ (PENDING, _('Pending')), @@ -52,7 +52,7 @@ class Meta: transactioner = models.ForeignKey(app_config.USER_CLASS, verbose_name=_('Transactioner'), null=True, blank=True, on_delete=SET_NULL) transaction_date = models.DateTimeField(null=True, blank=True) - status = models.IntegerField(_('Status'), choices=STATUSES, default=PENDING) + status = models.CharField(_('Status'), choices=STATUSES, max_length=100, default=PENDING) skipped = models.BooleanField(_('Skip'), default=False) diff --git a/river/tests/__init__.py b/river/tests/__init__.py index 0c9135a..54a6f1b 100644 --- a/river/tests/__init__.py +++ b/river/tests/__init__.py @@ -1 +1,13 @@ +from django.db.backends.signals import connection_created + __author__ = 'ahmetdal' + + +def activate_foreign_keys(sender, connection, **kwargs): + """Enable integrity constraint with sqlite.""" + if connection.vendor == 'sqlite': + cursor = connection.cursor() + cursor.execute('PRAGMA foreign_keys = ON;') + + +connection_created.connect(activate_foreign_keys) diff --git a/river/tests/tmigrations/test__migrations.py b/river/tests/tmigrations/test__migrations.py index 60d03ce..c80abff 100644 --- a/river/tests/tmigrations/test__migrations.py +++ b/river/tests/tmigrations/test__migrations.py @@ -1,9 +1,15 @@ import os import sys +from django.contrib.contenttypes.models import ContentType +from django.db import connection, transaction from django.test.utils import override_settings from hamcrest import assert_that, equal_to, has_length +from river.models.factories import StateObjectFactory, WorkflowFactory, TransitionApprovalMetaFactory +from river.tests.models import BasicTestModel +from river.tests.models.factories import BasicTestModelObjectFactory + try: from StringIO import StringIO except ImportError: @@ -78,3 +84,43 @@ def test__shouldNotKeepRecreatingMigrationsWhenNoChange(self): assert_that(out.getvalue(), equal_to("No changes detected in app 'tests'\n")) assert_that(self.migrations_after, has_length(len(self.migrations_before))) + + @override_settings(MIGRATION_MODULES={"tests": "river.tests.volatile.river_tests"}) + @transaction.atomic + def test__shouldMigrateTransitionApprovalStatusToStringInDB(self): + out = StringIO() + sys.stout = out + cur = connection.cursor() + + state1 = StateObjectFactory(label="state1") + state2 = StateObjectFactory(label="state2") + workflow = WorkflowFactory(initial_state=state1, content_type=ContentType.objects.get_for_model(BasicTestModel), field_name="my_field") + TransitionApprovalMetaFactory.create( + workflow=workflow, + source_state=state1, + destination_state=state2, + priority=0 + ) + workflow_object = BasicTestModelObjectFactory() + + result = cur.execute("select status from river_transitionapproval where object_id=%s;" % workflow_object.model.pk).fetchall() + assert_that(result[0][0], equal_to("pending")) + + call_command('migrate', 'river', '0004', stdout=out) + schema = cur.execute("PRAGMA table_info('river_transitionapproval');").fetchall() + self.migrations_after = list(filter(lambda f: f.endswith('.py') and f != '__init__.py', os.listdir('river/tests/volatile/river/'))) + status_col_type = list(filter(lambda column: column[1] == 'status', schema))[0][2] + assert_that(status_col_type, equal_to("integer")) + + result = cur.execute("select status from river_transitionapproval where object_id=%s;" % workflow_object.model.pk).fetchall() + assert_that(result[0][0], equal_to(0)) + + call_command('migrate', 'river', stdout=out) + schema = cur.execute("PRAGMA table_info('river_transitionapproval');").fetchall() + + self.migrations_after = list(filter(lambda f: f.endswith('.py') and f != '__init__.py', os.listdir('river/tests/volatile/river/'))) + status_col_type = list(filter(lambda column: column[1] == 'status', schema))[0][2] + assert_that(status_col_type, equal_to("varchar(100)")) + + result = cur.execute("select status from river_transitionapproval where object_id=%s;" % workflow_object.model.pk).fetchall() + assert_that(result[0][0], equal_to("pending"))