Exemple #1
0
def mine():
    """用户攒钱概况.

    :reqheader Authorization: OAuth 2.0 Bearer Token
    :status 200: 返回 :class:`~jupiter.views.api.v1.savings.ProfileSchema`
    """
    profile_schema = ProfileSchema(strict=True)
    profile = SavingsManager(request.oauth.user.id_)
    if request.user_agent.app_info.version <= parse_version('1.0'):
        profile.refresh_profile()
    conditional_for([
        unicode(profile.user_id),
        unicode(profile.on_account_invest_amount),
        unicode(profile.daily_profit),
        unicode(profile.total_profit),
        unicode(profile.total_orders),
    ])

    sxb_account = None
    sxb_vendor = Vendor.get_by_name(Provider.sxb)
    if sxb_vendor:
        sxb_account = NewAccount.get(sxb_vendor.id_, request.oauth.user.id_)
    profile.has_sxb_account = True if sxb_account else False

    return jsonify(success=True, data=profile_schema.dump(profile).data)
Exemple #2
0
def get_recommend_products(user=None):
    recommend_products = product_pool()
    from .product import get_products
    all_product = get_products()
    if not user:
        return wrapped_product(all_product,
                               recommend_products['high_priority_products'],
                               recommend_products)

    is_new_saving_user = SavingsManager(user.id_).is_new_savings_user
    if is_new_saving_user:
        return wrapped_product(all_product,
                               recommend_products['high_priority_products'],
                               recommend_products)

    sxb_products = recommend_products['medium_priority_products']
    is_sxb_on_sale = [p.is_on_sale for p in sxb_products]
    if any(is_sxb_on_sale):
        return wrapped_product(all_product, sxb_products, recommend_products)

    xm_products = recommend_products['low_priority_products']
    is_xm_in_stock = [p.is_on_sale for p in xm_products]
    if any(is_xm_in_stock):
        return wrapped_product(all_product, xm_products, recommend_products)

    return wrapped_product(all_product,
                           recommend_products['medium_priority_products'],
                           recommend_products)
Exemple #3
0
 def init():
     if not for_anonymous and not g.user:
         return redirect(url_for('accounts.login.login', next=request.path))
     g.yx_account = YixinAccount.get_by_local(g.user.id) if g.user else None
     g.zw_account = ZhiwangAccount.get_by_local(
         g.user.id) if g.user else None
     g.xm_account = XMAccount.get_by_local(g.user.id) if g.user else None
     g.savings_manager = SavingsManager(g.user.id_) if g.user else None
Exemple #4
0
def collect_user_tags(user_id):
    from core.models.hoard.manager import SavingsManager

    tags = set()

    # 判断用户是否是攒钱用户
    sm = SavingsManager(user_id)
    if not sm.is_new_savings_user:
        tags.add('savings')

    return tags
Exemple #5
0
def asset_profile():
    """用户资产概况

    :reqheader Authorization: OAuth 2.0 Bearer Token
    :reqheader If-None-Match: 客户端缓存的 ETag
    :resheader ETag: 客户端可缓存的 ETag
    :status 304: 客户端缓存未过期, 无需返回数据
    :status 200: 返回 :class:`.AssetProfile`
    """
    savings_manager = SavingsManager(request.oauth.user.id_)
    hoard_total = savings_manager.total_invest_amount
    hoard_daily_profit = savings_manager.daily_profit
    hoard_yesterday_profit = savings_manager.yesterday_profit

    wallet_total = 0
    wallet_yesterday_profit = 0
    wallet_account = WalletAccount.get_by_local_account(request.oauth.user, zhongshan)
    if wallet_account:
        dashboard = UserDashboard.today(wallet_account)
        wallet_total = dashboard.balance
        wallet_yesterday_profit = dashboard.latest_profit_amount

    profile = {
        'total_amount': float(hoard_total) + float(wallet_total),
        'total_yesterday_profit': float(hoard_yesterday_profit) + float(wallet_yesterday_profit),
        'hoard_amount': hoard_total,
        'hoard_daily_profit': hoard_daily_profit,
        'hoard_yesterday_profit': hoard_yesterday_profit,
        'wallet_amount': wallet_total,
        'wallet_yesterday_profit': wallet_yesterday_profit
    }

    conditional_for([
        unicode(profile['total_amount']),
        unicode(profile['total_yesterday_profit']),
        unicode(profile['hoard_amount']),
        unicode(profile['hoard_daily_profit']),
        unicode(profile['hoard_yesterday_profit']),
        unicode(profile['wallet_amount']),
        unicode(profile['wallet_yesterday_profit'])
    ])

    schema = AssetProfile()
    return jsonify(success=True, data=schema.dump(profile).data)
Exemple #6
0
def mine():
    # 攒钱助手
    savings_manager = SavingsManager(g.user.id_)
    savings_products = ZhiwangProduct.get_all()

    vendor = Vendor.get_by_name(Provider.sxb)
    sxb_products = Product.get_products_by_vendor_id(vendor.id_)
    xm_products = XMFixedDuedayProduct.get_all()

    # 零钱包
    wallet_dashboard = PublicDashboard.today()
    wallet_account = WalletAccount.get_by_local_account(g.user, zhongshan)
    if wallet_account:
        wallet_profile = UserDashboard.today(wallet_account)
        wallet_has_transaction = bool(
            WalletTransaction.get_ids_by_account(wallet_account.id_))
    else:
        wallet_profile = None
        wallet_has_transaction = False

    # 规划书
    report = Report.get_latest_by_plan_id(g.plan.id) if g.plan else None

    if not (report and report.status >= REPORT_STATUS.interdata):
        return render_template('/mine/center_unplanned.html', **locals())

    if int(report.formula_ver) < int(FORMULA_VER):
        regen_log(report, 'start regenerate inter data')
        cal_intermediate_data(report, force=True, log=regen_log)
        report.update_formula_ver(FORMULA_VER)
        regen_log(report,
                  'success regenerate inter data FV:%s' % report.formula_ver)

    inter_data = report.inter_data
    locals().update(inter_data)

    cur_path = 'center'
    return render_template('/mine/center.html', **locals())
Exemple #7
0
def products():
    """攒钱助手待售产品.

    :query partner: 可选参数,按合作方支持情况限制返回结果. 目前可为:

                    - ``"zw"``  指旺
                    - ``"xm"``  新米

    :reqheader Authorization: OAuth 2.0 Bearer Token
    :reqheader If-None-Match: 客户端缓存的 ETag
    :resheader ETag: 客户端可缓存的 ETag
    :status 304: 客户端缓存未过期, 无需返回数据
    :status 200: 返回 :class:`.ProductSchema` 列表
    """
    from .products.consts import sale_display_text
    product_schema = ProductSchema(strict=True, many=True)

    partners = frozenset(request.args.getlist('partner'))
    profile = SavingsManager(request.oauth.user.id_)
    profile.refresh_profile()
    services = []

    def product_sale_status_to_text(product):
        is_early_morning_product = isinstance(
            product, (XMProduct, ZhiwangWrappedProduct))
        if product.in_stock:
            return sale_display_text['on_sale']
        elif product.is_taken_down:
            if is_early_morning_product:
                return sale_display_text['early_morning_off_sale']
            return sale_display_text['late_morning_off_sale']
        elif product.is_either_sold_out:
            if is_early_morning_product:
                return sale_display_text['early_morning_sold_out']
            return sale_display_text['late_morning_sold_out']

    if 'zw' in partners and zhiwang_fdb_product_on_switch.is_enabled:
        zw_services = []
        for s in ZhiwangProduct.get_all():
            if s.product_type is ZhiwangProduct.Type.fangdaibao:
                zw_services.append(s)
            elif s.product_type is ZhiwangProduct.Type.classic:
                if s.profit_period['min'] not in (OriginProfitPeriod(
                        90, 'day'), OriginProfitPeriod(
                            180, 'day'), OriginProfitPeriod(
                                270, 'day'), OriginProfitPeriod(365, 'day')):
                    zw_services.append(s)
        zw_services.sort(key=attrgetter('annual_rate'))
        ZhiwangProfile.add(request.oauth.user.id_)
        for zw_service in zw_services:
            product_text = product_sale_status_to_text(zw_service)
            if product_text:
                zw_service.button_display_text, zw_service.button_click_text = product_text
            zw_service.is_able_purchased = zw_service.in_stock
            zw_service.introduction = ''
            zw_service.title = ''
            zw_service.activity_title = ''
            zw_service.activity_introduction = ''
            zw_service._total_amount = 0
            zw_service.agreement = url_for('savings.landing.agreement_zhiwang',
                                           _external=True)
            zw_service.annotations = ZhiwangProduct.get_product_annotations(
                g.coupon_manager, zw_service)
        services.extend(zw_services)
    if 'xm' in partners:
        xm_products = [s for s in XMProduct.get_all()]
        xm_products.sort(key=attrgetter('annual_rate'))
        XMProfile.add(request.oauth.user.id_)
        for xm_product in xm_products:
            product_text = product_sale_status_to_text(xm_product)
            if product_text:
                xm_product.button_display_text, xm_product.button_click_text = product_text
            xm_product.is_able_purchased = xm_product.in_stock
            xm_product.introduction = ''
            xm_product.title = ''
            xm_product.activity_title = ''
            xm_product.activity_introduction = ''
            xm_product._total_amount = 0
            xm_product.agreement = url_for('savings.landing.agreement_xinmi',
                                           _external=True)
            xm_product.annotations = XMProduct.get_product_annotations(
                g.coupon_manager, xm_product)
        services.extend(xm_products)

    product_data = product_schema.dump(services).data
    for product in product_data:
        product.update({'is_newcomer': False})

    all_product_data = []

    if 'sxb' in partners:
        from .products.sxb import get_sxb_products

        product_schema = SxbProductSchema(strict=True, many=True)
        sxb_products = get_sxb_products(request.oauth.user.id_)
        services.extend(sxb_products)
        sxb_father_products = [
            p for p in sxb_products if p.kind is Product.Kind.father
        ]
        sxb_father_product_data = product_schema.dump(sxb_father_products).data
        if SavingsManager(request.oauth.user.id_).is_new_savings_user:
            sxb_child_products = [
                p for p in sxb_products if p.kind is Product.Kind.child
            ]
            sxb_child_product_data = product_schema.dump(
                sxb_child_products).data
            for product in sxb_child_product_data:
                product.update({'is_newcomer': True})
            all_product_data.extend(sxb_child_product_data)
        all_product_data.extend(sxb_father_product_data)

    all_product_data.extend(product_data)
    conditional_for(json.dumps(all_product_data))

    return jsonify(success=True, data=all_product_data)
Exemple #8
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)