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 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 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']
Example #8
0
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 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)
Example #11
0
    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
Example #12
0
    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)
Example #13
0
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'
Example #15
0
    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
Example #19
0
    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
Example #23
0
    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)
Example #25
0
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
Example #26
0
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 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 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))
Example #34
0
    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()
Example #37
0
 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)
Example #40
0
    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()