Commit b97349ec by Łukasz Nowak

Merge branch 'master' into external_buildout

2 parents b376d945 1b1b35c6
Showing 101 changed files with 1229 additions and 469 deletions
0.3 (unreleased)
0.4 (unreleased)
================
* Do not use buildout internally, but rather call bootstrap command of any
provided buildout binary. [Łukasz Nowak]
0.3 (2011-06-14)
================
* slap: Implement SLA by filter_kw in OpenOrder.request. [Łukasz Nowak]
* slap: Timeout network operations. [Łukasz Nowak]
* slapformat: Make slapsoft and slapuser* system users. [Kazuhiko Shiozaki]
* slapgrid: Add more tolerance with supervisord. [Łukasz Nowak]
0.2 (2011-06-01)
================
......
......@@ -55,27 +55,6 @@ from AccessControl import getSecurityManager\n
from Products.ERP5Type.Log import log\n
\n
portal = context.getPortalObject()\n
bt = portal.portal_templates.getInstalledBusinessTemplate("erp5_demo_maxma_sample")\n
isTransitionPossible = portal.portal_workflow.isTransitionPossible\n
\n
for obj in portal.portal_catalog(path=["%%/%s" % i.replace("**", "%") for i in bt.getTemplatePathList()]):\n
obj.activate().updateLocalRolesOnSecurityGroups()\n
\n
for document in portal.portal_catalog(portal_type=bt.getTemplatePortalTypeRoleList()):\n
document.updateLocalRolesOnSecurityGroups()\n
\n
conversion_server_hostname = portal.portal_preferences.getPreferredOoodocServerAddress()\n
conversion_server_port = portal.portal_preferences.getPreferredOoodocServerPortNumber()\n
for preference_id in ["default_configurator_preference", "default_configurator_system_preference"]:\n
preference = getattr(portal.portal_preferences, preference_id)\n
if preference.getPortalType() == "System Preference":\n
preference.setPreferredOoodocServerPortNumber(conversion_server_port)\n
preference.setPreferredOoodocServerAddress(conversion_server_hostname)\n
\n
if isTransitionPossible(preference, "enable"):\n
preference.enable()\n
preference.updateLocalRolesOnSecurityGroups()\n
\n
for gadget in portal.portal_gadgets.objectValues():\n
if gadget.getValidationState() == \'invisible\':\n
gadget.visible()\n
......
......@@ -95,10 +95,10 @@ bt5_installation_list = ( \n
\'vifib_crm\', \n
\'vifib_forge_release\', \n
\'vifib_software_pdm\', \n
\'vifib_web\', \n
\'vifib_web\',\n
\'vifib_open_trade\', \n
\'vifib_l10n_fr\'\n
\'vifib_datas\'\n
\'vifib_l10n_fr\',\n
\'vifib_datas\',\n
\'vifib_erp5\'\n
)\n
\n
......
##############################################################################
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved.
# Rafael Monnerat <rafael@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 Products.ERP5Configurator.tests.ConfiguratorTestMixin import \
TestLiveConfiguratorWorkflowMixin
from Products.ERP5Type.tests.Sequence import SequenceList
class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
"""
Configurator Mixin Class
"""
# The list of standard business templates that the configurator should force
# to install
user_reference = "demo"
standard_bt5_list = ('erp5_simulation',
'erp5_dhtml_style',
'erp5_jquery',
'erp5_jquery_ui',
'erp5_xhtml_jquery_style',
'erp5_ingestion_mysql_innodb_catalog',
'erp5_ingestion',
'erp5_web',
'erp5_dms',
'erp5_crm',
'erp5_pdm',
'erp5_trade',
'erp5_knowledge_pad',
'erp5_accounting',
'erp5_tax_resource',
'erp5_discount_resource',
'erp5_invoicing',
'erp5_configurator_standard_categories',
'erp5_trade_knowledge_pad',
'erp5_crm_knowledge_pad',
'erp5_simulation_test',
'erp5_simplified_invoicing',
'erp5_ods_style',
'erp5_odt_style',
'erp5_ooo_import',
'erp5_accounting_l10n_fr',
'erp5_l10n_fr',
'erp5_l10n_pt-BR',
'erp5_demo_maxma_rule')
def getBusinessTemplateList(self):
return ('erp5_core_proxy_field_legacy',
'erp5_full_text_myisam_catalog',
'erp5_base',
'erp5_workflow',
'erp5_configurator',
'erp5_configurator_maxma_demo',)
def stepCreateBusinessConfiguration(self, sequence=None,\
sequence_list=None, **kw):
""" Create one Business Configuration """
module = self.portal.business_configuration_module
business_configuration = module.newContent(
portal_type="Business Configuration",
title='Test Configurator Maxma Demo Workflow')
next_dict = {}
sequence.edit(business_configuration=business_configuration,
next_dict=next_dict)
def stepCheckConfigureInstallationForm(self, sequence=None,\
sequence_list=None, **kw):
""" Check the installation form """
response_dict = sequence.get("response_dict")
# configuration is finished. We are at the Install state.
# On maxma demo, installation is the first slide.
self.assertEquals('show', response_dict['command'])
self.assertEquals('Install', response_dict['next'])
def stepSetMaxmaDemoWorkflow(self, sequence=None, sequence_list=None, **kw):
""" Set Consulting Workflow into Business Configuration """
business_configuration = sequence.get("business_configuration")
self.setBusinessConfigurationWorkflow(business_configuration,
"workflow_module/maxma_demo_configuration_workflow")
def stepViewCreatedPersons(self, sequence=None, sequence_list=None, **kw):
self.login(user_name='test_configurator_user')
person_list = self.portal.person_module.searchFolder()
self.assertNotEquals(0, len(person_list))
for entity in person_list:
for username in self.all_username_list:
self.failUnlessUserCanAccessDocument(username, entity)
self.failUnlessUserCanViewDocument(username, entity)
def stepViewCreatedOrganisations(self, sequence=None, sequence_list=None, **kw):
self.login(user_name='test_configurator_user')
organisation_list = self.portal.organisation_module.searchFolder()
self.assertNotEquals(0, len(organisation_list))
for entity in organisation_list:
for username in self.all_username_list:
self.failUnlessUserCanAccessDocument(username, entity)
self.failUnlessUserCanViewDocument(username, entity)
def stepViewCreatedAssignemnts(self, sequence=None, sequence_list=None, **kw):
self.login(user_name='test_configurator_user')
person_list = self.portal_person_module.searchFolder()
self.assertNotEquals(0, len(person_list))
for person in person_list:
for assignment in person.contentValues(portal_type='Assignment'):
for username in self.all_username_list:
self.failUnlessUserCanAccessDocument(username, assignment)
self.failUnlessUserCanViewDocument(username, assignment)
def stepCheckMaxmaDemoSampleObjectList(self, sequence=None, sequence_list=None, **kw):
""" Check if objects are placed into the appropriate state """
# Check Gadgets
for gadget in self.portal.portal_gadgets.searchFolder():
self.assertEquals('public', gadget.getValidationState(),
"%s is not public but %s" % (gadget.getRelativeUrl(),
gadget.getValidationState()))
gadget.Base_checkConsistency()
# Check if demo user is working.
user = self.portal.portal_catalog.getResultValue(portal_type="Person",
reference=self.user_reference)
self.assertNotEquals(user.Person_getAvailableAssignmentValueList(), [])
self.assertEquals(user.getTitle(), "Jack Vale")
self.assertEquals(user.getValidationState(), "validated")
self.assertEquals(user.getSubordination(),
'organisation_module/myorganisation')
self.assertEquals(user.getSubordinationTitle(), "Maxma Co")
### STEPS
DEFAULT_SEQUENCE_LIST = """
stepCreateBusinessConfiguration
stepTic
stepSetMaxmaDemoWorkflow
stepTic
stepConfiguratorNext
stepTic
stepCheckBT5ConfiguratorItem
stepCheckConfigureInstallationForm
stepSetupInstallConfiguration
stepConfiguratorNext
stepTic
stepCheckInstallConfiguration
stepStartConfigurationInstallation
stepTic
stepCheckInstanceIsConfigured%(country)s
stepCheckMaxmaDemoSampleObjectList
stepTic
stepViewAddGadget
stepViewEventModule
stepAddEvent
stepSentEventWorkflow
stepViewAccountModule
stepAddAccountModule
stepViewAccount
stepCopyPasteAccount
stepViewEntityModules
stepAddEntityModules
stepCopyAndPastePerson
stepCopyAndPasteOrganisation
stepEntityWorkflow
stepViewCreatedPersons
stepViewCreatedOrganisations
stepViewCreatedAssignemnts
stepAddAccoutingPeriod
stepValidatedAccountingPeriods
stepViewBankAccount
stepViewCreditCard
stepValidateAndModifyBankAccount
stepValidateAndModifyCreditCard
stepAddPaymentNodeInPerson
stepAddPaymentNodeInOrganisation
stepCopyAndPasteBankAccountInPerson
stepCopyAndPasteBankAccountInOrganisation
stepViewAccountingTransactionModule
stepAddAccountingTransactionModule
stepCopyAndPasteAccountingTransactions
stepTic
stepAccountingTransaction
stepTic
stepSaleInvoiceTransaction
stepTic
stepPurchaseInvoiceTransaction
stepTic
stepPaymentTransaction
stepTic
stepBalanceTransaction
stepTic
stepAccountingTransaction_getCausalityGroupedAccountingTransactionList
stepAddAssignments
stepAssignmentTI
stepEditAssignments
stepViewAcessAddPurchaseTradeCondition
stepViewAccessAddSaleTradeCondition
stepViewAccessAddSaleOrder
stepViewAccessAddSalePackingList
stepViewAccessPurchaseOrder
stepPurchasePackingList
"""
def test_maxma_demo_workflow(self):
""" Test the consulting workflow configuration"""
self.all_username_list = ["demo"]
self.accountant_username_list = self.all_username_list
self.sales_and_purchase_username_list = self.all_username_list
self.warehouse_username_list = self.all_username_list
self.simple_username_list = self.all_username_list
self.restricted_security = 0
sequence_list = SequenceList()
sequence_string = self.DEFAULT_SEQUENCE_LIST % dict(country='France')
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
import unittest
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestMaxmaDemoConfiguratorWorkflow))
return suite
##############################################################################
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved.
# Rafael Monnerat <rafael@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 Products.ERP5Configurator.tests.ConfiguratorTestMixin import \
TestLiveConfiguratorWorkflowMixin
from Products.ERP5Type.tests.Sequence import SequenceList
class TestVifibConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
"""
Configurator Mixin Class
"""
# The list of standard business templates that the configurator should force
# to install
user_reference = "demo"
standard_bt5_list = (
'erp5_simulation',
'erp5_administration',
'erp5_pdm',
'erp5_trade',
'erp5_simulation_test',
'erp5_item',
'erp5_open_trade',
'erp5_forge',
'erp5_ingestion_mysql_innodb_catalog',
'erp5_ingestion',
'erp5_crm',
'erp5_jquery',
'erp5_jquery_ui',
'erp5_knowledge_pad',
'erp5_web',
'erp5_dms',
'erp5_l10n_fr',
'erp5_content_translation',
'erp5_software_pdm',
'erp5_computer_immobilisation',
'erp5_accounting',
'erp5_accounting_l10n_fr',
'erp5_tax_resource',
'erp5_discount_resource',
'erp5_invoicing',
'erp5_ods_style',
'erp5_odt_style',
'erp5_ooo_import',
'erp5_simplified_invoicing',
'erp5_legacy_tax_system',
'erp5_commerce',
'erp5_project',
'erp5_credential',
'erp5_km',
'erp5_web_download_theme',
'vifib_mysql_innodb_catalog',
'vifib_core',
'vifib_base',
'vifib_slap',
'vifib_crm',
'vifib_forge_release',
'vifib_software_pdm',
'vifib_web',
'vifib_open_trade',
'vifib_l10n_fr',
'vifib_datas',
'vifib_erp5')
def getBusinessTemplateList(self):
return ('erp5_core_proxy_field_legacy',
'erp5_full_text_myisam_catalog',
'erp5_base',
'erp5_workflow',
'erp5_configurator',
'erp5_configurator_vifib',)
def stepCreateBusinessConfiguration(self, sequence=None,\
sequence_list=None, **kw):
""" Create one Business Configuration """
module = self.portal.business_configuration_module
business_configuration = module.newContent(
portal_type="Business Configuration",
title='Test Configurator Vifib Workflow')
next_dict = {}
sequence.edit(business_configuration=business_configuration,
next_dict=next_dict)
def stepCheckConfigureInstallationForm(self, sequence=None,\
sequence_list=None, **kw):
""" Check the installation form """
response_dict = sequence.get("response_dict")
# configuration is finished. We are at the Install state.
# On maxma demo, installation is the first slide.
self.assertEquals('show', response_dict['command'])
self.assertEquals('Install', response_dict['next'])
def stepSetVifibWorkflow(self, sequence=None, sequence_list=None, **kw):
""" Set Consulting Workflow into Business Configuration """
business_configuration = sequence.get("business_configuration")
self.setBusinessConfigurationWorkflow(business_configuration,
"workflow_module/vifib_configuration_workflow")
def stepCheckMaxmaDemoSampleObjectList(self, sequence=None, sequence_list=None, **kw):
""" Check if objects are placed into the appropriate state """
# Check Gadgets
for gadget in self.portal.portal_gadgets.searchFolder():
self.assertEquals('public', gadget.getValidationState(),
"%s is not public but %s" % (gadget.getRelativeUrl(),
gadget.getValidationState()))
gadget.Base_checkConsistency()
### STEPS
DEFAULT_SEQUENCE_LIST = """
stepCreateBusinessConfiguration
stepTic
stepSetVifibWorkflow
stepTic
stepConfiguratorNext
stepTic
stepCheckBT5ConfiguratorItem
stepCheckConfigureInstallationForm
stepSetupInstallConfiguration
stepConfiguratorNext
stepTic
stepCheckInstallConfiguration
stepStartConfigurationInstallation
stepTic
stepCheckInstanceIsConfigured%(country)s
"""
def test_vifib_workflow(self):
""" Test the consulting workflow configuration"""
self.all_username_list = ["demo"]
self.accountant_username_list = self.all_username_list
self.sales_and_purchase_username_list = self.all_username_list
self.warehouse_username_list = self.all_username_list
self.simple_username_list = self.all_username_list
self.restricted_security = 0
sequence_list = SequenceList()
sequence_string = self.DEFAULT_SEQUENCE_LIST % dict(country='France')
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
import unittest
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestVifibConfiguratorWorkflow))
return suite
8
\ No newline at end of file
11
\ No newline at end of file
testMaxmaDemoConfigurationWorkflow
\ No newline at end of file
testVifibConfigurationWorkflow
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>get_certificate</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>10.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Get Certificate</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Person_getCertificate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>revoke_certificate</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>11.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Revoke Certificate</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Person_revokeCertificate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from AccessControl import ClassSecurityInfo, Unauthorized, getSecurityManager
from Products.ERP5.Document.Person import Person as ERP5Person
class Person(ERP5Person):
security = ClassSecurityInfo()
security.declarePublic('getCertificate')
def _checkCertificateRequest(self):
try:
self.checkUserCanChangePassword()
except Unauthorized:
# in ERP5 user has no SetOwnPassword permission on Person document
# referring himself, so implement "security" by checking that currently
# logged in user is trying to get/revoke his own certificate
reference = self.getReference()
if not reference:
raise
if getSecurityManager().getUser().getId() != reference:
raise
def _getCertificate(self):
return self.getPortalObject().portal_certificate_authority\
.getNewCertificate(self.getReference())
def _revokeCertificate(self):
return self.getPortalObject().portal_certificate_authority\
.revokeCertificateByCommonName(self.getReference())
def getCertificate(self):
"""Returns new SSL certificate"""
self._checkCertificateRequest()
return self._getCertificate()
security.declarePublic('revokeCertificate')
def revokeCertificate(self):
"""Revokes existing certificate"""
self._checkCertificateRequest()
self._revokeCertificate()
......@@ -28,6 +28,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.Item import Item
from lxml import etree
class SoftwareInstance(Item):
"""
......@@ -42,3 +43,20 @@ class SoftwareInstance(Item):
security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declareProtected(Permissions.AccessContentsInformation,
'getSlaXmlAsDict')
def getSlaXmlAsDict(self):
"""Returns SLA XML as python dictionary"""
result_dict = {}
xml = self.getSlaXml()
if xml is not None and xml != '':
tree = etree.fromstring(xml.encode('utf-8'))
for element in tree.findall('parameter'):
key = element.get('id')
value = result_dict.get(key, None)
if value is not None:
value = value + ' ' + element.text
else:
value = element.text
result_dict[key] = value
return result_dict
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/text</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>XML Service Level Agreement parameters</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>sla_xml_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>