def create_email_template_folder(): response.generic_patterns = ['*.json'] name = request.vars.name # Check if the name is already exists under same domain existing_name = db((db.email_template_folder.name == name) & ( db.email_template_folder.domainId == auth.user.domainId)).select( db.email_template_folder.name).first() if existing_name: response.status = 400 return CustomErrorResponse.DUPLICATE_TEMPLATE_FOLDER domain_id = auth.user.domainId parent_id = request.vars.parentId if parent_id and db.email_template_folder(parent_id).domainId != domain_id: logger.error( "Error creating email campaign folder: parent ID %s does not belong to domain %s", parent_id, domain_id) raise HTTP(500, "500: Parent ID does not belong to the same domain") # Set isImmutable is_immutable = 0 if request.vars.isImmutable == "1" and not is_current_user_admin(): raise HTTP(500, "isImmutable = 1 but user is not admin") elif request.vars.isImmutable == "1": is_immutable = 1 email_template_folder_id = db.email_template_folder.insert( name=request.vars.name, domainId=domain_id, parentId=parent_id, isImmutable=is_immutable) return dict(id=email_template_folder_id)
def index(): campaigns_and_lists = get_campaigns_and_smart_lists( auth.user.domainId, get_last_sent_datetime=True) # Filter out subscription campaigns for non-admins current_user_admin = is_current_user_admin(auth.user_id) campaigns_and_lists = filter( lambda row: not row['isSubscription'] or current_user_admin, campaigns_and_lists) return dict(campaigns_and_lists=campaigns_and_lists)
def delete_user_email_template(): template = db(db.user_email_template.id == request.vars.id).select( db.user_email_template.isImmutable) if template[0].isImmutable == 1 and not is_current_user_admin(): raise HTTP(500, "Non-admin user trying to delete immutable template") else: result = db((db.user_email_template.id == request.vars.id) & (db.user_email_template.userId.belongs( db(db.user.domainId == auth.user.domainId)._select( db.user.id)))).delete() return dict(success=result)
def index(): response.title = "Analyze" # Data for graph chart_data = get_campaign_send_statistics(auth.user.domainId, num_data_points=5) # Sum up chart data numbers for each campaign, to display in table campaign_id_to_data = dict() campaign_id_data_tuples = [] from TalentUsers import is_current_user_admin current_user_admin = is_current_user_admin(auth.user_id) for row in chart_data: logger.debug('chart_data row, %s', row) campaign_id = row[1] row_data = row[2] # Filter out subscription campaigns for non-admins if row_data.get('is_subscription') and not current_user_admin: continue if not campaign_id_to_data.get(campaign_id): campaign_data = dict(sends=0, text_clicks=0, html_clicks=0, opens=0, bounces=0, user_id=row_data['user_id'], name=row_data['name'], date=row_data['date']) campaign_id_to_data[campaign_id] = campaign_data campaign_id_data_tuples.append([campaign_id, campaign_data]) else: campaign_id_data_tuples[-1][1]['date'] = row_data['date'] campaign_id_to_data[campaign_id]['sends'] += row_data['sends'] campaign_id_to_data[campaign_id]['text_clicks'] += row_data[ 'text_clicks'] campaign_id_to_data[campaign_id]['html_clicks'] += row_data[ 'html_clicks'] campaign_id_to_data[campaign_id]['opens'] += row_data['opens'] campaign_id_to_data[campaign_id]['bounces'] += row_data['bounces'] from TalentUsers import users_in_domain return dict(table_data=campaign_id_data_tuples, json_chart_data=simplejson.dumps(chart_data), users=users_in_domain(auth.user.domainId))
def save_user_email_template(): response.generic_patterns = ['*.json'] user_email_template = db.user_email_template(request.vars.id) # Verify owned by same domain owner_user = db.user(user_email_template.userId) if owner_user.domainId != auth.user.domainId: raise HTTP(500, "Template is not owned by same domain") # Verify isImmutable if user_email_template.isImmutable and not is_current_user_admin(): raise HTTP(500, "Non-admin user trying to save immutable template") user_email_template.update_record(emailBodyHtml=request.vars.emailBodyHtml or user_email_template.emailBodyHtml, emailBodyText=request.vars.emailBodyText or user_email_template.emailBodyText) return dict(success=1)
def delete(): from CustomErrors import CustomErrorResponse # Make sure list owner is current user, then delete smart_list = db.smart_list(request.vars.id) if not smart_list: response.status = 404 return dict(message="No list found") smart_list_owner_id = smart_list.userId # Check the current user is belongs to admin group from TalentUsers import is_current_user_admin, user_from_id is_user_admin = is_current_user_admin(auth.user.id) # Get the domain id of current user and smart_list owner user_row = user_from_id(smart_list_owner_id) smart_list_domain_id = user_row.domainId if smart_list_owner_id == auth.user.id or ( is_user_admin and smart_list_domain_id == auth.user.domainId): TalentSmartListAPI.delete(smart_list) return dict(message="List %s has been deleted" % smart_list.name) else: response.status = 401 return CustomErrorResponse.NOT_AUTHORIZED
def index(): from TalentUsers import is_current_user_admin response.title = "Dashboard" domain_id = auth.user.domainId # Get all owners (users) in current user's domain owners = db(db.user.domainId == domain_id).select() sources = db(db.candidate_source.domainId == auth.user.domainId).select() # Dashboard stats stats_json = simplejson.dumps(get_dashboard_stats(current_user=auth.user)) # Show/Hide Generate Report button domain_settings_dict = get_domain_settings_dict(db.domain(domain_id)) show_generate_report = 'generateReport' in get_hidden_fields_from_domain_settings_dict( 'dashboard', domain_settings_dict) layout_mode = get_hidden_fields_from_domain_settings_dict( 'layoutMode', domain_settings_dict) show_graph_by_status = 'graphByStatus' in get_hidden_fields_from_domain_settings_dict( 'dashboard', domain_settings_dict) show_graph_by_source = 'graphBySource' in get_hidden_fields_from_domain_settings_dict( 'dashboard', domain_settings_dict) show_graph_by_owner = 'graphByOwner' in get_hidden_fields_from_domain_settings_dict( 'dashboard', domain_settings_dict) show_graph_over_time = 'graphOverTime' in get_hidden_fields_from_domain_settings_dict( 'dashboard', domain_settings_dict) show_graph_areas_of_interest = 'graphAreasOfInterest' in get_hidden_fields_from_domain_settings_dict( 'dashboard', domain_settings_dict) return dict(owners=owners, sources=sources, stats_json=stats_json, is_current_user_admin=is_current_user_admin(), layout_mode=layout_mode, show_generate_report_button=show_generate_report, show_graph_by_status=show_graph_by_status, show_graph_by_source=show_graph_by_source, show_graph_by_owner=show_graph_by_owner, show_graph_over_time=show_graph_over_time, show_graph_areas_of_interest=show_graph_areas_of_interest)
def create_user_email_template(): response.generic_patterns = ['*.json'] name = request.vars.name # Check if the name is already exists in the domain existing_name = db((db.user_email_template.name == name) & (db.user_email_template.userId == db.user.id) & (db.user.domainId == auth.user.domainId)).select( db.user_email_template.name) if existing_name: response.status = 400 return CustomErrorResponse.DUPLICATE_TEMPLATE email_template_folder_id = int(request.vars.emailTemplateFolderId or 0) email_template_folder = db.email_template_folder( email_template_folder_id) if email_template_folder_id else None if email_template_folder and email_template_folder.domainId != auth.user.domainId: raise HTTP( 500, "Email template's folder (%s) is in the user's domain (%s)", email_template_folder.id, auth.user.domainId) # Set isImmutable is_immutable = 0 if request.vars.isImmutable == "1" and not is_current_user_admin(): raise HTTP(403, "isImmutable = 1 but user is not admin") elif request.vars.isImmutable == "1": is_immutable = 1 user_email_template_id = db.user_email_template.insert( userId=auth.user.id, type=TEMPLATE_EMAIL_MARKETING, name=request.vars.name, emailBodyHtml=request.vars.emailBodyHtml or None, emailBodyText=request.vars.emailBodyText or None, emailTemplateFolderId=email_template_folder.id if email_template_folder else None, isImmutable=is_immutable) return dict(id=user_email_template_id)
def builder(): from TalentEmailMarketing import schedule_email_campaign_sends # if not request.vars.sendTime: request.vars.sendTime = request.now.strftime("%Y-%m-%d %H:%M:%S") form = SQLFORM(db.email_campaign) if request.post_vars: # Set the campaign's user ID request.vars['userId'] = auth.user.id # Set the campaign's custom parameter JSON, if any if request.vars['customSrc']: import simplejson request.vars['customUrlParamsJson'] = simplejson.dumps( dict(src=request.vars.customSrc)) # If there is an HTML email but not plaintext, automatically set plaintext if not request.vars.emailBodyText and request.vars.emailBodyHtml: request.vars['emailBodyText'] = _html_to_text( request.vars.emailBodyHtml) # get html text from saved template table, # @TODO reply on user_email_template to get email content from, and connect it to email_campaign, no need for duplicate data if not request.post_vars.SelectedTemplateId: request.post_vars['emailBodyHtml'] = request.vars.emailBodyHtml request.post_vars['emailBodyText'] = _html_to_text( request.vars.emailBodyHtml) else: html_email = db(db.user_email_template.id == request.post_vars.SelectedTemplateId).select( db.user_email_template.emailBodyHtml, db.user_email_template.emailBodyText) request.post_vars['emailBodyHtml'] = html_email[0].emailBodyHtml request.post_vars['emailBodyText'] = html_email[ 0].emailBodyText or _html_to_text(request.vars.emailBodyHtml) current.email_campaign_validation_error = '' if form.process(session=None, formname=None, onvalidation=lambda (frm): email_campaign_validation( frm, request.vars, auth.user.domainId)).accepted: # Add activity activity_api = TalentActivityAPI() activity_api.create(auth.user.id, activity_api.CAMPAIGN_CREATE, source_table='email_campaign', source_id=form.vars.id, params=dict(id=form.vars.id, name=form.vars.name)) # Make email_campaign_smart_list records campaign = db.email_campaign(form.vars.id) TalentSmartListAPI.create_email_campaign_smart_lists( request.vars.smart_list_ids, campaign.id, auth.user_id) # Schedule the sending of emails schedule_email_campaign_sends(campaign, auth.user) session.flash = "Campaign %s successfully started" % form.vars.name redirect(URL('campaign', 'index')) return elif form.errors: logger.error("Received error saving email campaign form: %s", form.errors) if current.email_campaign_validation_error: response.flash = current.email_campaign_validation_error else: response.flash = "%s: %s" % ( "Enter a value for", db.email_campaign[form.errors.keys()[0]].label) frequencies = db(db.frequency.id > 0).select() smart_lists = TalentSmartListAPI.get_in_domain(auth.user.domainId, order=True, get_candidate_count=False) # Filter out smart lists that have 0 recipients # smart_lists = filter(lambda row: row.candidateCount > 0, smart_lists) send_once_frequency_id = [freq.id for freq in frequencies][0] # Templates templates = db((db.user_email_template.type == TEMPLATE_EMAIL_MARKETING) & (db.user_email_template.userId == db.user.id) & (db.user.domainId == auth.user.domainId)).select( db.user_email_template.ALL) # templates = templates.find(lambda row: row.isImmutable == 1) # mails = templates.find(lambda row: not row.isImmutable) # Set up folder_id_to_mails_dicts, which is like: [{1: mails}, {2: mails}, ..] folders = db( db.email_template_folder.domainId == auth.user.domainId).select() folder_id_to_mails_dicts = [{folder.id: []} for folder in folders] folder_id_to_mails_dicts.append({0: []}) # Uncategorized: No folder ID for template in templates: for folder_id_to_mails in folder_id_to_mails_dicts: # Get the dict of folder ID to mails folder_id = folder_id_to_mails.keys()[0] if folder_id == (template.emailTemplateFolderId or 0): # 0 is Uncategorized folder_id_to_mails[template.emailTemplateFolderId or 0].append(template) # print 'folder_id_to_mails_dicts keys before swapping', [e.keys() for e in folder_id_to_mails_dicts] # Make 'Uncategorized' folder last, and 'Templates' folder first if it exists uncategorized_index = -1 folder_called_templates_index = -1 folder_called_templates = folders.find( lambda row: row.name == 'Templates').first() for i, folder_id_to_mails in enumerate(folder_id_to_mails_dicts): folder_id = folder_id_to_mails.keys()[0] if folder_id == 0: uncategorized_index = i elif folder_called_templates and folder_id == folder_called_templates.id: folder_called_templates_index = i if uncategorized_index != -1: # Swap 'Uncategorized' and the last last = folder_id_to_mails_dicts[-1] folder_id_to_mails_dicts[-1] = folder_id_to_mails_dicts[ uncategorized_index] folder_id_to_mails_dicts[uncategorized_index] = last if folder_called_templates_index != -1: # Swap 'Templates' and the first first = folder_id_to_mails_dicts[0] folder_id_to_mails_dicts[0] = folder_id_to_mails_dicts[ folder_called_templates_index] folder_id_to_mails_dicts[folder_called_templates_index] = first # print 'folder_id_to_mails_dicts keys after swapping', [e.keys() for e in folder_id_to_mails_dicts] # Domain-wide default tracking code & from name domain = db.domain(auth.user.domainId) tracking_code = domain.defaultTrackingCode default_from_name = domain.defaultFromName # Show/Hide Generate Report button domain_settings_dict = get_domain_settings_dict( db.domain(auth.user.domainId)) hidden_fields = get_hidden_fields_from_domain_settings_dict( 'builder', domain_settings_dict) layout_mode = get_hidden_fields_from_domain_settings_dict( 'layoutMode', domain_settings_dict) # If domain is Kaiser Corporate, hide Job Alert smartlists for non-admin users if is_kaiser_domain(auth.user.domainId) and not is_current_user_admin( user_id=auth.user_id): smart_lists = filter(lambda row: 'Job Alerts' not in row.name, smart_lists) return dict(user=db.user(auth.user_id), smart_lists=smart_lists, frequencies=frequencies, send_once_frequency_id=send_once_frequency_id, templates=templates, folders=folders, folder_id_to_mails_dicts=folder_id_to_mails_dicts, DEFAULT_FIRST_NAME_MERGETAG=DEFAULT_FIRST_NAME_MERGETAG, DEFAULT_LAST_NAME_MERGETAG=DEFAULT_LAST_NAME_MERGETAG, tracking_code=tracking_code, default_from_name=default_from_name, hidden_fields=hidden_fields, is_current_user_admin=is_current_user_admin(), layout_mode=layout_mode)
def profile(): response.title = "Profile" if request.vars._formname == 'widget_page': existing_widget_page = db.widget_page(request.vars.id) existing_widget_page.update_record( replyAddress=request.vars.replyAddress, emailSource='"%s" <*****@*****.**>' % request.vars.emailSource, welcomeEmailSubject=request.vars.welcomeEmailSubject, welcomeEmailHtml=request.vars.welcomeEmailHtml, requestEmailHtml=request.vars.requestEmailHtml ) response.flash = 'Widget settings updated' custom_fields = None if request.vars._formname == 'custom_fields': custom_fields = db(db.custom_field.domainId == auth.user.domainId).select(cache=(cache.ram, 300)) current_custom_field_names = [row.name.strip() for row in custom_fields] # Convert custom field names & types to array if it's string new_custom_field_names = request.vars.get('custom_field.name') if isinstance(new_custom_field_names, basestring): new_custom_field_names = [new_custom_field_names] new_custom_field_types = request.vars.get('custom_field.type') if isinstance(new_custom_field_types, basestring): new_custom_field_types = [new_custom_field_types] new_custom_field_cats = request.vars.get('custom_field.category') if isinstance(new_custom_field_cats, int): new_custom_field_cats = [new_custom_field_cats] # Strip the names new_custom_field_names = [name.strip() for name in new_custom_field_names] # Make dict of new custom field name -> type new_name_to_type = dict() new_name_to_cat = dict() for index, new_custom_field_name in enumerate(new_custom_field_names): cf_type = new_custom_field_types[index] cat = new_custom_field_cats[index] new_name_to_type[new_custom_field_name] = cf_type if cf_type in ('string', 'datetime') else 'string' new_name_to_cat[new_custom_field_name] = int(cat) or None # Add in custom fields unless one with the same name already exists # hmm, can it be same name with different category ? and could not be done at the moment unless custom-field id comes back from solr @TODO refresh_custom_fields_cache = True for index, new_name in enumerate(new_custom_field_names): if new_name and new_name not in current_custom_field_names: db.custom_field.insert(domainId=auth.user.domainId, name=new_name, type=new_name_to_type[new_name], categoryId=new_name_to_cat[new_name]) refresh_custom_fields_cache = True elif new_name and new_name in current_custom_field_names: db((db.custom_field.name == new_name) & (db.custom_field.domainId == auth.user.domainId)).update( categoryId=new_name_to_cat[new_name]) if refresh_custom_fields_cache: custom_fields = db(db.custom_field.domainId == auth.user.domainId).select(cache=(cache.ram, 0)) # there's a bug in the change_password function in web2py - redirects before returning an error if request.vars.old_password and request.vars.new_password and request.vars.new_password2: if not auth.login_bare(auth.user.email, request.vars.old_password): request.vars.old_password = '' request.vars.new_password = '' request.vars.new_password2 = '' session.flash = 'Your old password is not correct. Please try again.' form = auth.change_password(next=URL('user', 'profile')) # Get custom fields & the # of candidates in each field if not custom_fields: custom_fields = db(db.custom_field.domainId == auth.user.domainId).select(cache=(cache.ram, 300)) custom_field_ids = [row.id for row in custom_fields] count = db.candidate_custom_field.id.count() candidate_custom_field_counts = db( db.candidate_custom_field.customFieldId.belongs(custom_field_ids) ).select(db.candidate_custom_field.ALL, count, groupby=db.candidate_custom_field.customFieldId) # find what values are assigned to each custom field count_values = db.candidate_custom_field.value.count() custom_fields_values = db( db.candidate_custom_field.customFieldId.belongs(custom_field_ids) ).select(count_values, db.candidate_custom_field.customFieldId, db.candidate_custom_field.value, groupby=db.candidate_custom_field.value) for custom_field in custom_fields: candidate_custom_field = candidate_custom_field_counts.find( lambda cf_row: cf_row.candidate_custom_field.customFieldId == custom_field.id).first() custom_field.num_candidates = candidate_custom_field[count] if candidate_custom_field else 0 # Default Tracking Code domain = db.domain(auth.user.domainId) if request.vars._formname == 'email_marketing': domain.update_record(defaultTrackingCode=request.vars.tracking_code, defaultFromName=request.vars.default_from_name) tracking_code = domain.defaultTrackingCode default_from_name = domain.defaultFromName # user is a Talent Customer admin(customer management tab) if auth.has_membership(group_id=1): domain_data = db().select(db.domain.id, db.domain.name) domain_ids = [row.id for row in domain_data] is_talent_admin = True else: domain_data = db(db.domain.id == auth.user.domainId).select(db.domain.id, db.domain.name) domain_ids = [auth.user.domainId] is_talent_admin = False customer_data = db(db.domain.id.belongs(domain_ids)).select(db.user.id, db.user.email, db.user.firstName, db.user.lastName, db.user.addedTime, db.user.expiration, db.user_attributes.brand, db.user_attributes.department, db.user_attributes.userGroup, db.user_attributes.KPI, db.candidate.id.count(), db.user.domainId, groupby=db.user.id, orderby=(~db.domain.addedTime), left=[ db.candidate.on( db.user.id == db.candidate.ownerUserId), db.domain.on(db.user.domainId == db.domain.id), db.user_attributes.on( db.user.id == db.user_attributes.userId), ] ) last_login_data = db.executesql("""SELECT * FROM (SELECT web_auth_event.time_stamp, web_auth_event.user_id FROM web_auth_event WHERE (web_auth_event.description LIKE '% Logged-in') ORDER BY web_auth_event.time_stamp DESC) as temp GROUP BY user_id;""", as_dict=True) user_admin_data = db(db.web_auth_membership.group_id == 2).select(db.web_auth_membership.user_id, db.web_auth_membership.group_id) last_logins = {} for row in last_login_data: last_login = row.get('time_stamp').strftime("%D") if row.get('time_stamp') else 'Never' last_logins.setdefault(row.get('user_id'), last_login) dashboard_data = [] for domain in domain_data: dashboard_row = {'domain': domain.name} domain_users = customer_data.find(lambda cd_row: cd_row.user.domainId == domain.id) domain_candidate_count = 0 for user in domain_users: account_type = user_admin_data.find(lambda uad_row: uad_row.user_id == user.user.id) domain_candidate_count += int(user['_extra']["COUNT(candidate.id)"]) user.user['last_login'] = last_logins.get(user.user.id) user.user['addedTime'] = user.user.addedTime.strftime("%D") user.user['expiration'] = user.user.expiration.strftime("%D") if user.user.expiration else '' user.user['account_type'] = 'Admin' if len(account_type) else 'Normal' dashboard_row['candidate_count'] = domain_candidate_count dashboard_row['users'] = domain_users dashboard_data.append(dashboard_row) from TalentUsers import is_current_user_admin is_company_admin = is_current_user_admin() widget_pages = db(db.user.domainId == auth.user.domainId)(db.widget_page.userId == db.user.id).select( db.widget_page.ALL) candidate_source_ids = [wp.candidateSourceId for wp in widget_pages] # In case widget has no candidate_source_ids if None in candidate_source_ids: candidate_source_ids = [] logger.error("A widget_page did not have a candidate_source_id: domainId=%s", auth.user.domainId) candidate_sources = db(db.candidate_source.id.belongs(candidate_source_ids)).select() if candidate_sources: widget_page = widget_pages.find( lambda widget_page_row: widget_page_row.candidateSourceId == candidate_sources.first().id).first() else: widget_page = get_or_create_widget_page(auth.user) # All custom fields in logged-in user's domain from TalentUsers import RATING_CATEGORY_NAME, get_or_create_rating_custom_fields get_or_create_rating_custom_fields(auth.user.domainId) domain_custom_fields = db(db.custom_field_category.domainId == auth.user.domainId).select( db.custom_field_category.ALL) # custom fields categories rating_category = domain_custom_fields.find(lambda cf_cat: cf_cat.name == RATING_CATEGORY_NAME).first() custom_fields_categories = domain_custom_fields.find(lambda cf_cat: cf_cat.name != RATING_CATEGORY_NAME) # Remove rating related fields from custom_fields, Rating will have separate UI. custom_fields_without_ratings = custom_fields.find(lambda cf: cf.categoryId != rating_category.id) # Custom fields for rating rating_custom_fields = custom_fields.find(lambda cf: cf.categoryId == rating_category.id) # areas of interest parents areas_of_interest_parents = db((db.area_of_interest.domainId == auth.user.domainId) & ( (db.area_of_interest.parentId == None) | (db.area_of_interest.parentId == 0))).select(db.area_of_interest.id, db.area_of_interest.description) # custom layout mode check domain_settings = get_domain_settings_dict(db.domain(auth.user.domainId)) current_layout_mode = domain_settings.get('layoutMode', 0) social_network_info = db(db.social_network.authUrl != None).select(db.social_network.name, db.social_network.clientKey, db.social_network.authUrl, db.social_network.redirectUri) return dict( social_network_info=social_network_info, form=form, widget_page=widget_page, custom_fields=custom_fields_without_ratings, candidate_custom_field_counts=candidate_custom_field_counts, tracking_code=tracking_code, default_from_name=default_from_name, domains=domain_data, dashboard_data=dashboard_data, is_gettalent_admin=is_talent_admin, is_company_admin=is_company_admin, candidate_sources=candidate_sources, custom_fields_categories=custom_fields_categories, areas_of_interest_parents=areas_of_interest_parents, current_layout_mode=current_layout_mode, custom_fields_values=custom_fields_values, count_values=count_values, rating_custom_fields=rating_custom_fields )