Commit c0c05a19 authored by Fabien Morin's avatar Fabien Morin

2008-06-04 fabien

* enhance EGov_Base_editAndNextStep script, now it should be possible to not
have a modified Base_edit script
* moved here some script from safi_tva bt

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@21324 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent bc1736fa
msgid ""
msgstr "Project-Id-Version: ERP5 Localized Interface\n"
"POT-Creation-Date: 2008-05-29 14:05+CET\n"
"PO-Revision-Date: 2008-05-29 14:05+CET\n"
"POT-Creation-Date: 2008-06-04 19:06+CET\n"
"PO-Revision-Date: 2008-06-04 19:06+CET\n"
"Last-Translator: <>\n"
"Language-Team: fr <>\n"
"MIME-Version: 1.0\n"
......@@ -561,6 +561,9 @@ msgstr "Alarme"
msgid "Alarm Tool"
msgstr "Outil Alarme"
msgid "All Applications"
msgstr ""
msgid "All Documents"
msgstr "Tous les documents"
......@@ -570,15 +573,24 @@ msgstr ""
msgid "All Rights Reserved to the DGID"
msgstr "Tous Droits réservés à la DGID"
msgid "All attached files add to your application"
msgstr ""
msgid "All documents"
msgstr ""
msgid "All documents add to your requests"
msgstr "Tous les documents ajoutés à votre demande"
msgid "All documents resulting of your application"
msgstr ""
msgid "All documents resulting of your requests"
msgstr "Tous les documents résultants de votre demande"
msgid "All events related on your application"
msgstr ""
msgid "All pending Applications"
msgstr "Toutes les demandes en cours"
......@@ -2322,9 +2334,15 @@ msgstr ""
msgid "ERP5 eGov Universal Workflow"
msgstr ""
msgid "ERP5 eGov anonymous Workflow"
msgstr ""
msgid "ERP5 eGov test Workflow"
msgstr ""
msgid "ERP5 eGov universal Workflow"
msgstr ""
msgid "Edit"
msgstr ""
......@@ -2766,6 +2784,9 @@ msgstr "Clé IBAN"
msgid "ID"
msgstr ""
msgid "ID Card"
msgstr ""
msgid "ID of a page template or form which defines the rendering layout for contents"
msgstr ""
......@@ -3123,6 +3144,9 @@ msgstr "Déconnexion"
msgid "Long Title"
msgstr ""
msgid "M0 Form"
msgstr ""
msgid "MIME Type"
msgstr ""
......@@ -3144,6 +3168,9 @@ msgstr ""
msgid "Manage Business Templates"
msgstr ""
msgid "Mandate Form"
msgstr ""
msgid "Mandate Form Module"
msgstr ""
......@@ -3456,6 +3483,9 @@ msgstr "Seulement les document de type"
msgid "Only document whith this actor"
msgstr ""
msgid "Only document with this actor"
msgstr ""
msgid "Open"
msgstr "Ouvert"
......@@ -4695,6 +4725,9 @@ msgstr "Tout Montrer"
msgid "Si vous n'êtes pas un citoyen sénégalais, vous devez joindre votre carte d'identité"
msgstr ""
msgid "Sign"
msgstr ""
msgid "Signature Preview"
msgstr "Aperçu de la signature"
......@@ -6057,6 +6090,12 @@ msgstr "Vous avez été déconnecté. Merci d'avoir utilisé ce site web."
msgid "You have no documents."
msgstr ""
msgid "You have to join the boss of the company identity card"
msgstr ""
msgid "You have to provide a M0 form copy"
msgstr ""
msgid "You may now logout or go home and proceed to other applications:"
msgstr "Vous pouvez maintenant vous déconnecter ou retourner à l'accueil pour effectuer d'autres demandes :"
......@@ -6072,6 +6111,9 @@ msgstr "Vous trouverez ci-dessous la liste des pièces jointe qui doivent ou peu
msgid "Your application has been submitted successfully"
msgstr "Votre demande à bien été prise en compte"
msgid "Your application has been submitted successfully under the reference"
msgstr ""
msgid "Your request has been submitted successfully"
msgstr "Votre demande à bien été prise en compte"
......@@ -6153,6 +6195,9 @@ msgstr ""
msgid "cash_status"
msgstr "Etat de valeur"
msgid "clean"
msgstr ""
msgid "closed"
msgstr ""
......
......@@ -86,7 +86,7 @@ if context.portal_membership.isAnonymousUser():\n
\n
next_url_dict = {\n
\'DeclarationTVA_view\' : \'DeclarationTVA_viewAttachmentList\',\n
\'DeclarationTVA_viewAttachmentList\' : \'PDFDocument_viewLoginInformation\'\n
\'SubscriptionForm_view\': \'SubscriptionForm_viewAttachmentList\',\n
}\n
\n
# edit the document with the entered data before to change of state\n
......@@ -101,15 +101,7 @@ context.Base_edit(form_id=form_id, \n
\n
if not next_url_dict.has_key(form_id):\n
next_url = \'PDFDocument_viewLoginInformation\'\n
context.submit()\n
else:\n
next_url = next_url_dict[form_id]\n
\n
successful_edit_redirect_url = \'%s/%s\' % (context.absolute_url(), next_url)\n
\n
# if the current step is DeclarationTVA_viewAttachmentList, the document must\n
# be submitted\n
if form_id == \'DeclarationTVA_viewAttachmentList\':\n
# if the next url is PDFDocument_viewLoginInformation, submit the application\n
try : \n
context.portal_workflow.doActionFor(context,\n
\'submit_action\')\n
......@@ -117,6 +109,11 @@ if form_id == \'DeclarationTVA_viewAttachmentList\':\n
return request[\'RESPONSE\'].redirect(\n
"%s/%s?portal_status_message=%s" %\n
(context.absolute_url(), form_id, message))\n
#context.submit()\n
else:\n
next_url = next_url_dict[form_id]\n
\n
successful_edit_redirect_url = \'%s/%s\' % (context.absolute_url(), next_url)\n
\n
result = request[\'RESPONSE\'].redirect(successful_edit_redirect_url) \n
return result\n
......
......@@ -65,34 +65,22 @@
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>\'\'\'This script check that all required files have been uploaded\'\'\'\n
from Products.DCWorkflow.DCWorkflow import ValidationFailed\n
portal = context.getPortalObject()\n
N_ = portal.Base_translateString\n
<value> <string>\'\'\'\n
Return a list of user documents corresponding to the title\n
\'\'\'\n
\n
document = state_change[\'object\']\n
portal_type = document.getPortalType()\n
\n
# dict of required documents\n
attachement_type_dict = {\'Carte ID\':\'Required\',\n
\'Tableau des d\xc3\xa9penses\':\'Optional\',\n
\'D\xc3\xa9tail des \xc3\xa9xon\xc3\xa9ratations\':\'Required\',\n
\'Application Certificate\':\'Optional\',\n
}\n
user_corresponding_document_list = []\n
\n
document_title_list = [x.getTitle() for x in document.contentValues(portal_type=\'File\')]\n
# here we must search in the user digital safe documents that have the given title\n
#XXX to be done\n
\n
required_title_list = [x for x,y in attachement_type_dict.items() if y == \'Required\']\n
if not len(user_corresponding_document_list):\n
user_corresponding_document_list.append(\'Your digital safe contains no relevant document\')\n
else:\n
user_corresponding_document_list.append(\'Other\')\n
\n
message = \'The following documents are missing to submit the request :\'\n
missing_document_list = []\n
for required_title in required_title_list:\n
if required_title not in document_title_list:\n
missing_document_list.append(\'%s\' % required_title)\n
\n
if len(missing_document_list):\n
message = N_(message)\n
raise ValidationFailed, "%s %s" % (message, \', \'.join(missing_document_list))\n
return user_corresponding_document_list\n
</string> </value>
</item>
<item>
......@@ -107,9 +95,15 @@ if len(missing_document_list):\n
<none/>
</value>
</item>
<item>
<key> <string>_owner</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
<value> <string>title=None</string> </value>
</item>
<item>
<key> <string>errors</string> </key>
......@@ -135,28 +129,10 @@ if len(missing_document_list):\n
<key> <string>co_varnames</string> </key>
<value>
<tuple>
<string>state_change</string>
<string>Products.DCWorkflow.DCWorkflow</string>
<string>ValidationFailed</string>
<string>_getattr_</string>
<string>context</string>
<string>portal</string>
<string>N_</string>
<string>_getitem_</string>
<string>document</string>
<string>portal_type</string>
<string>attachement_type_dict</string>
<string>append</string>
<string>$append0</string>
<string>_getiter_</string>
<string>x</string>
<string>document_title_list</string>
<string>y</string>
<string>required_title_list</string>
<string>message</string>
<string>missing_document_list</string>
<string>required_title</string>
<string>title</string>
<string>user_corresponding_document_list</string>
<string>len</string>
<string>_getattr_</string>
</tuple>
</value>
</item>
......@@ -168,12 +144,14 @@ if len(missing_document_list):\n
<item>
<key> <string>func_defaults</string> </key>
<value>
<tuple>
<none/>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PDFDocument_validateFormDataBeforeSubmission</string> </value>
<value> <string>EGov_getAttachmentListFromDigitalSafe</string> </value>
</item>
<item>
<key> <string>warnings</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<tuple>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Python_magic</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>__ac_local_roles__</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>params = context.portal_selections.getSelectionParamsFor(\'attachment_selection\',\n
REQUEST=context.REQUEST)\n
\n
return params[\'attachment_list\']\n
</string> </value>
</item>
<item>
<key> <string>_code</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>_filepath</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>_owner</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>*args,**kw</string> </value>
</item>
<item>
<key> <string>errors</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>func_code</string> </key>
<value>
<object>
<klass>
<global name="FuncCode" module="Shared.DC.Scripts.Signature"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>co_argcount</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>co_varnames</string> </key>
<value>
<tuple>
<string>args</string>
<string>kw</string>
<string>_getattr_</string>
<string>context</string>
<string>params</string>
<string>_getitem_</string>
</tuple>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>func_defaults</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>EGov_getAttachmentListFromReportSelection</string> </value>
</item>
<item>
<key> <string>warnings</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
##############################################################################
#
# Copyright (c) 2008 Nexedi SARL and Contributors. All Rights Reserved.
# Fabien Morin <fabien@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from Testing.ZopeTestCase.PortalTestCase import PortalTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.SecurityTestCase import SecurityTestCase
from AccessControl.SecurityManagement import getSecurityManager
from AccessControl import Unauthorized
from Testing import ZopeTestCase
class TestEGovMixin(SecurityTestCase):
"""Usefull methods for eGov Unit Tests."""
# define all username corresponding to all roles used in eGov
assignor_login = 'chef'
assignee_login = 'agent'
assignee_login_2 = 'agent_2'
associate_login = 'agent_requested'
organisation_1_login = 'societe_a'
organisation_2_login = 'societe_b'
all_username_list = ( assignor_login,
assignee_login,
assignee_login_2,
#associate_login,
organisation_1_login,
organisation_2_login)
all_role_list = ( 'Manager',
'Assignor',
'Assignee',
'Author',
'Associate',
'Auditor',)
#Permissions
VIEW = 'View'
ACCESS = 'Access contents information'
ADD = 'Add portal content'
MODIFY = 'Modify portal content'
DELETE = 'Delete objects'
def getBusinessTemplateList(self):
"""return list of business templates to be installed. """
return ( 'erp5_base',)
def afterSetUp(self):
"""
Method called before the launch of the test to initialize some data
"""
self.createManagerAndLogin()
# remove all message in the message_table because
# the previous test might have failed
message_list = self.getPortal().portal_activities.getMessageList()
for message in message_list:
self.getPortal().portal_activities.manageCancel(message.object_path,
message.method_id)
self.createUsers()
self.createOrganisations()
self.setUpEGovPas()
# XXX quick hack not to have mysql database pre-fill.
self.portal.__class__.DeclarationTVA_zGetSIGTASInformation \
= lambda x,**kw: []
get_transaction().commit()
self.tic()
def beforeTearDown(self):
"""Clean up."""
for module in self.portal.objectValues(spec=('ERP5 Folder',)):
# we want to keep some IDs
module.manage_delObjects([x for x in module.objectIds()
if x not in ('EUR',)])
get_transaction().commit()
self.tic()
def getUserFolder(self) :
return getattr(self.getPortal(), 'acl_users', None)
loginAsUser = PortalTestCase.login
diff_list = lambda self,x,y: [i for i in x if i not in y]
def createManagerAndLogin(self):
"""
Create a simple user in user_folder with manager rights.
This user will be used to initialize data in the method afterSetup
"""
self.getUserFolder()._doAddUser('manager', 'manager', self.all_role_list,
[])
self.login('manager')
def createOneUser(self, username, function=None, group=None):
"""Create one person that will be users."""
person_module = self.getPersonModule()
user = person_module.newContent(
portal_type='Person',
reference=username,
title=username,
id=username,
password='secret')
assignment = user.newContent(portal_type='Assignment')
if function is not None:
assignment.setFunction(function)
self.assertNotEqual(assignment.getFunctionValue(), None)
if group is not None:
assignment.setGroup(group)
self.assertNotEqual(assignment.getGroupValue(), None)
assignment.open()
def createUsers(self):
"""Create persons that will be users."""
module = self.getPersonModule()
if len(module.getObjectIds()) == 0:
# create users
self.createOneUser(self.assignor_login, 'function/section/chef',
'group/dgid/di/cge')
self.createOneUser(self.assignee_login, 'function/impots/inspecteur',
'group/dgid/di/cge')
self.createOneUser(self.assignee_login_2, 'function/impots/inspecteur',
'group/dgid/di/cge')
self.createOneUser(self.associate_login, 'function/section/chef',
'group/dgid/di/csf/bf')
# make this available to catalog
get_transaction().commit()
self.tic()
def createOneOrganisation(self, username, role=None, function=None,
group=None):
"""Create one organisation that will be user."""
organisation_module = self.getOrganisationModule()
user = organisation_module.newContent(
portal_type='Organisation',
title=username,
id=username,
reference=username,
password='secret')
user.setRole(role)
user.setFunction(function)
user.setGroup(group)
self.assertEqual(user.getRole(), role)
self.assertEqual(user.getFunction(), function)
self.assertEqual(user.getGroup(), group)
self.assertEqual(user.getReference(), username)
def createOrganisations(self):
"""Create organisations that will be users."""
module = self.getOrganisationModule()
if len(module.getObjectIds()) == 0:
self.createOneOrganisation(self.organisation_1_login,
role='registry/entreprise')
self.createOneOrganisation(self.organisation_2_login,
role='registry/entreprise')
# make this available to catalog
get_transaction().commit()
self.tic()
def setUpEGovPas(self):
'''use safi PAS to be able to login organisation'''
from Products import ERP5Security
from Products import PluggableAuthService
portal = self.getPortalObject()
acl_users = self.getUserFolder()
# Add SAFIUserManager
ZopeTestCase.installProduct('SAFISecurity')
erp5security_dispatcher = acl_users.manage_addProduct['SAFISecurity']
# don't add it if it's already here
if {'meta_type': 'SAFI User Manager', 'id': 'safi_users'} not in \
erp5security_dispatcher._d._objects:
erp5security_dispatcher.addSAFIUserManager('safi_users')
if {'meta_type': 'SAFI Group Manager', 'id': 'safi_groups'} not in \
erp5security_dispatcher._d._objects :
erp5security_dispatcher.addSAFIGroupManager('safi_groups')
# Register ERP5UserManager Interface
acl_users.safi_users.manage_activateInterfaces(('IAuthenticationPlugin',
'IUserEnumerationPlugin',))
acl_users.safi_groups.manage_activateInterfaces(('IGroupsPlugin',))
# desactivate the erp5 plugin
plugins = acl_users.safi_groups.plugins
interface = plugins._getInterfaceFromName('IGroupsPlugin')
if 'erp5_groups' in list(plugins._getPlugins(interface)):
plugins.deactivatePlugin( interface, 'erp5_groups')
plugins = acl_users.safi_users.plugins
interface = plugins._getInterfaceFromName('IAuthenticationPlugin')
if 'erp5_users' in list(plugins._getPlugins(interface)):
plugins.deactivatePlugin( interface, 'erp5_users')
interface = plugins._getInterfaceFromName('IUserEnumerationPlugin')
if 'erp5_users' in list(plugins._getPlugins(interface)):
plugins.deactivatePlugin( interface, 'erp5_users')
# set properties to enable the login on Person and Organisation
acl_users.safi_users.manage_changeProperties(portal_type_list=['Person',
'Organisation'],)
acl_users.safi_groups.manage_changeProperties(portal_type_list=['Person',
'Organisation'],)
def checkRights(self, object_list, security_mapping, username):
self.loginAsUser(username)
user = getSecurityManager().getUser()
if type(object_list) != type([]):
object_list = [object_list,]
for object in object_list:
for permission, has in security_mapping.items():
if user.has_permission(permission, object) and not has:
self.fail('%s Permission should be Unauthorized on %s\n%s' % \
( permission,
object.getRelativeUrl(),
object.Base_viewSecurity()))
if not(user.has_permission(permission, object)) and has:
self.fail('%s Permission should be Authorized on %s\n%s' % \
( permission,
object.getRelativeUrl(),
object.Base_viewSecurity()))
def checkTransition(self, object_list, possible_transition_list,
not_possible_transition_list, username):
if type(object_list) != type([]):
object_list = [object_list,]
for object in object_list:
for transition in possible_transition_list:
self.failUnlessUserCanPassWorkflowTransition(username, transition,
object)
for transition in not_possible_transition_list:
self.failIfUserCanPassWorkflowTransition(username, transition, object)
......@@ -38,7 +38,7 @@
<item>
<key> <string>guard</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
<none/>
</value>
</item>
<item>
......@@ -64,26 +64,4 @@
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="Guard" module="Products.DCWorkflow.Guard"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>roles</string> </key>
<value>
<tuple>
<string>Owner</string>
<string>Assignor</string>
<string>Assignee</string>
</tuple>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -70,6 +70,7 @@
<value>
<list>
<string>Declaration TVA</string>
<string>Subscription Form</string>
</list>
</value>
</item>
......
......@@ -67,28 +67,41 @@
<key> <string>_body</string> </key>
<value> <string>\'\'\'This script check that all required files have been uploaded\'\'\'\n
from Products.DCWorkflow.DCWorkflow import ValidationFailed\n
portal = state_change.getPortalObject()\n
document = state_change[\'object\']\n
portal = document.getPortalObject()\n
N_ = portal.Base_translateString\n
\n
document = state_change[\'object\']\n
portal_type = document.getPortalType()\n
\n
# dict of required documents\n
attachement_type_dict = {\'Carte ID\':\'Required\',\n
attachement_type_dict = { \'Declaration TVA\':\n
{\n
\'Carte ID\':\'Required\',\n
\'Tableau des d\xc3\xa9penses\':\'Optional\',\n
\'D\xc3\xa9tail des \xc3\xa9xon\xc3\xa9ratations\':\'Required\',\n
\'Application Certificate\':\'Optional\',\n
},\n
\'Subscription Form\':\n
{\n
\'ID Card\':\'Required\',\n
\'M0 Form\':\'Required\',\n
}\n
}\n
\n
# if the portal type is not mapped, no attached files are required\n
if not attachement_type_dict.has_key(portal_type):\n
return\n
\n
document_title_list = [x.getTitle() for x in document.contentValues(portal_type=\'File\')]\n
\n
required_title_list = [x for x,y in attachement_type_dict.items() if y == \'Required\']\n
# get only required documents\n
required_title_list = [x for x,y in attachement_type_dict[portal_type].items() if y == \'Required\']\n
\n
message = \'The following documents are missing to submit the request :\'\n
missing_document_list = []\n
for required_title in required_title_list:\n
if required_title not in document_title_list:\n
missing_document_list.append(\'%s\' % required_title)\n
missing_document_list.append(N_(required_title))\n
\n
if len(missing_document_list):\n
message = N_(message)\n
......@@ -138,11 +151,11 @@ if len(missing_document_list):\n
<string>state_change</string>
<string>Products.DCWorkflow.DCWorkflow</string>
<string>ValidationFailed</string>
<string>_getitem_</string>
<string>document</string>
<string>_getattr_</string>
<string>portal</string>
<string>N_</string>
<string>_getitem_</string>
<string>document</string>
<string>portal_type</string>
<string>attachement_type_dict</string>
<string>append</string>
......
2008-06-04 fabien
* enhance EGov_Base_editAndNextStep script, now it should be possible to not
have a modified Base_edit script
* moved here some script from safi_tva bt
2008-05-26 fabien
bt refactoring :
* change portal_types names
......
116
\ No newline at end of file
125
\ No newline at end of file
testEGovMixin
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment