Projet

Général

Profil

0001-misc-remap-statuses-in-a-transaction-38579.patch

Benjamin Dauvergne, 26 novembre 2020 18:45

Télécharger (8,06 ko)

Voir les différences:

Subject: [PATCH] misc: remap statuses in a transaction (#38579)

 tests/admin_pages/test_form.py |  7 ++++++
 wcs/admin/forms.py             | 39 +++++++++++-------------------
 wcs/formdef.py                 | 43 ++++++++++++++++++++++++++++++++++
 wcs/sql.py                     | 19 +++++++++++++++
 4 files changed, 83 insertions(+), 25 deletions(-)
tests/admin_pages/test_form.py
513 513
    formdata2.status = 'draft'
514 514
    formdata2.store()
515 515

  
516
    formdata3 = data_class()
517
    formdata3.status = 'wf-1'
518
    formdata3.store()
519

  
516 520
    Workflow.wipe()
517 521
    workflow = Workflow(name='Workflow One')
518 522
    workflow.store()
......
534 538
        assert len(resp.forms[0]['mapping-%s' % status.id].options) == 1
535 539
    assert data_class.get(formdata1.id).status == 'wf-new'
536 540
    assert data_class.get(formdata2.id).status == 'draft'
541
    assert data_class.get(formdata3.id).status == 'wf-1'
537 542
    resp = resp.forms[0].submit()
538 543
    assert data_class.get(formdata1.id).status == 'wf-finished'
539 544
    assert data_class.get(formdata2.id).status == 'draft'
545
    assert data_class.get(formdata3.id).status == 'wf-1-old-_default'
540 546

  
541 547
    # change to another workflow, with no mapping change
542 548
    workflow2 = workflow
......
557 563
    resp = resp.forms[0].submit()
558 564
    assert data_class.get(formdata1.id).status == 'wf-finished'
559 565
    assert data_class.get(formdata2.id).status == 'draft'
566
    assert data_class.get(formdata3.id).status == 'wf-1-old-_default'
560 567

  
561 568

  
562 569
def test_form_submitter_roles(pub):
wcs/admin/forms.py
864 864
                if workflow_id is None:
865 865
                    workflow_id = self.formdef_default_workflow
866 866
                return redirect('workflow-status-remapping?new=%s' % workflow_id)
867
            self.formdef.workflow_id = workflow_id
868
            self.formdef.store(comment=_('Workflow change'))
867
            self.formdef.change_workflow(workflow_id)
869 868
            return redirect('.')
870 869

  
871 870
    def workflow_status_remapping(self):
......
898 897
            r += form.render()
899 898
            return r.getvalue()
900 899
        else:
901
            get_logger().info('admin - form "%s", workflow is now "%s" (was "%s")' % (
902
                self.formdef.name, new_workflow.name, self.formdef.workflow.name))
903
            self.workflow_status_remapping_submit(form)
904
            if new_workflow.id == self.formdef_default_workflow:
905
                self.formdef.workflow_id = None
906
            else:
907
                self.formdef.workflow_id = new_workflow.id
908
            self.formdef.store(comment=_('Workflow change'))
909
            # instruct formdef to update its security rules
910
            self.formdef.data_class().rebuild_security()
911
            return redirect('.')
900
            return self.workflow_status_remapping_submit(form, new_workflow)
901

  
902
    def workflow_status_remapping_submit(self, form, new_workflow):
903
        get_logger().info('admin - form "%s", workflow is now "%s" (was "%s")' % (
904
            self.formdef.name, new_workflow.name, self.formdef.workflow.name))
912 905

  
913
    def workflow_status_remapping_submit(self, form):
914 906
        status_mapping = {}
915 907
        for status in self.formdef.workflow.possible_status:
916
            status_mapping['wf-%s' % status.id] = 'wf-%s' % \
917
                    form.get_widget('mapping-%s' % status.id).parse()
918
        if any([x[0] != x[1] for x in status_mapping.items()]):
919
            # if there are status changes, update all formdatas
920
            status_mapping.update({'draft': 'draft'})
921
            for item in self.formdef.data_class().select():
922
                item.status = status_mapping.get(item.status)
923
                if item.evolution:
924
                    for evo in item.evolution:
925
                        evo.status = status_mapping.get(evo.status)
926
                item.store()
908
            status_mapping[status.id] = form.get_widget('mapping-%s' % status.id).parse()
909

  
910
        if new_workflow.id == self.formdef_default_workflow:
911
            new_workflow_id = None
912
        else:
913
            new_workflow_id = new_workflow.id
914
        self.formdef.change_workflow(new_workflow_id, status_mapping)
915
        return redirect('.')
927 916

  
928 917
    def get_preview(self):
929 918
        form = Form(action='#', use_tokens=False)
wcs/formdef.py
1517 1517
        # chunk contains the fields.
1518 1518
        return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2)
1519 1519

  
1520
    def change_workflow(self, new_workflow_id, status_mapping=None):
1521
        old_workflow = self.get_workflow()
1522

  
1523
        formdata_count = self.data_class().count()
1524
        if formdata_count:
1525
            assert status_mapping, 'status mapping is required if there are formdatas'
1526
            assert all(status.id in status_mapping for status in old_workflow.possible_status), (
1527
                'a status was not mapped'
1528
            )
1529

  
1530
            mapping = {}
1531
            for old_status, new_status in status_mapping.items():
1532
                mapping['wf-%s' % old_status] = 'wf-%s' % new_status
1533
            mapping['draft'] = 'draft'
1534

  
1535
            if any([x[0] != x[1] for x in mapping.items()]):
1536
                # if there are status changes, update all formdatas
1537
                if get_publisher().is_using_postgresql():
1538
                    from . import sql
1539
                    sql.formdef_remap_statuses(self, mapping)
1540
                else:
1541
                    def map_status(status):
1542
                        if status is None:
1543
                            return None
1544
                        elif status in mapping:
1545
                            return mapping[status]
1546
                        elif '-old-' in status:
1547
                            return status
1548
                        else:
1549
                            return '%s-old-%s' % (status, old_workflow.id)
1550
                    for formdata in self.data_class().select():
1551
                        formdata.status = map_status(formdata.status)
1552
                        if formdata.evolution:
1553
                            for evo in formdata.evolution:
1554
                                evo.status = map_status(evo.status)
1555
                        formdata.store()
1556

  
1557
        self.workflow_id = new_workflow_id
1558
        self.store(comment=_('Workflow change'))
1559
        if formdata_count:
1560
            # instruct formdef to update its security rules
1561
            self.data_class().rebuild_security()
1562

  
1520 1563

  
1521 1564
from .qommon.admin.emails import EmailsDirectory
1522 1565

  
wcs/sql.py
2874 2874

  
2875 2875
    conn.commit()
2876 2876
    cur.close()
2877

  
2878

  
2879
@guard_postgres
2880
def formdef_remap_statuses(formdef, mapping):
2881
    conn, cur = get_connection_and_cursor()
2882
    table_name = get_formdef_table_name(formdef)
2883
    evolutions_table_name = table_name + '_evolutions'
2884
    old_workflow_id = formdef.workflow_id or '_default'
2885
    case_expression = '(CASE '
2886
    case_expression += 'WHEN status IS NULL THEN NULL '
2887
    for old_id, new_id in mapping.items():
2888
        case_expression += "WHEN status = '%s' THEN '%s' " % (old_id, new_id)
2889
    case_expression += " WHEN status LIKE '%-old-%' THEN status "
2890
    case_expression += " ELSE (status || '-old-%s') END)" % old_workflow_id
2891

  
2892
    cur.execute('BEGIN')
2893
    cur.execute('UPDATE %s SET status = %s' % (table_name, case_expression))
2894
    cur.execute('UPDATE %s SET status = %s' % (evolutions_table_name, case_expression))
2895
    cur.execute('COMMIT')
2877
-