Пример #1
0
    def lock_bonus(self):
        """对订单礼券、抵扣金进行加锁冻结(发生在订单提交支付前)"""
        from core.models.welfare import FirewoodWorkflow, FirewoodBurning

        if self.woods_burning:
            flow = FirewoodWorkflow(self.user_id)
            flow.pick(self.woods_burning,
                      tags=[FirewoodBurning.Kind.deduction.name])

        if self.coupon:
            self.coupon.shell_out(self.product, self.amount)
Пример #2
0
def initialize():
    if not g.user:
        return redirect(url_for('accounts.login.login', next=request.path))

    # 圣诞游戏获取红包的用户如果没有身份信息则跳转
    game_gift = ChristmasGift.get_by_mobile_phone(g.user.mobile)
    if not has_real_identity(
            g.user) and game_gift and game_gift.rank.award.firewood_wrapper:
        return redirect(url_for('profile.auth.supply', next=request.path))

    # 礼券管理
    g.coupon_manager = CouponManager(g.user.id_)
    # 为用户创建抵扣金账户
    g.firewood_flow = FirewoodWorkflow(g.user.id_)
    # 用户浏览任意福利相关页,则关闭福利提醒提示
    welfare_reminder_group.remove_member(g.user.id_)

    # 用户红包记录
    pileds = FirewoodPiling.get_multi_by_user(g.user.id_)
    burneds = FirewoodBurning.get_multi_by_user(g.user.id_)
    g.records = sorted(pileds + burneds,
                       key=attrgetter('creation_time'),
                       reverse=True)

    # 临时:用户访问该页面时默认将相关通知置为已读
    unread_notices = Notification.get_multi_unreads_by_user(g.user.id_)
    unread_notices = [
        n for n in unread_notices if n.kind is welfare_gift_notification
    ]
    for un in unread_notices:
        un.mark_as_read()
Пример #3
0
def initialize_bankcard_manager():
    if hasattr(request, 'oauth'):
        g.bankcard_manager = BankCardManager(request.oauth.user.id_)
        g.firewood_flow = FirewoodWorkflow(request.oauth.user.id_)
        g.coupon_manager = CouponManager(request.oauth.user.id_)
    else:
        g.bankcard_manager = None
Пример #4
0
    def confirm_bonus(self):
        """确认礼券、抵扣金被使用(发生在订单已经被告知成功)"""
        from core.models.welfare import FirewoodWorkflow
        if self.status is not self.Status.success:
            raise ValueError('order %s payment has not succeeded' % self.id_)

        if self.woods_burning:
            FirewoodWorkflow(self.user_id).burn(self.woods_burning)

        if self.coupon:
            self.coupon.confirm_consumption()
            self.coupon_record.commit()
Пример #5
0
    def unlock_bonus(self):
        """释放礼券、抵扣金(发生在订单已经被告知失败)"""
        from core.models.welfare import FirewoodWorkflow
        if self.status not in [self.Status.unpaid, self.Status.failure]:
            raise ValueError('order %s payment has not terminated' % self.id_)

        if self.woods_burning:
            FirewoodWorkflow(self.user_id).release(self.woods_burning)

        if self.coupon:
            self.coupon.put_back_wallet()

        for hike in self.profit_hikes:
            hike.renew()
Пример #6
0
def invite():
    code = request.args.get('inviter',
                            None) or request.cookies.get(INVITER_KEY)
    is_lottery = request.args.get('lottery', False)
    if not code:
        return abort(404)
    # 兼容已分享错误链接
    rs = re.search('^(\d+).*', code)
    if not rs:
        abort(404)
    code = rs.group(1)
    user_id = transform_digit(code)

    if g.user:
        if g.user.id_ == str(user_id):
            if not is_lottery:
                return redirect(url_for('.mine'))

            g.firewood_flow = FirewoodWorkflow(g.user.id_)
            if not g.firewood_flow.account_uid:
                return redirect(
                    url_for('profile.auth.supply', next=request.path))

            user_lottery = UserLottery.get(g.user.id_)
            return render_template('activity/lottery/index.html',
                                   remain_num=user_lottery.remain_num)

        else:
            return redirect(url_for('.login'))

    user = Account.get(user_id)
    if not user:
        abort(404)

    UserLotteryNum.add_by_share(user.id_)

    @after_this_request
    def set_cookie(response):
        response.set_cookie(key=INVITER_KEY,
                            value=str(code),
                            expires=datetime.now() +
                            timedelta(hours=INVITER_KEY_EXPIRE_HOURS))
        return response

    identity = Identity.get(user_id)
    inviter_name = identity.masked_name if identity else generate_nickname(
        user.mobile, ACCOUNT_REG_TYPE.MOBILE)
    return render_template('invite/invite.html', inviter_name=inviter_name)
Пример #7
0
def initialize():
    if not g.user:
        return redirect(url_for('accounts.login.login', next=request.path))
    g.firewood_flow = FirewoodWorkflow(g.user.id_)
    if not g.firewood_flow.account_uid:
        return redirect(url_for('profile.auth.supply', next=request.path))
Пример #8
0
    def unpack(self,
               user,
               reserved_sha1=None,
               allow_piling_firewood=True,
               dynamic_firewood_worth=None):
        """Unpacks package to get coupons.

        :param user: The user who gained this package.
        :param reserved_sha1: Optional. The reserved SHA1 token.
        """
        from core.models.welfare import Coupon, FirewoodWorkflow
        self._check_status_transfer(
            (self.Status.in_air, self.Status.under_foot),
            self.Status.in_pocket)

        # checks for reserved package
        if self.status is self.Status.under_foot:
            if reserved_sha1 is None:
                raise ValueError('reserved_sha1 is required')
            if not safe_str_cmp(reserved_sha1, self.reserved_sha1):
                raise WrongPackageTokenError('reserved_sha1 is wrong')
        if self.status is self.Status.in_air and reserved_sha1 is not None:
            raise ValueError('coupon package has not been reserved')

        # checks with strategy
        if self.kind.distributor and not self.kind.distributor.can_unpack(
                user=user, package=self):
            raise PackageDistributorDenied('distributor denied', self.id_)

        self.user_id = user.id_
        self.status = self.Status.in_pocket
        self.unpacked_time = datetime.now()
        sql = ('update {.table_name} set user_id=%s, status=%s, '
               'unpacked_time=%s where id=%s').format(self)
        params = (self.user_id, self.status.value, self.unpacked_time,
                  self.id_)
        db.execute(sql, params)
        db.commit()

        # release coupon here
        if self.kind.coupon_wrappers:
            try:
                for wrapper in self.kind.coupon_wrappers:
                    for _ in xrange(wrapper.amount):
                        Coupon.create(wrapper.name,
                                      wrapper.kind,
                                      self,
                                      wrapper.product_matcher_kind,
                                      wrapper.platforms,
                                      wrapper.expire_time,
                                      _commit=False)
            except:
                db.rollback()
                raise
            else:
                db.commit()

        # pile fire woods
        if allow_piling_firewood and self.kind.firewood_wrapper:
            FirewoodWorkflow(user.id_).pile(
                user,
                self.kind.firewood_wrapper.worth,
                self,
                tags=[self.kind.firewood_wrapper.name])

        self.clear_cache(self.id_)
        self.clear_cache_by_user(self.user_id)
Пример #9
0
def initialize():
    if not g.user:
        return redirect(url_for('accounts.login.login', next=request.path))
    g.zhiwang_profile = ZhiwangProfile.add(g.user.id_)
    g.coupon_manager = CouponManager(g.user.id_)
    g.firewood_flow = FirewoodWorkflow(g.user.id_)
Пример #10
0
def checkin():
    if not g.user:
        abort(401)
    g.firewood_flow = FirewoodWorkflow(g.user.id_)
    if not g.firewood_flow.account_uid:
        abort(401)
Пример #11
0
def initiaize():
    if hasattr(request, 'oauth'):
        g.coupon_manager = CouponManager(request.oauth.user.id_)
        g.firewood_flow = FirewoodWorkflow(request.oauth.user.id_)
        # TODO: 此处应根据用户所处平台进行礼券过滤
        g.available_coupons = g.coupon_manager.available_coupons
Пример #12
0
def subscribe_product(user,
                      product,
                      bankcard,
                      order_amount,
                      pay_amount,
                      due_date=None,
                      coupon=None,
                      pocket_deduction_amount=0):
    """申购产品"""
    # 检查礼券是否可用、返现账户抵扣是否可用、订单是否可建
    if coupon:
        coupon.check_before_use(product, order_amount)
    if pocket_deduction_amount > 0:
        FirewoodWorkflow(user.id_).check_deduction_enjoyable(
            product, order_amount, pocket_deduction_amount)
    XMOrder.check_before_adding(user.id_, bankcard.id_, product.product_id,
                                order_amount)

    # 获取订单优惠信息并检查合法性
    hike_list = collect_profit_hikes(user, coupon, pocket_deduction_amount)
    rate_bonus = max([h.annual_rate
                      for h in hike_list]) if hike_list else Decimal('0')
    discount_fee = sum([h.deduction_amount for h in hike_list])
    assert rate_bonus < Decimal('5.0')  # 新米最高加息限制
    assert order_amount - discount_fee == pay_amount
    # 新米使用加息券需要在赎回确认里加入
    redeem_confirm = u'1' if rate_bonus > Decimal('0.0') else None
    rate_fee = float(order_amount * rate_bonus * product.frozen_days / 100 /
                     365)

    order_code = XMOrder.gen_order_code()

    xm_cancel_order_prepare.produce(order_code, delay=TIME_OUT_SECONDS)

    identity = Identity.get(user.id_)

    buy_amount = order_amount
    try:
        # 向投米发起申购请求
        if DEBUG:
            # 测试环境要求 购买金额x100后为偶数 => 购买成功,否则失败。
            if int(buy_amount) % 2 != 0:
                buy_amount += round_half_up(0.01, 2)
            buy_amount = round_half_up(buy_amount, 2)
        response = xinmi.order_apply(product_id=product.product_id,
                                     order_id=order_code,
                                     buy_amount=buy_amount,
                                     discount_fee=discount_fee,
                                     user_id=user.id_,
                                     province=bankcard.province_id,
                                     city=bankcard.city_id,
                                     person_name=identity.person_name,
                                     person_ricn=identity.person_ricn,
                                     mobile=bankcard.mobile_phone,
                                     bank_code=bankcard.bank.xm_id,
                                     bank_account=bankcard.card_number,
                                     account_name=identity.person_name,
                                     redeem_confirm=redeem_confirm)

    except BusinessError as e:
        raise SubscribeProductError(u'申购产品失败: %s' % e)

    assert buy_amount == round_half_up(response.buy_amount, 2)

    if product.product_type == XMProduct.Type.classic:
        due_date = get_next_work_day(
            response.buy_time) + datetime.timedelta(days=product.frozen_days)
    # 创建订单
    order = XMOrder.add(user_id=user.id_,
                        product_id=product.product_id,
                        bankcard_id=bankcard.id_,
                        amount=buy_amount,
                        pay_amount=response['total_amount'],
                        expect_interest=response.return_amount + rate_fee,
                        start_date=get_next_work_day(response.buy_time),
                        due_date=due_date,
                        order_code=order_code,
                        pay_code=response.pay_code)
    # 创建优惠记录
    for hike in hike_list:
        # FIXME: the operation of hikes should be managed in one session
        Hike.add(user.id_, order.id_, hike.kind, hike.annual_rate,
                 hike.deduction_amount)
    # 订单预绑定礼券
    if coupon:
        CouponUsageRecord.add(coupon, user, provider_xinmi, order)
    # 创建抵扣使用记录
    if pocket_deduction_amount > 0:
        FirewoodBurning.add(user, pocket_deduction_amount,
                            FirewoodBurning.Kind.deduction, provider_xinmi,
                            order.id_)

    return order
Пример #13
0
def subscribe_product(user,
                      product,
                      bankcard,
                      order_amount,
                      pay_amount,
                      due_date,
                      wrapped_product=None,
                      coupon=None,
                      pocket_deduction_amount=0):
    """申购产品"""
    # 检查礼券是否可用、返现账户抵扣是否可用、订单是否可建
    if coupon:
        coupon.check_before_use(wrapped_product or product, order_amount)
    if pocket_deduction_amount > 0:
        FirewoodWorkflow(user.id_).check_deduction_enjoyable(
            wrapped_product or product, order_amount, pocket_deduction_amount)
    wrapped_product_id = wrapped_product.id_ if wrapped_product else None
    ZhiwangOrder.check_before_adding(user.id_, bankcard.id_,
                                     product.product_id, order_amount,
                                     wrapped_product_id)

    # 获取订单优惠信息并检查合法性
    hike_list = collect_profit_hikes(user, coupon, pocket_deduction_amount,
                                     wrapped_product)
    rate_bonus = max([h.annual_rate
                      for h in hike_list]) if hike_list else Decimal('0')
    deduction_bonus = sum([h.deduction_amount for h in hike_list])
    assert rate_bonus < Decimal('5.0')  # 指旺最高加息限制
    assert order_amount - deduction_bonus == pay_amount

    try:
        # 向指旺发起申购请求
        response = zhiwang.order_apply_with_coupon(
            ZhiwangAccount.get_by_local(user.id_).zhiwang_id,  # 用户的指旺ID
            product.product_id,  # 用户认购的产品
            rate_bonus,  # 加息值
            order_amount,  # 订单金额
            pay_amount,  # 实际支付金额
            bankcard.card_number,  # 银行卡号
            int(bankcard.bank.zwlib_id),  # 银行ID
            bankcard.mobile_phone,  # 银行预留手机号
            due_date.strftime('%Y-%m-%d')
            if due_date else None,  # TODO: 认购产品到期日
            Division.get(bankcard.province_id, year=2006).name,  # 银行卡开卡省份
            Division.get(bankcard.city_id, year=2006).name)  # 银行卡开卡市
    except RemoteError as e:
        err_msg = e.args[1]
        err_msg = ZWLIB_ERROR_MAPPING.get(err_msg, err_msg)
        raise SubscribeProductError(u'申购产品失败: %s' % err_msg)

    assert pay_amount == response.pay_amount

    # 创建订单
    order = ZhiwangOrder.add(user.id_, product.product_id, bankcard.id_,
                             order_amount, response.pay_amount,
                             response.expect_interest,
                             response.interest_start_date,
                             response.interest_end_date, response.order_code,
                             response.pay_code, wrapped_product_id)
    # 创建优惠记录
    for hike in hike_list:
        # FIXME: the operation of hikes should be managed in one session
        Hike.add(user.id_, order.id_, hike.kind, hike.annual_rate,
                 hike.deduction_amount)
    # 订单预绑定礼券
    if coupon:
        CouponUsageRecord.add(coupon, user, provider_zhiwang, order)
    # 创建抵扣使用记录
    if pocket_deduction_amount > 0:
        FirewoodBurning.add(user, pocket_deduction_amount,
                            FirewoodBurning.Kind.deduction, provider_zhiwang,
                            order.id_)
    return order