def resume_paused_agreement(agreement): azzert(agreement.status == InvestmentAgreement.STATUS_CREATED) message = create_agreement_confirmation_message(agreement) params = { 'token': agreement.token, 'amount': agreement.amount, 'currency': agreement.currency } msg = u'''We are ready to process your purchase. Is the following information correct? You would like to buy %(token)s for a total amount of **%(amount)s %(currency)s**. If you have not done so already, please go through the KYC procedure, which you can find in the service menu. After confirming and going through the KYC procedure, you will receive your personalised purchase agreement.''' % params parent_message_key = None member_user, app_id = get_app_user_tuple(agreement.app_user) member = MemberTO(app_id=app_id, member=member_user.email(), alert_flags=Message.ALERT_FLAG_VIBRATE) messaging.send(get_rogerthat_api_key(), parent_message_key, msg, message.answers, message.flags, [member], message.branding, message.tag, step_id=message.step_id)
def check_if_node_comes_online(order_key): order = order_key.get() # type: NodeOrder order_id = order.id if not order.odoo_sale_order_id: raise BusinessException( 'Cannot check status of node order without odoo_sale_order_id') node_id = get_node_id_from_odoo(order.odoo_sale_order_id) if not node_id: raise BusinessException( 'Could not find node id for sale order %s on odoo' % order_id) status = get_node_status(node_id) if status == u'running': logging.info('Marking node from node order %s as arrived', order_id) human_user, app_id = get_app_user_tuple(order.app_user) order.populate(arrival_time=now(), status=NodeOrderStatus.ARRIVED) order.put() deferred.defer(set_node_id_on_profile, order.app_user, node_id, _transactional=True) deferred.defer(update_hoster_progress, human_user.email(), app_id, HosterSteps.NODE_POWERED, _transactional=True) else: logging.info('Node from order %s is not online yet', order_id)
def trans(): agreement = InvestmentAgreement.create_key( tag_dict['agreement_id']).get() # type: InvestmentAgreement if answer_id != FormTO.POSITIVE: logging.info('Investment agreement sign aborted') return if agreement.status == InvestmentAgreement.STATUS_PAID: logging.warn( 'Ignoring request to set InvestmentAgreement %s as paid because it is already paid', agreement.id) return agreement.status = InvestmentAgreement.STATUS_PAID agreement.paid_time = now() agreement.put() user_email, app_id, = get_app_user_tuple(agreement.app_user) deferred.defer(transfer_genesis_coins_to_user, agreement.app_user, TokenType.I, long(agreement.token_count_float * 100), _transactional=True) deferred.defer(update_investor_progress, user_email.email(), app_id, INVESTMENT_TODO_MAPPING[agreement.status], _transactional=True) deferred.defer(_send_tokens_assigned_message, agreement.app_user, _transactional=True)
def send_message_and_email(app_user, message, subject): human_user, app_id = get_app_user_tuple(app_user) member = MemberTO(member=human_user.email(), app_id=app_id, alert_flags=0) iyo_username = get_iyo_username(app_user) deferred.defer(send_rogerthat_message, member, message) if not DEBUG: deferred.defer(send_intercom_email, iyo_username, subject, message)
def _send_ito_agreement_sign_message(agreement_key, app_user, pdf_url, attachment_name, pdf_size): logging.debug('Sending SIGN widget to app user') form = SignFormTO(positive_button_ui_flags=Message.UI_FLAG_EXPECT_NEXT_WAIT_5, widget=SignTO(algorithm=KEY_ALGORITHM, key_name=KEY_NAME, payload=base64.b64encode(pdf_url).decode('utf-8'))) attachment = AttachmentTO(content_type=u'application/pdf', download_url=pdf_url, name=attachment_name, size=pdf_size) tag = json.dumps({ u'__rt__.tag': u'sign_investment_agreement', u'agreement_id': agreement_key.id() }).decode('utf-8') flow_params = json.dumps({ 'form': form.to_dict(), 'attachments': [attachment.to_dict()] }) email, app_id = get_app_user_tuple(app_user) members = [MemberTO(member=email.email(), app_id=app_id, alert_flags=0)] messaging.start_local_flow(get_rogerthat_api_key(), None, members, None, tag=tag, context=None, flow=FLOW_SIGN_INVESTMENT, flow_params=flow_params) deferred.defer(_send_sign_investment_reminder, agreement_key.id(), u'long', _countdown=3600, _queue=SCHEDULED_QUEUE) deferred.defer(_send_sign_investment_reminder, agreement_key.id(), u'short', _countdown=3 * DAY, _queue=SCHEDULED_QUEUE) deferred.defer(_send_sign_investment_reminder, agreement_key.id(), u'short', _countdown=10 * DAY, _queue=SCHEDULED_QUEUE)
def store_referral_in_user_data(profile_key): profile = profile_key.get() user_data = { 'has_referrer': profile.referrer_user is not None } email, app_id = get_app_user_tuple(profile.app_user) api_key = get_rogerthat_api_key() system.put_user_data(api_key, email.email(), app_id, user_data)
def _create_node_order_pdf(node_order_id): node_order = get_node_order(node_order_id) user_email, app_id = get_app_user_tuple(node_order.app_user) logging.debug('Creating Hosting agreement') pdf_name = NodeOrder.filename(node_order_id) pdf_contents = create_hosting_agreement_pdf(node_order.billing_info.name, node_order.billing_info.address) pdf_url = upload_to_gcs(pdf_name, pdf_contents, 'application/pdf') deferred.defer(_order_node_iyo_see, node_order.app_user, node_order_id, pdf_url) deferred.defer(update_hoster_progress, user_email.email(), app_id, HosterSteps.FLOW_ADDRESS)
def send_kyc_flow(app_user, message=None): email, app_id = get_app_user_tuple(app_user) member = MemberTO(member=email.email(), app_id=app_id, alert_flags=0) push_message = u'KYC procedure has been initiated' # for iOS only messaging.start_local_flow(get_rogerthat_api_key(), None, [member], tag=KYC_FLOW_PART_1_TAG, flow=KYC_FLOW_PART_1, push_message=push_message, flow_params=json.dumps({'message': message}))
def send_rogerthat_flow(member, flow): if isinstance(member, users.User): human_user, app_id = get_app_user_tuple(member) member = MemberTO(member=human_user.email(), app_id=app_id, alert_flags=Message.ALERT_FLAG_VIBRATE) messaging.start_local_flow(api_key=get_rogerthat_api_key(), xml=None, members=[member], flow=flow)
def store_kyc_in_user_data(app_user): username = get_iyo_username(app_user) profile = get_tff_profile(username) user_data = { 'kyc': { 'status': profile.kyc.status, 'verified': profile.kyc.status == KYCStatus.VERIFIED } } email, app_id = get_app_user_tuple(app_user) api_key = get_rogerthat_api_key() return system.put_user_data(api_key, email.email(), app_id, user_data)
def migrate(dry_run=False): investments = InvestmentAgreement.query().fetch(1000) # type: list[InvestmentAgreement] updates = {} for investment in investments: new_status = INVESTMENT_TODO_MAPPING[investment.status] if investment.app_user not in updates or updates[investment.app_user] < new_status: updates[investment.app_user] = INVESTMENT_TODO_MAPPING[investment.status] if dry_run: return updates for app_user, step in updates.iteritems(): email, app_id = get_app_user_tuple(app_user) deferred.defer(update_investor_progress, email.email(), app_id, step)
def set_hoster_status_in_user_data(app_user, can_order=None): # type: (users.User, bool) -> None if not isinstance(can_order, bool): can_order = all(o.status == NodeOrderStatus.CANCELED for o in NodeOrder.list_by_user(app_user)) user_data = {'hoster': {'can_order': can_order}} api_key = get_rogerthat_api_key() email, app_id = get_app_user_tuple(app_user) current_user_data = system.get_user_data(api_key, email.email(), app_id, ['hoster']) if current_user_data != user_data: system.put_user_data(api_key, email.email(), app_id, user_data)
def put_node_order(order_id, order): # type: (long, NodeOrderTO) -> NodeOrder order_model = get_node_order(order_id) if order_model.status == NodeOrderStatus.CANCELED: raise HttpBadRequestException('order_canceled') if order.status not in (NodeOrderStatus.CANCELED, NodeOrderStatus.SENT, NodeOrderStatus.APPROVED, NodeOrderStatus.PAID): raise HttpBadRequestException('invalid_status') # Only support updating the status for now if order_model.status != order.status: if not _can_change_status(order_model.status, order.status): raise HttpBadRequestException( 'cannot_change_status', { 'from': order_model.status, 'to': order.status, 'allowed_new_statuses': _get_allowed_status( order_model.status) }) order_model.status = order.status human_user, app_id = get_app_user_tuple(order_model.app_user) if order_model.status == NodeOrderStatus.CANCELED: order_model.cancel_time = now() if order_model.odoo_sale_order_id: deferred.defer(update_odoo_quotation, order_model.odoo_sale_order_id, {'state': QuotationState.CANCEL.value}) deferred.defer(update_hoster_progress, human_user.email(), app_id, HosterSteps.NODE_POWERED) # nuke todo list deferred.defer(set_hoster_status_in_user_data, order_model.app_user, _countdown=2) elif order_model.status == NodeOrderStatus.SENT: if not order_model.odoo_sale_order_id or not get_nodes_from_odoo( order_model.odoo_sale_order_id): raise HttpBadRequestException( 'cannot_mark_sent_no_serial_number_configured_yet', {'sale_order': order_model.odoo_sale_order_id}) order_model.send_time = now() deferred.defer(update_hoster_progress, human_user.email(), app_id, HosterSteps.NODE_SENT) deferred.defer(_send_node_order_sent_message, order_id) elif order_model.status == NodeOrderStatus.APPROVED: deferred.defer(_create_node_order_pdf, order_id) elif order_model.status == NodeOrderStatus.PAID: deferred.defer(confirm_odoo_quotation, order_model.odoo_sale_order_id) else: logging.debug('Status was already %s, not doing anything', order_model.status) order_model.put() return order_model
def create_node_order(data): # type: (CreateNodeOrderTO) -> NodeOrder if data.status not in (NodeOrderStatus.SIGNED, NodeOrderStatus.SENT, NodeOrderStatus.ARRIVED, NodeOrderStatus.PAID): data.sign_time = MISSING if data.status not in (NodeOrderStatus.SENT, NodeOrderStatus.ARRIVED): data.send_time = MISSING app_user = users.User(data.app_user) order_count = NodeOrder.list_by_so(data.odoo_sale_order_id).count() if order_count > 0: raise OrderAlreadyExistsException(data.odoo_sale_order_id) try: nodes = get_nodes_from_odoo(data.odoo_sale_order_id) except (IndexError, TypeError): logging.warn('Could not get nodes from odoo for order id %s' % data.odoo_sale_order_id, exc_info=True) raise HttpBadRequestException('cannot_find_so_x', {'id': data.odoo_sale_order_id}) if not nodes: raise HttpBadRequestException('no_serial_number_configured_yet', {'sale_order': data.odoo_sale_order_id}) prefix, doc_content_base64 = data.document.split(',') content_type = prefix.split(';')[0].replace('data:', '') if content_type != 'application/pdf': raise InvalidContentTypeException(content_type, ['application/pdf']) doc_content = base64.b64decode(doc_content_base64) order_key = NodeOrder.create_key() pdf_name = NodeOrder.filename(order_key.id()) pdf_url = upload_to_gcs(pdf_name, doc_content, content_type) order = NodeOrder(key=order_key, app_user=app_user, **data.to_dict(exclude=['document', 'app_user'])) order.put() iyo_username = get_iyo_username(app_user) email, app_id = get_app_user_tuple(app_user) deferred.defer(add_nodes_to_profile, iyo_username, nodes) deferred.defer(set_hoster_status_in_user_data, order.app_user, False) deferred.defer(add_user_to_role, UserDetailsTO(email=email.email(), app_id=app_id), RogerthatRoles.HOSTERS) deferred.defer(tag_intercom_users, IntercomTags.HOSTER, [iyo_username]) deferred.defer(_order_node_iyo_see, order.app_user, order.id, pdf_url, len(doc_content), create_quotation=False) return order
def _send_ito_agreement_to_admin(agreement_key, admin_app_user): logging.debug('Sending SIGN widget to payment admin %s', admin_app_user) agreement = agreement_key.get() # type: InvestmentAgreement widget = SignTO() widget.algorithm = KEY_ALGORITHM widget.caption = u'Sign to mark this investment as paid.' widget.key_name = KEY_NAME widget.payload = base64.b64encode(str(agreement_key.id())).decode('utf-8') form = SignFormTO() form.negative_button = u'Abort' form.negative_button_ui_flags = 0 form.positive_button = u'Accept' form.positive_button_ui_flags = Message.UI_FLAG_EXPECT_NEXT_WAIT_5 form.type = SignTO.TYPE form.widget = widget member_user, app_id = get_app_user_tuple(admin_app_user) message = u"""Enter your pin code to mark purchase agreement %(investment)s (reference %(reference)s as paid. - from: %(user)s\n - amount: %(amount)s %(currency)s - %(token_count_float)s %(token_type)s tokens """ % { 'investment': agreement.reference, 'user': get_iyo_username(agreement.app_user), 'amount': agreement.amount, 'currency': agreement.currency, 'token_count_float': agreement.token_count_float, 'token_type': agreement.token, 'reference': agreement.reference } messaging.send_form(api_key=get_rogerthat_api_key(), parent_message_key=None, member=member_user.email(), message=message, form=form, flags=0, alert_flags=Message.ALERT_FLAG_VIBRATE, branding=get_main_branding_hash(), tag=json.dumps({ u'__rt__.tag': u'sign_investment_agreement_admin', u'agreement_id': agreement_key.id() }).decode('utf-8'), attachments=[], app_id=app_id, step_id=u'sign_investment_agreement_admin')
def add_nodes_to_profile(iyo_username, nodes): profile = TffProfile.create_key(iyo_username).get() existing_ids = [n.id for n in profile.nodes] for node in nodes: if node['id'] not in existing_ids: profile.nodes.append(NodeInfo(**node)) profile.put() user, app_id = get_app_user_tuple(profile.app_user) data = {'nodes': [n.to_dict() for n in profile.nodes]} deferred.defer(system.put_user_data, get_rogerthat_api_key(), user.email(), app_id, data, _transactional=True) return profile
def _set_node_status_arrived(order_key, iyo_username, nodes): order = order_key.get() logging.info('Marking nodes %s from node order %s as arrived', nodes, order_key) human_user, app_id = get_app_user_tuple(order.app_user) order.populate(arrival_time=now(), status=NodeOrderStatus.ARRIVED) order.put() deferred.defer(add_nodes_to_profile, iyo_username, nodes, _transactional=True) deferred.defer(update_hoster_progress, human_user.email(), app_id, HosterSteps.NODE_POWERED, _transactional=True)
def _send_kyc_approved_message(profile_key): profile = profile_key.get() # type: TffProfile email, app_id = get_app_user_tuple(profile.app_user) message = translate(DEFAULT_LANGUAGE, 'tff', 'you_have_been_kyc_approved') answers = [AnswerTO(type=u'button', action='smi://%s' % BUY_TOKENS_TAG, id=u'purchase', caption=translate(DEFAULT_LANGUAGE, 'tff', 'purchase_itokens'), ui_flags=0, color=None), AnswerTO(type=u'button', action=None, id=u'close', caption=translate(DEFAULT_LANGUAGE, 'tff', 'close'), ui_flags=0, color=None)] send_rogerthat_message(MemberTO(member=email.email(), app_id=app_id, alert_flags=Message.ALERT_FLAG_VIBRATE), message, answers, 0)
def _send_order_node_sign_message(app_user, order_id, pdf_url, attachment_name, order_name): logging.debug('Sending SIGN widget to app user') widget = SignTO() widget.algorithm = KEY_ALGORITHM widget.caption = u'Please enter your PIN code to digitally sign the terms and conditions' widget.key_name = KEY_NAME widget.payload = base64.b64encode(pdf_url).decode('utf-8') form = SignFormTO() form.negative_button = u'Abort' form.negative_button_ui_flags = 0 form.positive_button = u'Accept' form.positive_button_ui_flags = Message.UI_FLAG_EXPECT_NEXT_WAIT_5 form.type = SignTO.TYPE form.widget = widget attachment = AttachmentTO() attachment.content_type = u'application/pdf' attachment.download_url = pdf_url attachment.name = attachment_name message = u"""Order %(order_name)s Received You have now been approved for hosting duties! We will keep you updated of the Node shipping process through the app. Please review the terms and conditions and press the "Sign" button to accept. """ % {"order_name": order_name} member_user, app_id = get_app_user_tuple(app_user) messaging.send_form(api_key=get_rogerthat_api_key(), parent_message_key=None, member=member_user.email(), message=message, form=form, flags=0, alert_flags=Message.ALERT_FLAG_VIBRATE, branding=get_main_branding_hash(), tag=json.dumps({u'__rt__.tag': u'sign_order_node_tos', u'order_id': order_id}).decode('utf-8'), attachments=[attachment], app_id=app_id, step_id=u'sign_order_node_tos')
def send_message_and_email(app_user, message, subject): human_user, app_id = get_app_user_tuple(app_user) member = MemberTO(member=human_user.email(), app_id=app_id, alert_flags=0) deferred.defer(send_rogerthat_message, member, message, _transactional=ndb.in_transaction()) if not DEBUG: iyo_username = get_iyo_username(app_user) message += '\n\nKind regards,\nThe ThreeFold Team' if iyo_username is None: logging.error( 'Could not find itsyou.online username for app_user %s, not sending intercom email' '\nSubject: %s\nMessage:%s', app_user, subject, message) else: deferred.defer(send_intercom_email, iyo_username, subject, message, _transactional=ndb.in_transaction())
def _send_ito_agreement_sign_message(agreement_key, app_user, pdf_url, attachment_name): logging.debug('Sending SIGN widget to app user') widget = SignTO() widget.algorithm = KEY_ALGORITHM widget.caption = u'Please enter your PIN code to digitally sign the purchase agreement' widget.key_name = KEY_NAME widget.payload = base64.b64encode(pdf_url).decode('utf-8') form = SignFormTO() form.negative_button = u'Abort' form.negative_button_ui_flags = 0 form.positive_button = u'Accept' form.positive_button_ui_flags = Message.UI_FLAG_EXPECT_NEXT_WAIT_5 form.type = SignTO.TYPE form.widget = widget attachment = AttachmentTO() attachment.content_type = u'application/pdf' attachment.download_url = pdf_url attachment.name = attachment_name member_user, app_id = get_app_user_tuple(app_user) messaging.send_form( api_key=get_rogerthat_api_key(), parent_message_key=None, member=member_user.email(), message= u'Please review the purchase agreement and press the "Sign" button to accept.', form=form, flags=0, alert_flags=Message.ALERT_FLAG_VIBRATE, branding=get_main_branding_hash(), tag=json.dumps({ u'__rt__.tag': u'sign_investment_agreement', u'agreement_id': agreement_key.id() }).decode('utf-8'), attachments=[attachment], app_id=app_id, step_id=u'sign_investment_agreement')
def send_document_sign_message(document_key, username, pdf_url, attachment_name, pdf_size, tag, flow, push_message): app_user = get_app_user_from_iyo_username(username) logging.debug('Sending sign widget to app user %s for document %s', app_user, document_key) form = SignFormTO( positive_button_ui_flags=Message.UI_FLAG_EXPECT_NEXT_WAIT_5, widget=SignTO(algorithm=KEY_ALGORITHM, key_name=KEY_NAME, payload=base64.b64encode(pdf_url).decode('utf-8'))) attachment = AttachmentTO(content_type=u'application/pdf', download_url=pdf_url, name=attachment_name, size=pdf_size) tag = json.dumps({ u'__rt__.tag': tag, u'document_id': document_key.id() }).decode('utf-8') flow_params = json.dumps({ 'form': form.to_dict(), 'attachments': [attachment.to_dict()] }) email, app_id = get_app_user_tuple(app_user) members = [MemberTO(member=email.email(), app_id=app_id, alert_flags=0)] messaging.start_local_flow(get_rogerthat_api_key(), None, members, None, tag=tag, context=None, flow=flow, push_message=push_message, flow_params=flow_params)
def _send_order_node_sign_message(app_user, order_id, pdf_url, attachment_name, order_name, pdf_size): logging.debug('Sending SIGN widget to app user') widget = SignTO(algorithm=KEY_ALGORITHM, key_name=KEY_NAME, payload=base64.b64encode(pdf_url).decode('utf-8')) form = SignFormTO( positive_button_ui_flags=Message.UI_FLAG_EXPECT_NEXT_WAIT_5, widget=widget) attachment = AttachmentTO(content_type=u'application/pdf', download_url=pdf_url, name=attachment_name, size=pdf_size) member_user, app_id = get_app_user_tuple(app_user) members = [ MemberTO(member=member_user.email(), app_id=app_id, alert_flags=0) ] tag = json.dumps({ u'__rt__.tag': u'sign_order_node_tos', u'order_id': order_id }).decode('utf-8') flow_params = json.dumps({ 'order_name': order_name, 'form': form.to_dict(), 'attachments': [attachment.to_dict()] }) messaging.start_local_flow(get_rogerthat_api_key(), None, members, None, tag=tag, context=None, flow=FLOW_SIGN_HOSTING_AGREEMENT, flow_params=flow_params)
def _put_node_status_user_data(tff_profile_key): tff_profile = tff_profile_key.get() user, app_id = get_app_user_tuple(tff_profile.app_user) data = {'nodes': [n.to_dict() for n in tff_profile.nodes]} system.put_user_data(get_rogerthat_api_key(), user.email(), app_id, data)
def _send_utility_bill_received(app_user): email, app_id = get_app_user_tuple(app_user) members = [MemberTO(member=email.email(), app_id=app_id, alert_flags=0)] messaging.start_local_flow(get_rogerthat_api_key(), None, members, None, flow=FLOW_UTILITY_BILL_RECEIVED)
def put_user_data(app_user, updated_user_data): api_key = get_rogerthat_api_key() email, app_id = get_app_user_tuple(app_user) system.put_user_data(api_key, email.email(), app_id, updated_user_data)