Projet

Général

Profil

0001-wf-add-external-workflow-action-40204.patch

Voir les différences:

Subject: [PATCH] wf: add external workflow action (#40204)

 tests/test_admin_pages.py           |  72 ++++++++++-
 tests/test_workflow_import.py       |  41 +++++-
 tests/test_workflows.py             | 191 ++++++++++++++++++++++++++-
 wcs/admin/workflows.py              |   1 +
 wcs/carddef.py                      |   2 +-
 wcs/qommon/static/css/dc2/admin.css |   8 ++
 wcs/wf/external_workflow.py         | 193 ++++++++++++++++++++++++++++
 wcs/workflows.py                    |  26 ++++
 8 files changed, 530 insertions(+), 4 deletions(-)
 create mode 100644 wcs/wf/external_workflow.py
tests/test_admin_pages.py
1210 1210
    resp = resp.forms[0].submit()
1211 1211
    resp = resp.follow()
1212 1212
    assert len(FormDef.get(1).fields) == 0
1213
 
1213

  
1214

  
1214 1215
def test_form_duplicate_field(pub):
1215 1216
    user = create_superuser(pub)
1216 1217
    create_role()
......
3502 3503
    assert Workflow.get(workflow.id).global_actions[0].triggers[0].timeout == '-2'
3503 3504

  
3504 3505

  
3506
def test_workflows_global_actions_external_workflow_triggers(pub):
3507
    create_superuser(pub)
3508

  
3509
    Workflow.wipe()
3510
    workflow = Workflow(name='foo')
3511
    workflow.store()
3512

  
3513
    app = login(get_app(pub))
3514
    resp = app.get('/backoffice/workflows/%s/' % workflow.id)
3515
    resp = resp.click('add global action')
3516
    resp.forms[0]['name'] = 'Global Action with External workflow trigger'
3517

  
3518
    resp = resp.forms[0].submit('submit')
3519
    resp = resp.follow()
3520

  
3521
    # adding an external trigger
3522
    resp.forms[1]['type'] = 'External workflow'
3523
    resp = resp.forms[1].submit()
3524
    resp = resp.follow()
3525

  
3526
    assert 'External workflow (not configured)' in resp.text
3527
    resp = resp.click(href='triggers/%s/' % Workflow.get(workflow.id).global_actions[0].triggers[1].id, index=0)
3528
    resp.form['event_name'] = ''
3529
    resp = resp.form.submit()
3530
    assert 'required field' in resp.text
3531
    resp.form['event_name'] = 'Test'
3532
    resp = resp.form.submit('submit').follow()
3533
    assert Workflow.get(workflow.id).global_actions[0].triggers[1].event_name == 'Test'
3534

  
3535

  
3536
def test_workflows_global_actions_external_workflow_action(pub):
3537
    create_superuser(pub)
3538
    Workflow.wipe()
3539

  
3540
    wf = Workflow(name='external')
3541
    action = wf.add_global_action('Global action')
3542
    trigger = action.append_trigger('external_workflow')
3543
    trigger.event_name = 'test'
3544
    item = action.append_item('remove')
3545
    wf.store()
3546

  
3547
    formdef = FormDef()
3548
    formdef.name = 'external'
3549
    formdef.workflow = wf
3550
    formdef.store()
3551
    workflow = Workflow(name='foo')
3552
    st = workflow.add_status('New')
3553
    workflow.store()
3554

  
3555
    app = login(get_app(pub))
3556
    resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st.id))
3557
    resp.forms[0]['action-formdata-action'] = 'External workflow'
3558
    resp = resp.forms[0].submit().follow()
3559
    assert 'External workflow (not completed)' in resp.text
3560

  
3561
    resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (workflow.id, st.id))
3562
    resp.forms[0]['slug'] = 'formdef:%s' % formdef.url_name
3563
    resp = resp.forms[0].submit('submit').follow().follow()
3564
    assert 'External workflow (not completed)' in resp.text
3565
    resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (workflow.id, st.id))
3566
    assert resp.forms[0]['target_object$auto'].checked
3567
    resp.forms[0]['target_object$auto'].checked = False
3568
    resp = resp.forms[0].submit('submit')
3569
    assert "Auto or object identifier should be filled" in resp
3570
    resp.forms[0]['target_object$auto'].checked = True
3571
    resp.forms[0]['event'] = trigger.id
3572
    assert 'External workflow (event ' in resp.text
3573

  
3574

  
3505 3575
def test_workflows_criticality_levels(pub):
3506 3576
    create_superuser(pub)
3507 3577
    create_role()
tests/test_workflow_import.py
14 14
    Workflow, CommentableWorkflowStatusItem, WorkflowCriticalityLevel,
15 15
    WorkflowBackofficeFieldsFormDef, SendmailWorkflowStatusItem,
16 16
    SendSMSWorkflowStatusItem, WorkflowImportError, ChoiceWorkflowStatusItem,
17
    JumpOnSubmitWorkflowStatusItem)
17
    JumpOnSubmitWorkflowStatusItem, WorkflowGlobalActionExternalWorkflowTrigger)
18 18
from wcs.wf.wscall import WebserviceCallStatusItem
19 19
from wcs.wf.dispatch import DispatchWorkflowStatusItem
20 20
from wcs.wf.register_comment import RegisterCommenterWorkflowStatusItem
......
22 22
from wcs.wf.backoffice_fields import SetBackofficeFieldsWorkflowStatusItem
23 23
from wcs.wf.redirect_to_url import RedirectToUrlWorkflowStatusItem
24 24
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping
25
from wcs.wf.external_workflow import ExternalWorkflowGlobalAction, TargetObject
25 26
from wcs.roles import Role
26 27
from wcs.fields import StringField, FileField
27 28

  
......
753 754
    wf.store()
754 755

  
755 756
    assert_import_export_works(wf, include_id=True)
757

  
758

  
759
def test_external_workflow(pub):
760
    target_wf = Workflow(name='External global action')
761
    action = target_wf.add_global_action('Delete', 'delete')
762
    trigger = action.append_trigger('external_workflow')
763
    trigger.event_name = 'Cleanup'
764
    target_wf.store()
765

  
766
    target_formdef = FormDef()
767
    target_formdef.name = 'target form'
768
    target_formdef.workflow = target_wf
769
    target_formdef.store()
770

  
771
    wf = Workflow(name='External workflow call')
772
    st1 = wf.add_status('New')
773
    st2 = wf.add_status('Call external workflow')
774

  
775
    jump = ChoiceWorkflowStatusItem()
776
    jump.id = '_external'
777
    jump.label = 'Cleanup'
778
    jump.by = ['_submitter']
779
    jump.status = st2.id
780
    jump.parent = st1
781
    st1.items.append(jump)
782

  
783
    external_workflow = ExternalWorkflowGlobalAction()
784
    external_workflow.id = '_external_workflow'
785
    external_workflow.slug = 'formdef:%s' % target_formdef.url_name
786
    external_workflow.event = trigger.id
787

  
788
    external_workflow.target_object = TargetObject()
789
    external_workflow.parent = st2
790
    st2.items.append(external_workflow)
791

  
792
    wf.store()
793

  
794
    assert_import_export_works(wf, include_id=True)
tests/test_workflows.py
34 34
        CommentableWorkflowStatusItem, ChoiceWorkflowStatusItem,
35 35
        DisplayMessageWorkflowStatusItem,
36 36
        AbortActionException, WorkflowCriticalityLevel,
37
        AttachmentEvolutionPart, WorkflowBackofficeFieldsFormDef)
37
        AttachmentEvolutionPart, WorkflowBackofficeFieldsFormDef,
38
        perform_items)
38 39
from wcs.wf.aggregation_email import (AggregationEmailWorkflowStatusItem,
39 40
        AggregationEmail, send_aggregation_emails)
40 41
from wcs.wf.anonymise import AnonymiseWorkflowStatusItem
......
55 56
from wcs.wf.notification import SendNotificationWorkflowStatusItem
56 57
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping
57 58
from wcs.wf.create_carddata import CreateCarddataWorkflowStatusItem
59
from wcs.wf.external_workflow import ExternalWorkflowGlobalAction, TargetObject
58 60

  
59 61

  
60 62
from utilities import (create_temporary_pub, MockSubstitutionVariables,
......
4632 4634
    assert carddef.data_class().count() == 0
4633 4635
    formdata.perform_workflow()
4634 4636
    assert carddef.data_class().count() == 0
4637

  
4638

  
4639
def test_call_external_workflow_by_object_expression(pub):
4640
    FormDef.wipe()
4641
    LoggedError.wipe()
4642

  
4643
    external_formdef = FormDef()
4644
    external_formdef.name = 'External Form'
4645
    external_formdef.fields = [
4646
        StringField(id='0', label='string', varname='foo_string'),
4647
    ]
4648
    external_wf = Workflow(name='External Workflow')
4649
    action = external_wf.add_global_action('Delete', 'delete')
4650
    action.append_item('remove')
4651
    trigger = action.append_trigger('external_workflow')
4652
    trigger.event_name = 'delete'
4653
    external_wf.store()
4654

  
4655
    external_formdef.workflow = external_wf
4656
    external_formdef.store()
4657

  
4658
    wf = Workflow(name='External call')
4659
    st1 = wf.add_status('Call external workflow')
4660
    external_wf_action = ExternalWorkflowGlobalAction()
4661
    external_wf_action.slug = 'formdef:%s' % external_formdef.url_name
4662
    external_wf_action.event = 'unknown'
4663
    external_wf_action.target_object = TargetObject(False, '{{ form_var_target_id }}')
4664
    external_wf_action.parent = st1
4665
    st1.items.append(external_wf_action)
4666
    wf.store()
4667

  
4668
    formdef = FormDef()
4669
    formdef.name = 'External call form'
4670
    formdef.fields = [
4671
        StringField(id='0', label='string', varname='target_id'),
4672
    ]
4673
    formdef.workflow = wf
4674
    formdef.store()
4675

  
4676
    # unknown trigger
4677
    formdata = formdef.data_class()()
4678
    formdata.data = {'0': 'whatever'}
4679
    formdata.store()
4680
    formdata.just_created()
4681
    formdata.perform_workflow()
4682

  
4683
    assert LoggedError.count() == 1
4684
    logged_error = LoggedError.select()[0]
4685
    assert logged_error.summary == 'Could not find trigger "unknown"'
4686

  
4687
    # unknown object id
4688
    LoggedError.wipe()
4689

  
4690
    new_wf = Workflow(name='New external call')
4691
    st1 = new_wf.add_status('Call external workflow')
4692
    external_wf_action.event = trigger.id
4693
    st1.items.append(external_wf_action)
4694
    new_wf.store()
4695

  
4696
    formdef.workflow = new_wf
4697
    formdef.store()
4698

  
4699
    formdata = formdef.data_class()()
4700
    formdata.data = {'0': '42'}
4701
    formdata.store()
4702
    formdata.just_created()
4703
    formdata.perform_workflow()
4704

  
4705
    assert LoggedError.count() == 1
4706
    logged_error = LoggedError.select()[0]
4707
    assert logged_error.summary == 'Could not find object FormDef by id 42'
4708
    assert logged_error.exception_class == 'KeyError'
4709
    assert logged_error.expression == '{{ form_var_target_id }}'
4710

  
4711
    # no errors
4712
    LoggedError.wipe()
4713
    external_formdata = external_formdef.data_class()()
4714
    external_formdata.data = {'0': 'test'}
4715
    external_formdata.store()
4716
    assert external_formdef.data_class().count() == 1
4717

  
4718
    formdata = formdef.data_class()()
4719
    formdata.data = {'0': external_formdata.id}
4720
    formdata.store()
4721
    formdata.just_created()
4722
    formdata.perform_workflow()
4723

  
4724
    assert LoggedError.count() == 0
4725
    assert external_formdef.data_class().count() == 0
4726

  
4727

  
4728
def test_call_external_workflow_by_linked_object(pub):
4729
    FormDef.wipe()
4730
    CardDef.wipe()
4731
    LoggedError.wipe()
4732

  
4733
    external_wf = Workflow(name='External Workflow')
4734
    st1 = external_wf.add_status(name='New')
4735
    action = external_wf.add_global_action('Delete', 'delete')
4736
    action.append_item('remove')
4737
    trigger = action.append_trigger('external_workflow')
4738
    trigger.event_name = 'delete'
4739
    external_wf.store()
4740

  
4741
    external_formdef = FormDef()
4742
    external_formdef.name = 'External Form'
4743
    external_formdef.fields = [
4744
        StringField(id='0', label='string', varname='form_string'),
4745
    ]
4746
    external_formdef.workflow = external_wf
4747
    external_formdef.store()
4748

  
4749
    external_carddef = CardDef()
4750
    external_carddef.name = 'External Card'
4751
    external_carddef.fields = [
4752
        StringField(id='0', label='string', varname='card_string'),
4753
    ]
4754
    external_carddef.workflow = external_wf
4755
    external_carddef.store()
4756

  
4757
    wf = Workflow(name='External actions')
4758
    st1 = wf.add_status('Create external formdata')
4759
    create_formdata = CreateFormdataWorkflowStatusItem()
4760
    create_formdata.label = 'create linked form'
4761
    create_formdata.formdef_slug = external_formdef.url_name
4762
    create_formdata.varname = 'created_form'
4763
    create_formdata.id = '_create_form'
4764
    mappings = [
4765
        Mapping(field_id='0', expression='{{ form_var_string }}')
4766
    ]
4767
    create_formdata.mappings = mappings
4768
    create_formdata.parent = st1
4769

  
4770
    create_carddata = CreateCarddataWorkflowStatusItem()
4771
    create_carddata.label = 'create linked card'
4772
    create_carddata.formdef_slug = external_carddef.url_name
4773
    create_carddata.varname = 'created_card'
4774
    create_carddata.id = '_create_card'
4775
    create_carddata.mappings = mappings
4776
    create_carddata.parent = st1
4777

  
4778
    st1.items.append(create_formdata)
4779
    st1.items.append(create_carddata)
4780

  
4781
    global_action = wf.add_global_action('Delete external linked object', 'delete')
4782
    action = global_action.append_item('external_workflow_global_action')
4783
    action.slug = 'formdef:%s' % external_formdef.url_name
4784
    action.event = trigger.id
4785
    action.target_object = TargetObject()
4786
    wf.store()
4787

  
4788
    formdef = FormDef()
4789
    formdef.name = 'External action form'
4790
    formdef.fields = [
4791
        StringField(id='0', label='string', varname='string'),
4792
    ]
4793
    formdef.workflow = wf
4794
    formdef.store()
4795

  
4796
    assert external_formdef.data_class().count() == 0
4797
    assert external_carddef.data_class().count() == 0
4798

  
4799
    formdata = formdef.data_class()()
4800
    formdata.data = {'0': 'test form'}
4801
    formdata.store()
4802
    formdata.just_created()
4803

  
4804
    perform_items([action], formdata)
4805
    assert LoggedError.count() == 1
4806
    logged_error = LoggedError.select()[0]
4807
    assert logged_error.summary == 'No linked FormDef object'
4808

  
4809
    LoggedError.wipe()
4810
    formdata.perform_workflow()
4811

  
4812
    assert external_formdef.data_class().count() == 1
4813
    assert external_carddef.data_class().count() == 1
4814
    perform_items([action], formdata)
4815
    assert LoggedError.count() == 0
4816
    assert external_formdef.data_class().count() == 0
4817
    assert external_carddef.data_class().count() == 1
4818

  
4819
    perform_items([action], formdata)
4820
    assert LoggedError.count() == 1
4821
    logged_error = LoggedError.select()[0]
4822
    assert logged_error.summary == 'Linked object "External Form #1-1" does not exist'
4823
    assert logged_error.exception_class == 'KeyError'
wcs/admin/workflows.py
1301 1301
            ('timeout', _('Automatic')),
1302 1302
            ('manual', _('Manual')),
1303 1303
            ('webservice', _('Webservice')),
1304
            ('external_workflow', _('External workflow')),
1304 1305
        ]
1305 1306
        form.add(SingleSelectWidget, 'type', title=_('Type'),
1306 1307
                required=True, options=available_triggers)
wcs/carddef.py
22 22

  
23 23
from wcs.carddata import CardData
24 24
from wcs.formdef import FormDef
25
from wcs.workflows import Workflow
26 25

  
27 26
if not hasattr(types, 'ClassType'):
28 27
    types.ClassType = type
......
81 80
    @classmethod
82 81
    def get_default_workflow(cls):
83 82
        from wcs.workflows import EditableWorkflowStatusItem, ChoiceWorkflowStatusItem
83
        from wcs.workflows import Workflow
84 84
        from wcs.wf.remove import RemoveWorkflowStatusItem
85 85
        workflow = Workflow(name=_('Default (cards)'))
86 86
        workflow.id = '_carddef_default'
wcs/qommon/static/css/dc2/admin.css
1878 1878
	width: 40%;
1879 1879
	min-width: 10em;
1880 1880
}
1881

  
1882
.ObjectWidget > .content {
1883
	padding-left: 2em;
1884
}
1885

  
1886
.ObjectWidget br.content {
1887
	display: none;
1888
}
wcs/wf/external_workflow.py
1
# w.c.s. - web application for online forms
2
# Copyright (C) 2005-2016  Entr'ouvert
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16

  
17
import time
18
import xml.etree.ElementTree as ET
19

  
20
from quixote import get_request, get_session, get_publisher
21
from quixote.html import htmltext
22

  
23
from django.utils.functional import cached_property
24

  
25
from wcs.qommon import _
26
from wcs.qommon.form import (SingleSelectWidget, ComputedExpressionWidget,
27
                             CompositeWidget, CheckboxWidget)
28

  
29
from wcs.logged_errors import LoggedError
30
from wcs.workflows import WorkflowStatusItem, perform_items, register_item_class
31
from wcs.workflows import WorkflowGlobalActionExternalWorkflowTrigger, Workflow
32
from wcs.wf.create_formdata import LinkedFormdataEvolutionPart
33
from wcs.carddef import CardDef
34
from wcs.formdef import FormDef
35

  
36

  
37
class TargetObject(object):
38

  
39
    def __init__(self, auto=True, expression=None):
40
        self.auto = auto
41
        self.expression = expression
42

  
43

  
44
class ObjectWidget(CompositeWidget):
45
    def __init__(self, name, value=None,  **kwargs):
46
        value = value or TargetObject(True, '')
47
        super(ObjectWidget, self).__init__(name, value, **kwargs)
48

  
49
        self.add(CheckboxWidget,
50
                 name='auto',
51
                 title=_('Auto'),
52
                 hint=_('Reference linked object to current data'),
53
                 value=value.auto)
54
        self.add(ComputedExpressionWidget,
55
                 name='expression',
56
                 title=_('Or identifier'),
57
                 value=value.expression,
58
                 hint=_('Object identifier expression.'))
59

  
60
    def _parse(self, request):
61
        super(ObjectWidget, self)._parse(request)
62
        if self.get('auto') is False and not self.get('expression'):
63
            self.error = _('Auto or object identifier should be filled')
64
            return
65
        if self.get('auto') is not None:
66
            self.value = TargetObject(self.get('auto'), self.get('expression') or '')
67
        else:
68
            self.value = None
69

  
70

  
71
class ExternalWorkflowGlobalAction(WorkflowStatusItem):
72

  
73
    description = _('External workflow')
74
    key = 'external_workflow_global_action'
75
    category = 'formdata-action'
76

  
77
    slug = None
78
    target_object = None
79
    event = None
80

  
81
    def get_workflow_external_triggers(self, workflow):
82
        triggers = []
83
        for action in workflow.global_actions or []:
84
            for trigger in action.triggers or []:
85
                if isinstance(trigger, WorkflowGlobalActionExternalWorkflowTrigger):
86
                    triggers.append(trigger)
87
        return triggers
88

  
89
    def get_object_def(self):
90
        object_type, slug = self.slug.split(':')
91
        if object_type == 'formdef':
92
            object_class = FormDef
93
        elif object_type == 'carddef':
94
            object_class = CardDef
95
        try:
96
            return object_class.get_by_urlname(slug)
97
        except Exception as e:
98
            pass
99

  
100
    def get_trigger(self, workflow):
101
        for trigger in self.get_workflow_external_triggers(workflow):
102
            if trigger.id == self.event:
103
                return trigger
104

  
105
    def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
106
        super(ExternalWorkflowGlobalAction, self).add_parameters_widgets(
107
            form, parameters, prefix=prefix, formdef=formdef)
108

  
109
        if 'slug' in parameters:
110
            objects = [(None, '---', '')]
111
            for wf in Workflow.select():
112
                if self.get_workflow_external_triggers(wf):
113
                    for objectdef in wf.formdefs() + wf.carddefs():
114
                        object_slug = '%s:%s' % (objectdef.__class__.__name__.lower(),
115
                                                 objectdef.url_name)
116
                        objects += [(object_slug, objectdef.name, object_slug)]
117
            objects.sort(key=lambda x: x[1])
118
            form.add(SingleSelectWidget, 'slug',
119
                     title=_('Object type'),
120
                     value=self.slug,
121
                     options=objects)
122

  
123
        if 'target_object' in parameters and self.slug:
124
            form.add(ObjectWidget, '%starget_object' % prefix,
125
                     title=_('Target object'), value=self.target_object)
126

  
127
        if 'event' in parameters and self.slug:
128
            events = [(None, '---', '')]
129
            obj_def = self.get_object_def()
130
            for trigger in self.get_workflow_external_triggers(obj_def.workflow):
131
                events += [(trigger.id, trigger.event_name, trigger.id)]
132
            form.add(SingleSelectWidget, 'event',
133
                     title=_('Event'),
134
                     value=self.event,
135
                     options=events)
136

  
137
    def get_line_details(self):
138
        if self.slug and self.event:
139
            objectdef = self.get_object_def()
140
            trigger = self.get_trigger(objectdef.workflow)
141
            if trigger and objectdef:
142
                return _('event "%s" on %s' % (trigger.event_name, objectdef.name))
143
        return _('not completed')
144

  
145
    def get_parameters(self):
146
        return ('slug', 'target_object', 'event')
147

  
148
    def target_object__export_to_xml(self, parent, charset, include_id=False):
149
        container = ET.SubElement(parent, 'target_object')
150
        container.attrib['auto'] = self.target_object.auto
151
        container.text = self.target_object.expression
152

  
153
    def target_object__init_with_xml(self, container, charset, include_id=False):
154
        self.target_object = TargetObject(container.attrib['auto'], container.text)
155

  
156
    def perform(self, formdata):
157
        objectdef = self.get_object_def()
158
        if not objectdef:
159
            return
160

  
161
        trigger = self.get_trigger(objectdef.workflow)
162
        if not trigger:
163
            LoggedError.record('Could not find trigger "%s"' % self.event,
164
                               formdata=formdata)
165
            return
166

  
167
        if not self.target_object.auto:
168
            identifier = self.compute(self.target_object.expression, formdata=formdata)
169
            try:
170
                target_data = objectdef.data_class().get(identifier)
171
            except KeyError as e:
172
                LoggedError.record('Could not find object %s by id %s' % (objectdef.__class__.__name__,
173
                                                                          identifier),
174
                                   expression=self.target_object.expression,
175
                                   formdata=formdata, exception=e)
176
                return
177
        else:
178
            for part in formdata.iter_evolution_parts():
179
                if isinstance(part, LinkedFormdataEvolutionPart) and part.formdef_class == objectdef.__class__:
180
                    target_data = part._formdata
181
                    break
182
            else:
183
                LoggedError.record('No linked %s object' % (objectdef.__class__.__name__),
184
                                   formdata=formdata)
185
                return
186
        try:
187
            perform_items(trigger.parent.items, target_data)
188
        except KeyError as e:
189
            LoggedError.record('Linked object "%s" does not exist' % target_data.get_display_name(),
190
                               formdata=formdata, exception=e)
191

  
192

  
193
register_item_class(ExternalWorkflowGlobalAction)
wcs/workflows.py
44 44
from .roles import Role, logged_users_role, get_user_roles
45 45
from .fields import FileField
46 46
from .formdef import FormDef
47
from .carddef import CardDef
47 48
from .formdata import Evolution
48 49

  
49 50
if not __name__.startswith('wcs.') and not __name__ == "__main__":
......
834 835
    def formdefs(self, **kwargs):
835 836
        return list(FormDef.select(lambda x: x.workflow_id == self.id, **kwargs))
836 837

  
838
    def carddefs(self, **kwargs):
839
        return list(CardDef.select(lambda x: x.workflow_id == self.id, **kwargs))
840

  
837 841

  
838 842
class XmlSerialisable(object):
839 843
    node_name = None
......
1307 1311
        return [('hooks', WorkflowGlobalActionWebserviceHooksDirectory(formdata))]
1308 1312

  
1309 1313

  
1314
class WorkflowGlobalActionExternalWorkflowTrigger(WorkflowGlobalActionManualTrigger):
1315
    key = 'external_workflow'
1316
    event_name = None
1317

  
1318
    def get_parameters(self):
1319
        return ('event_name',)
1320

  
1321
    def render_as_line(self):
1322
        if self.event_name:
1323
            return _('External workflow (by event "%s")') % self.event_name
1324
        else:
1325
            return _('External workflow (not configured)')
1326

  
1327
    def form(self, workflow):
1328
        form = Form(enctype='multipart/form-data')
1329
        form.add(StringWidget, 'event_name', title=_('Event name'),
1330
                 required=True, value=self.event_name)
1331
        return form
1332

  
1333

  
1310 1334
class WorkflowGlobalAction(object):
1311 1335
    id = None
1312 1336
    name = None
......
1336 1360
            'manual': WorkflowGlobalActionManualTrigger,
1337 1361
            'timeout': WorkflowGlobalActionTimeoutTrigger,
1338 1362
            'webservice': WorkflowGlobalActionWebserviceTrigger,
1363
            'external_workflow': WorkflowGlobalActionExternalWorkflowTrigger,
1339 1364
        }
1340 1365
        o = trigger_types.get(type)()
1341 1366
        if not self.triggers:
......
2927 2952
    from .wf import notification
2928 2953
    from .wf import create_formdata
2929 2954
    from .wf import create_carddata
2955
    from .wf import external_workflow
2930 2956

  
2931 2957
from .wf.export_to_model import ExportToModel
2932
-