Projet

Général

Profil

0001-misc-split-workflow-tests.patch

Lauréline Guérin, 20 octobre 2022 11:01

Télécharger (103 ko)

Voir les différences:

Subject: [PATCH 1/3] misc: split workflow tests

 tests/workflow/test_all.py              | 1427 ----------------------
 tests/workflow/test_backoffice_field.py | 1484 +++++++++++++++++++++++
 2 files changed, 1484 insertions(+), 1427 deletions(-)
 create mode 100644 tests/workflow/test_backoffice_field.py
tests/workflow/test_all.py
4477 4477
        assert rsps.calls[-1].request.body == '{"bar": "2020-01-01"}'
4478 4478

  
4479 4479

  
4480
def test_set_backoffice_field(http_requests, pub):
4481
    Workflow.wipe()
4482
    FormDef.wipe()
4483
    wf = Workflow(name='xxx')
4484
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
4485
    wf.backoffice_fields_formdef.fields = [
4486
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
4487
    ]
4488
    st1 = wf.add_status('Status1')
4489
    wf.store()
4490

  
4491
    formdef = FormDef()
4492
    formdef.name = 'baz'
4493
    formdef.fields = [
4494
        StringField(id='00', label='String', type='string', varname='string'),
4495
        StringField(id='01', label='Other string', type='string', varname='other'),
4496
    ]
4497
    formdef.workflow_id = wf.id
4498
    formdef.store()
4499

  
4500
    formdata = formdef.data_class()()
4501
    formdata.data = {'00': 'HELLO'}
4502
    formdata.just_created()
4503
    formdata.store()
4504
    pub.substitutions.feed(formdata)
4505

  
4506
    item = SetBackofficeFieldsWorkflowStatusItem()
4507
    item.parent = st1
4508

  
4509
    assert item.render_as_line() == 'Backoffice Data'
4510
    assert item.get_jump_label('plop') == 'Backoffice Data'
4511
    item.label = 'label'
4512
    assert item.render_as_line() == 'Backoffice Data (label)'
4513
    assert item.get_jump_label('plop') == 'Backoffice Data "label"'
4514

  
4515
    item.perform(formdata)
4516
    formdata = formdef.data_class().get(formdata.id)
4517
    assert formdata.data.get('bo1') is None
4518

  
4519
    item.fields = [{'field_id': 'bo1', 'value': '=form_var_string'}]
4520
    item.perform(formdata)
4521
    formdata = formdef.data_class().get(formdata.id)
4522
    assert formdata.data['bo1'] == 'HELLO'
4523

  
4524
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_string }} WORLD'}]
4525
    item.perform(formdata)
4526
    formdata = formdef.data_class().get(formdata.id)
4527
    assert formdata.data['bo1'] == 'HELLO WORLD'
4528

  
4529
    item.fields = [{'field_id': 'bo1', 'value': '[form_var_string] GOODBYE'}]
4530
    item.perform(formdata)
4531
    formdata = formdef.data_class().get(formdata.id)
4532
    assert formdata.data['bo1'] == 'HELLO GOODBYE'
4533

  
4534
    item.fields = [{'field_id': 'bo1', 'value': '{{ form.var.string }} LAZY'}]
4535
    item.perform(formdata)
4536
    formdata = formdef.data_class().get(formdata.id)
4537
    assert formdata.data['bo1'] == 'HELLO LAZY'
4538

  
4539
    item.fields = [{'field_id': 'bo1', 'value': '=form.var.string'}]  # lazy python
4540
    item.perform(formdata)
4541
    formdata = formdef.data_class().get(formdata.id)
4542
    assert formdata.data['bo1'] == 'HELLO'
4543

  
4544
    item.fields = [{'field_id': 'bo1', 'value': '=vars().get("form_var_string") + " PLOP"'}]
4545
    item.perform(formdata)
4546
    formdata = formdef.data_class().get(formdata.id)
4547
    assert formdata.data['bo1'] == 'HELLO PLOP'
4548

  
4549
    item.fields = [
4550
        {'field_id': 'bo1', 'value': '=vars().get("form_var_other") or vars().get("form_var_string")'}
4551
    ]
4552
    item.perform(formdata)
4553
    formdata = formdef.data_class().get(formdata.id)
4554
    assert formdata.data['bo1'] == 'HELLO'
4555

  
4556
    item.fields = [{'field_id': 'bo1', 'value': '=vars().get("form_var_bouh", "X") + " PLOP"'}]
4557
    item.perform(formdata)
4558
    formdata = formdef.data_class().get(formdata.id)
4559
    assert formdata.data['bo1'] == 'X PLOP'
4560

  
4561
    item.fields = [{'field_id': 'bo1', 'value': None}]
4562
    item.perform(formdata)
4563
    formdata = formdef.data_class().get(formdata.id)
4564
    assert formdata.data['bo1'] is None
4565

  
4566
    item.fields = [{'field_id': 'bo1', 'value': ''}]
4567
    item.perform(formdata)
4568
    formdata = formdef.data_class().get(formdata.id)
4569
    assert formdata.data['bo1'] is None
4570

  
4571
    # check a value computed as the empty string is stored as an empty string, not None
4572
    item.fields = [{'field_id': 'bo1', 'value': '=""'}]
4573
    item.perform(formdata)
4574
    formdata = formdef.data_class().get(formdata.id)
4575
    assert formdata.data['bo1'] == ''
4576
    item.fields = [{'field_id': 'bo1', 'value': '{{ does_not_exist }}'}]
4577
    item.perform(formdata)
4578
    formdata = formdef.data_class().get(formdata.id)
4579
    assert formdata.data['bo1'] == ''
4580

  
4581
    assert pub.loggederror_class.count() == 0
4582

  
4583
    item.fields = [{'field_id': 'bo1', 'value': '= ~ invalid python ~'}]
4584
    item.perform(formdata)
4585
    formdata = formdef.data_class().get(formdata.id)
4586
    assert pub.loggederror_class.count() == 1
4587
    logged_error = pub.loggederror_class.select()[0]
4588
    assert logged_error.summary == 'Failed to compute Python expression'
4589
    assert logged_error.formdata_id == str(formdata.id)
4590
    assert logged_error.expression == ' ~ invalid python ~'
4591
    assert logged_error.expression_type == 'python'
4592
    assert logged_error.exception_class == 'SyntaxError'
4593
    assert logged_error.exception_message == 'invalid syntax (<string>, line 1)'
4594

  
4595
    pub.loggederror_class.wipe()
4596
    item.fields = [{'field_id': 'bo1', 'value': '{% if bad django %}'}]
4597
    item.perform(formdata)
4598
    formdata = formdef.data_class().get(formdata.id)
4599
    assert pub.loggederror_class.count() == 1
4600
    logged_error = pub.loggederror_class.select()[0]
4601
    assert logged_error.summary == 'Failed to compute template'
4602
    assert logged_error.formdata_id == str(formdata.id)
4603
    assert logged_error.expression == '{% if bad django %}'
4604
    assert logged_error.expression_type == 'template'
4605
    assert logged_error.exception_class == 'TemplateError'
4606
    assert logged_error.exception_message.startswith('syntax error in Django template')
4607

  
4608

  
4609
def test_set_backoffice_field_map(http_requests, pub):
4610
    Workflow.wipe()
4611
    FormDef.wipe()
4612
    wf = Workflow(name='xxx')
4613
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
4614
    wf.backoffice_fields_formdef.fields = [
4615
        MapField(id='bo1', label='1st backoffice field', type='map', varname='backoffice_blah'),
4616
    ]
4617
    st1 = wf.add_status('Status1')
4618
    wf.store()
4619

  
4620
    formdef = FormDef()
4621
    formdef.name = 'baz'
4622
    formdef.fields = [
4623
        MapField(id='1', label='Map1', type='map', varname='map1'),
4624
        MapField(id='2', label='Map2', type='map', varname='map2'),
4625
    ]
4626
    formdef.workflow_id = wf.id
4627
    formdef.store()
4628

  
4629
    formdata = formdef.data_class()()
4630
    formdata.data = {'1': '42;10', '2': None}
4631
    formdata.just_created()
4632
    formdata.store()
4633
    pub.substitutions.feed(formdata)
4634

  
4635
    item = SetBackofficeFieldsWorkflowStatusItem()
4636
    item.parent = st1
4637

  
4638
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_map1|default:"" }}'}]
4639
    item.perform(formdata)
4640
    formdata = formdef.data_class().get(formdata.id)
4641
    assert formdata.data.get('bo1') == '42;10'
4642

  
4643
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_map2|default:"" }}'}]
4644
    item.perform(formdata)
4645
    formdata = formdef.data_class().get(formdata.id)
4646
    assert formdata.data.get('bo1') is None
4647

  
4648
    assert pub.loggederror_class.count() == 0
4649

  
4650
    item.fields = [{'field_id': 'bo1', 'value': 'invalid value'}]
4651
    item.perform(formdata)
4652
    formdata = formdef.data_class().get(formdata.id)
4653
    assert pub.loggederror_class.count() == 1
4654
    logged_error = pub.loggederror_class.select()[0]
4655
    assert (
4656
        logged_error.summary
4657
        == "Failed to set Map field (bo1), error: invalid coordinates 'invalid value' (missing ;)"
4658
    )
4659
    assert logged_error.formdata_id == str(formdata.id)
4660
    assert logged_error.exception_class == 'SetValueError'
4661
    assert logged_error.exception_message == "invalid coordinates 'invalid value' (missing ;)"
4662
    pub.loggederror_class.wipe()
4663

  
4664
    item.fields = [{'field_id': 'bo1', 'value': 'XXX;YYY'}]
4665
    item.perform(formdata)
4666
    formdata = formdef.data_class().get(formdata.id)
4667
    assert pub.loggederror_class.count() == 1
4668
    logged_error = pub.loggederror_class.select()[0]
4669
    assert logged_error.summary == "Failed to set Map field (bo1), error: invalid coordinates 'XXX;YYY'"
4670
    assert logged_error.formdata_id == str(formdata.id)
4671
    assert logged_error.exception_class == 'SetValueError'
4672
    assert logged_error.exception_message == "invalid coordinates 'XXX;YYY'"
4673
    pub.loggederror_class.wipe()
4674

  
4675

  
4676
def test_set_backoffice_field_decimal(http_requests, pub):
4677
    Workflow.wipe()
4678
    FormDef.wipe()
4679
    wf = Workflow(name='xxx')
4680
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
4681
    wf.backoffice_fields_formdef.fields = [
4682
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
4683
    ]
4684
    st1 = wf.add_status('Status1')
4685
    wf.store()
4686

  
4687
    formdef = FormDef()
4688
    formdef.name = 'baz'
4689
    formdef.fields = [
4690
        StringField(id='1', label='String', type='string', varname='string'),
4691
    ]
4692
    formdef.workflow_id = wf.id
4693
    formdef.store()
4694

  
4695
    formdata = formdef.data_class()()
4696
    formdata.data = {'1': '1000'}
4697
    formdata.just_created()
4698
    formdata.store()
4699
    pub.substitutions.feed(formdata)
4700

  
4701
    item = SetBackofficeFieldsWorkflowStatusItem()
4702
    item.parent = st1
4703
    item.fields = [{'field_id': 'bo1', 'value': '{{ "100"|decimal }}'}]
4704
    item.perform(formdata)
4705
    assert formdef.data_class().get(formdata.id).data['bo1'] == '100'
4706

  
4707
    formdata.store()  # reset
4708
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_string|decimal }}'}]
4709
    item.perform(formdata)
4710
    assert formdef.data_class().get(formdata.id).data['bo1'] == '1000'
4711

  
4712

  
4713
def test_set_backoffice_field_file(http_requests, pub):
4714
    Workflow.wipe()
4715
    FormDef.wipe()
4716
    wf = Workflow(name='xxx')
4717
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
4718
    wf.backoffice_fields_formdef.fields = [
4719
        FileField(id='bo1', label='1st backoffice field', type='file', varname='backoffice_file'),
4720
        StringField(id='bo2', label='2nd backoffice field', type='string'),
4721
    ]
4722
    st1 = wf.add_status('Status1')
4723
    wf.store()
4724

  
4725
    formdef = FormDef()
4726
    formdef.name = 'baz'
4727
    formdef.fields = [
4728
        FileField(id='00', label='File', type='file', varname='file'),
4729
    ]
4730
    formdef.workflow_id = wf.id
4731
    formdef.store()
4732

  
4733
    item = SetBackofficeFieldsWorkflowStatusItem()
4734
    item.parent = st1
4735
    item.fields = [{'field_id': 'bo1', 'value': '=locals().get("form_var_file_raw")'}]
4736

  
4737
    # the file does not exist
4738
    formdata = formdef.data_class()()
4739
    formdata.data = {}
4740
    formdata.just_created()
4741
    formdata.store()
4742
    pub.substitutions.feed(formdata)
4743
    item.perform(formdata)
4744
    formdata = formdef.data_class().get(formdata.id)
4745
    assert formdata.data['bo1'] is None
4746

  
4747
    # store a PiclableUpload
4748
    upload = PicklableUpload('test.jpeg', 'image/jpeg')
4749
    with open(os.path.join(os.path.dirname(__file__), '..', 'image-with-gps-data.jpeg'), 'rb') as fd:
4750
        image_with_gps_data = fd.read()
4751
    upload.receive([image_with_gps_data])
4752

  
4753
    formdata = formdef.data_class()()
4754
    formdata.data = {'00': upload}
4755
    formdata.just_created()
4756
    formdata.store()
4757

  
4758
    pub.substitutions.feed(formdata)
4759
    item.perform(formdata)
4760

  
4761
    formdata = formdef.data_class().get(formdata.id)
4762
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
4763
    assert formdata.data['bo1'].content_type == 'image/jpeg'
4764
    assert formdata.data['bo1'].get_content() == image_with_gps_data
4765
    assert formdata.data['bo1'].get_base64_content() == base64.encodebytes(image_with_gps_data)
4766

  
4767
    # check with template string
4768
    formdata = formdef.data_class()()
4769
    formdata.data = {'00': upload}
4770
    formdata.just_created()
4771
    formdata.store()
4772

  
4773
    pub.substitutions.feed(formdata)
4774
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file_raw}}'}]
4775
    item.perform(formdata)
4776

  
4777
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
4778
    assert formdata.data['bo1'].content_type == 'image/jpeg'
4779
    assert formdata.data['bo1'].get_content() == image_with_gps_data
4780

  
4781
    # check with template string, without _raw
4782
    formdata = formdef.data_class()()
4783
    formdata.data = {'00': upload}
4784
    formdata.just_created()
4785
    formdata.store()
4786

  
4787
    pub.substitutions.feed(formdata)
4788
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file}}'}]
4789
    item.perform(formdata)
4790

  
4791
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
4792
    assert formdata.data['bo1'].content_type == 'image/jpeg'
4793
    assert formdata.data['bo1'].get_content() == image_with_gps_data
4794

  
4795
    # check |strip_metadata filter
4796
    formdata = formdef.data_class()()
4797
    formdata.data = {'00': upload}
4798
    formdata.just_created()
4799
    formdata.store()
4800

  
4801
    pub.substitutions.feed(formdata)
4802
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file|strip_metadata}}'}]
4803
    item.perform(formdata)
4804

  
4805
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
4806
    assert formdata.data['bo1'].content_type == 'image/jpeg'
4807
    assert b'JFIF' in formdata.data['bo1'].get_content()
4808
    assert b'<exif:XResolution>' not in formdata.data['bo1'].get_content()
4809

  
4810
    # check |rename_file filter
4811
    formdata = formdef.data_class()()
4812
    formdata.data = {'00': upload}
4813
    formdata.just_created()
4814
    formdata.store()
4815

  
4816
    pub.substitutions.feed(formdata)
4817
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file|rename_file:"foobar.jpeg"}}'}]
4818
    item.perform(formdata)
4819

  
4820
    assert formdata.data['bo1'].base_filename == 'foobar.jpeg'
4821
    assert formdata.data['bo1'].content_type == 'image/jpeg'
4822
    assert formdata.data['bo1'].get_content() == image_with_gps_data
4823

  
4824
    formdata = formdef.data_class()()
4825
    formdata.data = {'00': upload}
4826
    formdata.just_created()
4827
    formdata.store()
4828

  
4829
    pub.substitutions.feed(formdata)
4830
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file|rename_file:"foobar.$ext"}}'}]
4831
    item.perform(formdata)
4832

  
4833
    assert formdata.data['bo1'].base_filename == 'foobar.jpeg'
4834
    assert formdata.data['bo1'].content_type == 'image/jpeg'
4835
    assert formdata.data['bo1'].get_content() == image_with_gps_data
4836

  
4837
    # check |rename_file with invalid input
4838
    formdata = formdef.data_class()()
4839
    formdata.data = {'00': upload}
4840
    formdata.just_created()
4841
    formdata.store()
4842

  
4843
    pub.substitutions.feed(formdata)
4844

  
4845
    item.fields = [{'field_id': 'bo1', 'value': '{{"xxx"|rename_file:"foobar.jpeg"}}'}]
4846
    item.perform(formdata)
4847

  
4848
    assert 'bo1' not in formdata.data
4849

  
4850
    # check with a template string, into a string field
4851
    pub.substitutions.feed(formdata)
4852
    item.fields = [{'field_id': 'bo2', 'value': '{{form_var_file}}'}]
4853
    item.perform(formdata)
4854

  
4855
    assert formdata.data['bo2'] == 'test.jpeg'
4856

  
4857
    # check with template string and missing file
4858
    formdata = formdef.data_class()()
4859
    formdata.data = {'00': None}
4860
    formdata.just_created()
4861
    formdata.store()
4862

  
4863
    assert formdata.data.get('bo1') is None
4864

  
4865
    # check stripping metadata
4866
    pub.substitutions.feed(formdata)
4867
    item.fields = [
4868
        {
4869
            'field_id': 'bo1',
4870
            'value': '=utils.attachment(form_var_file_raw,'
4871
            + ' filename="new_"+form_var_file,'
4872
            + ' content_type="my content type",'
4873
            + ' strip_metadata=True)',
4874
        }
4875
    ]
4876
    formdata = formdef.data_class()()
4877
    formdata.data = {'00': upload}
4878
    formdata.just_created()
4879
    formdata.store()
4880
    pub.substitutions.feed(formdata)
4881
    item.perform(formdata)
4882
    formdata = formdef.data_class().get(formdata.id)
4883
    assert formdata.data['bo1'].base_filename == 'new_test.jpeg'
4884
    assert formdata.data['bo1'].content_type == 'my content type'
4885
    assert formdata.data['bo1'].qfilename != formdata.data['00'].qfilename
4886
    assert formdata.data['00'].get_content().find(b'<exif:XResolution>')
4887
    assert not Image or formdata.data['bo1'].get_content().find(b'<exif:XResolution>') == -1
4888

  
4889
    upload2 = PicklableUpload('test2.odt', 'application/vnd.oasis.opendocument.text')
4890
    with open(os.path.join(os.path.dirname(__file__), '..', 'template.odt'), 'rb') as fd:
4891
        template_odt = fd.read()
4892
    upload2.receive([template_odt])
4893
    formdata = formdef.data_class()()
4894
    formdata.data = {'00': upload2}
4895
    formdata.just_created()
4896
    formdata.store()
4897
    pub.substitutions.feed(formdata)
4898
    item.perform(formdata)
4899
    formdata = formdef.data_class().get(formdata.id)
4900
    assert formdata.data['bo1'].base_filename == 'new_test2.odt'
4901
    assert formdata.data['bo1'].content_type == 'my content type'
4902
    assert formdata.data['bo1'].get_content() == template_odt
4903
    assert formdata.data['bo1'].qfilename == formdata.data['00'].qfilename
4904

  
4905
    # check storing response as attachment
4906
    pub.substitutions.feed(formdata)
4907
    item = WebserviceCallStatusItem()
4908
    item.url = 'http://remote.example.net/xml'
4909
    item.varname = 'xxx'
4910
    item.response_type = 'attachment'
4911
    item.record_errors = True
4912
    item.perform(formdata)
4913
    attachment = formdata.evolution[-1].parts[-1]
4914
    assert isinstance(attachment, AttachmentEvolutionPart)
4915
    assert attachment.base_filename == 'xxx.xml'
4916
    assert attachment.content_type == 'text/xml'
4917

  
4918
    formdata = formdef.data_class().get(formdata.id)
4919
    pub.substitutions.feed(formdata)
4920
    item = SetBackofficeFieldsWorkflowStatusItem()
4921
    item.parent = st1
4922
    item.fields = [{'field_id': 'bo1', 'value': '=attachments.xxx'}]
4923
    item.perform(formdata)
4924

  
4925
    formdata = formdef.data_class().get(formdata.id)
4926
    assert formdata.data['bo1'].base_filename == 'xxx.xml'
4927

  
4928
    # check storing a file from an assembled dictionary
4929
    item = SetBackofficeFieldsWorkflowStatusItem()
4930
    item.parent = st1
4931
    item.fields = [{'field_id': 'bo1', 'value': '={"content": "hello world", "filename": "hello.txt"}'}]
4932
    item.perform(formdata)
4933

  
4934
    formdata = formdef.data_class().get(formdata.id)
4935
    assert formdata.data['bo1'].base_filename == 'hello.txt'
4936
    assert formdata.data['bo1'].get_content() == b'hello world'
4937

  
4938
    # check resetting a value
4939
    for value in ('', None):
4940
        item = SetBackofficeFieldsWorkflowStatusItem()
4941
        item.parent = st1
4942
        item.fields = [{'field_id': 'bo1', 'value': value}]
4943
        item.perform(formdata)
4944

  
4945
        formdata = formdef.data_class().get(formdata.id)
4946
        assert formdata.data['bo1'] is None
4947

  
4948
    # set from base64 content
4949
    item = SetBackofficeFieldsWorkflowStatusItem()
4950
    item.parent = st1
4951
    item.fields = [
4952
        {'field_id': 'bo1', 'value': '={"b64_content": "SEVMTE8gV09STEQ=", "filename": "hello.txt"}'}
4953
    ]
4954
    item.perform(formdata)
4955

  
4956
    formdata = formdef.data_class().get(formdata.id)
4957
    assert formdata.data['bo1'].base_filename == 'hello.txt'
4958
    assert formdata.data['bo1'].get_content() == b'HELLO WORLD'
4959

  
4960
    hello_world = formdata.data['bo1']
4961
    # check wrong value
4962
    for value in ('="HELLO"', 'BAD'):
4963
        formdata.data['bo1'] = hello_world
4964
        formdata.store()
4965

  
4966
        item = SetBackofficeFieldsWorkflowStatusItem()
4967
        item.parent = st1
4968
        item.fields = [{'field_id': 'bo1', 'value': value}]
4969

  
4970
        pub.loggederror_class.wipe()
4971
        item.perform(formdata)
4972

  
4973
        formdata = formdef.data_class().get(formdata.id)
4974
        assert formdata.data['bo1'].base_filename == 'hello.txt'
4975
        assert formdata.data['bo1'].get_content() == b'HELLO WORLD'
4976
        assert pub.loggederror_class.count() == 1
4977
        logged_error = pub.loggederror_class.select()[0]
4978
        assert logged_error.summary.startswith('Failed to convert')
4979
        assert logged_error.formdata_id == str(formdata.id)
4980
        assert logged_error.exception_class == 'ValueError'
4981

  
4982
    # check wrong field
4983
    item = SetBackofficeFieldsWorkflowStatusItem()
4984
    item.parent = st1
4985
    item.fields = [{'field_id': 'bo3', 'value': '=form_var_file_raw'}]
4986
    item.perform(formdata)
4987

  
4988
    formdata = formdef.data_class().get(formdata.id)
4989
    assert formdata.data.get('bo3') is None
4990

  
4991

  
4992
def test_set_backoffice_field_item(pub):
4993
    Workflow.wipe()
4994
    FormDef.wipe()
4995
    wf = Workflow(name='xxx')
4996
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
4997
    st1 = wf.add_status('Status1')
4998
    wf.backoffice_fields_formdef.fields = [
4999
        ItemField(
5000
            id='bo1',
5001
            label='1st backoffice field',
5002
            type='item',
5003
            varname='backoffice_item',
5004
            items=['a', 'b', 'c'],
5005
        ),
5006
    ]
5007
    wf.store()
5008

  
5009
    formdef = FormDef()
5010
    formdef.name = 'baz'
5011
    formdef.fields = []
5012
    formdef.workflow_id = wf.id
5013
    formdef.store()
5014

  
5015
    formdata = formdef.data_class()()
5016
    formdata.data = {}
5017
    formdata.just_created()
5018
    formdata.store()
5019

  
5020
    item = SetBackofficeFieldsWorkflowStatusItem()
5021
    item.parent = st1
5022
    item.fields = [{'field_id': 'bo1', 'value': 'a'}]
5023
    item.perform(formdata)
5024

  
5025
    formdata = formdef.data_class().get(formdata.id)
5026
    assert formdata.data['bo1'] == 'a'
5027
    assert formdata.data['bo1_display'] == 'a'
5028

  
5029
    datasource = {'type': 'formula', 'value': repr([('a', 'aa'), ('b', 'bb'), ('c', 'cc')])}
5030

  
5031
    wf.backoffice_fields_formdef.fields = [
5032
        ItemField(
5033
            id='bo1',
5034
            label='1st backoffice field',
5035
            type='item',
5036
            varname='backoffice_item',
5037
            data_source=datasource,
5038
        ),
5039
    ]
5040
    wf.store()
5041

  
5042
    item = SetBackofficeFieldsWorkflowStatusItem()
5043
    item.parent = st1
5044
    item.fields = [{'field_id': 'bo1', 'value': 'a'}]
5045
    item.perform(formdata)
5046

  
5047
    formdata = formdef.data_class().get(formdata.id)
5048
    assert formdata.data['bo1'] == 'a'
5049
    assert formdata.data['bo1_display'] == 'aa'
5050

  
5051
    datasource = {
5052
        'type': 'formula',
5053
        'value': repr([{'id': 'a', 'text': 'aa', 'more': 'aaa'}, {'id': 'b', 'text': 'bb', 'more': 'bbb'}]),
5054
    }
5055

  
5056
    wf.backoffice_fields_formdef.fields = [
5057
        ItemField(
5058
            id='bo1',
5059
            label='1st backoffice field',
5060
            type='item',
5061
            varname='backoffice_item',
5062
            data_source=datasource,
5063
        ),
5064
    ]
5065
    wf.store()
5066

  
5067
    item = SetBackofficeFieldsWorkflowStatusItem()
5068
    item.parent = st1
5069
    item.fields = [{'field_id': 'bo1', 'value': 'a'}]
5070
    item.perform(formdata)
5071

  
5072
    formdata = formdef.data_class().get(formdata.id)
5073
    assert formdata.data['bo1'] == 'a'
5074
    assert formdata.data['bo1_display'] == 'aa'
5075
    assert formdata.data['bo1_structured'] == {'id': 'a', 'more': 'aaa', 'text': 'aa'}
5076

  
5077
    # check when assigning using the display value
5078
    formdata = formdef.data_class()()
5079
    formdata.data = {}
5080
    formdata.just_created()
5081
    formdata.store()
5082

  
5083
    item = SetBackofficeFieldsWorkflowStatusItem()
5084
    item.parent = st1
5085
    item.fields = [{'field_id': 'bo1', 'value': 'aa'}]
5086
    item.perform(formdata)
5087

  
5088
    formdata = formdef.data_class().get(formdata.id)
5089
    assert formdata.data['bo1'] == 'a'
5090
    assert formdata.data['bo1_display'] == 'aa'
5091
    assert formdata.data['bo1_structured'] == {'id': 'a', 'more': 'aaa', 'text': 'aa'}
5092

  
5093
    # check with unknown value
5094
    formdata = formdef.data_class()()
5095
    formdata.data = {}
5096
    formdata.just_created()
5097
    formdata.store()
5098

  
5099
    item = SetBackofficeFieldsWorkflowStatusItem()
5100
    item.parent = st1
5101
    item.fields = [{'field_id': 'bo1', 'value': 'foobar'}]
5102
    item.perform(formdata)
5103

  
5104
    formdata = formdef.data_class().get(formdata.id)
5105
    assert formdata.data['bo1'] == 'foobar'
5106
    assert formdata.data.get('bo1_display') is None
5107
    assert formdata.data.get('bo1_structured') is None
5108

  
5109

  
5110
def test_set_backoffice_field_card_item(pub):
5111
    CardDef.wipe()
5112
    Workflow.wipe()
5113
    FormDef.wipe()
5114

  
5115
    carddef = CardDef()
5116
    carddef.name = 'items'
5117
    carddef.digest_templates = {'default': '{{form_var_name}}'}
5118
    carddef.fields = [
5119
        StringField(id='0', label='string', varname='name'),
5120
        StringField(id='1', label='string', varname='attr'),
5121
    ]
5122
    carddef.store()
5123
    carddef.data_class().wipe()
5124
    for i, value in enumerate(['foo', 'bar', 'baz']):
5125
        carddata = carddef.data_class()()
5126
        carddata.data = {
5127
            '0': value,
5128
            '1': 'attr%s' % i,
5129
        }
5130
        carddata.just_created()
5131
        carddata.store()
5132
    latest_carddata = carddata
5133
    latest_carddata_id = carddata.id
5134
    ds = {'type': 'carddef:%s' % carddef.url_name}
5135

  
5136
    wf = Workflow(name='xxx')
5137
    wf.store()
5138

  
5139
    formdef = FormDef()
5140
    formdef.name = 'baz'
5141
    formdef.workflow_id = wf.id
5142
    formdef.fields = [
5143
        ItemField(id='0', label='string', type='item', data_source=ds, display_disabled_items=True)
5144
    ]
5145
    formdef.store()
5146

  
5147
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5148
    st1 = wf.add_status('Status1')
5149
    wf.backoffice_fields_formdef.fields = [
5150
        ItemField(
5151
            id='bo1', label='1st backoffice field', type='item', varname='backoffice_item', data_source=ds
5152
        ),
5153
    ]
5154
    wf.store()
5155

  
5156
    formdef = FormDef()
5157
    formdef.name = 'baz'
5158
    formdef.fields = []
5159
    formdef.workflow_id = wf.id
5160
    formdef.store()
5161

  
5162
    formdata = formdef.data_class()()
5163
    formdata.data = {}
5164
    formdata.just_created()
5165
    formdata.store()
5166

  
5167
    item = SetBackofficeFieldsWorkflowStatusItem()
5168
    item.parent = st1
5169
    item.fields = [{'field_id': 'bo1', 'value': str(latest_carddata_id)}]
5170
    item.perform(formdata)
5171

  
5172
    formdata = formdef.data_class().get(formdata.id)
5173
    assert formdata.data['bo1'] == str(latest_carddata_id)
5174
    assert formdata.data['bo1_display'] == 'baz'
5175
    assert formdata.data['bo1_structured']['attr'] == 'attr2'
5176

  
5177
    # reset, and get by display id value
5178
    formdata.data = {}
5179
    formdata.store()
5180
    item.fields = [{'field_id': 'bo1', 'value': latest_carddata.get_display_id()}]
5181
    item.perform(formdata)
5182
    formdata = formdef.data_class().get(formdata.id)
5183
    assert formdata.data['bo1'] == str(latest_carddata_id)
5184
    assert formdata.data['bo1_display'] == 'baz'
5185
    assert formdata.data['bo1_structured']['attr'] == 'attr2'
5186

  
5187
    # reset, and get by text value
5188
    formdata.data = {}
5189
    formdata.store()
5190
    item.fields = [{'field_id': 'bo1', 'value': 'bar'}]
5191
    item.perform(formdata)
5192
    formdata = formdef.data_class().get(formdata.id)
5193
    assert formdata.data['bo1'] != str(latest_carddata_id)
5194
    assert formdata.data['bo1_display'] == 'bar'
5195
    assert formdata.data['bo1_structured']['attr'] == 'attr1'
5196

  
5197
    # reset, with unknown value
5198
    pub.loggederror_class.wipe()
5199
    formdata.data = {}
5200
    formdata.store()
5201
    item.fields = [{'field_id': 'bo1', 'value': 'xxx'}]
5202
    item.perform(formdata)
5203
    formdata = formdef.data_class().get(formdata.id)
5204
    assert formdata.data.get('bo1') is None  # invalid value is not stored
5205
    assert formdata.data.get('bo1_display') is None
5206
    assert formdata.data.get('bo1_structured') is None
5207
    assert pub.loggederror_class.count() == 1
5208
    logged_error = pub.loggederror_class.select()[0]
5209
    assert logged_error.summary.startswith('Failed to convert')
5210

  
5211
    # reset, and get empty value
5212
    formdata.data = {}
5213
    formdata.store()
5214
    item.fields = [{'field_id': 'bo1', 'value': ''}]
5215
    item.perform(formdata)
5216
    formdata = formdef.data_class().get(formdata.id)
5217
    assert formdata.data['bo1'] is None
5218
    assert formdata.data.get('bo1_display') is None
5219
    assert formdata.data.get('bo1_structured') is None
5220

  
5221

  
5222
def test_set_backoffice_field_items(pub):
5223
    Workflow.wipe()
5224
    FormDef.wipe()
5225
    wf = Workflow(name='xxx')
5226
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5227
    st1 = wf.add_status('Status1')
5228
    wf.backoffice_fields_formdef.fields = [
5229
        ItemsField(
5230
            id='bo1',
5231
            label='1st backoffice field',
5232
            type='items',
5233
            varname='backoffice_item',
5234
            items=['a', 'b', 'c'],
5235
        ),
5236
    ]
5237
    wf.store()
5238

  
5239
    formdef = FormDef()
5240
    formdef.name = 'baz'
5241
    formdef.fields = []
5242
    formdef.workflow_id = wf.id
5243
    formdef.store()
5244

  
5245
    formdata = formdef.data_class()()
5246
    formdata.data = {}
5247
    formdata.just_created()
5248
    formdata.store()
5249

  
5250
    item = SetBackofficeFieldsWorkflowStatusItem()
5251
    item.parent = st1
5252
    item.fields = [{'field_id': 'bo1', 'value': "=['a', 'b']"}]
5253
    item.perform(formdata)
5254

  
5255
    formdata = formdef.data_class().get(formdata.id)
5256
    assert formdata.data['bo1'] == ['a', 'b']
5257
    assert formdata.data['bo1_display'] == 'a, b'
5258

  
5259
    datasource = {'type': 'formula', 'value': repr([('a', 'aa'), ('b', 'bb'), ('c', 'cc')])}
5260

  
5261
    wf.backoffice_fields_formdef.fields = [
5262
        ItemsField(
5263
            id='bo1',
5264
            label='1st backoffice field',
5265
            type='items',
5266
            varname='backoffice_item',
5267
            data_source=datasource,
5268
        ),
5269
    ]
5270
    wf.store()
5271

  
5272
    item = SetBackofficeFieldsWorkflowStatusItem()
5273
    item.parent = st1
5274
    item.fields = [{'field_id': 'bo1', 'value': "=['a', 'b']"}]
5275
    item.perform(formdata)
5276

  
5277
    formdata = formdef.data_class().get(formdata.id)
5278
    assert formdata.data['bo1'] == ['a', 'b']
5279
    assert formdata.data['bo1_display'] == 'aa, bb'
5280

  
5281
    datasource = {
5282
        'type': 'formula',
5283
        'value': repr(
5284
            [
5285
                {'id': 'a', 'text': 'aa', 'more': 'aaa'},
5286
                {'id': 'b', 'text': 'bb', 'more': 'bbb'},
5287
                {'id': 'c', 'text': 'cc', 'more': 'ccc'},
5288
            ]
5289
        ),
5290
    }
5291

  
5292
    wf.backoffice_fields_formdef.fields = [
5293
        ItemsField(
5294
            id='bo1',
5295
            label='1st backoffice field',
5296
            type='items',
5297
            varname='backoffice_item',
5298
            data_source=datasource,
5299
        ),
5300
    ]
5301
    wf.store()
5302

  
5303
    item = SetBackofficeFieldsWorkflowStatusItem()
5304
    item.parent = st1
5305
    item.fields = [{'field_id': 'bo1', 'value': "=['a', 'c']"}]
5306
    item.perform(formdata)
5307

  
5308
    formdata = formdef.data_class().get(formdata.id)
5309
    assert formdata.data['bo1'] == ['a', 'c']
5310
    assert formdata.data['bo1_display'] == 'aa, cc'
5311
    assert len(formdata.data['bo1_structured']) == 2
5312
    assert {'id': 'a', 'more': 'aaa', 'text': 'aa'} in formdata.data['bo1_structured']
5313
    assert {'id': 'c', 'more': 'ccc', 'text': 'cc'} in formdata.data['bo1_structured']
5314

  
5315
    # from formdata field
5316
    formdef.fields = [
5317
        ItemsField(id='1', label='field', type='items', varname='items', data_source=datasource),
5318
    ]
5319
    formdef.store()
5320

  
5321
    formdata = formdef.data_class()()
5322
    formdata.data = {'1': ['a', 'c']}
5323
    formdata.data['1_display'] = formdef.fields[0].store_display_value(formdata.data, '1')
5324
    formdata.data['1_structured'] = formdef.fields[0].store_structured_value(formdata.data, '1')
5325
    formdata.just_created()
5326
    formdata.store()
5327
    pub.substitutions.feed(formdata)
5328

  
5329
    item = SetBackofficeFieldsWorkflowStatusItem()
5330
    item.parent = st1
5331
    item.fields = [{'field_id': 'bo1', 'value': "=form_var_items_raw"}]
5332
    item.perform(formdata)
5333

  
5334
    assert formdata.data['bo1'] == ['a', 'c']
5335
    assert formdata.data['bo1_display'] == 'aa, cc'
5336
    assert len(formdata.data['bo1_structured']) == 2
5337
    assert {'id': 'a', 'more': 'aaa', 'text': 'aa'} in formdata.data['bo1_structured']
5338
    assert {'id': 'c', 'more': 'ccc', 'text': 'cc'} in formdata.data['bo1_structured']
5339

  
5340
    # with a template
5341
    formdata = formdef.data_class()()
5342
    formdata.data = {'1': ['a', 'c']}
5343
    formdata.data['1_display'] = formdef.fields[0].store_display_value(formdata.data, '1')
5344
    formdata.data['1_structured'] = formdef.fields[0].store_structured_value(formdata.data, '1')
5345
    formdata.just_created()
5346
    formdata.store()
5347
    pub.substitutions.reset()
5348
    pub.substitutions.feed(formdata)
5349

  
5350
    item.fields = [{'field_id': 'bo1', 'value': "{{form_var_items_raw}}"}]
5351
    item.perform(formdata)
5352

  
5353
    # using a single int
5354
    datasource = {
5355
        'type': 'formula',
5356
        'value': repr(
5357
            [
5358
                {'id': 1, 'text': 'aa', 'more': 'aaa'},
5359
                {'id': 2, 'text': 'bb', 'more': 'bbb'},
5360
                {'id': 3, 'text': 'cc', 'more': 'ccc'},
5361
            ]
5362
        ),
5363
    }
5364

  
5365
    wf.backoffice_fields_formdef.fields = [
5366
        ItemsField(
5367
            id='bo1',
5368
            label='1st backoffice field',
5369
            type='items',
5370
            varname='backoffice_item',
5371
            data_source=datasource,
5372
        ),
5373
    ]
5374
    wf.store()
5375

  
5376
    item = SetBackofficeFieldsWorkflowStatusItem()
5377
    item.parent = st1
5378
    item.fields = [{'field_id': 'bo1', 'value': "=2"}]
5379
    item.perform(formdata)
5380

  
5381
    formdata = formdef.data_class().get(formdata.id)
5382
    assert formdata.data['bo1'] == ['2']
5383
    assert formdata.data['bo1_display'] == 'bb'
5384
    assert len(formdata.data['bo1_structured']) == 1
5385

  
5386
    # using an invalid value
5387
    formdata.data = {}
5388
    formdata.store()
5389
    pub.loggederror_class.wipe()
5390
    item = SetBackofficeFieldsWorkflowStatusItem()
5391
    item.parent = st1
5392
    item.fields = [{'field_id': 'bo1', 'value': "=Ellipsis"}]
5393
    item.perform(formdata)
5394
    assert pub.loggederror_class.count() == 1
5395
    logged_error = pub.loggederror_class.select()[0]
5396
    assert 'Failed to convert' in logged_error.summary
5397

  
5398
    # using a string with multiple values
5399
    item = SetBackofficeFieldsWorkflowStatusItem()
5400
    item.parent = st1
5401
    item.fields = [{'field_id': 'bo1', 'value': "1|3"}]
5402
    item.perform(formdata)
5403

  
5404
    formdata = formdef.data_class().get(formdata.id)
5405
    assert formdata.data['bo1'] == ['1', '3']
5406
    assert formdata.data['bo1_display'] == 'aa, cc'
5407
    assert len(formdata.data['bo1_structured']) == 2
5408
    assert {'id': 1, 'more': 'aaa', 'text': 'aa'} in formdata.data['bo1_structured']
5409
    assert {'id': 3, 'more': 'ccc', 'text': 'cc'} in formdata.data['bo1_structured']
5410

  
5411

  
5412
def test_set_backoffice_field_date(pub):
5413
    Workflow.wipe()
5414
    FormDef.wipe()
5415
    wf = Workflow(name='xxx')
5416
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5417
    st1 = wf.add_status('Status1')
5418
    wf.backoffice_fields_formdef.fields = [
5419
        DateField(id='bo1', label='1st backoffice field', type='date', varname='backoffice_date'),
5420
    ]
5421
    wf.store()
5422

  
5423
    formdef = FormDef()
5424
    formdef.name = 'baz'
5425
    formdef.fields = []
5426
    formdef.workflow_id = wf.id
5427
    formdef.store()
5428

  
5429
    formdata = formdef.data_class()()
5430
    formdata.data = {}
5431
    formdata.just_created()
5432
    formdata.store()
5433

  
5434
    item = SetBackofficeFieldsWorkflowStatusItem()
5435
    item.parent = st1
5436
    item.fields = [{'field_id': 'bo1', 'value': "=utils.today()"}]
5437
    item.perform(formdata)
5438

  
5439
    formdata = formdef.data_class().get(formdata.id)
5440
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date.today()
5441

  
5442
    formdata.data['bo1'] = None
5443
    formdata.store()
5444
    item = SetBackofficeFieldsWorkflowStatusItem()
5445
    item.parent = st1
5446
    item.fields = [{'field_id': 'bo1', 'value': '{% now "j/n/Y" %}'}]
5447
    item.perform(formdata)
5448

  
5449
    formdata = formdef.data_class().get(formdata.id)
5450
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date.today()
5451

  
5452
    item = SetBackofficeFieldsWorkflowStatusItem()
5453
    item.parent = st1
5454
    item.fields = [{'field_id': 'bo1', 'value': "23/3/2017"}]
5455
    item.perform(formdata)
5456

  
5457
    formdata = formdef.data_class().get(formdata.id)
5458
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23)
5459

  
5460
    # invalid values => do nothing
5461
    assert pub.loggederror_class.count() == 0
5462
    for value in ('plop', '={}', '=[]'):
5463
        item = SetBackofficeFieldsWorkflowStatusItem()
5464
        item.parent = st1
5465
        item.fields = [{'field_id': 'bo1', 'value': value}]
5466

  
5467
        pub.loggederror_class.wipe()
5468
        item.perform(formdata)
5469
        formdata = formdef.data_class().get(formdata.id)
5470
        assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23)
5471
        assert pub.loggederror_class.count() == 1
5472
        assert pub.loggederror_class.select()[0].summary.startswith('Failed to convert')
5473

  
5474
    # None : empty date
5475
    item = SetBackofficeFieldsWorkflowStatusItem()
5476
    item.parent = st1
5477
    item.fields = [{'field_id': 'bo1', 'value': None}]
5478
    item.perform(formdata)
5479

  
5480
    formdata = formdef.data_class().get(formdata.id)
5481
    assert formdata.data['bo1'] is None
5482

  
5483

  
5484
def test_set_backoffice_field_boolean(pub):
5485
    Workflow.wipe()
5486
    FormDef.wipe()
5487
    wf = Workflow(name='xxx')
5488
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5489
    st1 = wf.add_status('Status1')
5490
    wf.backoffice_fields_formdef.fields = [
5491
        BoolField(id='bo1', label='1st backoffice field', type='bool', varname='backoffice_bool'),
5492
    ]
5493
    wf.store()
5494

  
5495
    formdef = FormDef()
5496
    formdef.name = 'baz'
5497
    formdef.fields = [BoolField(id='1', label='field', type='bool', varname='foo')]
5498
    formdef.workflow_id = wf.id
5499
    formdef.store()
5500

  
5501
    formdata = formdef.data_class()()
5502
    formdata.data = {'1': True}
5503
    formdata.just_created()
5504
    formdata.store()
5505
    get_publisher().substitutions.feed(formdata)
5506

  
5507
    for value in ('=True', '=form_var_foo_raw', '{{ form_var_foo_raw }}', 'True', 'Yes', 'true', 'yes'):
5508
        item = SetBackofficeFieldsWorkflowStatusItem()
5509
        item.parent = st1
5510
        item.fields = [{'field_id': 'bo1', 'value': value}]
5511
        item.perform(formdata)
5512
        formdata = formdef.data_class().get(formdata.id)
5513
        assert formdata.data['bo1'] is True
5514
        formdata.data['bo1'] = None
5515
        formdata.store()
5516

  
5517
    for value in ('=False', '=not(form_var_foo_raw)', 'False', 'plop', ''):
5518
        item = SetBackofficeFieldsWorkflowStatusItem()
5519
        item.parent = st1
5520
        item.fields = [{'field_id': 'bo1', 'value': value}]
5521
        item.perform(formdata)
5522
        formdata = formdef.data_class().get(formdata.id)
5523
        assert formdata.data['bo1'] is False
5524
        formdata.data['bo1'] = None
5525
        formdata.store()
5526

  
5527

  
5528
def test_set_backoffice_field_str_time_filter(pub):
5529
    Workflow.wipe()
5530
    FormDef.wipe()
5531
    wf = Workflow(name='xxx')
5532
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5533
    st1 = wf.add_status('Status1')
5534
    wf.backoffice_fields_formdef.fields = [
5535
        StringField(id='bo1', label='1st backoffice field', type='str', varname='backoffice_str'),
5536
    ]
5537
    wf.store()
5538

  
5539
    formdef = FormDef()
5540
    formdef.name = 'baz'
5541
    formdef.fields = [StringField(id='1', label='field', type='str', varname='foo')]
5542
    formdef.workflow_id = wf.id
5543
    formdef.store()
5544

  
5545
    formdata = formdef.data_class()()
5546
    formdata.data = {'1': '09:00'}
5547
    formdata.just_created()
5548
    formdata.store()
5549
    get_publisher().substitutions.feed(formdata)
5550

  
5551
    item = SetBackofficeFieldsWorkflowStatusItem()
5552
    item.parent = st1
5553
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_foo|time:"H:i:s" }}'}]
5554
    item.perform(formdata)
5555
    formdata = formdef.data_class().get(formdata.id)
5556
    assert formdata.data['bo1'] == '09:00:00'
5557
    formdata.data['bo1'] = None
5558
    formdata.store()
5559

  
5560
    # |time will yield the default django reprentation
5561
    item = SetBackofficeFieldsWorkflowStatusItem()
5562
    item.parent = st1
5563
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_foo|time }}'}]
5564
    item.perform(formdata)
5565
    formdata = formdef.data_class().get(formdata.id)
5566
    assert formdata.data['bo1'] == '9 a.m.'
5567
    formdata.data['bo1'] = None
5568
    formdata.store()
5569

  
5570

  
5571
def test_set_backoffice_field_block(pub):
5572
    BlockDef.wipe()
5573
    Workflow.wipe()
5574
    FormDef.wipe()
5575

  
5576
    block = BlockDef()
5577
    block.name = 'foobar'
5578
    block.digest_template = 'X{{foobar_var_foo}}Y'
5579
    block.fields = [
5580
        StringField(id='123', required=True, label='Test', type='string', varname='foo'),
5581
        StringField(id='234', required=True, label='Test2', type='string', varname='bar'),
5582
    ]
5583
    block.store()
5584

  
5585
    wf = Workflow(name='xxx')
5586
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5587
    st1 = wf.add_status('Status1')
5588
    wf.backoffice_fields_formdef.fields = [
5589
        BlockField(id='bo1', label='1st backoffice field', type='block:foobar'),
5590
        StringField(id='bo2', label='2nd backoffice field', type='string'),
5591
    ]
5592
    wf.store()
5593

  
5594
    formdef = FormDef()
5595
    formdef.name = 'baz'
5596
    formdef.fields = [
5597
        BlockField(id='1', label='test', type='block:foobar', max_items=3, varname='foo'),
5598
    ]
5599
    formdef.workflow_id = wf.id
5600
    formdef.store()
5601

  
5602
    formdata = formdef.data_class()()
5603
    # value from test_block_digest in tests/test_form_pages.py
5604
    formdata.data = {
5605
        '1': {
5606
            'data': [{'123': 'foo', '234': 'bar'}, {'123': 'foo2', '234': 'bar2'}],
5607
            'schema': {'123': 'string', '234': 'string'},
5608
        },
5609
        '1_display': 'XfooY, Xfoo2Y',
5610
    }
5611
    formdata.just_created()
5612
    formdata.store()
5613
    get_publisher().substitutions.feed(formdata)
5614

  
5615
    item = SetBackofficeFieldsWorkflowStatusItem()
5616
    item.parent = st1
5617
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_foo_raw}}'}]
5618
    item.perform(formdata)
5619
    formdata = formdef.data_class().get(formdata.id)
5620
    assert formdata.data['bo1'] == formdata.data['1']
5621
    assert formdata.data['bo1_display'] == formdata.data['1_display']
5622

  
5623
    # without _raw suffix
5624
    formdata = formdef.data_class()()
5625
    # value from test_block_digest in tests/test_form_pages.py
5626
    formdata.data = {
5627
        '1': {
5628
            'data': [{'123': 'foo', '234': 'bar'}, {'123': 'foo2', '234': 'bar2'}],
5629
            'schema': {'123': 'string', '234': 'string'},
5630
        },
5631
        '1_display': 'XfooY, Xfoo2Y',
5632
    }
5633
    formdata.just_created()
5634
    formdata.store()
5635
    get_publisher().substitutions.reset()
5636
    get_publisher().substitutions.feed(formdata)
5637

  
5638
    item = SetBackofficeFieldsWorkflowStatusItem()
5639
    item.parent = st1
5640
    item.fields = [
5641
        {'field_id': 'bo1', 'value': '{{form_var_foo}}'},
5642
        {'field_id': 'bo2', 'value': '{{form_var_foo}}'},
5643
    ]
5644
    item.perform(formdata)
5645
    formdata = formdef.data_class().get(formdata.id)
5646
    assert formdata.data['bo1'] == formdata.data['1']
5647
    assert formdata.data['bo1_display'] == formdata.data['1_display']
5648
    assert formdata.data['bo2'] == formdata.data['1_display']
5649

  
5650

  
5651
def test_set_backoffice_field_block_template_tag(pub):
5652
    BlockDef.wipe()
5653
    Workflow.wipe()
5654
    FormDef.wipe()
5655

  
5656
    block = BlockDef()
5657
    block.name = 'foobar'
5658
    block.digest_template = 'X{{foobar_var_foo}}Y'
5659
    block.fields = [
5660
        StringField(id='123', required=True, label='Test', type='string', varname='foo'),
5661
        StringField(id='234', required=True, label='Test2', type='string', varname='bar'),
5662
    ]
5663
    block.store()
5664

  
5665
    wf = Workflow(name='xxx')
5666
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5667
    st1 = wf.add_status('Status1')
5668
    wf.backoffice_fields_formdef.fields = [
5669
        BlockField(id='bo1', label='1st backoffice field', max_items=3, type='block:foobar'),
5670
    ]
5671
    wf.store()
5672

  
5673
    formdef = FormDef()
5674
    formdef.name = 'baz'
5675
    formdef.fields = [
5676
        StringField(id='1', label='test', varname='foo'),
5677
    ]
5678
    formdef.workflow_id = wf.id
5679
    formdef.store()
5680

  
5681
    formdata = formdef.data_class()()
5682
    formdata.data = {'1': 'plop'}
5683
    formdata.just_created()
5684
    formdata.store()
5685
    get_publisher().substitutions.feed(formdata)
5686

  
5687
    item = SetBackofficeFieldsWorkflowStatusItem()
5688
    item.parent = st1
5689
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value foo=form_var_foo bar="xxx" %}'}]
5690
    item.perform(formdata)
5691
    formdata = formdef.data_class().get(formdata.id)
5692
    assert formdata.data['bo1'] == {
5693
        'data': [{'123': 'plop', '234': 'xxx'}],
5694
        'schema': {'123': 'string', '234': 'string'},
5695
    }
5696
    assert formdata.data['bo1_display'] == 'XplopY'
5697

  
5698
    # override
5699
    item = SetBackofficeFieldsWorkflowStatusItem()
5700
    item.parent = st1
5701
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value foo=form_var_foo bar="yyy" %}'}]
5702
    item.perform(formdata)
5703
    formdata = formdef.data_class().get(formdata.id)
5704
    assert formdata.data['bo1'] == {
5705
        'data': [{'123': 'plop', '234': 'yyy'}],
5706
        'schema': {'123': 'string', '234': 'string'},
5707
    }
5708
    assert formdata.data['bo1_display'] == 'XplopY'
5709

  
5710
    # append
5711
    item = SetBackofficeFieldsWorkflowStatusItem()
5712
    item.parent = st1
5713
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value append=True foo="zzz" bar=form_var_foo %}'}]
5714
    item.perform(formdata)
5715
    formdata = formdef.data_class().get(formdata.id)
5716
    assert formdata.data['bo1'] == {
5717
        'data': [{'123': 'plop', '234': 'yyy'}, {'123': 'zzz', '234': 'plop'}],
5718
        'schema': {'123': 'string', '234': 'string'},
5719
    }
5720
    assert formdata.data['bo1_display'] == 'XplopY, XzzzY'
5721

  
5722
    # merge (into last row)
5723
    item = SetBackofficeFieldsWorkflowStatusItem()
5724
    item.parent = st1
5725
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value merge=True foo="AAA" %}'}]
5726
    item.perform(formdata)
5727
    formdata = formdef.data_class().get(formdata.id)
5728
    assert formdata.data['bo1'] == {
5729
        'data': [{'123': 'plop', '234': 'yyy'}, {'123': 'AAA', '234': 'plop'}],
5730
        'schema': {'123': 'string', '234': 'string'},
5731
    }
5732
    assert formdata.data['bo1_display'] == 'XplopY, XAAAY'
5733

  
5734
    # merge (into given row)
5735
    item = SetBackofficeFieldsWorkflowStatusItem()
5736
    item.parent = st1
5737
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value merge=0 foo="BBB" %}'}]
5738
    item.perform(formdata)
5739
    formdata = formdef.data_class().get(formdata.id)
5740
    assert formdata.data['bo1'] == {
5741
        'data': [{'123': 'BBB', '234': 'yyy'}, {'123': 'AAA', '234': 'plop'}],
5742
        'schema': {'123': 'string', '234': 'string'},
5743
    }
5744
    assert formdata.data['bo1_display'] == 'XBBBY, XAAAY'
5745

  
5746
    # merge with indexerror (ignored)
5747
    item = SetBackofficeFieldsWorkflowStatusItem()
5748
    item.parent = st1
5749
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value merge=50 foo="CCC" %}'}]
5750
    item.perform(formdata)
5751
    formdata = formdef.data_class().get(formdata.id)
5752
    assert formdata.data['bo1'] == {
5753
        'data': [{'123': 'BBB', '234': 'yyy'}, {'123': 'AAA', '234': 'plop'}],
5754
        'schema': {'123': 'string', '234': 'string'},
5755
    }
5756
    assert formdata.data['bo1_display'] == 'XBBBY, XAAAY'
5757

  
5758
    # "item" subfield, make sure raw and display and structured values are stored
5759
    datasource = {
5760
        'type': 'formula',
5761
        'value': repr(
5762
            [
5763
                {'id': 'a', 'text': 'aa', 'more': 'aaa'},
5764
                {'id': 'b', 'text': 'bb', 'more': 'bbb'},
5765
                {'id': 'c', 'text': 'cc', 'more': 'ccc'},
5766
            ]
5767
        ),
5768
    }
5769
    block.fields.append(
5770
        ItemField(id='345', label='Test3', type='item', varname='item', data_source=datasource)
5771
    )
5772
    block.store()
5773
    wf.backoffice_fields_formdef.fields[0]._block = None  # remove cache
5774

  
5775
    item = SetBackofficeFieldsWorkflowStatusItem()
5776
    item.parent = st1
5777
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value item="b" %}'}]
5778
    item.perform(formdata)
5779
    formdata = formdef.data_class().get(formdata.id)
5780
    assert formdata.data['bo1'] == {
5781
        'data': [
5782
            {'345': 'b', '345_display': 'bb', '345_structured': {'id': 'b', 'text': 'bb', 'more': 'bbb'}}
5783
        ],
5784
        'schema': {'123': 'string', '234': 'string', '345': 'item'},
5785
    }
5786
    assert formdata.data['bo1_display'] == 'XNoneY'
5787

  
5788
    # append to invalid existing value (should not happen)
5789
    formdata.data['bo1'] = {'invalid': 'value'}
5790
    item = SetBackofficeFieldsWorkflowStatusItem()
5791
    item.parent = st1
5792
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value item="b" append=True %}'}]
5793
    item.perform(formdata)
5794
    formdata = formdef.data_class().get(formdata.id)
5795
    assert formdata.data['bo1'] == {
5796
        'data': [
5797
            {'345': 'b', '345_display': 'bb', '345_structured': {'id': 'b', 'text': 'bb', 'more': 'bbb'}}
5798
        ],
5799
        'schema': {'123': 'string', '234': 'string', '345': 'item'},
5800
    }
5801
    assert formdata.data['bo1_display'] == 'XNoneY'
5802

  
5803

  
5804
def test_set_backoffice_field_invalid_block_value(pub):
5805
    BlockDef.wipe()
5806
    Workflow.wipe()
5807
    FormDef.wipe()
5808

  
5809
    block = BlockDef()
5810
    block.name = 'foobar'
5811
    block.fields = [StringField(id='123', required=True, label='Test', type='string', varname='foo')]
5812
    block.store()
5813

  
5814
    wf = Workflow(name='xxx')
5815
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5816
    st1 = wf.add_status('Status1')
5817
    wf.backoffice_fields_formdef.fields = [
5818
        BlockField(id='bo1', label='1st backoffice field', max_items=3, type='block:foobar'),
5819
    ]
5820
    wf.store()
5821

  
5822
    formdef = FormDef()
5823
    formdef.name = 'baz'
5824
    formdef.fields = []
5825
    formdef.workflow_id = wf.id
5826
    formdef.store()
5827

  
5828
    formdata = formdef.data_class()()
5829
    formdata.just_created()
5830
    formdata.store()
5831
    get_publisher().substitutions.feed(formdata)
5832

  
5833
    item = SetBackofficeFieldsWorkflowStatusItem()
5834
    item.parent = st1
5835
    item.fields = [{'field_id': 'bo1', 'value': 'xxx'}]
5836

  
5837
    pub.loggederror_class.wipe()
5838
    item.perform(formdata)
5839
    assert pub.loggederror_class.count() == 1
5840
    logged_error = pub.loggederror_class.select()[0]
5841
    assert (
5842
        logged_error.summary
5843
        == 'Failed to set Field Block (foobar) field (bo1), error: invalid value for block'
5844
    )
5845

  
5846
    formdata = formdef.data_class().get(formdata.id)
5847
    assert not formdata.data.get('bo1')
5848

  
5849

  
5850
def test_set_backoffice_field_immediate_use(http_requests, pub):
5851
    Workflow.wipe()
5852
    FormDef.wipe()
5853
    wf = Workflow(name='xxx')
5854
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
5855
    wf.backoffice_fields_formdef.fields = [
5856
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
5857
        StringField(id='bo2', label='2nd backoffice field', type='string', varname='backoffice_barr'),
5858
    ]
5859
    st1 = wf.add_status('Status1')
5860
    wf.store()
5861

  
5862
    formdef = FormDef()
5863
    formdef.name = 'baz'
5864
    formdef.fields = [
5865
        StringField(id='00', label='String', type='string', varname='string'),
5866
    ]
5867
    formdef.workflow_id = wf.id
5868
    formdef.store()
5869

  
5870
    formdata = formdef.data_class()()
5871
    formdata.data = {'00': 'HELLO'}
5872
    formdata.just_created()
5873
    formdata.store()
5874
    item = SetBackofficeFieldsWorkflowStatusItem()
5875
    item.parent = st1
5876

  
5877
    item.fields = [
5878
        {'field_id': 'bo1', 'value': '{{form_var_string}}'},
5879
    ]
5880
    pub.substitutions.reset()
5881
    pub.substitutions.feed(formdata)
5882
    item.perform(formdata)
5883
    formdata = formdef.data_class().get(formdata.id)
5884
    assert formdata.data.get('bo1') == 'HELLO'
5885

  
5886
    item.fields = [
5887
        {'field_id': 'bo1', 'value': 'WORLD'},
5888
    ]
5889
    pub.substitutions.reset()
5890
    pub.substitutions.feed(formdata)
5891
    item.perform(formdata)
5892
    formdata = formdef.data_class().get(formdata.id)
5893
    assert formdata.data.get('bo1') == 'WORLD'
5894

  
5895
    item.fields = [
5896
        {'field_id': 'bo1', 'value': 'X{{form_var_string}}X'},
5897
        {'field_id': 'bo2', 'value': "Y{{form_var_backoffice_blah}}Y"},
5898
    ]
5899
    pub.substitutions.reset()
5900
    pub.substitutions.feed(formdata)
5901
    item.perform(formdata)
5902
    formdata = formdef.data_class().get(formdata.id)
5903
    assert formdata.data.get('bo1') == 'XHELLOX'
5904
    assert formdata.data.get('bo2') == 'YXHELLOXY'
5905

  
5906

  
5907 4480
def test_redirect_to_url(pub):
5908 4481
    formdef = FormDef()
5909 4482
    formdef.name = 'baz'
tests/workflow/test_backoffice_field.py
1
import base64
2
import datetime
3
import os
4

  
5
import pytest
6

  
7
try:
8
    from PIL import Image
9
except ImportError:
10
    Image = None
11

  
12
from quixote import cleanup, get_publisher
13

  
14
from wcs import sessions
15
from wcs.blocks import BlockDef
16
from wcs.carddef import CardDef
17
from wcs.fields import (
18
    BlockField,
19
    BoolField,
20
    DateField,
21
    FileField,
22
    ItemField,
23
    ItemsField,
24
    MapField,
25
    StringField,
26
)
27
from wcs.formdef import FormDef
28
from wcs.qommon.http_request import HTTPRequest
29
from wcs.qommon.upload_storage import PicklableUpload
30
from wcs.wf.backoffice_fields import SetBackofficeFieldsWorkflowStatusItem
31
from wcs.wf.wscall import WebserviceCallStatusItem
32
from wcs.workflows import AttachmentEvolutionPart, Workflow, WorkflowBackofficeFieldsFormDef
33

  
34
from ..utilities import clean_temporary_pub, create_temporary_pub
35

  
36

  
37
def setup_module(module):
38
    cleanup()
39

  
40

  
41
def teardown_module(module):
42
    clean_temporary_pub()
43

  
44

  
45
@pytest.fixture
46
def pub():
47
    pub = create_temporary_pub()
48
    pub.cfg['language'] = {'language': 'en'}
49
    pub.cfg['identification'] = {'methods': ['password']}
50
    pub.write_cfg()
51
    req = HTTPRequest(None, {'SERVER_NAME': 'example.net', 'SCRIPT_NAME': ''})
52
    req.response.filter = {}
53
    req._user = None
54
    pub._set_request(req)
55
    req.session = sessions.BasicSession(id=1)
56
    pub.set_config(req)
57
    return pub
58

  
59

  
60
def test_set_backoffice_field(http_requests, pub):
61
    Workflow.wipe()
62
    FormDef.wipe()
63
    wf = Workflow(name='xxx')
64
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
65
    wf.backoffice_fields_formdef.fields = [
66
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
67
    ]
68
    st1 = wf.add_status('Status1')
69
    wf.store()
70

  
71
    formdef = FormDef()
72
    formdef.name = 'baz'
73
    formdef.fields = [
74
        StringField(id='00', label='String', type='string', varname='string'),
75
        StringField(id='01', label='Other string', type='string', varname='other'),
76
    ]
77
    formdef.workflow_id = wf.id
78
    formdef.store()
79

  
80
    formdata = formdef.data_class()()
81
    formdata.data = {'00': 'HELLO'}
82
    formdata.just_created()
83
    formdata.store()
84
    pub.substitutions.feed(formdata)
85

  
86
    item = SetBackofficeFieldsWorkflowStatusItem()
87
    item.parent = st1
88

  
89
    assert item.render_as_line() == 'Backoffice Data'
90
    assert item.get_jump_label('plop') == 'Backoffice Data'
91
    item.label = 'label'
92
    assert item.render_as_line() == 'Backoffice Data (label)'
93
    assert item.get_jump_label('plop') == 'Backoffice Data "label"'
94

  
95
    item.perform(formdata)
96
    formdata = formdef.data_class().get(formdata.id)
97
    assert formdata.data.get('bo1') is None
98

  
99
    item.fields = [{'field_id': 'bo1', 'value': '=form_var_string'}]
100
    item.perform(formdata)
101
    formdata = formdef.data_class().get(formdata.id)
102
    assert formdata.data['bo1'] == 'HELLO'
103

  
104
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_string }} WORLD'}]
105
    item.perform(formdata)
106
    formdata = formdef.data_class().get(formdata.id)
107
    assert formdata.data['bo1'] == 'HELLO WORLD'
108

  
109
    item.fields = [{'field_id': 'bo1', 'value': '[form_var_string] GOODBYE'}]
110
    item.perform(formdata)
111
    formdata = formdef.data_class().get(formdata.id)
112
    assert formdata.data['bo1'] == 'HELLO GOODBYE'
113

  
114
    item.fields = [{'field_id': 'bo1', 'value': '{{ form.var.string }} LAZY'}]
115
    item.perform(formdata)
116
    formdata = formdef.data_class().get(formdata.id)
117
    assert formdata.data['bo1'] == 'HELLO LAZY'
118

  
119
    item.fields = [{'field_id': 'bo1', 'value': '=form.var.string'}]  # lazy python
120
    item.perform(formdata)
121
    formdata = formdef.data_class().get(formdata.id)
122
    assert formdata.data['bo1'] == 'HELLO'
123

  
124
    item.fields = [{'field_id': 'bo1', 'value': '=vars().get("form_var_string") + " PLOP"'}]
125
    item.perform(formdata)
126
    formdata = formdef.data_class().get(formdata.id)
127
    assert formdata.data['bo1'] == 'HELLO PLOP'
128

  
129
    item.fields = [
130
        {'field_id': 'bo1', 'value': '=vars().get("form_var_other") or vars().get("form_var_string")'}
131
    ]
132
    item.perform(formdata)
133
    formdata = formdef.data_class().get(formdata.id)
134
    assert formdata.data['bo1'] == 'HELLO'
135

  
136
    item.fields = [{'field_id': 'bo1', 'value': '=vars().get("form_var_bouh", "X") + " PLOP"'}]
137
    item.perform(formdata)
138
    formdata = formdef.data_class().get(formdata.id)
139
    assert formdata.data['bo1'] == 'X PLOP'
140

  
141
    item.fields = [{'field_id': 'bo1', 'value': None}]
142
    item.perform(formdata)
143
    formdata = formdef.data_class().get(formdata.id)
144
    assert formdata.data['bo1'] is None
145

  
146
    item.fields = [{'field_id': 'bo1', 'value': ''}]
147
    item.perform(formdata)
148
    formdata = formdef.data_class().get(formdata.id)
149
    assert formdata.data['bo1'] is None
150

  
151
    # check a value computed as the empty string is stored as an empty string, not None
152
    item.fields = [{'field_id': 'bo1', 'value': '=""'}]
153
    item.perform(formdata)
154
    formdata = formdef.data_class().get(formdata.id)
155
    assert formdata.data['bo1'] == ''
156
    item.fields = [{'field_id': 'bo1', 'value': '{{ does_not_exist }}'}]
157
    item.perform(formdata)
158
    formdata = formdef.data_class().get(formdata.id)
159
    assert formdata.data['bo1'] == ''
160

  
161
    assert pub.loggederror_class.count() == 0
162

  
163
    item.fields = [{'field_id': 'bo1', 'value': '= ~ invalid python ~'}]
164
    item.perform(formdata)
165
    formdata = formdef.data_class().get(formdata.id)
166
    assert pub.loggederror_class.count() == 1
167
    logged_error = pub.loggederror_class.select()[0]
168
    assert logged_error.summary == 'Failed to compute Python expression'
169
    assert logged_error.formdata_id == str(formdata.id)
170
    assert logged_error.expression == ' ~ invalid python ~'
171
    assert logged_error.expression_type == 'python'
172
    assert logged_error.exception_class == 'SyntaxError'
173
    assert logged_error.exception_message == 'invalid syntax (<string>, line 1)'
174

  
175
    pub.loggederror_class.wipe()
176
    item.fields = [{'field_id': 'bo1', 'value': '{% if bad django %}'}]
177
    item.perform(formdata)
178
    formdata = formdef.data_class().get(formdata.id)
179
    assert pub.loggederror_class.count() == 1
180
    logged_error = pub.loggederror_class.select()[0]
181
    assert logged_error.summary == 'Failed to compute template'
182
    assert logged_error.formdata_id == str(formdata.id)
183
    assert logged_error.expression == '{% if bad django %}'
184
    assert logged_error.expression_type == 'template'
185
    assert logged_error.exception_class == 'TemplateError'
186
    assert logged_error.exception_message.startswith('syntax error in Django template')
187

  
188

  
189
def test_set_backoffice_field_map(http_requests, pub):
190
    Workflow.wipe()
191
    FormDef.wipe()
192
    wf = Workflow(name='xxx')
193
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
194
    wf.backoffice_fields_formdef.fields = [
195
        MapField(id='bo1', label='1st backoffice field', type='map', varname='backoffice_blah'),
196
    ]
197
    st1 = wf.add_status('Status1')
198
    wf.store()
199

  
200
    formdef = FormDef()
201
    formdef.name = 'baz'
202
    formdef.fields = [
203
        MapField(id='1', label='Map1', type='map', varname='map1'),
204
        MapField(id='2', label='Map2', type='map', varname='map2'),
205
    ]
206
    formdef.workflow_id = wf.id
207
    formdef.store()
208

  
209
    formdata = formdef.data_class()()
210
    formdata.data = {'1': '42;10', '2': None}
211
    formdata.just_created()
212
    formdata.store()
213
    pub.substitutions.feed(formdata)
214

  
215
    item = SetBackofficeFieldsWorkflowStatusItem()
216
    item.parent = st1
217

  
218
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_map1|default:"" }}'}]
219
    item.perform(formdata)
220
    formdata = formdef.data_class().get(formdata.id)
221
    assert formdata.data.get('bo1') == '42;10'
222

  
223
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_map2|default:"" }}'}]
224
    item.perform(formdata)
225
    formdata = formdef.data_class().get(formdata.id)
226
    assert formdata.data.get('bo1') is None
227

  
228
    assert pub.loggederror_class.count() == 0
229

  
230
    item.fields = [{'field_id': 'bo1', 'value': 'invalid value'}]
231
    item.perform(formdata)
232
    formdata = formdef.data_class().get(formdata.id)
233
    assert pub.loggederror_class.count() == 1
234
    logged_error = pub.loggederror_class.select()[0]
235
    assert (
236
        logged_error.summary
237
        == "Failed to set Map field (bo1), error: invalid coordinates 'invalid value' (missing ;)"
238
    )
239
    assert logged_error.formdata_id == str(formdata.id)
240
    assert logged_error.exception_class == 'SetValueError'
241
    assert logged_error.exception_message == "invalid coordinates 'invalid value' (missing ;)"
242
    pub.loggederror_class.wipe()
243

  
244
    item.fields = [{'field_id': 'bo1', 'value': 'XXX;YYY'}]
245
    item.perform(formdata)
246
    formdata = formdef.data_class().get(formdata.id)
247
    assert pub.loggederror_class.count() == 1
248
    logged_error = pub.loggederror_class.select()[0]
249
    assert logged_error.summary == "Failed to set Map field (bo1), error: invalid coordinates 'XXX;YYY'"
250
    assert logged_error.formdata_id == str(formdata.id)
251
    assert logged_error.exception_class == 'SetValueError'
252
    assert logged_error.exception_message == "invalid coordinates 'XXX;YYY'"
253
    pub.loggederror_class.wipe()
254

  
255

  
256
def test_set_backoffice_field_decimal(http_requests, pub):
257
    Workflow.wipe()
258
    FormDef.wipe()
259
    wf = Workflow(name='xxx')
260
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
261
    wf.backoffice_fields_formdef.fields = [
262
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
263
    ]
264
    st1 = wf.add_status('Status1')
265
    wf.store()
266

  
267
    formdef = FormDef()
268
    formdef.name = 'baz'
269
    formdef.fields = [
270
        StringField(id='1', label='String', type='string', varname='string'),
271
    ]
272
    formdef.workflow_id = wf.id
273
    formdef.store()
274

  
275
    formdata = formdef.data_class()()
276
    formdata.data = {'1': '1000'}
277
    formdata.just_created()
278
    formdata.store()
279
    pub.substitutions.feed(formdata)
280

  
281
    item = SetBackofficeFieldsWorkflowStatusItem()
282
    item.parent = st1
283
    item.fields = [{'field_id': 'bo1', 'value': '{{ "100"|decimal }}'}]
284
    item.perform(formdata)
285
    assert formdef.data_class().get(formdata.id).data['bo1'] == '100'
286

  
287
    formdata.store()  # reset
288
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_string|decimal }}'}]
289
    item.perform(formdata)
290
    assert formdef.data_class().get(formdata.id).data['bo1'] == '1000'
291

  
292

  
293
def test_set_backoffice_field_file(http_requests, pub):
294
    Workflow.wipe()
295
    FormDef.wipe()
296
    wf = Workflow(name='xxx')
297
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
298
    wf.backoffice_fields_formdef.fields = [
299
        FileField(id='bo1', label='1st backoffice field', type='file', varname='backoffice_file'),
300
        StringField(id='bo2', label='2nd backoffice field', type='string'),
301
    ]
302
    st1 = wf.add_status('Status1')
303
    wf.store()
304

  
305
    formdef = FormDef()
306
    formdef.name = 'baz'
307
    formdef.fields = [
308
        FileField(id='00', label='File', type='file', varname='file'),
309
    ]
310
    formdef.workflow_id = wf.id
311
    formdef.store()
312

  
313
    item = SetBackofficeFieldsWorkflowStatusItem()
314
    item.parent = st1
315
    item.fields = [{'field_id': 'bo1', 'value': '=locals().get("form_var_file_raw")'}]
316

  
317
    # the file does not exist
318
    formdata = formdef.data_class()()
319
    formdata.data = {}
320
    formdata.just_created()
321
    formdata.store()
322
    pub.substitutions.feed(formdata)
323
    item.perform(formdata)
324
    formdata = formdef.data_class().get(formdata.id)
325
    assert formdata.data['bo1'] is None
326

  
327
    # store a PiclableUpload
328
    upload = PicklableUpload('test.jpeg', 'image/jpeg')
329
    with open(os.path.join(os.path.dirname(__file__), '..', 'image-with-gps-data.jpeg'), 'rb') as fd:
330
        image_with_gps_data = fd.read()
331
    upload.receive([image_with_gps_data])
332

  
333
    formdata = formdef.data_class()()
334
    formdata.data = {'00': upload}
335
    formdata.just_created()
336
    formdata.store()
337

  
338
    pub.substitutions.feed(formdata)
339
    item.perform(formdata)
340

  
341
    formdata = formdef.data_class().get(formdata.id)
342
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
343
    assert formdata.data['bo1'].content_type == 'image/jpeg'
344
    assert formdata.data['bo1'].get_content() == image_with_gps_data
345
    assert formdata.data['bo1'].get_base64_content() == base64.encodebytes(image_with_gps_data)
346

  
347
    # check with template string
348
    formdata = formdef.data_class()()
349
    formdata.data = {'00': upload}
350
    formdata.just_created()
351
    formdata.store()
352

  
353
    pub.substitutions.feed(formdata)
354
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file_raw}}'}]
355
    item.perform(formdata)
356

  
357
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
358
    assert formdata.data['bo1'].content_type == 'image/jpeg'
359
    assert formdata.data['bo1'].get_content() == image_with_gps_data
360

  
361
    # check with template string, without _raw
362
    formdata = formdef.data_class()()
363
    formdata.data = {'00': upload}
364
    formdata.just_created()
365
    formdata.store()
366

  
367
    pub.substitutions.feed(formdata)
368
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file}}'}]
369
    item.perform(formdata)
370

  
371
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
372
    assert formdata.data['bo1'].content_type == 'image/jpeg'
373
    assert formdata.data['bo1'].get_content() == image_with_gps_data
374

  
375
    # check |strip_metadata filter
376
    formdata = formdef.data_class()()
377
    formdata.data = {'00': upload}
378
    formdata.just_created()
379
    formdata.store()
380

  
381
    pub.substitutions.feed(formdata)
382
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file|strip_metadata}}'}]
383
    item.perform(formdata)
384

  
385
    assert formdata.data['bo1'].base_filename == 'test.jpeg'
386
    assert formdata.data['bo1'].content_type == 'image/jpeg'
387
    assert b'JFIF' in formdata.data['bo1'].get_content()
388
    assert b'<exif:XResolution>' not in formdata.data['bo1'].get_content()
389

  
390
    # check |rename_file filter
391
    formdata = formdef.data_class()()
392
    formdata.data = {'00': upload}
393
    formdata.just_created()
394
    formdata.store()
395

  
396
    pub.substitutions.feed(formdata)
397
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file|rename_file:"foobar.jpeg"}}'}]
398
    item.perform(formdata)
399

  
400
    assert formdata.data['bo1'].base_filename == 'foobar.jpeg'
401
    assert formdata.data['bo1'].content_type == 'image/jpeg'
402
    assert formdata.data['bo1'].get_content() == image_with_gps_data
403

  
404
    formdata = formdef.data_class()()
405
    formdata.data = {'00': upload}
406
    formdata.just_created()
407
    formdata.store()
408

  
409
    pub.substitutions.feed(formdata)
410
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_file|rename_file:"foobar.$ext"}}'}]
411
    item.perform(formdata)
412

  
413
    assert formdata.data['bo1'].base_filename == 'foobar.jpeg'
414
    assert formdata.data['bo1'].content_type == 'image/jpeg'
415
    assert formdata.data['bo1'].get_content() == image_with_gps_data
416

  
417
    # check |rename_file with invalid input
418
    formdata = formdef.data_class()()
419
    formdata.data = {'00': upload}
420
    formdata.just_created()
421
    formdata.store()
422

  
423
    pub.substitutions.feed(formdata)
424

  
425
    item.fields = [{'field_id': 'bo1', 'value': '{{"xxx"|rename_file:"foobar.jpeg"}}'}]
426
    item.perform(formdata)
427

  
428
    assert 'bo1' not in formdata.data
429

  
430
    # check with a template string, into a string field
431
    pub.substitutions.feed(formdata)
432
    item.fields = [{'field_id': 'bo2', 'value': '{{form_var_file}}'}]
433
    item.perform(formdata)
434

  
435
    assert formdata.data['bo2'] == 'test.jpeg'
436

  
437
    # check with template string and missing file
438
    formdata = formdef.data_class()()
439
    formdata.data = {'00': None}
440
    formdata.just_created()
441
    formdata.store()
442

  
443
    assert formdata.data.get('bo1') is None
444

  
445
    # check stripping metadata
446
    pub.substitutions.feed(formdata)
447
    item.fields = [
448
        {
449
            'field_id': 'bo1',
450
            'value': '=utils.attachment(form_var_file_raw,'
451
            + ' filename="new_"+form_var_file,'
452
            + ' content_type="my content type",'
453
            + ' strip_metadata=True)',
454
        }
455
    ]
456
    formdata = formdef.data_class()()
457
    formdata.data = {'00': upload}
458
    formdata.just_created()
459
    formdata.store()
460
    pub.substitutions.feed(formdata)
461
    item.perform(formdata)
462
    formdata = formdef.data_class().get(formdata.id)
463
    assert formdata.data['bo1'].base_filename == 'new_test.jpeg'
464
    assert formdata.data['bo1'].content_type == 'my content type'
465
    assert formdata.data['bo1'].qfilename != formdata.data['00'].qfilename
466
    assert formdata.data['00'].get_content().find(b'<exif:XResolution>')
467
    assert not Image or formdata.data['bo1'].get_content().find(b'<exif:XResolution>') == -1
468

  
469
    upload2 = PicklableUpload('test2.odt', 'application/vnd.oasis.opendocument.text')
470
    with open(os.path.join(os.path.dirname(__file__), '..', 'template.odt'), 'rb') as fd:
471
        template_odt = fd.read()
472
    upload2.receive([template_odt])
473
    formdata = formdef.data_class()()
474
    formdata.data = {'00': upload2}
475
    formdata.just_created()
476
    formdata.store()
477
    pub.substitutions.feed(formdata)
478
    item.perform(formdata)
479
    formdata = formdef.data_class().get(formdata.id)
480
    assert formdata.data['bo1'].base_filename == 'new_test2.odt'
481
    assert formdata.data['bo1'].content_type == 'my content type'
482
    assert formdata.data['bo1'].get_content() == template_odt
483
    assert formdata.data['bo1'].qfilename == formdata.data['00'].qfilename
484

  
485
    # check storing response as attachment
486
    pub.substitutions.feed(formdata)
487
    item = WebserviceCallStatusItem()
488
    item.url = 'http://remote.example.net/xml'
489
    item.varname = 'xxx'
490
    item.response_type = 'attachment'
491
    item.record_errors = True
492
    item.perform(formdata)
493
    attachment = formdata.evolution[-1].parts[-1]
494
    assert isinstance(attachment, AttachmentEvolutionPart)
495
    assert attachment.base_filename == 'xxx.xml'
496
    assert attachment.content_type == 'text/xml'
497

  
498
    formdata = formdef.data_class().get(formdata.id)
499
    pub.substitutions.feed(formdata)
500
    item = SetBackofficeFieldsWorkflowStatusItem()
501
    item.parent = st1
502
    item.fields = [{'field_id': 'bo1', 'value': '=attachments.xxx'}]
503
    item.perform(formdata)
504

  
505
    formdata = formdef.data_class().get(formdata.id)
506
    assert formdata.data['bo1'].base_filename == 'xxx.xml'
507

  
508
    # check storing a file from an assembled dictionary
509
    item = SetBackofficeFieldsWorkflowStatusItem()
510
    item.parent = st1
511
    item.fields = [{'field_id': 'bo1', 'value': '={"content": "hello world", "filename": "hello.txt"}'}]
512
    item.perform(formdata)
513

  
514
    formdata = formdef.data_class().get(formdata.id)
515
    assert formdata.data['bo1'].base_filename == 'hello.txt'
516
    assert formdata.data['bo1'].get_content() == b'hello world'
517

  
518
    # check resetting a value
519
    for value in ('', None):
520
        item = SetBackofficeFieldsWorkflowStatusItem()
521
        item.parent = st1
522
        item.fields = [{'field_id': 'bo1', 'value': value}]
523
        item.perform(formdata)
524

  
525
        formdata = formdef.data_class().get(formdata.id)
526
        assert formdata.data['bo1'] is None
527

  
528
    # set from base64 content
529
    item = SetBackofficeFieldsWorkflowStatusItem()
530
    item.parent = st1
531
    item.fields = [
532
        {'field_id': 'bo1', 'value': '={"b64_content": "SEVMTE8gV09STEQ=", "filename": "hello.txt"}'}
533
    ]
534
    item.perform(formdata)
535

  
536
    formdata = formdef.data_class().get(formdata.id)
537
    assert formdata.data['bo1'].base_filename == 'hello.txt'
538
    assert formdata.data['bo1'].get_content() == b'HELLO WORLD'
539

  
540
    hello_world = formdata.data['bo1']
541
    # check wrong value
542
    for value in ('="HELLO"', 'BAD'):
543
        formdata.data['bo1'] = hello_world
544
        formdata.store()
545

  
546
        item = SetBackofficeFieldsWorkflowStatusItem()
547
        item.parent = st1
548
        item.fields = [{'field_id': 'bo1', 'value': value}]
549

  
550
        pub.loggederror_class.wipe()
551
        item.perform(formdata)
552

  
553
        formdata = formdef.data_class().get(formdata.id)
554
        assert formdata.data['bo1'].base_filename == 'hello.txt'
555
        assert formdata.data['bo1'].get_content() == b'HELLO WORLD'
556
        assert pub.loggederror_class.count() == 1
557
        logged_error = pub.loggederror_class.select()[0]
558
        assert logged_error.summary.startswith('Failed to convert')
559
        assert logged_error.formdata_id == str(formdata.id)
560
        assert logged_error.exception_class == 'ValueError'
561

  
562
    # check wrong field
563
    item = SetBackofficeFieldsWorkflowStatusItem()
564
    item.parent = st1
565
    item.fields = [{'field_id': 'bo3', 'value': '=form_var_file_raw'}]
566
    item.perform(formdata)
567

  
568
    formdata = formdef.data_class().get(formdata.id)
569
    assert formdata.data.get('bo3') is None
570

  
571

  
572
def test_set_backoffice_field_item(pub):
573
    Workflow.wipe()
574
    FormDef.wipe()
575
    wf = Workflow(name='xxx')
576
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
577
    st1 = wf.add_status('Status1')
578
    wf.backoffice_fields_formdef.fields = [
579
        ItemField(
580
            id='bo1',
581
            label='1st backoffice field',
582
            type='item',
583
            varname='backoffice_item',
584
            items=['a', 'b', 'c'],
585
        ),
586
    ]
587
    wf.store()
588

  
589
    formdef = FormDef()
590
    formdef.name = 'baz'
591
    formdef.fields = []
592
    formdef.workflow_id = wf.id
593
    formdef.store()
594

  
595
    formdata = formdef.data_class()()
596
    formdata.data = {}
597
    formdata.just_created()
598
    formdata.store()
599

  
600
    item = SetBackofficeFieldsWorkflowStatusItem()
601
    item.parent = st1
602
    item.fields = [{'field_id': 'bo1', 'value': 'a'}]
603
    item.perform(formdata)
604

  
605
    formdata = formdef.data_class().get(formdata.id)
606
    assert formdata.data['bo1'] == 'a'
607
    assert formdata.data['bo1_display'] == 'a'
608

  
609
    datasource = {'type': 'formula', 'value': repr([('a', 'aa'), ('b', 'bb'), ('c', 'cc')])}
610

  
611
    wf.backoffice_fields_formdef.fields = [
612
        ItemField(
613
            id='bo1',
614
            label='1st backoffice field',
615
            type='item',
616
            varname='backoffice_item',
617
            data_source=datasource,
618
        ),
619
    ]
620
    wf.store()
621

  
622
    item = SetBackofficeFieldsWorkflowStatusItem()
623
    item.parent = st1
624
    item.fields = [{'field_id': 'bo1', 'value': 'a'}]
625
    item.perform(formdata)
626

  
627
    formdata = formdef.data_class().get(formdata.id)
628
    assert formdata.data['bo1'] == 'a'
629
    assert formdata.data['bo1_display'] == 'aa'
630

  
631
    datasource = {
632
        'type': 'formula',
633
        'value': repr([{'id': 'a', 'text': 'aa', 'more': 'aaa'}, {'id': 'b', 'text': 'bb', 'more': 'bbb'}]),
634
    }
635

  
636
    wf.backoffice_fields_formdef.fields = [
637
        ItemField(
638
            id='bo1',
639
            label='1st backoffice field',
640
            type='item',
641
            varname='backoffice_item',
642
            data_source=datasource,
643
        ),
644
    ]
645
    wf.store()
646

  
647
    item = SetBackofficeFieldsWorkflowStatusItem()
648
    item.parent = st1
649
    item.fields = [{'field_id': 'bo1', 'value': 'a'}]
650
    item.perform(formdata)
651

  
652
    formdata = formdef.data_class().get(formdata.id)
653
    assert formdata.data['bo1'] == 'a'
654
    assert formdata.data['bo1_display'] == 'aa'
655
    assert formdata.data['bo1_structured'] == {'id': 'a', 'more': 'aaa', 'text': 'aa'}
656

  
657
    # check when assigning using the display value
658
    formdata = formdef.data_class()()
659
    formdata.data = {}
660
    formdata.just_created()
661
    formdata.store()
662

  
663
    item = SetBackofficeFieldsWorkflowStatusItem()
664
    item.parent = st1
665
    item.fields = [{'field_id': 'bo1', 'value': 'aa'}]
666
    item.perform(formdata)
667

  
668
    formdata = formdef.data_class().get(formdata.id)
669
    assert formdata.data['bo1'] == 'a'
670
    assert formdata.data['bo1_display'] == 'aa'
671
    assert formdata.data['bo1_structured'] == {'id': 'a', 'more': 'aaa', 'text': 'aa'}
672

  
673
    # check with unknown value
674
    formdata = formdef.data_class()()
675
    formdata.data = {}
676
    formdata.just_created()
677
    formdata.store()
678

  
679
    item = SetBackofficeFieldsWorkflowStatusItem()
680
    item.parent = st1
681
    item.fields = [{'field_id': 'bo1', 'value': 'foobar'}]
682
    item.perform(formdata)
683

  
684
    formdata = formdef.data_class().get(formdata.id)
685
    assert formdata.data['bo1'] == 'foobar'
686
    assert formdata.data.get('bo1_display') is None
687
    assert formdata.data.get('bo1_structured') is None
688

  
689

  
690
def test_set_backoffice_field_card_item(pub):
691
    CardDef.wipe()
692
    Workflow.wipe()
693
    FormDef.wipe()
694

  
695
    carddef = CardDef()
696
    carddef.name = 'items'
697
    carddef.digest_templates = {'default': '{{form_var_name}}'}
698
    carddef.fields = [
699
        StringField(id='0', label='string', varname='name'),
700
        StringField(id='1', label='string', varname='attr'),
701
    ]
702
    carddef.store()
703
    carddef.data_class().wipe()
704
    for i, value in enumerate(['foo', 'bar', 'baz']):
705
        carddata = carddef.data_class()()
706
        carddata.data = {
707
            '0': value,
708
            '1': 'attr%s' % i,
709
        }
710
        carddata.just_created()
711
        carddata.store()
712
    latest_carddata = carddata
713
    latest_carddata_id = carddata.id
714
    ds = {'type': 'carddef:%s' % carddef.url_name}
715

  
716
    wf = Workflow(name='xxx')
717
    wf.store()
718

  
719
    formdef = FormDef()
720
    formdef.name = 'baz'
721
    formdef.workflow_id = wf.id
722
    formdef.fields = [
723
        ItemField(id='0', label='string', type='item', data_source=ds, display_disabled_items=True)
724
    ]
725
    formdef.store()
726

  
727
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
728
    st1 = wf.add_status('Status1')
729
    wf.backoffice_fields_formdef.fields = [
730
        ItemField(
731
            id='bo1', label='1st backoffice field', type='item', varname='backoffice_item', data_source=ds
732
        ),
733
    ]
734
    wf.store()
735

  
736
    formdef = FormDef()
737
    formdef.name = 'baz'
738
    formdef.fields = []
739
    formdef.workflow_id = wf.id
740
    formdef.store()
741

  
742
    formdata = formdef.data_class()()
743
    formdata.data = {}
744
    formdata.just_created()
745
    formdata.store()
746

  
747
    item = SetBackofficeFieldsWorkflowStatusItem()
748
    item.parent = st1
749
    item.fields = [{'field_id': 'bo1', 'value': str(latest_carddata_id)}]
750
    item.perform(formdata)
751

  
752
    formdata = formdef.data_class().get(formdata.id)
753
    assert formdata.data['bo1'] == str(latest_carddata_id)
754
    assert formdata.data['bo1_display'] == 'baz'
755
    assert formdata.data['bo1_structured']['attr'] == 'attr2'
756

  
757
    # reset, and get by display id value
758
    formdata.data = {}
759
    formdata.store()
760
    item.fields = [{'field_id': 'bo1', 'value': latest_carddata.get_display_id()}]
761
    item.perform(formdata)
762
    formdata = formdef.data_class().get(formdata.id)
763
    assert formdata.data['bo1'] == str(latest_carddata_id)
764
    assert formdata.data['bo1_display'] == 'baz'
765
    assert formdata.data['bo1_structured']['attr'] == 'attr2'
766

  
767
    # reset, and get by text value
768
    formdata.data = {}
769
    formdata.store()
770
    item.fields = [{'field_id': 'bo1', 'value': 'bar'}]
771
    item.perform(formdata)
772
    formdata = formdef.data_class().get(formdata.id)
773
    assert formdata.data['bo1'] != str(latest_carddata_id)
774
    assert formdata.data['bo1_display'] == 'bar'
775
    assert formdata.data['bo1_structured']['attr'] == 'attr1'
776

  
777
    # reset, with unknown value
778
    pub.loggederror_class.wipe()
779
    formdata.data = {}
780
    formdata.store()
781
    item.fields = [{'field_id': 'bo1', 'value': 'xxx'}]
782
    item.perform(formdata)
783
    formdata = formdef.data_class().get(formdata.id)
784
    assert formdata.data.get('bo1') is None  # invalid value is not stored
785
    assert formdata.data.get('bo1_display') is None
786
    assert formdata.data.get('bo1_structured') is None
787
    assert pub.loggederror_class.count() == 1
788
    logged_error = pub.loggederror_class.select()[0]
789
    assert logged_error.summary.startswith('Failed to convert')
790

  
791
    # reset, and get empty value
792
    formdata.data = {}
793
    formdata.store()
794
    item.fields = [{'field_id': 'bo1', 'value': ''}]
795
    item.perform(formdata)
796
    formdata = formdef.data_class().get(formdata.id)
797
    assert formdata.data['bo1'] is None
798
    assert formdata.data.get('bo1_display') is None
799
    assert formdata.data.get('bo1_structured') is None
800

  
801

  
802
def test_set_backoffice_field_items(pub):
803
    Workflow.wipe()
804
    FormDef.wipe()
805
    wf = Workflow(name='xxx')
806
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
807
    st1 = wf.add_status('Status1')
808
    wf.backoffice_fields_formdef.fields = [
809
        ItemsField(
810
            id='bo1',
811
            label='1st backoffice field',
812
            type='items',
813
            varname='backoffice_item',
814
            items=['a', 'b', 'c'],
815
        ),
816
    ]
817
    wf.store()
818

  
819
    formdef = FormDef()
820
    formdef.name = 'baz'
821
    formdef.fields = []
822
    formdef.workflow_id = wf.id
823
    formdef.store()
824

  
825
    formdata = formdef.data_class()()
826
    formdata.data = {}
827
    formdata.just_created()
828
    formdata.store()
829

  
830
    item = SetBackofficeFieldsWorkflowStatusItem()
831
    item.parent = st1
832
    item.fields = [{'field_id': 'bo1', 'value': "=['a', 'b']"}]
833
    item.perform(formdata)
834

  
835
    formdata = formdef.data_class().get(formdata.id)
836
    assert formdata.data['bo1'] == ['a', 'b']
837
    assert formdata.data['bo1_display'] == 'a, b'
838

  
839
    datasource = {'type': 'formula', 'value': repr([('a', 'aa'), ('b', 'bb'), ('c', 'cc')])}
840

  
841
    wf.backoffice_fields_formdef.fields = [
842
        ItemsField(
843
            id='bo1',
844
            label='1st backoffice field',
845
            type='items',
846
            varname='backoffice_item',
847
            data_source=datasource,
848
        ),
849
    ]
850
    wf.store()
851

  
852
    item = SetBackofficeFieldsWorkflowStatusItem()
853
    item.parent = st1
854
    item.fields = [{'field_id': 'bo1', 'value': "=['a', 'b']"}]
855
    item.perform(formdata)
856

  
857
    formdata = formdef.data_class().get(formdata.id)
858
    assert formdata.data['bo1'] == ['a', 'b']
859
    assert formdata.data['bo1_display'] == 'aa, bb'
860

  
861
    datasource = {
862
        'type': 'formula',
863
        'value': repr(
864
            [
865
                {'id': 'a', 'text': 'aa', 'more': 'aaa'},
866
                {'id': 'b', 'text': 'bb', 'more': 'bbb'},
867
                {'id': 'c', 'text': 'cc', 'more': 'ccc'},
868
            ]
869
        ),
870
    }
871

  
872
    wf.backoffice_fields_formdef.fields = [
873
        ItemsField(
874
            id='bo1',
875
            label='1st backoffice field',
876
            type='items',
877
            varname='backoffice_item',
878
            data_source=datasource,
879
        ),
880
    ]
881
    wf.store()
882

  
883
    item = SetBackofficeFieldsWorkflowStatusItem()
884
    item.parent = st1
885
    item.fields = [{'field_id': 'bo1', 'value': "=['a', 'c']"}]
886
    item.perform(formdata)
887

  
888
    formdata = formdef.data_class().get(formdata.id)
889
    assert formdata.data['bo1'] == ['a', 'c']
890
    assert formdata.data['bo1_display'] == 'aa, cc'
891
    assert len(formdata.data['bo1_structured']) == 2
892
    assert {'id': 'a', 'more': 'aaa', 'text': 'aa'} in formdata.data['bo1_structured']
893
    assert {'id': 'c', 'more': 'ccc', 'text': 'cc'} in formdata.data['bo1_structured']
894

  
895
    # from formdata field
896
    formdef.fields = [
897
        ItemsField(id='1', label='field', type='items', varname='items', data_source=datasource),
898
    ]
899
    formdef.store()
900

  
901
    formdata = formdef.data_class()()
902
    formdata.data = {'1': ['a', 'c']}
903
    formdata.data['1_display'] = formdef.fields[0].store_display_value(formdata.data, '1')
904
    formdata.data['1_structured'] = formdef.fields[0].store_structured_value(formdata.data, '1')
905
    formdata.just_created()
906
    formdata.store()
907
    pub.substitutions.feed(formdata)
908

  
909
    item = SetBackofficeFieldsWorkflowStatusItem()
910
    item.parent = st1
911
    item.fields = [{'field_id': 'bo1', 'value': "=form_var_items_raw"}]
912
    item.perform(formdata)
913

  
914
    assert formdata.data['bo1'] == ['a', 'c']
915
    assert formdata.data['bo1_display'] == 'aa, cc'
916
    assert len(formdata.data['bo1_structured']) == 2
917
    assert {'id': 'a', 'more': 'aaa', 'text': 'aa'} in formdata.data['bo1_structured']
918
    assert {'id': 'c', 'more': 'ccc', 'text': 'cc'} in formdata.data['bo1_structured']
919

  
920
    # with a template
921
    formdata = formdef.data_class()()
922
    formdata.data = {'1': ['a', 'c']}
923
    formdata.data['1_display'] = formdef.fields[0].store_display_value(formdata.data, '1')
924
    formdata.data['1_structured'] = formdef.fields[0].store_structured_value(formdata.data, '1')
925
    formdata.just_created()
926
    formdata.store()
927
    pub.substitutions.reset()
928
    pub.substitutions.feed(formdata)
929

  
930
    item.fields = [{'field_id': 'bo1', 'value': "{{form_var_items_raw}}"}]
931
    item.perform(formdata)
932

  
933
    # using a single int
934
    datasource = {
935
        'type': 'formula',
936
        'value': repr(
937
            [
938
                {'id': 1, 'text': 'aa', 'more': 'aaa'},
939
                {'id': 2, 'text': 'bb', 'more': 'bbb'},
940
                {'id': 3, 'text': 'cc', 'more': 'ccc'},
941
            ]
942
        ),
943
    }
944

  
945
    wf.backoffice_fields_formdef.fields = [
946
        ItemsField(
947
            id='bo1',
948
            label='1st backoffice field',
949
            type='items',
950
            varname='backoffice_item',
951
            data_source=datasource,
952
        ),
953
    ]
954
    wf.store()
955

  
956
    item = SetBackofficeFieldsWorkflowStatusItem()
957
    item.parent = st1
958
    item.fields = [{'field_id': 'bo1', 'value': "=2"}]
959
    item.perform(formdata)
960

  
961
    formdata = formdef.data_class().get(formdata.id)
962
    assert formdata.data['bo1'] == ['2']
963
    assert formdata.data['bo1_display'] == 'bb'
964
    assert len(formdata.data['bo1_structured']) == 1
965

  
966
    # using an invalid value
967
    formdata.data = {}
968
    formdata.store()
969
    pub.loggederror_class.wipe()
970
    item = SetBackofficeFieldsWorkflowStatusItem()
971
    item.parent = st1
972
    item.fields = [{'field_id': 'bo1', 'value': "=Ellipsis"}]
973
    item.perform(formdata)
974
    assert pub.loggederror_class.count() == 1
975
    logged_error = pub.loggederror_class.select()[0]
976
    assert 'Failed to convert' in logged_error.summary
977

  
978
    # using a string with multiple values
979
    item = SetBackofficeFieldsWorkflowStatusItem()
980
    item.parent = st1
981
    item.fields = [{'field_id': 'bo1', 'value': "1|3"}]
982
    item.perform(formdata)
983

  
984
    formdata = formdef.data_class().get(formdata.id)
985
    assert formdata.data['bo1'] == ['1', '3']
986
    assert formdata.data['bo1_display'] == 'aa, cc'
987
    assert len(formdata.data['bo1_structured']) == 2
988
    assert {'id': 1, 'more': 'aaa', 'text': 'aa'} in formdata.data['bo1_structured']
989
    assert {'id': 3, 'more': 'ccc', 'text': 'cc'} in formdata.data['bo1_structured']
990

  
991

  
992
def test_set_backoffice_field_date(pub):
993
    Workflow.wipe()
994
    FormDef.wipe()
995
    wf = Workflow(name='xxx')
996
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
997
    st1 = wf.add_status('Status1')
998
    wf.backoffice_fields_formdef.fields = [
999
        DateField(id='bo1', label='1st backoffice field', type='date', varname='backoffice_date'),
1000
    ]
1001
    wf.store()
1002

  
1003
    formdef = FormDef()
1004
    formdef.name = 'baz'
1005
    formdef.fields = []
1006
    formdef.workflow_id = wf.id
1007
    formdef.store()
1008

  
1009
    formdata = formdef.data_class()()
1010
    formdata.data = {}
1011
    formdata.just_created()
1012
    formdata.store()
1013

  
1014
    item = SetBackofficeFieldsWorkflowStatusItem()
1015
    item.parent = st1
1016
    item.fields = [{'field_id': 'bo1', 'value': "=utils.today()"}]
1017
    item.perform(formdata)
1018

  
1019
    formdata = formdef.data_class().get(formdata.id)
1020
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date.today()
1021

  
1022
    formdata.data['bo1'] = None
1023
    formdata.store()
1024
    item = SetBackofficeFieldsWorkflowStatusItem()
1025
    item.parent = st1
1026
    item.fields = [{'field_id': 'bo1', 'value': '{% now "j/n/Y" %}'}]
1027
    item.perform(formdata)
1028

  
1029
    formdata = formdef.data_class().get(formdata.id)
1030
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date.today()
1031

  
1032
    item = SetBackofficeFieldsWorkflowStatusItem()
1033
    item.parent = st1
1034
    item.fields = [{'field_id': 'bo1', 'value': "23/3/2017"}]
1035
    item.perform(formdata)
1036

  
1037
    formdata = formdef.data_class().get(formdata.id)
1038
    assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23)
1039

  
1040
    # invalid values => do nothing
1041
    assert pub.loggederror_class.count() == 0
1042
    for value in ('plop', '={}', '=[]'):
1043
        item = SetBackofficeFieldsWorkflowStatusItem()
1044
        item.parent = st1
1045
        item.fields = [{'field_id': 'bo1', 'value': value}]
1046

  
1047
        pub.loggederror_class.wipe()
1048
        item.perform(formdata)
1049
        formdata = formdef.data_class().get(formdata.id)
1050
        assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23)
1051
        assert pub.loggederror_class.count() == 1
1052
        assert pub.loggederror_class.select()[0].summary.startswith('Failed to convert')
1053

  
1054
    # None : empty date
1055
    item = SetBackofficeFieldsWorkflowStatusItem()
1056
    item.parent = st1
1057
    item.fields = [{'field_id': 'bo1', 'value': None}]
1058
    item.perform(formdata)
1059

  
1060
    formdata = formdef.data_class().get(formdata.id)
1061
    assert formdata.data['bo1'] is None
1062

  
1063

  
1064
def test_set_backoffice_field_boolean(pub):
1065
    Workflow.wipe()
1066
    FormDef.wipe()
1067
    wf = Workflow(name='xxx')
1068
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1069
    st1 = wf.add_status('Status1')
1070
    wf.backoffice_fields_formdef.fields = [
1071
        BoolField(id='bo1', label='1st backoffice field', type='bool', varname='backoffice_bool'),
1072
    ]
1073
    wf.store()
1074

  
1075
    formdef = FormDef()
1076
    formdef.name = 'baz'
1077
    formdef.fields = [BoolField(id='1', label='field', type='bool', varname='foo')]
1078
    formdef.workflow_id = wf.id
1079
    formdef.store()
1080

  
1081
    formdata = formdef.data_class()()
1082
    formdata.data = {'1': True}
1083
    formdata.just_created()
1084
    formdata.store()
1085
    get_publisher().substitutions.feed(formdata)
1086

  
1087
    for value in ('=True', '=form_var_foo_raw', '{{ form_var_foo_raw }}', 'True', 'Yes', 'true', 'yes'):
1088
        item = SetBackofficeFieldsWorkflowStatusItem()
1089
        item.parent = st1
1090
        item.fields = [{'field_id': 'bo1', 'value': value}]
1091
        item.perform(formdata)
1092
        formdata = formdef.data_class().get(formdata.id)
1093
        assert formdata.data['bo1'] is True
1094
        formdata.data['bo1'] = None
1095
        formdata.store()
1096

  
1097
    for value in ('=False', '=not(form_var_foo_raw)', 'False', 'plop', ''):
1098
        item = SetBackofficeFieldsWorkflowStatusItem()
1099
        item.parent = st1
1100
        item.fields = [{'field_id': 'bo1', 'value': value}]
1101
        item.perform(formdata)
1102
        formdata = formdef.data_class().get(formdata.id)
1103
        assert formdata.data['bo1'] is False
1104
        formdata.data['bo1'] = None
1105
        formdata.store()
1106

  
1107

  
1108
def test_set_backoffice_field_str_time_filter(pub):
1109
    Workflow.wipe()
1110
    FormDef.wipe()
1111
    wf = Workflow(name='xxx')
1112
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1113
    st1 = wf.add_status('Status1')
1114
    wf.backoffice_fields_formdef.fields = [
1115
        StringField(id='bo1', label='1st backoffice field', type='str', varname='backoffice_str'),
1116
    ]
1117
    wf.store()
1118

  
1119
    formdef = FormDef()
1120
    formdef.name = 'baz'
1121
    formdef.fields = [StringField(id='1', label='field', type='str', varname='foo')]
1122
    formdef.workflow_id = wf.id
1123
    formdef.store()
1124

  
1125
    formdata = formdef.data_class()()
1126
    formdata.data = {'1': '09:00'}
1127
    formdata.just_created()
1128
    formdata.store()
1129
    get_publisher().substitutions.feed(formdata)
1130

  
1131
    item = SetBackofficeFieldsWorkflowStatusItem()
1132
    item.parent = st1
1133
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_foo|time:"H:i:s" }}'}]
1134
    item.perform(formdata)
1135
    formdata = formdef.data_class().get(formdata.id)
1136
    assert formdata.data['bo1'] == '09:00:00'
1137
    formdata.data['bo1'] = None
1138
    formdata.store()
1139

  
1140
    # |time will yield the default django reprentation
1141
    item = SetBackofficeFieldsWorkflowStatusItem()
1142
    item.parent = st1
1143
    item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_foo|time }}'}]
1144
    item.perform(formdata)
1145
    formdata = formdef.data_class().get(formdata.id)
1146
    assert formdata.data['bo1'] == '9 a.m.'
1147
    formdata.data['bo1'] = None
1148
    formdata.store()
1149

  
1150

  
1151
def test_set_backoffice_field_block(pub):
1152
    BlockDef.wipe()
1153
    Workflow.wipe()
1154
    FormDef.wipe()
1155

  
1156
    block = BlockDef()
1157
    block.name = 'foobar'
1158
    block.digest_template = 'X{{foobar_var_foo}}Y'
1159
    block.fields = [
1160
        StringField(id='123', required=True, label='Test', type='string', varname='foo'),
1161
        StringField(id='234', required=True, label='Test2', type='string', varname='bar'),
1162
    ]
1163
    block.store()
1164

  
1165
    wf = Workflow(name='xxx')
1166
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1167
    st1 = wf.add_status('Status1')
1168
    wf.backoffice_fields_formdef.fields = [
1169
        BlockField(id='bo1', label='1st backoffice field', type='block:foobar'),
1170
        StringField(id='bo2', label='2nd backoffice field', type='string'),
1171
    ]
1172
    wf.store()
1173

  
1174
    formdef = FormDef()
1175
    formdef.name = 'baz'
1176
    formdef.fields = [
1177
        BlockField(id='1', label='test', type='block:foobar', max_items=3, varname='foo'),
1178
    ]
1179
    formdef.workflow_id = wf.id
1180
    formdef.store()
1181

  
1182
    formdata = formdef.data_class()()
1183
    # value from test_block_digest in tests/test_form_pages.py
1184
    formdata.data = {
1185
        '1': {
1186
            'data': [{'123': 'foo', '234': 'bar'}, {'123': 'foo2', '234': 'bar2'}],
1187
            'schema': {'123': 'string', '234': 'string'},
1188
        },
1189
        '1_display': 'XfooY, Xfoo2Y',
1190
    }
1191
    formdata.just_created()
1192
    formdata.store()
1193
    get_publisher().substitutions.feed(formdata)
1194

  
1195
    item = SetBackofficeFieldsWorkflowStatusItem()
1196
    item.parent = st1
1197
    item.fields = [{'field_id': 'bo1', 'value': '{{form_var_foo_raw}}'}]
1198
    item.perform(formdata)
1199
    formdata = formdef.data_class().get(formdata.id)
1200
    assert formdata.data['bo1'] == formdata.data['1']
1201
    assert formdata.data['bo1_display'] == formdata.data['1_display']
1202

  
1203
    # without _raw suffix
1204
    formdata = formdef.data_class()()
1205
    # value from test_block_digest in tests/test_form_pages.py
1206
    formdata.data = {
1207
        '1': {
1208
            'data': [{'123': 'foo', '234': 'bar'}, {'123': 'foo2', '234': 'bar2'}],
1209
            'schema': {'123': 'string', '234': 'string'},
1210
        },
1211
        '1_display': 'XfooY, Xfoo2Y',
1212
    }
1213
    formdata.just_created()
1214
    formdata.store()
1215
    get_publisher().substitutions.reset()
1216
    get_publisher().substitutions.feed(formdata)
1217

  
1218
    item = SetBackofficeFieldsWorkflowStatusItem()
1219
    item.parent = st1
1220
    item.fields = [
1221
        {'field_id': 'bo1', 'value': '{{form_var_foo}}'},
1222
        {'field_id': 'bo2', 'value': '{{form_var_foo}}'},
1223
    ]
1224
    item.perform(formdata)
1225
    formdata = formdef.data_class().get(formdata.id)
1226
    assert formdata.data['bo1'] == formdata.data['1']
1227
    assert formdata.data['bo1_display'] == formdata.data['1_display']
1228
    assert formdata.data['bo2'] == formdata.data['1_display']
1229

  
1230

  
1231
def test_set_backoffice_field_block_template_tag(pub):
1232
    BlockDef.wipe()
1233
    Workflow.wipe()
1234
    FormDef.wipe()
1235

  
1236
    block = BlockDef()
1237
    block.name = 'foobar'
1238
    block.digest_template = 'X{{foobar_var_foo}}Y'
1239
    block.fields = [
1240
        StringField(id='123', required=True, label='Test', type='string', varname='foo'),
1241
        StringField(id='234', required=True, label='Test2', type='string', varname='bar'),
1242
    ]
1243
    block.store()
1244

  
1245
    wf = Workflow(name='xxx')
1246
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1247
    st1 = wf.add_status('Status1')
1248
    wf.backoffice_fields_formdef.fields = [
1249
        BlockField(id='bo1', label='1st backoffice field', max_items=3, type='block:foobar'),
1250
    ]
1251
    wf.store()
1252

  
1253
    formdef = FormDef()
1254
    formdef.name = 'baz'
1255
    formdef.fields = [
1256
        StringField(id='1', label='test', varname='foo'),
1257
    ]
1258
    formdef.workflow_id = wf.id
1259
    formdef.store()
1260

  
1261
    formdata = formdef.data_class()()
1262
    formdata.data = {'1': 'plop'}
1263
    formdata.just_created()
1264
    formdata.store()
1265
    get_publisher().substitutions.feed(formdata)
1266

  
1267
    item = SetBackofficeFieldsWorkflowStatusItem()
1268
    item.parent = st1
1269
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value foo=form_var_foo bar="xxx" %}'}]
1270
    item.perform(formdata)
1271
    formdata = formdef.data_class().get(formdata.id)
1272
    assert formdata.data['bo1'] == {
1273
        'data': [{'123': 'plop', '234': 'xxx'}],
1274
        'schema': {'123': 'string', '234': 'string'},
1275
    }
1276
    assert formdata.data['bo1_display'] == 'XplopY'
1277

  
1278
    # override
1279
    item = SetBackofficeFieldsWorkflowStatusItem()
1280
    item.parent = st1
1281
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value foo=form_var_foo bar="yyy" %}'}]
1282
    item.perform(formdata)
1283
    formdata = formdef.data_class().get(formdata.id)
1284
    assert formdata.data['bo1'] == {
1285
        'data': [{'123': 'plop', '234': 'yyy'}],
1286
        'schema': {'123': 'string', '234': 'string'},
1287
    }
1288
    assert formdata.data['bo1_display'] == 'XplopY'
1289

  
1290
    # append
1291
    item = SetBackofficeFieldsWorkflowStatusItem()
1292
    item.parent = st1
1293
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value append=True foo="zzz" bar=form_var_foo %}'}]
1294
    item.perform(formdata)
1295
    formdata = formdef.data_class().get(formdata.id)
1296
    assert formdata.data['bo1'] == {
1297
        'data': [{'123': 'plop', '234': 'yyy'}, {'123': 'zzz', '234': 'plop'}],
1298
        'schema': {'123': 'string', '234': 'string'},
1299
    }
1300
    assert formdata.data['bo1_display'] == 'XplopY, XzzzY'
1301

  
1302
    # merge (into last row)
1303
    item = SetBackofficeFieldsWorkflowStatusItem()
1304
    item.parent = st1
1305
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value merge=True foo="AAA" %}'}]
1306
    item.perform(formdata)
1307
    formdata = formdef.data_class().get(formdata.id)
1308
    assert formdata.data['bo1'] == {
1309
        'data': [{'123': 'plop', '234': 'yyy'}, {'123': 'AAA', '234': 'plop'}],
1310
        'schema': {'123': 'string', '234': 'string'},
1311
    }
1312
    assert formdata.data['bo1_display'] == 'XplopY, XAAAY'
1313

  
1314
    # merge (into given row)
1315
    item = SetBackofficeFieldsWorkflowStatusItem()
1316
    item.parent = st1
1317
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value merge=0 foo="BBB" %}'}]
1318
    item.perform(formdata)
1319
    formdata = formdef.data_class().get(formdata.id)
1320
    assert formdata.data['bo1'] == {
1321
        'data': [{'123': 'BBB', '234': 'yyy'}, {'123': 'AAA', '234': 'plop'}],
1322
        'schema': {'123': 'string', '234': 'string'},
1323
    }
1324
    assert formdata.data['bo1_display'] == 'XBBBY, XAAAY'
1325

  
1326
    # merge with indexerror (ignored)
1327
    item = SetBackofficeFieldsWorkflowStatusItem()
1328
    item.parent = st1
1329
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value merge=50 foo="CCC" %}'}]
1330
    item.perform(formdata)
1331
    formdata = formdef.data_class().get(formdata.id)
1332
    assert formdata.data['bo1'] == {
1333
        'data': [{'123': 'BBB', '234': 'yyy'}, {'123': 'AAA', '234': 'plop'}],
1334
        'schema': {'123': 'string', '234': 'string'},
1335
    }
1336
    assert formdata.data['bo1_display'] == 'XBBBY, XAAAY'
1337

  
1338
    # "item" subfield, make sure raw and display and structured values are stored
1339
    datasource = {
1340
        'type': 'formula',
1341
        'value': repr(
1342
            [
1343
                {'id': 'a', 'text': 'aa', 'more': 'aaa'},
1344
                {'id': 'b', 'text': 'bb', 'more': 'bbb'},
1345
                {'id': 'c', 'text': 'cc', 'more': 'ccc'},
1346
            ]
1347
        ),
1348
    }
1349
    block.fields.append(
1350
        ItemField(id='345', label='Test3', type='item', varname='item', data_source=datasource)
1351
    )
1352
    block.store()
1353
    wf.backoffice_fields_formdef.fields[0]._block = None  # remove cache
1354

  
1355
    item = SetBackofficeFieldsWorkflowStatusItem()
1356
    item.parent = st1
1357
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value item="b" %}'}]
1358
    item.perform(formdata)
1359
    formdata = formdef.data_class().get(formdata.id)
1360
    assert formdata.data['bo1'] == {
1361
        'data': [
1362
            {'345': 'b', '345_display': 'bb', '345_structured': {'id': 'b', 'text': 'bb', 'more': 'bbb'}}
1363
        ],
1364
        'schema': {'123': 'string', '234': 'string', '345': 'item'},
1365
    }
1366
    assert formdata.data['bo1_display'] == 'XNoneY'
1367

  
1368
    # append to invalid existing value (should not happen)
1369
    formdata.data['bo1'] = {'invalid': 'value'}
1370
    item = SetBackofficeFieldsWorkflowStatusItem()
1371
    item.parent = st1
1372
    item.fields = [{'field_id': 'bo1', 'value': '{% block_value item="b" append=True %}'}]
1373
    item.perform(formdata)
1374
    formdata = formdef.data_class().get(formdata.id)
1375
    assert formdata.data['bo1'] == {
1376
        'data': [
1377
            {'345': 'b', '345_display': 'bb', '345_structured': {'id': 'b', 'text': 'bb', 'more': 'bbb'}}
1378
        ],
1379
        'schema': {'123': 'string', '234': 'string', '345': 'item'},
1380
    }
1381
    assert formdata.data['bo1_display'] == 'XNoneY'
1382

  
1383

  
1384
def test_set_backoffice_field_invalid_block_value(pub):
1385
    BlockDef.wipe()
1386
    Workflow.wipe()
1387
    FormDef.wipe()
1388

  
1389
    block = BlockDef()
1390
    block.name = 'foobar'
1391
    block.fields = [StringField(id='123', required=True, label='Test', type='string', varname='foo')]
1392
    block.store()
1393

  
1394
    wf = Workflow(name='xxx')
1395
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1396
    st1 = wf.add_status('Status1')
1397
    wf.backoffice_fields_formdef.fields = [
1398
        BlockField(id='bo1', label='1st backoffice field', max_items=3, type='block:foobar'),
1399
    ]
1400
    wf.store()
1401

  
1402
    formdef = FormDef()
1403
    formdef.name = 'baz'
1404
    formdef.fields = []
1405
    formdef.workflow_id = wf.id
1406
    formdef.store()
1407

  
1408
    formdata = formdef.data_class()()
1409
    formdata.just_created()
1410
    formdata.store()
1411
    get_publisher().substitutions.feed(formdata)
1412

  
1413
    item = SetBackofficeFieldsWorkflowStatusItem()
1414
    item.parent = st1
1415
    item.fields = [{'field_id': 'bo1', 'value': 'xxx'}]
1416

  
1417
    pub.loggederror_class.wipe()
1418
    item.perform(formdata)
1419
    assert pub.loggederror_class.count() == 1
1420
    logged_error = pub.loggederror_class.select()[0]
1421
    assert (
1422
        logged_error.summary
1423
        == 'Failed to set Field Block (foobar) field (bo1), error: invalid value for block'
1424
    )
1425

  
1426
    formdata = formdef.data_class().get(formdata.id)
1427
    assert not formdata.data.get('bo1')
1428

  
1429

  
1430
def test_set_backoffice_field_immediate_use(http_requests, pub):
1431
    Workflow.wipe()
1432
    FormDef.wipe()
1433
    wf = Workflow(name='xxx')
1434
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
1435
    wf.backoffice_fields_formdef.fields = [
1436
        StringField(id='bo1', label='1st backoffice field', type='string', varname='backoffice_blah'),
1437
        StringField(id='bo2', label='2nd backoffice field', type='string', varname='backoffice_barr'),
1438
    ]
1439
    st1 = wf.add_status('Status1')
1440
    wf.store()
1441

  
1442
    formdef = FormDef()
1443
    formdef.name = 'baz'
1444
    formdef.fields = [
1445
        StringField(id='00', label='String', type='string', varname='string'),
1446
    ]
1447
    formdef.workflow_id = wf.id
1448
    formdef.store()
1449

  
1450
    formdata = formdef.data_class()()
1451
    formdata.data = {'00': 'HELLO'}
1452
    formdata.just_created()
1453
    formdata.store()
1454
    item = SetBackofficeFieldsWorkflowStatusItem()
1455
    item.parent = st1
1456

  
1457
    item.fields = [
1458
        {'field_id': 'bo1', 'value': '{{form_var_string}}'},
1459
    ]
1460
    pub.substitutions.reset()
1461
    pub.substitutions.feed(formdata)
1462
    item.perform(formdata)
1463
    formdata = formdef.data_class().get(formdata.id)
1464
    assert formdata.data.get('bo1') == 'HELLO'
1465

  
1466
    item.fields = [
1467
        {'field_id': 'bo1', 'value': 'WORLD'},
1468
    ]
1469
    pub.substitutions.reset()
1470
    pub.substitutions.feed(formdata)
1471
    item.perform(formdata)
1472
    formdata = formdef.data_class().get(formdata.id)
1473
    assert formdata.data.get('bo1') == 'WORLD'
1474

  
1475
    item.fields = [
1476
        {'field_id': 'bo1', 'value': 'X{{form_var_string}}X'},
1477
        {'field_id': 'bo2', 'value': "Y{{form_var_backoffice_blah}}Y"},
1478
    ]
1479
    pub.substitutions.reset()
1480
    pub.substitutions.feed(formdata)
1481
    item.perform(formdata)
1482
    formdata = formdef.data_class().get(formdata.id)
1483
    assert formdata.data.get('bo1') == 'XHELLOX'
1484
    assert formdata.data.get('bo2') == 'YXHELLOXY'
0
-