Beispiel #1
0
    def test_profile_attrs(self):
        profile = HoardProfile.add(self.local_account.id)
        assert profile.plan_amount == 0

        profile.plan_amount = 10000

        profile = HoardProfile.get(self.local_account.id)
        assert profile.plan_amount == 10000
        assert profile.creation_time <= datetime.datetime.now()
Beispiel #2
0
    def test_create_profile(self):
        profile = HoardProfile.get(self.local_account.id)
        assert profile is None

        profile = HoardProfile.add(self.local_account.id)
        assert profile.account_id == self.local_account.id

        # add again
        profile = HoardProfile.add(self.local_account.id)
        assert profile.account_id == self.local_account.id

        profile = HoardProfile.get(self.local_account.id)
        assert profile.account_id == self.local_account.id
Beispiel #3
0
def order_status(order_id, new_status):
    """Edits the status of specific order."""
    if new_status in remote_statuses():
        new_status = new_status.decode(sys.stdin.encoding)
    else:
        status_list = ', '.join(remote_statuses())
        bcolors.fail('status must be one of %s' % status_list)
        return

    order = HoardOrder.get(order_id)
    if not order:
        bcolors.fail('order not found')
        return

    profile = HoardProfile.get(order.user_id)
    matched_index = [
        index for index, order_info in enumerate(profile.person_account_info)
        if order_info['finOrderNo'] == order.fin_order_id
    ]

    if not matched_index:
        bcolors.fail('failed')
        return

    account_info = list(profile.person_account_info)
    account_info[matched_index[0]]['finOrderStatus'] = unicode(new_status)
    profile.person_account_info = account_info

    bcolors.success('done')
Beispiel #4
0
 def __init__(self, user_id):
     self.user_id = user_id
     self.yx_profile = HoardProfile.get(user_id)
     self.zw_profile = ZhiwangProfile.get(user_id)
     self.xm_profile = XMProfile.get(user_id)
     from core.models.hoarder.profile import HoarderProfile
     self.hoarder_profile = HoarderProfile(user_id)
Beispiel #5
0
def update_savings_amount():
    if not g.user:
        abort(401)

    form = PlanAmountForm()
    if not form.validate():
        return jsonify(r=False, error='\n'.join(chain(*form.errors.values())))

    profile = HoardProfile.add(g.user.id)
    profile.plan_amount = form.data['amount']

    return jsonify(r=True)
Beispiel #6
0
def hoard_yrd_payment_tracking(order_id):
    """同步用户宜人贷订单支付状态"""
    from core.models.hoard import HoardOrder, HoardProfile
    from core.models.hoard.profile import fetch_account_info, clear_account_info_cache

    order = HoardOrder.get(order_id)

    # take account info fetch as payment status sync trick
    profile = HoardProfile.add(order.user_id)
    clear_account_info_cache(order.user_id)
    fetch_account_info(profile)

    order = HoardOrder.get(order_id)
    rsyslog.send('%s\t%s' % (order_id, order.status),
                 tag='yixin_payment_track')

    if not order.is_success and not order.is_failure:
        raise WorkerTaskError(hoard_yrd_payment_tracking.tube)
Beispiel #7
0
def record():
    cur_path = 'record'
    yx_profile = HoardProfile.add(g.user.id_)
    zw_profile = ZhiwangProfile.add(g.user.id_)

    if not yx_profile and not zw_profile:
        return redirect(url_for('savings.landing.index'))

    filtered = bool(request.args.get('filter'))
    yx_orders = yx_profile.orders(filter_due=filtered)
    zw_mixins = zw_profile.mixins(filter_due=filtered)

    records = yx_orders + zw_mixins
    records = sorted(records, key=lambda x: x[0].creation_time, reverse=True)
    return render_template('savings/record.html',
                           records=records,
                           filter_due=filtered,
                           cur_path=cur_path)
Beispiel #8
0
def orders(user_alias):
    """Lists all orders of specific user."""
    user = Account.get_by_alias(user_alias)
    if not user:
        bcolors.fail('user not found')
        return

    profile = HoardProfile.get(user.id)
    if not profile:
        bcolors.fail('profile not initialized')
        return

    for order, _, status in profile.orders():
        data = [
            order.id_,
            order.creation_time,
            round(order.order_amount, 2),
            order.service.p2pservice_name,
            status,
        ]
        print(u'\t'.join(map(unicode, data)))
Beispiel #9
0
def hoard_yrd_exiting_checker(order_id):
    """确认宜人贷订单转出状态."""
    from core.models.hoard import HoardOrder, HoardProfile
    from core.models.hoard.profile import clear_account_info_cache

    order = HoardOrder.get(order_id)
    profile = HoardProfile.get(order.user_id)
    orders = profile.orders()

    if order.fetch_status(orders) == u'已转出':
        order.mark_as_exited()
    elif order.fetch_status(orders) == u'已结束':
        order.mark_as_exited()
    else:
        clear_account_info_cache(order.user_id)
        orders = profile.orders()

        if order.fetch_status(orders) == u'已转出':
            order.mark_as_exited()
        if order.fetch_status(orders) == u'已结束':
            order.mark_as_exited()
Beispiel #10
0
def hoard_yrd_sms_sender(order_id):
    """宜人贷转出订单发送到期短信"""
    from core.models.sms import ShortMessage
    from core.models.sms.kind import savings_order_exited_sms
    from core.models.hoard import HoardOrder, HoardProfile
    from core.models.hoard.profile import clear_account_info_cache

    order = HoardOrder.get(order_id)
    user = Account.get(order.user_id)
    profile = HoardProfile.get(order.user_id)
    if not user.has_mobile():
        return

    # 更新订单最新信息
    clear_account_info_cache(order.user_id)
    orders = profile.orders()
    profit = order.fetch_profit_until(datetime.date.today(), orders)

    # 发送短信
    sms = ShortMessage.create(user.mobile,
                              savings_order_exited_sms,
                              order_amount=int(order.order_amount),
                              profit=str(round_half_up(profit, 2)))
    sms.send_async()
Beispiel #11
0
def orders():
    """用户已有订单.

    :reqheader Authorization: OAuth 2.0 Bearer Token
    :reqheader If-None-Match: 客户端缓存的 ETag
    :resheader ETag: 客户端可缓存的 ETag
    :status 304: 客户端缓存未过期, 无需返回数据
    :status 200: 返回 :class:`.YixinOrderSchema` 、`.XinmiOrderSchema`  或 `.ZhiwangOrderSchema` 列表
    :query: 可选参数,按订单请求数限制返回结果. 目前可为:

                - ``"offset"`` 开始条数
                - ``"count"`` 每页数量
                - ``"only_due"`` 展示攒钱中的订单

    """
    yixin_order_schema = YixinOrderSchema(strict=True, many=True)
    zhiwang_order_schema = ZhiwangOrderSchema(strict=True, many=True)
    xm_order_schema = XinmiOrderSchema(strict=True, many=True)
    offset = request.args.get('offset', type=int, default=0)
    count = request.args.get('count', type=int, default=20)
    only_due = request.args.get('only_due', type=bool, default=False)
    order_data = []

    yixin_profile = HoardProfile.add(request.oauth.user.id_)
    yixin_orders = []
    for order, order_info, order_status in yixin_profile.orders(
            filter_due=only_due):
        order._coupon = None
        order._coupon_benefit = None
        order._order_status = order_status
        order._status_color = ORDER_STATUS_COLOR_MAP.get(
            order_status, '#9B9B9B')
        order._due_date = arrow_parse(order_info['frozenDatetime']).date()
        if order_status == u'确认中':
            order._confirm_desc = u'支付成功后1-3工作日'
        else:
            order._confirm_desc = order_info['startCalcDate']

        yixin_orders.append(order)
    order_data.extend(yixin_order_schema.dump(yixin_orders).data)

    zhiwang_profile = ZhiwangProfile.add(request.oauth.user.id_)
    zhiwang_orders = []
    for order, asset in zhiwang_profile.mixins(filter_due=only_due):
        order._display_status = asset.display_status if asset else order.display_status
        order._status_color = ORDER_STATUS_COLOR_MAP.get(
            order._display_status, '#9B9B9B')
        order._due_date = order.due_date.date()

        if order.display_status == u'处理中':
            order._confirm_desc = u'支付成功后第二个工作日'
        else:
            order._confirm_desc = order.start_date.date()
        zhiwang_orders.append(order)
    order_data.extend(zhiwang_order_schema.dump(zhiwang_orders).data)

    xm_profile = XMProfile.add(request.oauth.user.id_)
    xm_orders = []
    for order, asset in xm_profile.mixins(filter_due=only_due):
        order._display_status = asset.display_status if asset else order.display_status
        order._status_color = ORDER_STATUS_COLOR_MAP.get(
            order._display_status, '#9B9B9B')
        order._due_date = order.due_date.date()

        if order.display_status == u'处理中':
            order._confirm_desc = u'支付成功后第二个工作日'
        else:
            order._confirm_desc = order.start_date.date()
            xm_orders.append(order)
    order_data.extend(xm_order_schema.dump(xm_orders).data)

    if only_due:
        order_data = sorted(order_data, key=itemgetter('due_date'))
    else:
        order_data = sorted(order_data,
                            key=itemgetter('created_at'),
                            reverse=True)
    order_data = order_data[offset:offset + count]

    conditional_for(
        u'{0}#{1}#{2}'.format(o['uid'], unicode(o['status']), o['status_text'])
        for o in order_data)

    return jsonify(success=True, data=order_data)
Beispiel #12
0
def hoard_yrd_order_syncronizer(account_id):
    """宜人贷订单每日定时同步"""
    from core.models.hoard.profile import HoardProfile, fetch_account_info

    profile = HoardProfile.get(account_id)
    fetch_account_info(profile)
Beispiel #13
0
 def get_savings_users(cls):
     return HoardProfile.get_savings_users().union(
         ZhiwangProfile.get_savings_users())
Beispiel #14
0
def orders():
    if not g.user:
        abort(401)

    limit = int(request.args.get('limit', 0))
    filtered = bool(request.args.get('filter'))
    info = {}
    savings_records = []

    yx_profile = HoardProfile.add(g.user.id_)
    zw_profile = ZhiwangProfile.add(g.user.id_)
    xm_profile = XMProfile.add(g.user.id_)
    yx_orders = yx_profile.orders(filter_due=filtered)
    zw_mixins = zw_profile.mixins(filter_due=filtered)
    xm_mixins = xm_profile.mixins(filter_due=filtered)

    placebo_order_ids = PlaceboOrder.get_ids_by_user(g.user.id_)
    placebo_orders = PlaceboOrder.get_multi(placebo_order_ids)
    if filtered:
        placebo_orders = [
            o for o in placebo_orders
            if o.status is not PlaceboOrder.Status.exited
        ]
    placebo_mixins = [(order, ) for order in placebo_orders]

    records = yx_orders + zw_mixins + xm_mixins + placebo_mixins
    if filtered:
        records = sorted(records, key=lambda x: x[0].due_date)
    else:
        records = sorted(records,
                         key=lambda x: x[0].creation_time,
                         reverse=True)
    saving_manager = SavingsManager(g.user.id_)

    info['plan_amount'] = yx_profile.plan_amount
    info['on_account_invest_amount'] = round_half_up(
        saving_manager.on_account_invest_amount, 2)
    info['fin_ratio'] = round_half_up(saving_manager.fin_ratio, 2)
    info['daily_profit'] = round_half_up(saving_manager.daily_profit, 2)
    info['total_profit'] = round_half_up(saving_manager.total_profit, 2)
    limit = limit if 0 < limit < len(records) else len(records)

    for record_info in records[:limit]:
        data = dict()
        base_record = record_info[0]
        exit_type = u'到期自动转回银行卡'

        if base_record.provider is yirendai:
            order, order_info, order_status = record_info
            rebates = HoardRebate.get_by_order_pk(order.id_)

            data['annual_rate'] = order.service.expected_income
            data['frozen_time'] = '%s 个月' % order.service.frozen_time
            data['order_status'] = order_status
            data['savings_money'] = order_info['investAmount']
            data['invest_date'] = order_info['investDate']
            data['exit_type'] = exit_type if order_info[
                'exitType'] == u'退回到划扣银行卡' else order_info['exitType']

            if rebates:
                data['rebates'] = HoardRebate.get_display(rebates)

            if order_status == u'确认中':
                data['interest_start_date'] = u'攒钱后1-3工作日'
            else:
                data['interest_start_date'] = order_info['startCalcDate']

            if order_status == u'已转出':
                data['income_amount'] = u'%s 元' % order_info['incomeAmount']
            else:
                data['expect_income_amount'] = u'%s 元' % order_info[
                    'expectedIncomeAmount']

            data['due_date'] = order.due_date.strftime('%Y-%m-%d')

            if order.bankcard:
                data['bankcard'] = u'%s (%s)' % (
                    order.bankcard.bank_name,
                    order.bankcard.display_card_number)
        elif base_record.provider is zhiwang:
            order, asset = record_info

            data['annual_rate'] = round_half_up(order.actual_annual_rate, 2)
            if order.profit_period.unit == 'day':
                data['frozen_time'] = '%s 天' % order.profit_period.value
            elif order.profit_period.unit == 'month':
                data['frozen_time'] = '%s 个月' % order.profit_period.value
            else:
                raise ValueError('invalid unit %s' % order.profit_period.unit)

            data[
                'order_status'] = asset.display_status if asset else order.display_status
            if order.profit_hikes:
                data['hikes'] = {
                    h.kind.label: h.display_text
                    for h in order.profit_hikes
                }
            data['savings_money'] = int(order.amount)
            data['invest_date'] = unicode(order.creation_time.date())
            data['exit_type'] = exit_type
            data['interest_start_date'] = order.start_date.strftime('%Y-%m-%d')
            if asset and asset.status == ZhiwangAsset.Status.redeemed:
                data['income_amount'] = u'%s 元' % round_half_up(
                    asset.current_interest, 2)
            else:
                # 尽可能显示已加息收益
                # FIXME (tonyseek) 这个做法太粗暴,有赖于资产的更新
                if order.asset:
                    expect_interest = order.asset.expect_interest
                else:
                    expect_interest = order.expect_interest
                data['expect_income_amount'] = u'%s 元' % round_half_up(
                    expect_interest, 2)
            data['due_date'] = order.due_date.strftime('%Y-%m-%d')

            data['contract_url'] = url_for(
                'savings.zhiwang.asset_contract',
                asset_no=asset.asset_no) if asset else ''
            if asset and asset.bankcard:
                # 指旺回款卡以资产的银行卡为准,可能会与订单中的不一致
                data['bankcard'] = u'%s (%s)' % (
                    asset.bankcard.bank.name,
                    asset.bankcard.display_card_number)
        elif base_record.provider is placebo:
            if base_record.status is PlaceboOrder.Status.failure:
                continue
            order = base_record
            profit_amount = order.calculate_profit_amount()
            profit_amount_text = u'%s 元' % round_half_up(profit_amount, 2)
            if base_record.status is PlaceboOrder.Status.exited:
                data['income_amount'] = profit_amount_text
            else:
                data['expect_income_amount'] = profit_amount_text
            data['annual_rate'] = round_half_up(order.profit_annual_rate, 2)
            data['frozen_time'] = order.profit_period.display_text
            data['order_status'] = order.status.display_text
            data['order_type'] = u'体验金'

            data['spring_festival'] = spring_promotion_switch.is_enabled

            data['savings_money'] = int(order.amount)
            data['invest_date'] = unicode(order.start_date)
            data['due_date'] = unicode(order.due_date.date())
            data['bankcard'] = u'%s (%s)' % (
                order.bankcard.bank.name, order.bankcard.display_card_number)
        elif base_record.provider is xmpay:
            order, asset = record_info

            data['annual_rate'] = round_half_up(order.actual_annual_rate, 2)
            if order.profit_period.unit == 'day':
                data['frozen_time'] = '%s 天' % order.profit_period.value
            elif order.profit_period.unit == 'month':
                data['frozen_time'] = '%s 个月' % order.profit_period.value
            else:
                raise ValueError('invalid unit %s' % order.profit_period.unit)

            data[
                'order_status'] = asset.display_status if asset else order.display_status
            if order.profit_hikes:
                data['hikes'] = {
                    h.kind.label: h.display_text
                    for h in order.profit_hikes
                }
            data['savings_money'] = int(order.amount)
            data['invest_date'] = unicode(order.creation_time.date())
            data['exit_type'] = exit_type
            data['interest_start_date'] = order.start_date.strftime('%Y-%m-%d')
            if asset and asset.status == XMAsset.Status.redeemed:
                data['income_amount'] = u'%s 元' % round_half_up(
                    asset.current_interest, 2)
            else:
                # 尽可能显示已加息收益
                if order.asset:
                    expect_interest = order.asset.expect_interest
                else:
                    expect_interest = order.expect_interest
                data['expect_income_amount'] = u'%s 元' % round_half_up(
                    expect_interest, 2)
            # 尽量使用第三方返回的到期日期。
            if order.asset:
                data['due_date'] = order.asset.interest_end_date.strftime(
                    '%Y-%m-%d')
            else:
                data['due_date'] = order.due_date.strftime('%Y-%m-%d')

            data['contract_url'] = url_for(
                'savings.xinmi.asset_contract',
                asset_no=asset.asset_no) if asset else ''
            if asset and asset.bankcard:
                # 投米回款卡以资产的银行卡为准,可能会与订单中的不一致
                data['bankcard'] = u'%s (%s)' % (
                    asset.bankcard.bank_name,
                    asset.bankcard.display_card_number)
        savings_records.append(data)
    return jsonify(r=True, records=savings_records, info=info)
Beispiel #15
0
def initialize_profile():
    # disables the landing page
    g.hoard_profile = HoardProfile.add(g.user.id_)