in ForgeTracker/forgetracker/model/ticket.py [0:0]
def move(self, app_config, notify=True):
'''Move ticket from current tickets app to tickets app with given app_config'''
app = app_config.project.app_instance(app_config)
prior_url = self.url()
prior_app = self.app
prior_ticket_num = self.ticket_num
attachments = self.attachments
attach_metadata = BaseAttachment.metadata_for(self)
prior_cfs = [
(cf['name'], cf['type'], cf['label'])
for cf in prior_app.globals.custom_fields or []]
new_cfs = [
(cf['name'], cf['type'], cf['label'])
for cf in app.globals.custom_fields or []]
skipped_fields = []
user_fields = []
for cf in prior_cfs:
if cf not in new_cfs: # can't convert
skipped_fields.append(cf)
elif cf[1] == 'user': # can convert and field type == user
user_fields.append(cf)
messages = []
for cf in skipped_fields:
name = cf[0]
messages.append('- **%s**: %s' %
(name, self.custom_fields.get(name, '')))
for cf in user_fields:
name = cf[0]
username = self.custom_fields.get(name, None)
user = app_config.project.user_in_project(username)
if not user or user == User.anonymous():
messages.append('- **%s**: %s (user not in project)' %
(name, username))
self.custom_fields[name] = ''
# special case: not custom user field (assigned_to_id)
user = self.assigned_to
if user and not app_config.project.user_in_project(user.username):
messages.append('- **assigned_to**: %s (user not in project)' %
user.username)
self.assigned_to_id = None
custom_fields = {}
for cf in new_cfs:
fn, ft, fl = cf
old_val = self.custom_fields.get(fn, None)
if old_val is None:
custom_fields[fn] = None if ft == 'user' else ''
custom_fields[fn] = old_val
self.custom_fields = custom_fields
# move ticket. ensure unique ticket_num
while True:
with h.push_context(app_config.project_id, app_config_id=app_config._id):
ticket_num = app.globals.next_ticket_num()
self.ticket_num = ticket_num
self.app_config_id = app_config._id
new_url = app_config.url() + str(self.ticket_num) + '/'
try:
session(self).flush(self)
break
except OperationFailure as err:
if 'duplicate' in err.args[0]:
log.warning(
'Try to create duplicate ticket %s when moving from %s' %
(new_url, prior_url))
session(self).expunge(self)
continue
attach_metadata['type'] = 'thumbnail'
self._move_attach(attachments, attach_metadata, app_config)
# move ticket's discussion thread, thus all new comments will go to a
# new ticket's feed
self.discussion_thread.app_config_id = app_config._id
self.discussion_thread.discussion_id = app_config.discussion_id
for post in self.discussion_thread.posts:
attach_metadata = BaseAttachment.metadata_for(post)
attach_metadata['type'] = 'thumbnail'
self._move_attach(post.attachments, attach_metadata, app_config)
post.app_config_id = app_config._id
post.app_id = app_config._id
post.discussion_id = app_config.discussion_id
session(self.discussion_thread).flush(self.discussion_thread)
# need this to reset app_config RelationProperty on ticket to a new one
session(self.discussion_thread).expunge(self.discussion_thread)
session(self).expunge(self)
ticket = Ticket.query.find(dict(
app_config_id=app_config._id, ticket_num=self.ticket_num)).first()
# move individual subscriptions
# (may cause an unnecessary subscription if user is already subscribed to destination tool)
Mailbox.query.update({
'artifact_index_id': ticket.index_id(), # this is unique
'project_id': prior_app.project._id, # include this to use an index
}, {'$set': {
'project_id': app_config.project_id,
'app_config_id': app_config._id,
'artifact_url': ticket.url(),
'artifact_title': h.get_first(ticket.index(), 'title'),
}}, multi=True)
# create subscriptions for 'All artifacts' tool-level subscriptions
tool_subs = Mailbox.query.find({'project_id': prior_app.project._id,
'app_config_id': prior_app.config._id,
'artifact_index_id': None,
}).all()
for tool_sub in tool_subs:
Mailbox.subscribe(user_id=tool_sub.user_id, project_id=app_config.project_id, app_config_id=app_config._id,
artifact=ticket)
# creating MovedTicket to be able to redirect from this url
moved_ticket = MovedTicket(
app_config_id=prior_app.config._id, ticket_num=prior_ticket_num,
moved_to_url=ticket.url(),
)
message = 'Ticket moved from %s' % prior_url
if messages:
message += '\n\nCan\'t be converted:\n\n'
message += '\n'.join(messages)
with h.push_context(ticket.project_id, app_config_id=app_config._id):
ticket.discussion_thread.add_post(text=message, notify=notify)
return ticket