Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adjust export import for new demo profile #173

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 111 additions & 13 deletions src/Products/PloneMeeting/exportimport/content.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from collections import OrderedDict

from collective.contact.plonegroup.browser.settings import invalidate_soev_cache
from collective.contact.plonegroup.browser.settings import invalidate_ssoev_cache
Expand All @@ -17,6 +18,7 @@
from imio.helpers.security import generate_password
from imio.helpers.security import is_develop_environment
from plone import api
from plone.app.textfield import RichTextValue
from plone.namedfile.file import NamedBlobFile
from plone.namedfile.file import NamedBlobImage
from plone.namedfile.file import NamedImage
Expand All @@ -37,7 +39,7 @@
from Products.PloneMeeting.config import TOOL_FOLDER_RECURRING_ITEMS
from Products.PloneMeeting.Extensions.imports import import_contacts
from Products.PloneMeeting.profiles import DEFAULT_USER_PASSWORD
from Products.PloneMeeting.utils import org_id_to_uid
from Products.PloneMeeting.utils import org_id_to_uid, cleanMemoize
from Products.PloneMeeting.utils import updateCollectionCriterion
from z3c.relationfield.relation import RelationValue
from zope.component import getUtility
Expand All @@ -48,12 +50,11 @@
import os
import transaction


# PloneMeeting-Error related constants -----------------------------------------
MEETING_CONFIG_ERROR = 'A validation error occurred while instantiating ' \
'meeting configuration "%s" with id "%s". %s'
MEETINGCONFIG_BADREQUEST_ERROR = 'There was an error during creation of ' \
'MeetingConfig with id "%s". Original error : "%s"'
'MeetingConfig with id "%s". Original error : "%s"'


def update_labels_jar(jar, values):
Expand All @@ -80,9 +81,14 @@ def __init__(self, context, productname):
self.tool = self.portal.portal_plonemeeting
# set correct title
self.tool.setTitle(translate('pm_configuration',
domain='PloneMeeting',
context=self.request))
domain='PloneMeeting',
context=self.request))
self.profileData = self.getProfileData()

self.wfTool = api.portal.get_tool('portal_workflow')
self.pTool = api.portal.get_tool('plone_utils')
self.mTool = api.portal.get_tool('portal_membership')

# Initialize the tool if we have data
if not self.profileData:
return
Expand Down Expand Up @@ -220,13 +226,105 @@ def run(self):

# commit before continuing so elements like scales on annex types are correctly saved
transaction.commit()

# manage meeting and item creation
for cfg in self.data.meetingConfigs:
cleanMemoize(self.portal)
self._add_meeting_and_items(cfg)

return self.successMessage

def _add_meeting_and_items(self, meeting_cfg):
cfg = getattr(self.tool, meeting_cfg.id)
if meeting_cfg.meetings:
for meeting in meeting_cfg.meetings:
self._create_meeting(meeting, cfg)

if meeting_cfg.items:
for item in meeting_cfg.items:
self._create_item(item, cfg)

def _create_item(self, item, cfg):
user_folder = self.tool.getPloneMeetingFolder(cfg.getId(), item.creator)
with api.env.adopt_user(username=item.creator):
self.tool.invalidateAllCache()
template = getattr(self.tool.getMeetingConfig(user_folder).itemtemplates, item.itemTemplate)
item_obj = template.clone(newOwnerId=item.creator,
destFolder=user_folder,
newPortalType=cfg.getItemTypeName())
item_obj.setTitle(item.title)
item_obj.setBudgetRelated(item.budget_related)
if item.to_state == 'proposed':
self.wfTool.doActionFor(item_obj, 'propose')

# todo handle asking advice
# todo handle annexes
if item.to_state in ('validated', 'presented'):
self.wfTool.doActionFor(item_obj, 'validate')
if item.to_state == 'presented':
self.wfTool.doActionFor(item_obj, 'present')
else:
for transaction in cfg.getTransitionsForPresentingAnItem():
if item_obj.query_state() == item.to_state:
break
self.wfTool.doActionFor(item_obj, transaction)

return item_obj

def _create_meeting(self, meeting, cfg):
user_folder = self.tool.getPloneMeetingFolder(cfg.getId(), meeting.creator)

meeting_id = user_folder.invokeFactory(
cfg.getMeetingTypeName(),
id=meeting.date.strftime('%Y%m%d'),
date=meeting.date,
start_date=meeting.start_date,
end_date=meeting.end_date,
)
meeting_obj = getattr(user_folder, meeting_id)

attendees = OrderedDict({})
if meeting.attendees:
for attendee_id in meeting.attendees:
attendees[org_id_to_uid(attendee_id)] = meeting.attendees[attendee_id]
else:
for attendee_uid in cfg.getOrderedContacts():
attendees[attendee_uid] = 'attendee'

signatories = {}
# todo need a tool like held_position_id_to_uid or force static uids
for attendee_uid in attendees:
held_position = api.content.uuidToObject(attendee_uid)
if held_position.signature_number:
signatories[attendee_uid] = held_position.signature_number

meeting_obj._do_update_contacts(attendees=attendees, signatories=signatories)

if meeting.observations:
meeting_obj.observations = RichTextValue(meeting.observations)

self.pTool.changeOwnershipOf(meeting_obj, meeting.creator)
self.portal.REQUEST["PUBLISHED"] = meeting_obj
for item in meeting.items:
item.to_state = 'presented'
self._create_item(item, cfg)

if meeting.to_state != 'created':
state_transactions = {
'frozen': 'freeze',
'decided': 'decide',
'closed': 'close',
}
for state in state_transactions:
if meeting.to_state == meeting_obj.query_state():
break
self.wfTool.doActionFor(meeting_obj, state_transactions[state])

def _correct_advice_states(self, advice_states):
""" """
return ['{0}__state__{1}'.format(
self.cfg_num_to_id(v.split('__state__')[0]),
v.split('__state__')[1]) for v in advice_states]
self.cfg_num_to_id(v.split('__state__')[0]),
v.split('__state__')[1]) for v in advice_states]

def _finishConfigFor(self, cfg, data):
"""When the MeetingConfig has been created, some parameters still need to be applied
Expand Down Expand Up @@ -269,7 +367,7 @@ def _finishConfigFor(self, cfg, data):
cfg.setOrderedContacts(selectableOrderedContacts)

# turn contact path to uid
for org_storing_field in ('orderedContacts', ):
for org_storing_field in ('orderedContacts',):
org_storing_data = getattr(data, org_storing_field, [])
if org_storing_data:
contact_uids = []
Expand Down Expand Up @@ -462,8 +560,8 @@ def addItemToConfig(self, cfg, descr, isRecurring=True):
folder = getattr(cfg, TOOL_FOLDER_ITEM_TEMPLATES)
data = descr.__dict__
itemType = isRecurring and \
cfg.getItemTypeName(configType='MeetingItemRecurring') or \
cfg.getItemTypeName(configType='MeetingItemTemplate')
cfg.getItemTypeName(configType='MeetingItemRecurring') or \
cfg.getItemTypeName(configType='MeetingItemTemplate')
folder.invokeFactory(itemType, **data)
item = getattr(folder, descr.id)
# adapt org related values as we have org id on descriptor and we need to set org UID
Expand All @@ -478,7 +576,7 @@ def addItemToConfig(self, cfg, descr, isRecurring=True):
proposing_group_uid = org_id_to_uid(proposing_group_id)
group_in_charge_uid = org_id_to_uid(group_in_charge_id)
item.setProposingGroup(proposing_group_uid)
item.setGroupsInCharge((group_in_charge_uid, ))
item.setGroupsInCharge((group_in_charge_uid,))
item.proposingGroupWithGroupInCharge = '{0}__groupincharge__{1}'.format(
proposing_group_uid, group_in_charge_uid)
if item.associatedGroups:
Expand Down Expand Up @@ -593,13 +691,13 @@ def addPodTemplate(self, container, pt, source):
if not pod_template_to_use_cfg:
logger.warning(
'Cfg with id {0} not found when adding Pod template {1}, template was not added'.format(
pt.pod_template_to_use['cfg_id'], pt.pod_template_to_use['template_id']))
pt.pod_template_to_use['cfg_id'], pt.pod_template_to_use['template_id']))
return
pod_template = pod_template_to_use_cfg.podtemplates.get(pt.pod_template_to_use['template_id'])
if not pod_template:
logger.warning(
'Pod template with id {0} not found in cfg with id {1}, template was not added'.format(
pt.pod_template_to_use['template_id'], pt.pod_template_to_use['cfg_id']))
pt.pod_template_to_use['template_id'], pt.pod_template_to_use['cfg_id']))
return
pod_template_to_use = pod_template.UID()
else:
Expand Down
98 changes: 73 additions & 25 deletions src/Products/PloneMeeting/profiles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
#
# GNU General Public License (GPL)
#
from collections import OrderedDict

from collective.contact.plonegroup.config import PLONEGROUP_ORG
from plone.api.validation import at_least_one_of
from Products.PloneMeeting.config import DEFAULT_LIST_TYPES
from Products.PloneMeeting.config import DEFAULT_LIST_TYPES, ITEM_DEFAULT_TEMPLATE_ID
from Products.PloneMeeting.config import DEFAULT_USER_PASSWORD
from Products.PloneMeeting.config import MEETING_GROUP_SUFFIXES

Expand Down Expand Up @@ -51,48 +52,90 @@ def getData(self, **kw):
return res


class RecurringItemDescriptor(Descriptor):
class ItemAdviceDescriptor(Descriptor):

def __init__(self, adviser_group, adviser, delay=None, delay_started_on=None, delay_ended_on=None,
advice_type=None):
self.adviser_group = adviser_group
self.delay = delay
self.delay_started_on = delay_started_on
self.delay_ended_on = delay_ended_on
self.adviser = adviser
self.advice_type = advice_type


class ItemDescriptor(Descriptor):
excludedFields = ['title']

def __init__(self, id, title, proposingGroup='', groupsInCharge=(), proposingGroupWithGroupInCharge='',
description='', category='', associatedGroups=(), decision='',
itemKeywords='', itemTags=(), meetingTransitionInsertingMe='_init_', privacy='public'):
self.id = id
@at_least_one_of('proposingGroup', 'proposingGroupWithGroupInCharge')
def __init__(self, title, creator, proposingGroup='', groupsInCharge=(), proposingGroupWithGroupInCharge='',
itemTemplate=ITEM_DEFAULT_TEMPLATE_ID, description='', category='', classifier='', associatedGroups=(), motivation='',
decision='', itemKeywords='', itemTags=(), privacy='public', listType='normal', to_state='validated',
advices=[], annexes=[], budget_related=False):
self.title = title
self.creator = creator
# the proposingGroup can be empty ('') for itemtemplate
self.proposingGroup = proposingGroup
self.groupsInCharge = groupsInCharge
self.proposingGroupWithGroupInCharge = proposingGroupWithGroupInCharge
self.itemTemplate = itemTemplate
self.description = description
self.category = category
self.classifier = classifier
self.associatedGroups = associatedGroups
self.motivation = motivation
self.decision = decision
self.itemKeywords = itemKeywords
self.itemTags = itemTags
self.meetingTransitionInsertingMe = meetingTransitionInsertingMe
self.privacy = privacy
self.listType = listType
self.to_state = to_state
self.budget_related = budget_related
self.advices = advices
self.annexes = annexes


class ItemTemplateDescriptor(Descriptor):
class RecurringItemDescriptor(ItemDescriptor):
excludedFields = ['title']

@at_least_one_of('proposingGroup', 'proposingGroupWithGroupInCharge')
def __init__(self, id, title, proposingGroup='', groupsInCharge=(), proposingGroupWithGroupInCharge='',
description='', category='', associatedGroups=(), decision='',
itemKeywords='', itemTags=(), templateUsingGroups=[], privacy='public'):
def __init__(self, id, title, creator='dgen', proposingGroup='', groupsInCharge=(), proposingGroupWithGroupInCharge='',
description='', category='', classifier='', associatedGroups=(), motivation='', decision='',
itemKeywords='', itemTags=(), meetingTransitionInsertingMe='_init_', privacy='public'):
super(RecurringItemDescriptor, self).__init__(title, creator, proposingGroup, groupsInCharge,
proposingGroupWithGroupInCharge, description, category,
classifier, associatedGroups, motivation, decision, itemKeywords,
itemTags, privacy)
self.id = id
self.meetingTransitionInsertingMe = meetingTransitionInsertingMe


class ItemTemplateDescriptor(ItemDescriptor):
excludedFields = ['title']

@at_least_one_of('proposingGroup', 'proposingGroupWithGroupInCharge')
def __init__(self, id, title, creator='dgen', proposingGroup='', groupsInCharge=(), proposingGroupWithGroupInCharge='',
description='', category='', associatedGroups=(), decision='', itemKeywords='', itemTags=(),
templateUsingGroups=[], privacy='public'):
super(ItemTemplateDescriptor, self).__init__(title, creator, proposingGroup, groupsInCharge,
proposingGroupWithGroupInCharge, description, category,
associatedGroups, decision, itemKeywords, itemTags, privacy)
self.id = id
self.title = title
# the proposingGroup can be empty ('') for itemtemplate
self.proposingGroup = proposingGroup
self.groupsInCharge = groupsInCharge
self.proposingGroupWithGroupInCharge = proposingGroupWithGroupInCharge
self.description = description
self.category = category
self.associatedGroups = associatedGroups
self.decision = decision
self.itemKeywords = itemKeywords
self.itemTags = itemTags
self.templateUsingGroups = templateUsingGroups
self.privacy = privacy


class MeetingDescriptor(Descriptor):
def __init__(self, date, creator='dgen', start_date=None, end_date=None, observations=None, items=[],
attendees=OrderedDict({}), signatories={}, to_state='closed'):
self.date = date
self.creator = creator
self.start_date = start_date
self.end_date = end_date
self.observations = observations
self.items = items
self.attendees = attendees
self.signatories = signatories
self.to_state = to_state


class CategoryDescriptor(Descriptor):
Expand Down Expand Up @@ -359,6 +402,7 @@ def get(klass):
if not klass.instance:
klass.instance = OrgDescriptor(None, None, None)
return klass.instance

get = classmethod(get)

def __init__(self, id, title, acronym, description=u'',
Expand Down Expand Up @@ -419,9 +463,10 @@ def get(klass):
if not klass.instance:
klass.instance = MeetingConfigDescriptor(None, None, None)
return klass.instance

get = classmethod(get)

def __init__(self, id, title, folderTitle, isDefault=False, active=True):
def __init__(self, id, title, folderTitle, isDefault=False, active=True, meetings=[], items=[]):
self.id = id # Identifier of the meeting config.
self.title = title
self.active = active
Expand Down Expand Up @@ -820,6 +865,8 @@ def __init__(self, id, title, folderTitle, isDefault=False, active=True):

# content_category_groups parameters -----------------------------------
self.category_group_activated_attrs = {}
self.meetings = meetings
self.items = items


class PloneMeetingConfiguration(Descriptor):
Expand All @@ -836,6 +883,7 @@ def get(klass):
if not klass.instance:
klass.instance = PloneMeetingConfiguration('My meetings', [], [])
return klass.instance

get = classmethod(get)

def __init__(self, meetingFolderTitle, meetingConfigs, orgs):
Expand Down Expand Up @@ -886,4 +934,4 @@ def __init__(self, meetingFolderTitle, meetingConfigs, orgs):
self.directory_position_types = []
self.contactsTemplates = [] # ~[PodTemplateDescriptor]~

# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------