From 6fd8453e6fc5cc3f5202de09bfe829789040faa8 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Fri, 18 Mar 2022 18:40:27 +0100
Subject: [PATCH] orange: invert sender checkbox (#62336)

---
 .../0011_orangesmsgateway_default_sender.py   | 22 +++++++++++++
 .../migrations/0012_invert_sender_checkbox.py | 29 +++++++++++++++++
 ..._remove_orangesmsgateway_provide_sender.py | 17 ++++++++++
 passerelle/apps/orange/models.py              | 12 ++++---
 tests/test_orange.py                          | 31 ++++++++++++++++++-
 5 files changed, 105 insertions(+), 6 deletions(-)
 create mode 100644 passerelle/apps/orange/migrations/0011_orangesmsgateway_default_sender.py
 create mode 100644 passerelle/apps/orange/migrations/0012_invert_sender_checkbox.py
 create mode 100644 passerelle/apps/orange/migrations/0013_remove_orangesmsgateway_provide_sender.py

diff --git a/passerelle/apps/orange/migrations/0011_orangesmsgateway_default_sender.py b/passerelle/apps/orange/migrations/0011_orangesmsgateway_default_sender.py
new file mode 100644
index 00000000..b926c65c
--- /dev/null
+++ b/passerelle/apps/orange/migrations/0011_orangesmsgateway_default_sender.py
@@ -0,0 +1,22 @@
+# Generated by Django 2.2.19 on 2022-03-18 16:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orange', '0010_orangesmsgateway_provide_sender'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='orangesmsgateway',
+            name='default_sender',
+            field=models.BooleanField(
+                default=True,
+                help_text='If unchecked, sender configurated with Publik must also be configurated in Orange backoffice',
+                verbose_name='Use sender configurated in Orange backoffice',
+            ),
+        ),
+    ]
diff --git a/passerelle/apps/orange/migrations/0012_invert_sender_checkbox.py b/passerelle/apps/orange/migrations/0012_invert_sender_checkbox.py
new file mode 100644
index 00000000..8d5689e8
--- /dev/null
+++ b/passerelle/apps/orange/migrations/0012_invert_sender_checkbox.py
@@ -0,0 +1,29 @@
+# Generated by Django 2.2.19 on 2022-03-18 16:52
+
+from django.db import migrations
+
+
+def forwards_func(apps, schema_editor):
+    OrangeSMSGateway = apps.get_model('orange', 'OrangeSMSGateway')
+    for con in OrangeSMSGateway.objects.all():
+        con.default_sender = not con.provide_sender
+        con.save()
+
+
+def reverse_func(apps, schema_editor):
+    OrangeSMSGateway = apps.get_model('orange', 'OrangeSMSGateway')
+    for con in OrangeSMSGateway.objects.all():
+        con.provide_sender = not con.default_sender
+        con.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orange', '0011_orangesmsgateway_default_sender'),
+    ]
+
+    operations = [
+        # invert "sender" checkbox
+        migrations.RunPython(forwards_func, reverse_func),
+    ]
diff --git a/passerelle/apps/orange/migrations/0013_remove_orangesmsgateway_provide_sender.py b/passerelle/apps/orange/migrations/0013_remove_orangesmsgateway_provide_sender.py
new file mode 100644
index 00000000..6bbd1499
--- /dev/null
+++ b/passerelle/apps/orange/migrations/0013_remove_orangesmsgateway_provide_sender.py
@@ -0,0 +1,17 @@
+# Generated by Django 2.2.19 on 2022-03-18 17:00
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orange', '0012_invert_sender_checkbox'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='orangesmsgateway',
+            name='provide_sender',
+        ),
+    ]
diff --git a/passerelle/apps/orange/models.py b/passerelle/apps/orange/models.py
index a382cde3..90a472bb 100644
--- a/passerelle/apps/orange/models.py
+++ b/passerelle/apps/orange/models.py
@@ -44,20 +44,22 @@ def get_json(response):
 
 class OrangeSMSGateway(SMSResource):
     hide_description_fields = ['groupname']
 
     username = models.CharField(verbose_name=_('Identifier'), max_length=64)
     password = models.CharField(verbose_name=_('Password'), max_length=64)
     groupname = models.CharField(verbose_name=_('Group'), max_length=64)
 
-    provide_sender = models.BooleanField(
-        _('Use sender configurated with Publik'),
-        default=False,
-        help_text=_('Sender name must be allowed by orange'),
+    default_sender = models.BooleanField(
+        _('Use sender configurated in Orange backoffice'),
+        default=True,
+        help_text=_(
+            'If unchecked, sender configurated with Publik must also be configurated in Orange backoffice'
+        ),
     )
 
     class Meta:
         verbose_name = _('Orange')
         db_table = 'sms_orange'
 
     def get_access_token(self):
         headers = {'content-type': 'application/x-www-form-urlencoded'}
@@ -90,17 +92,17 @@ class OrangeSMSGateway(SMSResource):
             'content-type': 'application/json',
             'authorization': 'Bearer %s' % access_token,
         }
         payload = {
             'name': 'Send a SMS from passerelle',
             'msisdns': destinations,
             'smsParam': {'encoding': 'GSM7', 'body': message},
         }
-        if self.provide_sender:
+        if not self.default_sender:
             payload['smsParam']['senderName'] = sender
         response = self.requests.post(URL_DIFFUSION % group_id, json=payload, headers=headers)
         if response.status_code != 201:
             raise OrangeError('Orange fails to send SMS: %s, %s' % (response.status_code, response.text))
         return get_json(response)
 
     def send_msg(self, text, sender, destinations, **kwargs):
         '''Send a SMS using the Orange provider'''
diff --git a/tests/test_orange.py b/tests/test_orange.py
index bcb78a4c..4d3f2092 100644
--- a/tests/test_orange.py
+++ b/tests/test_orange.py
@@ -15,16 +15,18 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import json
 
 import httmock
 import pytest
 from django.contrib.contenttypes.models import ContentType
+from django.db import connection
+from django.db.migrations.executor import MigrationExecutor
 from django.utils.encoding import force_text
 
 from passerelle.apps.orange.models import OrangeError, OrangeSMSGateway
 from passerelle.base.models import AccessRight, ApiUser, Job
 from passerelle.utils.jsonresponse import APIError
 
 NETLOC = 'contact-everyone.orange-business.com'
 JSON_HEADERS = {'content-type': 'application/json'}
@@ -174,17 +176,17 @@ def test_diffusion(app, connector):
             {
                 'code': 'SenderNameNotAllowed',
                 'field': 'smsParam.senderName',
                 'message': 'The given sender name is not allowed.',
             }
         ]
         return httmock.response(400, json.dumps(error_response))
 
-    orange.provide_sender = True
+    orange.default_sender = False
     orange.save()
     with pytest.raises(OrangeError, match='The given sender name is not allowed.'):
         with httmock.HTTMock(mocked_response):
             orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'], PAYLOAD['from'])
 
 
 def test_send_msg(app, connector):
     url = '/%s/%s/send/' % (connector.get_connector_slug(), connector.slug)
@@ -200,8 +202,35 @@ def test_send_msg(app, connector):
     resp = app.post_json(url, params=PAYLOAD, status=200)
     assert not resp.json['err']
     assert Job.objects.count() == 2
     with httmock.HTTMock(response_token_ok, response_group_ok, response_500):
         connector.jobs()
     job = Job.objects.all()[1]
     assert job.status == 'failed'
     assert 'Orange fails to send SMS: 500, my_error' in job.status_details['error_summary']
+
+
+def test_invert_sender_flag_formward_migration(transactional_db):
+    migrate_from = [('orange', '0010_orangesmsgateway_provide_sender'), ('base', '0029_auto_20210202_1627')]
+    migrate_to = [('orange', '0013_remove_orangesmsgateway_provide_sender')]
+
+    executor = MigrationExecutor(connection)
+    old_apps = executor.loader.project_state(migrate_from).apps
+    executor.migrate(migrate_from)
+
+    OrangeSMSGateway = old_apps.get_model('orange', 'OrangeSMSGateway')
+    OrangeSMSGateway.objects.create(slug='con1', username='jdoe', password='secret', groupname='group2')
+    OrangeSMSGateway.objects.create(
+        slug='con2', username='jdoe', password='secret', groupname='group2', provide_sender=True
+    )
+    assert OrangeSMSGateway.objects.get(slug='con1').provide_sender == False
+    assert OrangeSMSGateway.objects.get(slug='con2').provide_sender == True
+
+    # ensure migration fixes state
+    executor = MigrationExecutor(connection)
+    executor.migrate(migrate_to)
+    executor.loader.build_graph()
+    apps = executor.loader.project_state(migrate_to).apps
+
+    OrangeSMSGateway = apps.get_model('orange', 'OrangeSMSGateway')
+    assert OrangeSMSGateway.objects.get(slug='con1').default_sender == True
+    assert OrangeSMSGateway.objects.get(slug='con2').default_sender == False
-- 
2.30.2

