Ejemplo n.º 1
0
def kyc_part_1(message_flow_run_id, member, steps, end_id, end_message_flow_id,
               parent_message_key, tag, result_key, flush_id,
               flush_message_flow_id, service_identity, user_details,
               flow_params):
    iyo_username = get_iyo_username(user_details[0])
    if not iyo_username:
        logging.error('No username found for user %s', user_details[0])
        return create_error_message(FlowMemberResultCallbackResultTO())
    result = _validate_kyc_status(iyo_username)
    if isinstance(result, FlowMemberResultCallbackResultTO):
        return result
    step = get_step(steps, 'message_nationality') or get_step(
        steps, 'message_nationality_with_vibration')
    assert isinstance(step, FormFlowStepTO)
    assert isinstance(step.form_result, FormResultTO)
    assert isinstance(step.form_result.result, UnicodeWidgetResultTO)
    country_code = step.form_result.result.value
    ref_step = get_step(steps, 'message_referrer')
    if ref_step and not result.referrer_user:
        try:
            api_set_referral({'code': ref_step.get_value()}, user_details[0])
        except ApiCallException as e:
            return create_error_message(FlowMemberResultCallbackResultTO(),
                                        e.message)
    xml, flow_params = generate_kyc_flow(country_code, iyo_username)
    result = FlowCallbackResultTypeTO(flow=xml,
                                      tag=KYC_FLOW_PART_2_TAG,
                                      force_language=None,
                                      flow_params=json.dumps(flow_params))
    return FlowMemberResultCallbackResultTO(type=TYPE_FLOW, value=result)
Ejemplo n.º 2
0
def kyc_part_1(message_flow_run_id, member, steps, end_id, end_message_flow_id,
               parent_message_key, tag, result_key, flush_id,
               flush_message_flow_id, service_identity, user_details,
               flow_params):
    iyo_username = get_iyo_username(user_details[0])
    if not iyo_username:
        logging.error('No username found for user %s', user_details[0])
        return create_error_message()
    if flush_id == 'flush_corporation':
        url = get_base_url() + '/users/%s' % iyo_username
        msg = """"User %s (%s) wants to be KYC approved using his partnership/corporation or trust""" % (
            iyo_username, url)
        send_emails_to_support('Corporation wants to sign up', msg)

    result = validate_kyc_status(get_tff_profile(iyo_username))
    if isinstance(result, FlowMemberResultCallbackResultTO):
        return result
    if flush_id == 'flush_corporation':
        return
    step = get_step(steps, 'message_nationality') or get_step(
        steps, 'message_nationality_with_vibration')
    assert isinstance(step, FormFlowStepTO)
    assert isinstance(step.form_result, FormResultTO)
    assert isinstance(step.form_result.result, UnicodeWidgetResultTO)
    country_code = step.form_result.result.value
    xml, flow_params = generate_kyc_flow(country_code, iyo_username)
    result = FlowCallbackResultTypeTO(flow=xml,
                                      tag=KYC_FLOW_PART_2_TAG,
                                      force_language=None,
                                      flow_params=json.dumps(flow_params))
    return FlowMemberResultCallbackResultTO(type=TYPE_FLOW, value=result)
Ejemplo n.º 3
0
def invest(message_flow_run_id, member, steps, end_id, end_message_flow_id, parent_message_key, tag, result_key,
           flush_id, flush_message_flow_id, service_identity, user_details, flow_params, token):
    if flush_id == 'flush_kyc' or flush_id == 'flush_corporation':
        # KYC flow started from within the invest flow
        return kyc_part_1(message_flow_run_id, member, steps, end_id, end_message_flow_id, parent_message_key, tag,
                          result_key, flush_id, flush_message_flow_id, service_identity, user_details, flow_params)

    try:
        email = user_details[0].email
        app_id = user_details[0].app_id
        app_user = create_app_user_by_email(email, app_id)
        logging.info('User %s wants to invest', email)
        version = get_key_name_from_key_string(steps[0].message_flow_id)
        currency = get_step_value(steps, 'message_get_currency').replace('_cur', '')
        if version.startswith(BUY_TOKENS_FLOW_V3) or version.startswith(BUY_TOKENS_FLOW_V5):
            amount = float(get_step_value(steps, 'message_get_order_size_ITO').replace(',', '.'))
            token_count_float = get_token_count(currency, amount)
        else:
            token_count_float = float(get_step_value(steps, 'message_get_order_size_ITO'))
            amount = get_investment_amount(currency, token_count_float)
        username = get_iyo_username(app_user)
        agreement = _create_investment_agreement(amount, currency, token, token_count_float, username, version,
                                                 app_user, status=InvestmentAgreement.STATUS_CREATED)
        payment_info = []
        usd_within_uae_step = get_step(steps, 'message_usd_within_uae')
        if usd_within_uae_step and usd_within_uae_step.answer_id == 'button_yes':
            payment_info.append(PaymentInfo.UAE.value)
        agreement.payment_info.extend(payment_info)
        agreement.put()

        if version == BUY_TOKENS_FLOW_V3_PAUSED:
            return None

        utility_bill_step = get_step(steps, 'message_utility_bill')
        if utility_bill_step:
            azzert(utility_bill_step.answer_id == FormTO.POSITIVE)
            url = utility_bill_step.get_value()
            deferred.defer(save_utility_bill, url, TffProfile.create_key(get_iyo_username(user_details[0])))

        tag = {
            '__rt__.tag': INVEST_FLOW_TAG,
            'investment_id': agreement.id
        }
        flow_params = {
            'token': agreement.token,
            'amount': agreement.amount,
            'currency': agreement.currency
        }
        result = FlowCallbackResultTypeTO(flow=FLOW_CONFIRM_INVESTMENT,
                                          tag=json.dumps(tag).decode('utf-8'),
                                          force_language=None,
                                          flow_params=json.dumps(flow_params))
        return FlowMemberResultCallbackResultTO(type=TYPE_FLOW, value=result)
    except Exception as e:
        logging.exception(e)
        return create_error_message()
Ejemplo n.º 4
0
def investment_agreement_signed(message_flow_run_id, member, steps, end_id, end_message_flow_id, parent_message_key,
                                tag, result_key, flush_id, flush_message_flow_id, service_identity, user_details,
                                flow_params):
    try:
        user_detail = user_details[0]
        tag_dict = json.loads(tag)
        agreement = InvestmentAgreement.create_key(tag_dict['agreement_id']).get()  # type: InvestmentAgreement

        last_step = steps[-1]
        assert isinstance(last_step, FormFlowStepTO)
        if last_step.answer_id != FormTO.POSITIVE:
            logging.info('Investment agreement was canceled')
            agreement.status = InvestmentAgreement.STATUS_CANCELED
            agreement.cancel_time = now()
            agreement.put()
            return None

        logging.info('Received signature for Investment Agreement')

        sign_result = last_step.form_result.result.get_value()
        assert isinstance(sign_result, SignWidgetResultTO)
        iyo_username = get_iyo_username(user_detail)
        sign_see_document(iyo_username, agreement.iyo_see_id, sign_result, user_detail)

        logging.debug('Storing signature in DB')
        agreement.populate(status=InvestmentAgreement.STATUS_SIGNED,
                           signature=sign_result.payload_signature,
                           sign_time=now())
        agreement.put_async()

        deferred.defer(add_user_to_role, user_detail, RogerthatRoles.INVESTOR)
        intercom_tags = get_intercom_tags_for_investment(agreement)
        if intercom_tags:
            for i_tag in intercom_tags:
                deferred.defer(intercom_helpers.tag_intercom_users, i_tag, [iyo_username])
        deferred.defer(update_investor_progress, user_detail.email, user_detail.app_id,
                       INVESTMENT_TODO_MAPPING[agreement.status])
        deferred.defer(_inform_support_of_new_investment, iyo_username, agreement.id, agreement.token_count_float)
        if needs_utility_bill(agreement):
            logging.debug('Sending "utility bill received" message')
            deferred.defer(_send_utility_bill_received, agreement.app_user)
        else:
            logging.debug('Sending confirmation message')
            deferred.defer(send_payment_instructions, agreement.app_user, agreement.id, '')
            deferred.defer(send_hoster_reminder, agreement.app_user, _countdown=1)
        result = FlowCallbackResultTypeTO(flow=FLOW_INVESTMENT_CONFIRMED,
                                          tag=None,
                                          force_language=None,
                                          flow_params=json.dumps({'reference': agreement.reference}))
        return FlowMemberResultCallbackResultTO(type=TYPE_FLOW, value=result)
    except:
        logging.exception('An unexpected error occurred')
        return create_error_message()
Ejemplo n.º 5
0
def invest(message_flow_run_id, member, steps, end_id, end_message_flow_id,
           parent_message_key, tag, result_key, flush_id,
           flush_message_flow_id, service_identity, user_details, flow_params,
           token):
    if flush_id == 'flush_kyc':
        # KYC flow started from within the invest flow
        return kyc_part_1(message_flow_run_id, member, steps, end_id,
                          end_message_flow_id, parent_message_key, tag,
                          result_key, flush_id, flush_message_flow_id,
                          service_identity, user_details, flow_params)
    try:
        email = user_details[0].email
        app_id = user_details[0].app_id
        app_user = create_app_user_by_email(email, app_id)
        logging.info('User %s wants to invest', email)
        version = db.Key(steps[0].message_flow_id).name()
        currency = get_step_value(steps,
                                  'message_get_currency').replace('_cur', '')
        if version.startswith(BUY_TOKENS_FLOW_V3):
            amount = float(
                get_step_value(steps,
                               'message_get_order_size_ITO').replace(',', '.'))
            token_count_float = get_token_count(currency, amount)
        else:
            token_count_float = float(
                get_step_value(steps, 'message_get_order_size_ITO'))
            amount = get_investment_amount(currency, token_count_float)
        username = get_iyo_username(app_user)
        agreement = _create_investment_agreement(
            amount,
            currency,
            token,
            token_count_float,
            username,
            version,
            app_user,
            status=InvestmentAgreement.STATUS_CREATED)
        agreement.put()

        if version == BUY_TOKENS_FLOW_V3_PAUSED:
            return None

        result = FlowMemberResultCallbackResultTO(type=TYPE_MESSAGE)
        result.value = create_agreement_confirmation_message(agreement)
        return result
    except Exception as e:
        logging.exception(e)
        return create_error_message(FlowMemberResultCallbackResultTO())
Ejemplo n.º 6
0
def validate_kyc_status(profile):
    if profile.kyc:
        status = profile.kyc.status
        if status not in (KYCStatus.UNVERIFIED, KYCStatus.PENDING_SUBMIT):
            message = None
            if status == KYCStatus.DENIED:
                message = 'Sorry, we are regrettably not able to accept you as a customer.'
            elif status == KYCStatus.PENDING_APPROVAL or status == KYCStatus.SUBMITTED:
                message = 'We already have the information we currently need to pass on to our KYC provider.' \
                          ' We will contact you if we need more info.' \
                          ' Please contact us if you want to update your information.'
            elif status == KYCStatus.VERIFIED:
                message = 'You have already been verified, so you do not need to enter this process again. Thank you!'
            if not DEBUG:
                return create_error_message(message)
    return profile
Ejemplo n.º 7
0
def order_node_signed(message_flow_run_id, member, steps, end_id,
                      end_message_flow_id, parent_message_key, tag, result_key,
                      flush_id, flush_message_flow_id, service_identity,
                      user_details, flow_params):
    try:
        user_detail = user_details[0]
        tag_dict = json.loads(tag)
        order = get_node_order(tag_dict['order_id'])

        last_step = steps[-1]
        if last_step.answer_id != FormTO.POSITIVE:
            logging.info('Zero-Node order was canceled')
            deferred.defer(_cancel_quotation, order.id)
            return None

        logging.info('Received signature for Zero-Node order')

        sign_result = last_step.form_result.result.get_value()
        assert isinstance(sign_result, SignWidgetResultTO)
        iyo_username = get_iyo_username(user_detail)
        sign_see_document(iyo_username, order.tos_iyo_see_id, sign_result,
                          user_detail)

        logging.debug('Storing signature in DB')
        order.populate(status=NodeOrderStatus.SIGNED,
                       signature=sign_result.payload_signature,
                       sign_time=now())
        order.put()

        # TODO: send mail to TF support
        deferred.defer(add_user_to_role, user_detail, RogerthatRoles.HOSTERS)
        deferred.defer(update_hoster_progress, user_detail.email,
                       user_detail.app_id, HosterSteps.FLOW_SIGN)
        intercom_tags = get_intercom_tags_for_node_order(order)
        for intercom_tag in intercom_tags:
            deferred.defer(tag_intercom_users, intercom_tag, [iyo_username])

        logging.debug('Sending confirmation message')
        result = FlowCallbackResultTypeTO(
            flow=FLOW_HOSTER_SIGNATURE_RECEIVED,
            tag=None,
            force_language=None,
            flow_params=json.dumps({'orderId': order.human_readable_id}))
        return FlowMemberResultCallbackResultTO(type=TYPE_FLOW, value=result)
    except:
        logging.exception('An unexpected error occurred')
        return create_error_message()
Ejemplo n.º 8
0
def generate_kyc_flow(country_code, iyo_username):
    logging.info('Generating KYC flow for user %s and country %s', iyo_username, country_code)
    flow_params = {'nationality': country_code}
    properties = DEFAULT_KYC_STEPS.union(_get_extra_properties(country_code))
    try:
        known_information = _get_known_information(iyo_username)
        known_information['address_country'] = country_code
    except HttpNotFoundException:
        logging.error('No profile found for user %s!', iyo_username)
        return create_error_message(FlowMemberResultCallbackResultTO())

    steps = []
    branding_key = get_main_branding_hash()
    for prop in properties:
        step_info = _get_step_info(prop)
        if not step_info:
            raise BusinessException('Unsupported step type: %s' % prop)
        value = known_information.get(prop)
        steps.append({
            'reference': 'message_%s' % prop,
            'positive_reference': None,
            'positive_caption': step_info.get('positive_caption', 'Continue'),
            'negative_reference': 'end_premature_end',
            'negative_caption': step_info.get('negative_caption', 'Cancel'),
            'keyboard_type': step_info.get('keyboard_type', 'DEFAULT'),
            'type': step_info.get('widget', 'TextLineWidget'),
            'value': value or step_info.get('value') or '',
            'choices': step_info.get('choices', []),
            'message': step_info['message'],
            'branding_key': branding_key,
            'order': step_info['order']
        })
    sorted_steps = sorted(steps, key=lambda k: k['order'])
    for i, step in enumerate(sorted_steps):
        if len(sorted_steps) > i + 1:
            step['positive_reference'] = sorted_steps[i + 1]['reference']
        else:
            step['positive_reference'] = 'flush_results'
    template_params = {
        'start_reference': sorted_steps[0]['reference'],
        'steps': sorted_steps,
        'language': DEFAULT_LANGUAGE,
        'branding_key': branding_key
    }
    return FLOWS_JINJA_ENVIRONMENT.get_template('kyc_part_2.xml').render(template_params), flow_params
Ejemplo n.º 9
0
def _kyc_part_2(message_flow_run_id, member, steps, end_id,
                end_message_flow_id, parent_message_key, tag, result_key,
                flush_id, flush_message_flow_id, service_identity,
                user_details, flow_params):
    parsed_flow_params = json.loads(flow_params)
    applicant = Applicant(nationality=parsed_flow_params['nationality'],
                          addresses=[Address()])
    documents = []
    username = get_iyo_username(user_details[0])
    if not username:
        logging.error('Could not find username for user %s!' % user_details[0])
        return create_error_message()
    profile = get_tff_profile(username)
    result = validate_kyc_status(profile)
    if isinstance(result, FlowMemberResultCallbackResultTO):
        return result

    def _set_attr(prop, value):
        if hasattr(applicant, prop):
            setattr(applicant, prop, value)
        elif prop.startswith('address_'):
            prop = prop.replace('address_', '')
            if prop == 'country':
                applicant.country = value
            setattr(applicant.addresses[0], prop, value)
        else:
            logging.warn('Ignoring unknown property %s with value %s', prop,
                         value)

    for step in steps:
        # In case of the flowcode_check_skip_passport step
        if not isinstance(step, FormFlowStepTO):
            continue
        step_id_split = step.step_id.split('_', 1)
        if step_id_split[0] == 'message':
            prop = step_id_split[
                1]  # 'type' from one of plugins.tff_backend.consts.kyc.kyc_steps
            step_value = step.form_result.result.get_value()
            if prop.startswith('national_identity_card'):
                side = None
                if prop.endswith('front'):
                    side = 'front'
                elif prop.endswith('back'):
                    side = 'back'
                documents.append({
                    'type': 'national_identity_card',
                    'side': side,
                    'value': step_value
                })
            elif prop == 'utility_bill':
                deferred.defer(save_utility_bill,
                               step_value,
                               profile.key,
                               _transactional=True)
            elif prop.startswith('passport'):
                documents.append({'type': 'passport', 'value': step_value})
            elif isinstance(step.form_result.result, UnicodeWidgetResultTO):
                _set_attr(prop, step.form_result.result.value.strip())
            elif isinstance(step.form_result.result, LongWidgetResultTO):
                # date step
                date = datetime.datetime.utcfromtimestamp(step_value).strftime(
                    '%Y-%m-%d')
                _set_attr(prop, date)
            else:
                logging.info('Ignoring step %s', step)
    try:
        if profile.kyc.applicant_id:
            applicant = update_applicant(profile.kyc.applicant_id, applicant)
        else:
            applicant = create_applicant(applicant)
            profile.kyc.applicant_id = applicant.id
    except ApiException as e:
        if e.status in xrange(400, 499):
            raise BusinessException('Invalid status code from onfido: %s %s' %
                                    (e.status, e.body))
        raise
    for document in documents:
        deferred.defer(upload_document,
                       applicant.id,
                       document['type'],
                       document['value'],
                       document.get('side'),
                       _transactional=True)
    profile.kyc.set_status(KYCStatus.SUBMITTED.value, username)
    profile.put()
    deferred.defer(index_profile, Profile.create_key(username))

    # Automatically set status to PENDING_APPROVAL after 5 minutes
    payload = SetKYCPayloadTO(status=KYCStatus.PENDING_APPROVAL.value,
                              comment='Verification started automatically')
    deferred.defer(_set_kyc_status,
                   username,
                   payload,
                   current_user_id=username,
                   _countdown=300,
                   _queue=SCHEDULED_QUEUE)
Ejemplo n.º 10
0
def investment_agreement_signed(status, form_result, answer_id, member,
                                message_key, tag, received_timestamp,
                                acked_timestamp, parent_message_key,
                                result_key, service_identity, user_details):
    """
    Args:
        status (int)
        form_result (FormResultTO)
        answer_id (unicode)
        member (unicode)
        message_key (unicode)
        tag (unicode)
        received_timestamp (int)
        acked_timestamp (int)
        parent_message_key (unicode)
        result_key (unicode)
        service_identity (unicode)
        user_details(list[UserDetailsTO])

    Returns:
        FormAcknowledgedCallbackResultTO
    """
    try:
        user_detail = user_details[0]
        tag_dict = json.loads(tag)
        agreement = InvestmentAgreement.create_key(
            tag_dict['agreement_id']).get()  # type: InvestmentAgreement

        if answer_id != FormTO.POSITIVE:
            logging.info('Investment agreement was canceled')
            agreement.status = InvestmentAgreement.STATUS_CANCELED
            agreement.cancel_time = now()
            agreement.put()
            return None

        logging.info('Received signature for Investment Agreement')

        sign_result = form_result.result.get_value()
        assert isinstance(sign_result, SignWidgetResultTO)
        payload_signature = sign_result.payload_signature

        iyo_organization_id = get_iyo_organization_id()
        iyo_username = get_iyo_username(user_detail)

        logging.debug('Getting IYO SEE document %s', agreement.iyo_see_id)
        doc = get_see_document(iyo_organization_id, iyo_username,
                               agreement.iyo_see_id)
        doc_view = IYOSeeDocumentView(username=doc.username,
                                      globalid=doc.globalid,
                                      uniqueid=doc.uniqueid,
                                      **serialize_complex_value(
                                          doc.versions[-1],
                                          IYOSeeDocumenVersion, False))
        doc_view.signature = payload_signature
        keystore_label = get_publickey_label(sign_result.public_key.public_key,
                                             user_detail)
        if not keystore_label:
            return create_error_message(FormAcknowledgedCallbackResultTO())
        doc_view.keystore_label = keystore_label
        logging.debug('Signing IYO SEE document')
        sign_see_document(iyo_organization_id, iyo_username, doc_view)

        logging.debug('Storing signature in DB')
        agreement.populate(status=InvestmentAgreement.STATUS_SIGNED,
                           signature=payload_signature,
                           sign_time=now())
        agreement.put_async()

        deferred.defer(add_user_to_role, user_detail, RogerthatRoles.INVESTOR)
        intercom_tags = get_intercom_tags_for_investment(agreement)
        if intercom_tags:
            for i_tag in intercom_tags:
                deferred.defer(intercom_helpers.tag_intercom_users, i_tag,
                               [iyo_username])
        deferred.defer(update_investor_progress, user_detail.email,
                       user_detail.app_id,
                       INVESTMENT_TODO_MAPPING[agreement.status])
        deferred.defer(_inform_support_of_new_investment, iyo_username,
                       agreement.id, agreement.token_count_float)
        logging.debug('Sending confirmation message')
        prefix_message = u'Thank you. We successfully received your digital signature.' \
                         u' We have stored a copy of this agreement in your ThreeFold Documents.' \
                         u' We will contact you again when we have received your payment.' \
                         u' Thanks again for your purchase and your support of the ThreeFold Foundation!' \
                         u'\n\nWe would like to take this opportunity to remind you once again to keep a back-up of' \
                         u' your wallet in a safe place, by writing down the 29 words that can be used to restore it' \
                         u' to a different device.' \
                         u' As usual, if you have any questions, don\'t hesitate to contact us.\n\n'
        msg = u'%sReference: %s' % (prefix_message, agreement.reference)
        deferred.defer(send_payment_instructions, agreement.app_user,
                       agreement.id, prefix_message)

        message = MessageCallbackResultTypeTO()
        message.alert_flags = Message.ALERT_FLAG_VIBRATE
        message.answers = []
        message.branding = get_main_branding_hash()
        message.dismiss_button_ui_flags = 0
        message.flags = Message.FLAG_ALLOW_DISMISS | Message.FLAG_AUTO_LOCK
        message.message = msg
        message.step_id = u'investment_agreement_accepted'
        message.tag = None

        result = FormAcknowledgedCallbackResultTO()
        result.type = TYPE_MESSAGE
        result.value = message
        return result
    except:
        logging.exception('An unexpected error occurred')
        return create_error_message(FormAcknowledgedCallbackResultTO())
Ejemplo n.º 11
0
def order_node_signed(status, form_result, answer_id, member, message_key, tag, received_timestamp, acked_timestamp,
                      parent_message_key, result_key, service_identity, user_details):
    """
    Args:
        status (int)
        form_result (FormResultTO)
        answer_id (unicode)
        member (unicode)
        message_key (unicode)
        tag (unicode)
        received_timestamp (int)
        acked_timestamp (int)
        parent_message_key (unicode)
        result_key (unicode)
        service_identity (unicode)
        user_details(list[UserDetailsTO])

    Returns:
        FormAcknowledgedCallbackResultTO
    """
    try:
        user_detail = user_details[0]
        tag_dict = json.loads(tag)
        order = get_node_order(tag_dict['order_id'])

        if answer_id != FormTO.POSITIVE:
            logging.info('Zero-Node order was canceled')
            deferred.defer(_cancel_quotation, order.id)
            return None

        logging.info('Received signature for Zero-Node order')

        sign_result = form_result.result.get_value()
        assert isinstance(sign_result, SignWidgetResultTO)
        payload_signature = sign_result.payload_signature

        iyo_organization_id = get_iyo_organization_id()
        iyo_username = get_iyo_username(user_detail)

        logging.debug('Getting IYO SEE document %s', order.tos_iyo_see_id)
        doc = get_see_document(iyo_organization_id, iyo_username, order.tos_iyo_see_id)
        doc_view = IYOSeeDocumentView(username=doc.username,
                                      globalid=doc.globalid,
                                      uniqueid=doc.uniqueid,
                                      **serialize_complex_value(doc.versions[-1], IYOSeeDocumenVersion, False))
        doc_view.signature = payload_signature
        keystore_label = get_publickey_label(sign_result.public_key.public_key, user_detail)
        if not keystore_label:
            return create_error_message(FormAcknowledgedCallbackResultTO())
        doc_view.keystore_label = keystore_label
        logging.debug('Signing IYO SEE document')
        sign_see_document(iyo_organization_id, iyo_username, doc_view)

        logging.debug('Storing signature in DB')
        order.populate(status=NodeOrderStatus.SIGNED,
                       signature=payload_signature,
                       sign_time=now())
        order.put()

        # TODO: send mail to TF support
        deferred.defer(add_user_to_role, user_detail, RogerthatRoles.HOSTERS)
        deferred.defer(update_hoster_progress, user_detail.email, user_detail.app_id, HosterSteps.FLOW_SIGN)
        intercom_tags = get_intercom_tags_for_node_order(order)
        for intercom_tag in intercom_tags:
            deferred.defer(tag_intercom_users, intercom_tag, [iyo_username])

        logging.debug('Sending confirmation message')
        message = MessageCallbackResultTypeTO()
        message.alert_flags = Message.ALERT_FLAG_VIBRATE
        message.answers = []
        message.branding = get_main_branding_hash()
        message.dismiss_button_ui_flags = 0
        message.flags = Message.FLAG_ALLOW_DISMISS | Message.FLAG_AUTO_LOCK
        message.message = u'Thank you. We successfully received your digital signature.' \
                          u' We have stored a copy of this agreement in your ThreeFold Documents.\n\n' \
                          u'Your order with ID "%s" has been placed successfully.\n' % order.human_readable_id
        message.step_id = u'order_completed'
        message.tag = None

        result = FormAcknowledgedCallbackResultTO()
        result.type = TYPE_MESSAGE
        result.value = message
        return result
    except:
        logging.exception('An unexpected error occurred')
        return create_error_message(FormAcknowledgedCallbackResultTO())
Ejemplo n.º 12
0
def generate_kyc_flow(country_code, iyo_username):
    logging.info('Generating KYC flow for user %s and country %s',
                 iyo_username, country_code)
    flow_params = {'nationality': country_code}
    properties = DEFAULT_KYC_STEPS.union(_get_extra_properties(country_code))
    try:
        known_information = _get_known_information(iyo_username)
        known_information['address_country'] = country_code
    except HttpNotFoundException:
        logging.error('No profile found for user %s!', iyo_username)
        return create_error_message()

    steps = []
    branding_key = get_main_branding_hash()
    must_ask_passport = 'passport' not in REQUIRED_DOCUMENT_TYPES[country_code]
    for prop in properties:
        step_info = _get_step_info(prop)
        if not step_info:
            raise BusinessException('Unsupported step type: %s' % prop)
        value = known_information.get(prop)
        reference = 'message_%s' % prop
        # If yes, go to passport step. If no, go to national identity step
        if prop in ('national_identity_card',
                    'national_identity_card_front') and must_ask_passport:
            steps.append({
                'reference':
                'message_has_passport',
                'message':
                """Are you in the possession of a valid passport?

Note: If you do not have a passport (and only a national id), you will only be able to wire the funds to our UAE Mashreq bank account.""",
                'type':
                None,
                'order':
                step_info['order'] - 0.5,
                'answers': [{
                    'id': 'yes',
                    'caption': 'Yes',
                    'reference': 'message_passport'
                }, {
                    'id':
                    'no',
                    'caption':
                    'No',
                    'reference':
                    'message_national_identity_card'
                    if 'national_identity_card' in properties else
                    'message_national_identity_card_front'
                }]
            })
        steps.append({
            'reference':
            reference,
            'positive_reference':
            None,
            'positive_caption':
            step_info.get('positive_caption', 'Continue'),
            'negative_reference':
            'flush_monitoring_end_canceled',
            'negative_caption':
            step_info.get('negative_caption', 'Cancel'),
            'keyboard_type':
            step_info.get('keyboard_type', 'DEFAULT'),
            'type':
            step_info.get('widget', 'TextLineWidget'),
            'value':
            value or step_info.get('value') or '',
            'choices':
            step_info.get('choices', []),
            'message':
            step_info['message'],
            'branding_key':
            branding_key,
            'order':
            step_info['order']
        })
    sorted_steps = sorted(steps, key=lambda k: k['order'])
    for i, step in enumerate(sorted_steps):
        if len(sorted_steps) > i + 1:
            if 'positive_reference' in step:
                if step['reference'] == 'message_passport':
                    sorted_steps[i - 1][
                        'positive_reference'] = 'flowcode_check_skip_passport'
                step['positive_reference'] = sorted_steps[i + 1]['reference']
        else:
            step['positive_reference'] = 'flush_results'
    template_params = {
        'start_reference': sorted_steps[0]['reference'],
        'steps': sorted_steps,
        'language': DEFAULT_LANGUAGE,
        'branding_key': branding_key
    }
    return FLOWS_JINJA_ENVIRONMENT.get_template('kyc_part_2.xml').render(
        template_params), flow_params