def availableDonationForms(context): terms = [] settings = get_settings() default = settings.default_donation_form terms.append(SimpleVocabulary.createTerm(default, default, 'Stripe Donation Form')) try: campaign_getter = context.get_fundraising_campaign except AttributeError: # The campaign hasn't been created yet, so there are no # available campaign-specific donation forms yet. pass else: campaign = campaign_getter() query = { "portal_type": "collective.salesforce.fundraising.productform", "path": '/'.join(campaign.getPhysicalPath()), } pc = getToolByName(context, 'portal_catalog') res = pc.searchResults(**query) for form in res: form_id = form.id + '/donation_form_stripe' terms.append( SimpleVocabulary.createTerm(form_id, form_id, 'Product Form: ' + form.Title)) return SimpleVocabulary(terms)
def get_default(self, field): # Skip lookup if there is no id (i.e. object is still being created) if self.id: # Try campaign if different from page (i.e. personal campaign page # or campaign variation) try: campaign = self.get_fundraising_campaign() except AttributeError: # FIXME: For some reason sometimes there is no __parent__ # set at this point. This seems to occur after edit of a # personal campaign page return None if campaign != self.get_fundraising_campaign_page(): val = getattr(campaign, '_%s' % field, None) # convert rich text objects, if present: if isinstance(val, RichTextValue): val = val.output if val is not None: return val # Try global using 'default_' as field name prefix for settings settings = get_settings() val = getattr(settings, 'default_%s' % field, None) return val
def email_failure_from_portal(portal, info): from_name = portal.getProperty('email_from_name') from_address = portal.getProperty('email_from_address') from_formatted = formataddr((from_name, from_address)) settings = get_settings() to_address = settings.async_error_email all_info = info.copy() all_info.update({ 'from_formatted': from_formatted, 'to_formatted': to_address, 'hostname': socket.gethostname(), 'pid': os.getpid(), 'thread_id': thread.get_ident(), 'datetime_utc': datetime.datetime.utcnow().isoformat(), 'datetime_local': datetime.datetime.now().isoformat(), 'mymod': __name__, }) msg = msg_template.format(**all_info).encode('utf-8') # The ``immediate`` parameter causes an email to be sent immediately # (if any error is raised) rather than sent at the transaction # boundary or queued for later delivery. mh = getToolByName(portal, 'MailHost') mh.send(msg, immediate=True)
def __call__(self): settings = get_settings() self.organization_name = settings.organization_name self.campaign = self.context.get_fundraising_campaign() self.page = self.context.get_fundraising_campaign_page() self.donation_receipt_legal = self.campaign.donation_receipt_legal self.products = [] if self.context.products: for product in self.context.products: price, quantity, product_uuid = product.split('|', 2) total = int(price) * int(quantity) product = uuidToObject(product_uuid) if not product: continue if product.donation_only: price = total quantity = '-' self.products.append({ 'price': price, 'quantity': quantity, 'product': product, 'total': total, }) self.is_personal = self.page.is_personal() module = os.sys.modules[martian.util.caller_module()] _prefix = os.path.dirname(module.__file__) pt = PageTemplateFile('donation_templates/receipt.pt') return pt.pt_render({'view': self})
def update(self): self.settings = get_settings() self.amount = self.request.form.get('x_amount', None) if self.amount is not None: self.amount = int(self.amount) self.states = [] self.countries = [] self.states = [] self.update_levels() self.error = None self.update_countries() self.update_states() self.recurring = False self.recurring_id = None self.recurring_title = None campaign = self.context.get_fundraising_campaign() self.default_gift_type = campaign.default_gift_type if campaign.stripe_recurring_plan: self.recurring = True self.recurring_id = campaign.stripe_recurring_plan # FIXME: Lookup the title from the vocabulary and cache it for a bit self.recurring_title = 'Monthly recurring gift'
def createSalesforceCampaign(message, event): # Set the parent_sf_id using the parent if not message.parent_sf_id: message.parent_sf_id = aq_parent(message).sf_object_id # create Share Message campaign in Salesforce site = getSite() sfconn = getUtility(ISalesforceUtility).get_connection() data = { 'Type': 'Share Message', 'Name': message.title, 'Public_Name__c': message.title, 'Status': message.status, 'ParentId': message.parent_sf_id, } settings = get_settings() if settings.sf_campaign_record_type_share: data['RecordTypeId'] = settings.sf_campaign_record_type_share res = sfconn.Campaign.create(data) if not res['success']: raise Exception(res['errors'][0]) message.sf_object_id = res['id']
def handleFundraisingCampaignCreated(campaign, event): # Add campaign in Salesforce if it doesn't have a Salesforce id yet if getattr(campaign, 'sf_object_id', None) is None: sfconn = getUtility(ISalesforceUtility).get_connection() settings = get_settings() # Only parse the dates if they have a value start_date = campaign.date_start if start_date: start_date = start_date.isoformat() end_date = campaign.date_end if end_date: end_date = end_date.isoformat() data = { 'Type': 'Fundraising', 'Name': campaign.title, 'Public_Name__c': campaign.title, 'Description': campaign.description, 'Status': campaign.status, 'ExpectedRevenue': campaign.goal, 'Allow_Personal__c': campaign.allow_personal, 'StartDate': start_date, 'EndDate': end_date, } if settings.sf_campaign_record_type: data['RecordTypeId'] = settings.sf_campaign_record_type res = sfconn.Campaign.create(data) if not res['success']: raise Exception(res['errors'][0]) campaign.sf_object_id = res['id'] campaign.reindexObject(idxs=['sf_object_id'])
def get_header_image_url(self): local_image = getattr(self, 'header_image', None) if local_image and local_image.filename: return '%s/@@images/header_image' % self.absolute_url() settings = get_settings() return getattr(settings, 'default_header_image_url', None)
def availableDonationForms(context): terms = [] settings = get_settings() default = settings.default_donation_form terms.append( SimpleVocabulary.createTerm(default, default, 'Stripe Donation Form')) try: campaign_getter = context.get_fundraising_campaign except AttributeError: # The campaign hasn't been created yet, so there are no # available campaign-specific donation forms yet. pass else: campaign = campaign_getter() query = { "portal_type": "collective.salesforce.fundraising.productform", "path": '/'.join(campaign.getPhysicalPath()), } pc = getToolByName(context, 'portal_catalog') res = pc.searchResults(**query) for form in res: form_id = form.id + '/donation_form_stripe' terms.append( SimpleVocabulary.createTerm(form_id, form_id, 'Product Form: ' + form.Title)) return SimpleVocabulary(terms)
def update(self): self.settings = get_settings() self.amount = self.request.form.get('x_amount', None) if self.amount is not None: self.amount = int(self.amount) self.states = [] self.countries = [] self.states = [] self.update_levels() self.error = None self.update_countries() self.update_states() self.recurring = False self.recurring_id = None self.recurring_title = None campaign = self.context.get_fundraising_campaign() if campaign.stripe_recurring_plan: self.recurring = True self.recurring_id = campaign.stripe_recurring_plan # FIXME: Lookup the title from the vocabulary and cache it for a bit self.recurring_title = 'Monthly recurring gift'
def render(self): # Get the site id and app_id from registry settings = get_settings() janrain_site_id = settings.janrain_site_id janrain_sharing_app_id = settings.janrain_sharing_app_id if not janrain_site_id: return '' # Get callback url context = aq_inner(self.context) portal_state = getMultiAdapter((context, self.request), name=u'plone_portal_state') portal_url = portal_state.portal_url() token_url = portal_url + '/@@rpx_post_login' # render the js template return js_template % { 'site_id': janrain_site_id, 'token_url': token_url, 'app_id': janrain_sharing_app_id, 'came_from': self.request.get('came_from', self.context.absolute_url()), }
def send_donation_receipt(self): settings = get_settings() res = self.send_email_thank_you() self.is_receipt_sent = True return res logger.warning('collective.salesforce.fundraising: Send Donation Receipt: No template found')
def update(self): # if we are a Tribute Campaign, set a value to be picked up by the # template if IFundraisingTributeCampaignPage.providedBy(self.context): self.is_tribute = True else: self.is_tribute = False # Set a cookie with referrer as source_url if no cookie has yet been # set for the session source_url = self.request.get( 'collective.salesforce.fundraising.source_url', None) if not source_url: referrer = self.request.get_header('referrer') if referrer: self.request.response.setCookie( 'collective.salesforce.fundraising.source_url', referrer) # Set a cookie with the source code if it was passed in the request self.source_campaign = self.request.get('source_campaign', None) if self.source_campaign: self.request.response.setCookie( 'collective.salesforce.fundraising.source_campaign', self.source_campaign) tabs = [] donation_form = self.context.donation_form if donation_form: html = self.context.unrestrictedTraverse( donation_form.split('/'), default=None) if html is None: html = '<code>Form missing: <em>%s</em></code>' % donation_form tabs.append({ 'id': donation_form, 'label': u'Donate', 'html': html, }) self.donation_form_tabs = tabs # Handle form validation errors from 3rd party # (right now only Authorize.net) by receiving the error codes and # looking up their text self.error = self.request.form.get('error', None) self.response_code = self.request.form.get( 'response_code', None) self.reason_code = self.request.form.get('reason_code', None) settings = get_settings() self.ssl_seal = settings.ssl_seal for name in ['donation_form_header', 'donation_form_description']: setattr(self, name, self.get_local_or_default(name))
def get_email_recurring_template(self, field): settings = get_settings() uuid = getattr(settings, field, None) if not uuid: logger.warning('collective.salesforce.fundraising: get_email_recurring_template: No template configured for %s' % field) return template = uuidToObject(uuid) if not template: logger.warning('collective.salesforce.fundraising: get_email_recurring_template: No template found for %s' % field) return return template
def update(self): # if we are a Tribute Campaign, set a value to be picked up by the # template if IFundraisingTributeCampaignPage.providedBy(self.context): self.is_tribute = True else: self.is_tribute = False # Set a cookie with referrer as source_url if no cookie has yet been # set for the session source_url = self.request.get( 'collective.salesforce.fundraising.source_url', None) if not source_url: referrer = self.request.get_header('referrer') if referrer: self.request.response.setCookie( 'collective.salesforce.fundraising.source_url', referrer) # Set a cookie with the source code if it was passed in the request self.source_campaign = self.request.get('source_campaign', None) if self.source_campaign: self.request.response.setCookie( 'collective.salesforce.fundraising.source_campaign', self.source_campaign) tabs = [] donation_form = self.context.donation_form if donation_form: html = self.context.unrestrictedTraverse(donation_form.split('/'), default=None) if html is None: html = '<code>Form missing: <em>%s</em></code>' % donation_form tabs.append({ 'id': donation_form, 'label': u'Donate', 'html': html, }) self.donation_form_tabs = tabs # Handle form validation errors from 3rd party # (right now only Authorize.net) by receiving the error codes and # looking up their text self.error = self.request.form.get('error', None) self.response_code = self.request.form.get('response_code', None) self.reason_code = self.request.form.get('reason_code', None) settings = get_settings() self.ssl_seal = settings.ssl_seal for name in ['donation_form_header', 'donation_form_description']: setattr(self, name, self.get_local_or_default(name))
def get_email_recurring_template(field): """ Looks for value of field in settings and tries to look up a template using the value as uuid """ settings = get_settings() uuid = getattr(settings, field, None) if not uuid: logger.warning('collective.salesforce.fundraising: get_email_recurring_template: No template configured for %s' % field) return template = uuidToObject(uuid) if not template: logger.warning('collective.salesforce.fundraising: get_email_recurring_template: No template found for %s' % field) return return template
def update(self): self.link_id = 'share-message-' + self.context.id if not hasattr(self, 'url'): self.set_url() self.show_email_share = get_settings().enable_share_via_email comment = self.context.comment if comment: comment = comment.replace("'","\\'") self.message_js = SHARE_JS_TEMPLATE % { 'link_id': self.link_id, 'url': self.url, 'title': self.context.title.replace("'","\\'"), 'description': self.context.description.replace("'","\\'"), 'image': self.context.absolute_url() + '/@@images/image', 'message': comment, }
def get_local_or_default(self, field): """for fields of the context object with both local and site-wide default values. Return the local value if provided, else return the setting, else return None always looks for values on the fundraising campaign object only """ local_campaign = self.context.get_fundraising_campaign() val = getattr(local_campaign, field, None) if not val: settings = get_settings() val = getattr(settings, field, None) # convert rich text objects, if present: if val and isinstance(val, RichTextValue): val = val.output return val
def availableDonationForms(context): query = { "portal_type": "collective.salesforce.fundraising.productform", "path": '/'.join(context.getPhysicalPath()), } terms = [] settings = get_settings() default = settings.default_donation_form terms.append(SimpleVocabulary.createTerm( default, default, 'Stripe Donation Form')) pc = getToolByName(context, 'portal_catalog') res = pc.searchResults(**query) for form in res: form_id = form.id + '/donation_form_stripe' terms.append(SimpleVocabulary.createTerm( form_id, form_id, 'Product Form: ' + form.Title)) return SimpleVocabulary(terms)
def get_email_recurring_template(field): """ Looks for value of field in settings and tries to look up a template using the value as uuid """ settings = get_settings() uuid = getattr(settings, field, None) if not uuid: logger.warning( 'collective.salesforce.fundraising: get_email_recurring_template: No template configured for %s' % field) return template = uuidToObject(uuid) if not template: logger.warning( 'collective.salesforce.fundraising: get_email_recurring_template: No template found for %s' % field) return return template
def get_container_for_invoice(invoice): """ Get the container where a donation for the invoice should be created """ mode = 'live' if invoice['livemode'] == False: mode = 'test' stripe_util = getUtility(IStripeUtility) stripe_api = stripe_util.get_stripe_api(mode=mode) customer = stripe_api.Customer.retrieve(invoice['customer']) if customer['description']: # container's sf_id is in the third column of a pipe delimited string desc_parts = customer['description'].split('|') if len(desc_parts) >= 3: container_id = desc_parts[2] if container_id: pc = getToolByName(getSite(), 'portal_catalog') res = pc.searchResults( object_provides= 'collective.salesforce.fundraising.fundraising_campaign.IFundraisingCampaignPage', sf_object_id=container_id, sort_index='created', sort_limit=1, ) if res: return res[0].getObject() # Find the site default settings = get_settings() if settings.default_campaign: container = uuidToObject(settings.default_campaign) if container: return container # This is the ultimate fallback. Find the campaign with the most donations and assume it is the default campaign. pc = getToolByName(getSite(), 'portal_catalog') res = pc.searchResults( portal_type='collective.salesforce.fundraising.fundraisingcampaign', sort_on='donations_count', sort_order='descending', ) if res: return res[0].getObject()
def get_container_for_invoice(invoice): """ Get the container where a donation for the invoice should be created """ mode = 'live' if invoice['livemode'] == False: mode = 'test' stripe_util = getUtility(IStripeUtility) stripe_api = stripe_util.get_stripe_api(mode=mode) customer = stripe_api.Customer.retrieve(invoice['customer']) if customer['description']: # container's sf_id is in the third column of a pipe delimited string desc_parts = customer['description'].split('|') if len(desc_parts) >= 3: container_id = desc_parts[2] if container_id: pc = getToolByName(getSite(), 'portal_catalog') res = pc.searchResults( object_provides='collective.salesforce.fundraising.fundraising_campaign.IFundraisingCampaignPage', sf_object_id = container_id, sort_index = 'created', sort_limit = 1, ) if res: return res[0].getObject() # Find the site default settings = get_settings() if settings.default_campaign: container = uuidToObject(settings.default_campaign) if container: return container # This is the ultimate fallback. Find the campaign with the most donations and assume it is the default campaign. pc = getToolByName(getSite(), 'portal_catalog') res = pc.searchResults( portal_type='collective.salesforce.fundraising.fundraisingcampaign', sort_on='donations_count', sort_order='descending', ) if res: return res[0].getObject()
def get_seals(self): seal_paths = [] if self.context.fundraising_seals: seal_paths = self.context.fundraising_seals else: settings = get_settings() seal_paths = settings.default_fundraising_seals if not seal_paths: return [] # Fetch the seal objects pc = getToolByName(self.context, 'portal_catalog') res = pc.searchResults(path=seal_paths) seals = [] for b in res: seals.append(b.getObject()) return seals
def render_janrain_share(self): settings = get_settings() comment = settings.thank_you_share_message if not comment: comment = '' amount_str = '' amount_str = u' $%s' % self.context.amount comment = comment.replace('{{ amount }}', str(self.context.amount)) campaign = self.context.get_fundraising_campaign_page() if not campaign: return '' return SHARE_JS_TEMPLATE % { 'link_id': 'share-message-thank-you', 'url': campaign.absolute_url() + '?SOURCE_CODE=thank_you_share', 'title': campaign.title.replace("'","\\'"), 'description': campaign.description.replace("'","\\'"), 'image': campaign.absolute_url() + '/@@images/image', 'message': comment, }
def sync_to_salesforce(self): self.sfconn = getUtility(ISalesforceUtility).get_connection() self.campaign = self.context.get_fundraising_campaign() self.page = self.context.get_fundraising_campaign_page() self.pricebook_id = None self.settings = get_settings() if not self.context.synced_contact: self.sync_contact() transaction.commit() self.get_products() if not self.context.synced_recurring: self.upsert_recurring() transaction.commit() if not self.context.synced_opportunity or \ not self.context.synced_honorary_data: self.upsert_opportunity() transaction.commit() # The following are only synced on the initial sync. Logic needs to be added to query then # update as there is no external key that can be used for these. if not self.context.synced_products: self.create_products() transaction.commit() if not self.context.synced_contact_role: self.create_opportunity_contact_role() transaction.commit() if not self.context.synced_campaign_member: self.create_campaign_member() transaction.commit() self.context.reindexObject() return 'Successfully synced donation %s' % self.context.absolute_url()
def render(self): # Get the site id and app_id from registry settings = get_settings() janrain_site_id = settings.janrain_site_id janrain_sharing_app_id = settings.janrain_sharing_app_id if not janrain_site_id: return "" # Get callback url context = aq_inner(self.context) portal_state = getMultiAdapter((context, self.request), name=u"plone_portal_state") portal_url = portal_state.portal_url() token_url = portal_url + "/@@rpx_post_login" # render the js template return js_template % { "site_id": janrain_site_id, "token_url": token_url, "app_id": janrain_sharing_app_id, "came_from": self.request.get("came_from", self.context.absolute_url()), }
def update(self): # Set a cookie with referrer as source_url if no cookie has yet been set for the session source_url = self.request.get('collective.salesforce.fundraising.source_url', None) if not source_url: referrer = self.request.get_header('referrer') if referrer: self.request.response.setCookie('collective.salesforce.fundraising.source_url', referrer) # Set a cookie with the source code if it was passed in the request self.source_campaign = self.request.get('source_campaign', None) if self.source_campaign: self.request.response.setCookie('collective.salesforce.fundraising.source_campaign', self.source_campaign) tabs = [] donation_form = self.context.donation_form if donation_form: html = self.context.unrestrictedTraverse(donation_form.split('/')) tabs.append({ 'id': donation_form, 'label': u'Donate', 'html': html, }) self.donation_form_tabs = tabs # Handle form validation errors from 3rd party (right now only Authorize.net) # by receiving the error codes and looking up their text self.error = self.request.form.get('error', None) self.response_code = self.request.form.get('response_code',None) self.reason_code = self.request.form.get('reason_code', None) settings = get_settings() self.ssl_seal = settings.ssl_seal for name in ['donation_form_header', 'donation_form_description']: setattr(self, name, self.get_local_or_default(name))
def render(self): # Get the api key from registry settings = get_settings() # workaround for http://bugs.python.org/issue5285, # map unicode to strings janrain_api_key = str(settings.janrain_api_key) if not janrain_api_key: return 'No Janrain API key configured' # Get the token token = self.request.form.get('token', None) if not token: return 'No token passed in request' # Get the user profile from Janrain auth_info_url = '%s/auth_info?apiKey=%s&token=%s' % ( JANRAIN_API_BASE_URL, janrain_api_key, token, ) if settings.janrain_use_extended_profile: auth_info_url = auth_info_url + '&extended=true' resp = urllib2.urlopen(auth_info_url) auth_info = simplejson.loads(resp.read()) # This is for Plone's built in member management instead of membrane # See if a user already exists for the profile's email # email = auth_info['profile']['email'] # member = None # if email: # member = mtool.getMemberById(email) # See if user already exists using dexterity.membrane profile = auth_info.get('profile', {}) email = profile.get('verifiedEmail', None) # NB: Do NOT accept the 'email' attribute as an alternative # to 'verifiedEmail'. The 'email' attribute can be entered by # users and therefore would be a security hole. if not email: raise AttributeError( 'No email provided from social profile, unable to create ' 'account') email = email.lower() res = get_brains_for_email(self.context, email, self.request) if not res: # create new Person if no existing Person was found # with the same email name = profile.get('name', {}) address = profile.get('address', {}) if not address: addresses = profile.get('addresses', []) if addresses: address = addresses[0] data = { 'first_name': name.get('givenName', None), 'last_name': name.get('familyName', None), 'email': email, 'street_address': address.get('streetAddress', None), 'city': address.get('locality', None), 'state': address.get('region', None), 'zip': address.get('postalCode', None), 'country': address.get('country', None), # 'gender': profile.get('gender', None), 'social_signin': True, } # Create the user people_container = getattr(getSite(), 'people') person = createContentInContainer( people_container, 'collective.salesforce.fundraising.person', checkConstraints=False, **data) # Authenticate the user mtool = getToolByName(self.context, 'portal_membership') acl = getToolByName(self.context, 'acl_users') newSecurityManager(None, acl.getUser(email)) mtool.loginUser() # or use the existing Person if found else: # Authenticate the user mtool = getToolByName(self.context, 'portal_membership') acl = getToolByName(self.context, 'acl_users') newSecurityManager(None, acl.getUser(email)) mtool.loginUser() person = res[0].getObject() if not person.social_signin: person.social_signin = True # Set the photo photo = profile.get('photo', None) if not photo: photos = profile.get('photos', []) if photos: photo = photos[0] if photo and (not person.portrait or not person.portrait.size): img_data = urllib2.urlopen(photo).read() person.portrait = NamedBlobImage(img_data) # See if came_from was passed came_from = self.request.form.get('came_from', None) # fix odd bug where came_from is a list of two values if came_from and isinstance(came_from, (list, tuple)): came_from = came_from[0] if came_from: return self.request.response.redirect(came_from) # merge in with standard plone login process. login_next = self.context.restrictedTraverse('login_next') login_next()
def get_display_goal_pct(self): settings = get_settings() return settings.personal_campaign_status_completion_threshold
def render(self): # Get the api key from registry settings = get_settings() # workaround for http://bugs.python.org/issue5285, map unicode to strings janrain_api_key = str(settings.janrain_api_key) if not janrain_api_key: return 'No Janrain API key configured' # Get the token token = self.request.form.get('token', None) if not token: return 'No token passed in request' # Get the user profile from Janrain auth_info_url = '%s/auth_info?apiKey=%s&token=%s' % ( JANRAIN_API_BASE_URL, janrain_api_key, token, ) if settings.janrain_use_extended_profile: auth_info_url = auth_info_url + '&extended=true' resp = urllib2.urlopen(auth_info_url) auth_info = simplejson.loads(resp.read()) # This is for Plone's built in member management instead of membrane # See if a user already exists for the profile's email #email = auth_info['profile']['email'] #member = None #if email: #member = mtool.getMemberById(email) # See if user already exists using dexterity.membrane profile = auth_info.get('profile',{}) email = profile.get('verifiedEmail', None) if not email: email = profile.get('email', None) if not email: raise AttributeError('No email provided from social profile, unable to create account') email = email.lower() res = get_brains_for_email(self.context, email, self.request) if not res: # create new Person if no existing Person was found with the same email name = profile.get('name',{}) address = profile.get('address',{}) if not address: addresses = profile.get('addresses', []) if addresses: address = addresses[0] data = { 'first_name': name.get('givenName', None), 'last_name': name.get('familyName', None), 'email': email, 'street_address': address.get('streetAddress', None), 'city': address.get('locality', None), 'state': address.get('region', None), 'zip': address.get('postalCode', None), 'country': address.get('country', None), #'gender': profile.get('gender', None), 'social_signin': True, } # Create the user people_container = getattr(getSite(), 'people') person = createContentInContainer( people_container, 'collective.salesforce.fundraising.person', checkConstraints=False, **data ) # Authenticate the user mtool = getToolByName(self.context, 'portal_membership') acl = getToolByName(self.context, 'acl_users') newSecurityManager(None, acl.getUser(email)) mtool.loginUser() # or use the existing Person if found else: # Authenticate the user mtool = getToolByName(self.context, 'portal_membership') acl = getToolByName(self.context, 'acl_users') newSecurityManager(None, acl.getUser(email)) mtool.loginUser() person = res[0].getObject() if person.social_signin == False: person.social_signin = True # Set the photo photo = profile.get('photo', None) if not photo: photos = profile.get('photos',[]) if photos: photo = photos[0] if photo and (not person.portrait or not person.portrait.size): img_data = urllib2.urlopen(photo).read() person.portrait = NamedBlobImage(img_data) # See if came_from was passed came_from = self.request.form.get('came_from', None) # fix odd bug where came_from is a list of two values if came_from and isinstance(came_from, (list, tuple)): came_from = came_from[0] if came_from: return self.request.response.redirect(came_from) # merge in with standard plone login process. login_next = self.context.restrictedTraverse('login_next') login_next()
def get_display_goal_pct(self): settings = get_settings() return settings.campaign_status_completion_threshold
def handleOk(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # Don't allow creation of a personal page if one already exists existing_personal_campaign = \ self.context.get_personal_fundraising_campaign_url() if existing_personal_campaign: messages = IStatusMessage(self.request) messages.add("You can't create more than one " "personal page per campaign.") self.request.response.redirect(self.context.absolute_url()) return # Add a personal campaign within the current context, # using the data from the form. parent_campaign = self.context campaign = createContentInContainer( parent_campaign, 'collective.salesforce.fundraising.personalcampaignpage', checkConstraints=False, **data ) mtool = getToolByName(self.context, 'portal_membership') member = mtool.getAuthenticatedMember() person_res = get_brains_for_email( self.context, member.getProperty('email') ) person = None contact_id = None if person_res: person = person_res[0].getObject() contact_id = person.sf_object_id settings = get_settings() # Add the campaign in Salesforce sfconn = getUtility(ISalesforceUtility).get_connection() data = { 'Type': 'Personal Fundraising', 'ParentId': parent_campaign.sf_object_id, 'Name': data['title'], 'Description': data['description'], 'Public_Name__c': data['title'], 'ExpectedRevenue': data['goal'], 'Personal_Campaign_Contact__c': contact_id, 'IsActive': True, 'Status': 'In Progress', } if settings.sf_campaign_record_type_personal: data['RecordTypeID'] = settings.sf_campaign_record_type_personal res = sfconn.Campaign.create(data) if not res['success']: raise Exception(res['errors'][0]) # Save the Id of the new campaign so it can be updated later. campaign.parent_sf_id = parent_campaign.sf_object_id campaign.sf_object_id = res['id'] campaign.contact_sf_id = contact_id campaign.reindexObject() # Send email confirmation and links. try: campaign.send_email_personal_page_created() except HTTPRequestException as e: failure = { 'func_name': 'MemorialEmailView', 'func': '', 'args': '', 'kwargs': '', 'portal_path': '', 'context_path': repr(self.context), 'userfolder_path': '', 'user_id': '', 'tb': e, } email_failure_from_portal(self.context, failure) # Send the user to their new campaign. IStatusMessage(self.request).add(u'Welcome to your fundraising page!') self.request.response.redirect(campaign.absolute_url())
def render(self): charge_id = self.request.form.get('charge_id') page = self.context.get_fundraising_campaign_page() if not charge_id: logger.warning('collective.salesforce.fundraising: Record Stripe Donation Error: no charge_id passed in request') return self.request.response.redirect(page.absolute_url() + '/@@post_donation_error') # Check to make sure a donation does not already exist for this transaction. If it does, redirect to it. pc = getToolByName(self.context, 'portal_catalog') res = pc.searchResults( portal_type='collective.salesforce.fundraising.donation', transaction_id=charge_id, sort_limit=1 ) if len(res) == 1: # Redirect to the donation or the honorary-memorial form if needed donation = res[0].getObject() # If this is an honorary or memorial donation, redirect to the form to provide details is_honorary = self.request.form.get('is_honorary', None) if is_honorary == 'true' and donation.honorary_type is None: redirect_url = '%s/honorary-memorial-donation?key=%s' % (donation.absolute_url(), donation.secret_key) else: redirect_url = '%s?key=%s' % (donation.absolute_url(), donation.secret_key) return self.request.response.redirect(redirect_url) stripe_util = getUtility(IStripeUtility) stripe_api = stripe_util.get_stripe_api(page) charge = stripe_api.Charge.retrieve(charge_id, expand=['customer.subscription','invoice']) # What happens if there is no charge_id passed or no charge was found? if not charge: logger.warning('collective.salesforce.fundraising: Record Stripe Donation Error: charge_id %s was not found' % charge_id) return self.request.response.redirect(page.absolute_url() + '/@@post_donation_error') pc = getToolByName(self.context, 'portal_catalog') # Handle Donation Product forms product = None product_id = self.request.form.get('c_product_id', None) c_products = self.request.form.get('c_products', None) quantity = self.request.form.get('c_quantity', None) pricebook_id = None if product_id: res = pc.searchResults(sf_object_id=product_id, portal_type='collective.salesforce.fundraising.donationproduct') if not res: raise ValueError('collective.salesforce.fundraising: Stripe Post Payment Error: Product with ID %s not found' % product_id) product = res[0].getObject() if product_id or c_products: sfbc = getToolByName(self.context, 'portal_salesforcebaseconnector') pricebook_id = get_standard_pricebook_id(sfbc) # Handle Product Forms with multiple products, each with their own quantity products = [] if c_products: for item in c_products.split(','): item_id, item_quantity = item.split(':') product_res = pc.searchResults(sf_object_id = item_id, portal_type='collective.salesforce.fundraising.donationproduct') if not product_res: raise ValueError('collective.salesforce.fundraising: Stripe Post Payment Error: Product with ID %s not found' % item_id) products.append({'id': item_id, 'quantity': item_quantity, 'product': product_res[0].getObject()}) settings = get_settings() # lowercase all email addresses to avoid lookup errors if typed with different caps email = self.request.form.get('email', None) if email: email = email.lower() first_name = self.request.form.get('first_name', None) last_name = self.request.form.get('last_name', None) email_opt_in = self.request.form.get('email_signup', None) == 'YES' phone = self.request.form.get('phone', None) address = self.request.form.get('address', None) city = self.request.form.get('city', None) state = self.request.form.get('state', None) zipcode = self.request.form.get('zip', None) country = self.request.form.get('country', None) amount = int(float(self.request.form.get('x_amount', None))) data = { 'first_name': first_name, 'last_name': last_name, 'email': email, 'email_opt_in': email_opt_in, 'phone': phone, 'address_street': address, 'address_city': city, 'address_state': state, 'address_zip': zipcode, 'address_country': zipcode, 'secret_key': build_secret_key(), 'amount': amount, 'stage': 'Posted', 'products': [], 'campaign_sf_id': page.sf_object_id, 'source_campaign_sf_id': page.get_source_campaign(), 'source_url': page.get_source_url(), 'payment_method': 'Stripe', } # Stripe invoices are only used for recurring so if there is an invoice. if charge['invoice']: invoice = charge['invoice'] customer = charge['customer'] subscription = customer['subscription'] plan = invoice['lines']['data'][0]['plan'] data['stripe_customer_id'] = customer['id'] data['stripe_plan_id'] = plan['id'] data['transaction_id'] = charge['id'] data['is_test'] = charge['livemode'] == False data['title'] = '%s %s - $%i per %s' % (first_name, last_name, amount, plan['interval']) data['payment_date'] = stripe_timestamp_to_date(subscription['current_period_start']) data['next_payment_date'] = stripe_timestamp_to_date(subscription['current_period_end']) else: # One time donation data['payment_date'] = stripe_timestamp_to_date(charge['created']) data['transaction_id'] = charge['id'] data['is_test'] = charge['livemode'] == False data['title'] = '%s %s - $%i One Time Donation' % (first_name, last_name, amount) if product_id and product is not None: # Set a custom name with the product info and quantity data['title'] = '%s %s - %s (Qty %s)' % (first_name, last_name, product.title, quantity) elif products: # Set a custom name with the product info and quantity parent_form = products[0]['product'].get_parent_product_form() title = 'Donation' if parent_form: title = parent_form.title data['title'] = '%s %s - %s' % (first_name, last_name, title) if product_id and product is not None: data['products'].append('%s|%s|%s' % product.price, quantity, IUUID(product)) if products: for item in products: data['products'].append('%s|%s|%s' % (item['product'].price, item['quantity'], IUUID(item['product']))) donation = createContentInContainer( page, 'collective.salesforce.fundraising.donation', checkConstraints=False, **data ) # If this is an honorary or memorial donation, redirect to the form to provide details is_honorary = self.request.form.get('is_honorary', None) if is_honorary == 'true': redirect_url = '%s/honorary-memorial-donation?key=%s' % (donation.absolute_url(), donation.secret_key) else: redirect_url = '%s?key=%s' % (donation.absolute_url(), donation.secret_key) return self.request.response.redirect(redirect_url)
def handleOk(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # Don't allow creation of a personal page if one already exists existing_personal_campaign = \ self.context.get_personal_fundraising_campaign_url() if existing_personal_campaign: messages = IStatusMessage(self.request) messages.add("You can't create more than one " "personal page per campaign.") self.request.response.redirect(self.context.absolute_url()) return # Add a personal campaign within the current context, # using the data from the form. parent_campaign = self.context campaign = createContentInContainer( parent_campaign, 'collective.salesforce.fundraising.personalcampaignpage', checkConstraints=False, **data) mtool = getToolByName(self.context, 'portal_membership') member = mtool.getAuthenticatedMember() person_res = get_brains_for_email(self.context, member.getProperty('email')) person = None contact_id = None if person_res: person = person_res[0].getObject() contact_id = person.sf_object_id settings = get_settings() # Add the campaign in Salesforce sfconn = getUtility(ISalesforceUtility).get_connection() data = { 'Type': 'Personal Fundraising', 'ParentId': parent_campaign.sf_object_id, 'Name': data['title'], 'Description': data['description'], 'Public_Name__c': data['title'], 'ExpectedRevenue': data['goal'], 'Personal_Campaign_Contact__c': contact_id, 'IsActive': True, 'Status': 'In Progress', } if settings.sf_campaign_record_type_personal: data['RecordTypeID'] = settings.sf_campaign_record_type_personal res = sfconn.Campaign.create(data) if not res['success']: raise Exception(res['errors'][0]) # Save the Id of the new campaign so it can be updated later. campaign.parent_sf_id = parent_campaign.sf_object_id campaign.sf_object_id = res['id'] campaign.contact_sf_id = contact_id campaign.reindexObject() # Send email confirmation and links. try: campaign.send_email_personal_page_created() except HTTPRequestException as e: failure = { 'func_name': 'MemorialEmailView', 'func': '', 'args': '', 'kwargs': '', 'portal_path': '', 'context_path': repr(self.context), 'userfolder_path': '', 'user_id': '', 'tb': e, } email_failure_from_portal(self.context, failure) # Send the user to their new campaign. IStatusMessage(self.request).add(u'Welcome to your fundraising page!') self.request.response.redirect(campaign.absolute_url())
def render(self): # Get the api key from registry settings = get_settings() # workaround for http://bugs.python.org/issue5285, # map unicode to strings janrain_api_key = str(settings.janrain_api_key) if not janrain_api_key: return "No Janrain API key configured" # Get the token token = self.request.form.get("token", None) if not token: return "No token passed in request" # Get the user profile from Janrain auth_info_url = "%s/auth_info?apiKey=%s&token=%s" % (JANRAIN_API_BASE_URL, janrain_api_key, token) if settings.janrain_use_extended_profile: auth_info_url = auth_info_url + "&extended=true" resp = urllib2.urlopen(auth_info_url) auth_info = simplejson.loads(resp.read()) # This is for Plone's built in member management instead of membrane # See if a user already exists for the profile's email # email = auth_info['profile']['email'] # member = None # if email: # member = mtool.getMemberById(email) # See if user already exists using dexterity.membrane profile = auth_info.get("profile", {}) email = profile.get("verifiedEmail", None) # NB: Do NOT accept the 'email' attribute as an alternative # to 'verifiedEmail'. The 'email' attribute can be entered by # users and therefore would be a security hole. if not email: raise AttributeError("No email provided from social profile, unable to create " "account") email = email.lower() res = get_brains_for_email(self.context, email, self.request) if not res: # create new Person if no existing Person was found # with the same email name = profile.get("name", {}) address = profile.get("address", {}) if not address: addresses = profile.get("addresses", []) if addresses: address = addresses[0] data = { "first_name": name.get("givenName", None), "last_name": name.get("familyName", None), "email": email, "street_address": address.get("streetAddress", None), "city": address.get("locality", None), "state": address.get("region", None), "zip": address.get("postalCode", None), "country": address.get("country", None), # 'gender': profile.get('gender', None), "social_signin": True, } # Create the user people_container = getattr(getSite(), "people") person = createContentInContainer( people_container, "collective.salesforce.fundraising.person", checkConstraints=False, **data ) # Authenticate the user mtool = getToolByName(self.context, "portal_membership") acl = getToolByName(self.context, "acl_users") newSecurityManager(None, acl.getUser(email)) mtool.loginUser() # or use the existing Person if found else: # Authenticate the user mtool = getToolByName(self.context, "portal_membership") acl = getToolByName(self.context, "acl_users") newSecurityManager(None, acl.getUser(email)) mtool.loginUser() person = res[0].getObject() if not person.social_signin: person.social_signin = True # Set the photo photo = profile.get("photo", None) if not photo: photos = profile.get("photos", []) if photos: photo = photos[0] if photo and (not person.portrait or not person.portrait.size): img_data = urllib2.urlopen(photo).read() person.portrait = NamedBlobImage(img_data) # See if came_from was passed came_from = self.request.form.get("came_from", None) # fix odd bug where came_from is a list of two values if came_from and isinstance(came_from, (list, tuple)): came_from = came_from[0] if came_from: return self.request.response.redirect(came_from) # merge in with standard plone login process. login_next = self.context.restrictedTraverse("login_next") login_next()