Esempio n. 1
0
    def get(self):
        try:
            data = self.get_query_args()
            data = Schema({
                'app_name': schema_utf8,
                'platform': schema_utf8,
                Optional('version', default=0): Use(int),
            }).validate(data)
            app_name = data['app_name']
            platform = data['platform']
            version = data['version']
        except (SchemaError, Exception):
            logging.exception("参数解析出错")
            self.write_parse_args_failed_response()
            return

        utc_now = TimeZone.utc_now()
        if version == 0:
            app = Application.objects(
                app_name=app_name,
                platform=platform,
                release_time__lte=utc_now).order_by("-release_time").first()
        else:
            app = Application.objects(app_name=app_name,
                                      platform=platform,
                                      version=version).first()
        if not app:
            self.write_not_found_entity_response()
            return

        app.update(inc__download_times=1)
        self.write_response(content=app.link)
Esempio n. 2
0
 def save(self, *args, **kwargs):
     """
     重写保存
     """
     # 保存的时候检查有没有leancloud的conversation,没有则创建
     if not self.channel_leancloud_id:
         cl_c = _Conversation()
         cl_c.set("n", self.name)
         cl_c.set("sys", True)
         cl_c.save()
         self.channel_leancloud_id = cl_c.id
     else:
         qs = Query(_Conversation)
         cl_c = qs.get(self.channel_leancloud_id)
         if cl_c.get("name") != self.name:
             cl_c.set("name", self.name)
             cl_c.save()
         # 更新 update_time
         self.update_time = TimeZone.utc_now()
     super(Channel, self).save(*args, **kwargs)
Esempio n. 3
0
 def get(self):
     try:
         data = self.get_query_args()
         data = Schema({
             'app_name': schema_utf8,
             'platform': schema_utf8
         }).validate(data)
         app_name = data['app_name']
         platform = data['platform']
     except (SchemaError, Exception):
         logging.exception("参数解析出错")
         self.write_parse_args_failed_response()
         return
     utc_now = TimeZone.utc_now()
     app = Application.objects(
         app_name=app_name, platform=platform,
         release_time__lte=utc_now).order_by("-release_time").first()
     if not app:
         self.write_not_found_entity_response()
         return
     self.write_response(content=app.format_response())
Esempio n. 4
0
    def update_status(cls, operator_type, expr, operation, operator, current_status=None, **kwargs):
        """
        更新对象的状态
        :param operator_type: 'OUTSIDE'/'INSIDE'
        :param expr: 运单对象
        :param current_status: 当前状态, 如果为None就拿expr的status字段
        :param operation: 运单事件类型
        :param operator: 运单责任人
        :param kwargs: 除去状态, 其他需要修改的信息. 目前支持:
            var_a: info a
            var_b: info b
        :return: (True, expr) 或 (False, error_msg)
        """
        if current_status is None:
            current_status = expr.status
        next_state = cls.get_next_state(operator_type, current_status, operation)
        next_status = next_state['next'] if next_state else None

        if operator_type == 'INSIDE':
            # ===> 上帝操作!!! <===
            if operation == cls.EVENT_RESET:
                next_status = cls.STATUS_CREATED_CREATED
            # ===> 不给钱操作!!! <===
            elif operation == cls.EVENT_NO_CASH:
                next_status = cls.STATUS_FINISHED_NO_CASH

        # 日志
        debug_str = 'expr[%s]: from [%s] to [%s], event[%s].' % (
            expr.number, current_status['sub_status'], next_status, operation)
        logging.info(debug_str) if next_status else logging.warning(debug_str)

        if next_status:
            start = time.time()
            # ==> 更新状态, 修改相关信息
            from_status = current_status
            status, sub_status = next_status.split('.')
            kwargs['status'] = dict(status=status, sub_status=sub_status)

            # 过滤掉不需要的字段
            kw = Express.filter_expr(kwargs, excludes=('number', 'pkg_id', 'fee', 'watcher', 'assignee'))

            # 事件发生后, 记录操作人的操作时间: 目前只记录EVENT_SJ, EVENT_QJ, EVENT_TT
            time_name = ExprState.build_time_name(operator.get("m_type"), operation)
            now = TimeZone.utc_now()
            if time_name:
                kw["times__" + time_name] = now
            # ==> 判断是否有多余的expr,trace参数要修改
            trace_msg = None
            if next_state and 'do' in next_state:
                s1 = time.time()
                kw, trace_msg = next_state['do'](kw, expr=expr, now=now, operator=operator)
                e1 = time.time()
                logging.info('@@@: [do] = %s' % datetime.timedelta(seconds=(e1 - s1)))

            expr.modify(**kw)

            # ==> 事件记录
            msg = kwargs.get('msg', '')
            fsm_log = dict(number=expr.number,
                           from_status=from_status['sub_status'],
                           to_status=sub_status,
                           event=operation,
                           event_source=expr.third_party.get('name', '') if expr.third_party else '',
                           operator=operator,
                           msg=trace_msg if trace_msg else msg,
                           create_time=now)
            Trace(**fsm_log).save()

            # ==> 判断是否要发送短信提醒
            if "sms" in next_state:
                next_state['sms'](expr, msg=msg)

            end = time.time()
            logging.info('@@@: [expr] = %s' % datetime.timedelta(seconds=(end - start)))
            return expr
        else:
            raise ValueError('操作失败')
Esempio n. 5
0
def api_trigger_man_event(operation):
    """
    @api {post} /deliveryman/event 事件
    @apiDescription 触发派件员事件, 如果需要, 更新派件员状态和基本信息.
    @apiName api_trigger_man_event
    @apiGroup man

    @apiParam {int} man_id URI中: 派件员工号
    @apiParam {str(32)} event URI中: 派件员事件/操作类型, 支持: `ADD_ACCOUNT`, `ADD_FAMILIAR`, `DEL_FAMILIAR`,
    `COMPLETE_INFO`, `EVENT_RESET`
    @apiParam {int} [operator_id] 操作人id
    @apiParam {str(382)} [remark] 操作备注

    @apiParamExample {json} 请求url示例:
        /deliveryman/event
    @apiParamExample {json} 请求body示例:
        {
            "operator_id": 7774123,
            "remark": "运营拉黑"
        }
    @apiSuccessExample {json} 成功示例:
        HTTP/1.1 200 OK
        {
            "status": "CHECK_WORKING"
        }
    @apiErrorExample {json} 失败示例:
        HTTP/1.1 400 ValueError
        {
            "message": "State change failed."
        }
    @apiErrorExample {json} 失败示例:
        HTTP/1.1 400 ValueError
        {
            "message": "Event[EVENT_CITY_SCORE_APP_YE] should be in EMAP..."
        }
    """
    operation = str(operation).upper().strip()
    kw = ctx.request.input()
    # 添加支付宝账户
    if operation == OPERATIONS.ADD_ACCOUNT:
        # required: id, account{name, id}
        result = Man.objects(id=kw.man_id).update_one(
            add_to_set__accounts=dict(name=kw.name, id=kw.id),
            full_result=True)
        if result['nModified'] == 0:
            logging.warning("Account[%s:%s] already added for man=[%s]." %
                            (kw.id, kw.name, kw.man_id))
            raise ValueError("帐号重复添加.")
    # 添加送单区域
    elif operation == OPERATIONS.ADD_FAMILIAR:
        result = Man.objects(id=kw.man_id).update_one(
            add_to_set__familiars=dict(name=kw.name,
                                       city=kw.city,
                                       addr=kw.addr,
                                       lat=kw.lat,
                                       lng=kw.lng),
            full_result=True)
        if result['nModified'] == 0:
            logging.warning("Familiar already added for man=[%s]." % kw.man_id)
            raise ValueError("送单区域重复添加.")
    # 移除送单区域
    elif operation == OPERATIONS.DEL_FAMILIAR:
        Man.objects(id=kw.man_id).update_one(pull__familiars=dict(
            name=kw.name, city=kw.city, addr=kw.addr, lat=kw.lat, lng=kw.lng))
    # 添加取货点(限定是区域经理)
    elif operation == OPERATIONS.ADD_PICKUP:
        pick_up = dict(name=kw.name,
                       city=kw.city,
                       addr=kw.addr,
                       lat=kw.lat,
                       lng=kw.lng)
        result = Man.objects(id=kw.man_id).update_one(
            add_to_set__pick_up_locations=pick_up, full_result=True)
        if result['nModified'] == 0:
            logging.warning("Pick-up location %s already added for man=[%s]." %
                            (pick_up, kw.man_id))
            raise ValueError("取货点重复添加.")
    # 移除取货点(限定是区域经理)
    elif operation == OPERATIONS.DEL_PICKUP:
        pick_up = dict(name=kw.name,
                       city=kw.city,
                       addr=kw.addr,
                       lat=kw.lat,
                       lng=kw.lng)
        Man.objects(id=kw.man_id).update_one(pull__pick_up_locations=pick_up)
    # 完善资料/修改资料(特殊的事件,不单单是改状态,涉及到基本信息修改)
    elif operation == ManFSM.EVENT_COMPLETE_INFO:
        # 对完善资料特殊添加时间信息
        if 'recommended_by' in kw:
            kw['recommended_by']['time'] = TimeZone.utc_now()
        kw.id_card_num = str(kw.id_card_num).strip().upper()
        man = Man.objects(id_card_num=kw.id_card_num).first()
        # 该身份证号码已经存在且不是本人
        if man and str(man.pk) != str(kw.man_id):
            logging.warning(
                "Man[%s][%s] with id_card_num[%s] already exists." %
                (man.pk, man.name, kw.id_card_num))
            raise ValueError("该身份证号码已存在")
        # 身份证号可用, 根据man_id找到需要更新资料的人.
        man = Man.objects(id=kw.man_id).first()
        # 此人存在
        if man:
            operator_type = kw.operator_type
            kw.pop('operator_type')
            # 更新参数: name, id_card_num, avatar, id_card_back
            modified_man = ManFSM.update_status(operator_type, man,
                                                ManFSM.EVENT_COMPLETE_INFO,
                                                **kw)
            # 资料更新失败:
            if not modified_man:
                logging.warning("Update info for man[%s][%s][%s] failed." %
                                (man.pk, man.name, man.status))
                raise ValueError("资料更新失败")
            return ManLogic.pack_man(modified_man)
        # 此人不存在
        else:
            logging.warning(
                "Trying to update a man[%s]'s info that does not exist." %
                kw.man_id)
            raise ValueError("资料更新失败")
    elif operation in ManFSM.APP_EVENTS or operation in ManFSM.FE_EVENTS:
        # 根据man_id找到需要变更的人.
        man = Man.objects(id=kw.man_id).first()
        # 此人存在
        if man:
            operator_type = kw.operator_type
            kw.pop('operator_type')
            modified_man = ManFSM.update_status(operator_type, man, operation,
                                                **kw)
            if not modified_man:
                logging.warning(
                    "State transfer for man[%s][%s][%s] using [%s] failed." %
                    (kw.man_id, man.name, man.status, operation))
                raise ValueError("操作失败.")
            return ManLogic.pack_man(modified_man)
    else:
        raise ValueError("OPERATION[%s] should be in %s." %
                         (operation, set(OPERATIONS.keys()).union(
                             ManFSM.FE_EVENTS).union(ManFSM.APP_EVENTS)))
Esempio n. 6
0
def api_shop_operation(operation):
    def set_token(inner_who):
        token = hashlib.md5('%s%s' % (inner_who, utc_8_now())).hexdigest()
        key = key_shop_token.format(content=token)
        # 插入token到redis中, 7天有效期: get shop:token:fe11ad907e2fa779ed2f363ef589d3f9 => 7740959
        redis_client.setex(key, inner_who, 7 * 24 * 3600)
        return token

    operation = str(operation).upper().strip()
    kw = ctx.request.input()
    # ==> 商户注册
    if operation == OPERATIONS.REGISTER:
        kw = Schema({
            'tel': schema_unicode,
            'sms_code': schema_unicode,
            'password': schema_unicode,
            Optional('name'): schema_unicode,
            'contact': {
                Optional('name', default=''): schema_unicode_empty,
                Optional('tel', default=''): schema_unicode_empty
            },
            Optional("loc"): {
                "address": schema_unicode,
                "longitude": schema_float,
                "latitude": schema_float,
                Optional(object): object
            },
            Optional('recommended_by'): {
                'tel': schema_unicode_empty
            },
        }).validate(ctx.request.input())
        tel = kw['tel']
        sms_code = kw['sms_code']
        password = kw['password']
        # song.123feng.com/APP注册: 手机号+验证码
        if tel:
            sms_key = key_sms_code.format(tel=tel)
            # 验证成功: 验证码匹配 get sms:code:15901739717 => 123456
            sms_code_in_redis = redis_client.get(sms_key)
            if sms_code_in_redis == sms_code:
                shop = Shop.objects(tel=tel).first()
                if not shop:
                    # 记录商户到mongodb(如无记录): status=STATUS_VALID
                    # 记录商户到mongodb(如无记录): status=STATUS_INFO_YES
                    if 'recommended_by' in kw:
                        kw['recommended_by']['time'] = TimeZone.utc_now()
                    kw_filtered = ShopLogic.filter_shop(kw)
                    shop = Shop(**kw_filtered).save()
                    # ===== 注册风信账户 =====
                    http_client = HTTPClient()
                    http_client.fetch(account.req_create(
                        account_type=conf.ACCOUNT_TYPE_SHOP,
                        account_id=str(shop.pk)),
                                      raise_error=False)
                else:
                    # 允许重复注册, 改一下密码
                    shop.password = password
                    shop.save()
                shop.reload()
                shop_id = str(shop.pk)
                content = set_token(shop_id)
                s_packed = ShopLogic.pack_shop(shop)
                s_packed.update(dict(token=content))
                return s_packed
            # 登录失败
            else:
                logging.info(
                    "SMS code validation for [%s]=[%s] failed, expected[%s]." %
                    (tel, sms_code, sms_code_in_redis))
                raise ValueError("验证码验证失败.")
    # ==> 商户事件
    elif operation in ShopFSM.FE_INSIDE_EVENTS or operation in ShopFSM.OUTSIDE_EVENTS:
        # 对完善资料特殊添加时间信息
        if operation == ShopFSM.EVENT_COMPLETE_INFO and 'recommended_by' in kw:
            kw['recommended_by']['time'] = TimeZone.utc_now()
        # 对修改定价特殊处理: 能用tel找商户id
        if operation == ShopFSM.EVENT_ALTER_INFO:
            shop = Shop.objects(tel=kw.tel).first()
        # 其他事件一概用shop_id
        else:
            shop = Shop.objects(id=kw.shop_id).first()
        if shop:
            operator_type = kw.operator_type
            kw.pop('operator_type')
            modified_shop = ShopFSM.update_status(operator_type, shop,
                                                  operation, **kw)
            if not modified_shop:
                raise ValueError(
                    "State transfer for shop[%s][%s][%s] using [%s] failed." %
                    (kw.shop_id, shop.name, shop.status, operation))
            return ShopLogic.pack_shop(modified_shop)

    else:
        pass
Esempio n. 7
0
                          data=urllib.parse.urlencode(params),
                          headers=headers,
                          timeout=5)
    except Exception as e:
        print((traceback.format_exc()))
        return False, {'error': str(e)}
    response = r.json()

    if "response_params" in response:
        return True, {}
    else:
        return False, response


if __name__ == '__main__':
    from tools_lib.common_util.archived.gtz import TimeZone

    msg = {
        "source": "deliver",
        "type": "force_deliver_notice",
        "content": {
            "title": "测试",
            "body": "同志们好,首长好",
            "create_time": TimeZone.datetime_to_str(TimeZone.utc_now()),
        }
    }

    print((baidu_push_v3('3737072413124982526',
                         msg,
                         device_type=PLATFORM_ANDROID)))
Esempio n. 8
0
 def get(self):
     now = TimeZone.utc_now()
     self.write_response(content=TimeZone.datetime_to_str(now))
Esempio n. 9
0
def shop_reward():
    logging.info("invitation shop reward start...")
    man_conn = mongodb_client['profile']['man']
    shop_conn = mongodb_client['profile']['shop']
    express = mongodb_client['aeolus']['express']

    now = TimeZone.utc_now()
    local = TimeZone.local_now()
    cursor = shop_conn.find({
        "recommended_by.tel": {
            "$exists": True
        },
        "recommended_by.time": {
            "$gt": TimeZone.decrement_months(now, 2)
        }
    })

    m_type = "shop_invitation"
    for doc in cursor:
        man = man_conn.find_one({"tel": doc['recommended_by']['tel']})
        if not man:
            logging.warning("no man tel:%s", doc['recommended_by']['tel'])
            continue

        shop_id = str(doc['_id'])
        shop_name = utf8(doc.get("name", "新客户"))
        man = format_man(man, 'parttime')
        invite_time = TimeZone.naive_to_aware(doc['recommended_by']['time'],
                                              pytz.utc)

        # 拿出这个人对应商户所有的奖励, 用来计算已经奖励了多少钱
        reward_list = Rewards.objects(man__id=man['id'],
                                      source__shop_id=shop_id,
                                      m_type=m_type)

        # 计算还剩多少可以奖励
        count = 0
        for r in reward_list:
            count += r.money
        count = int(count)
        left = 100 - count

        # 如果没剩了, 不能再奖励了
        if left <= 0:
            continue
        # 计算最近一次需要计算的日期,
        try:
            reward = reward_list[0]
            start_date = TimeZone.utc_to_local(
                TimeZone.increment_days(reward.create_time, 1)).date()

        except IndexError:
            start_date = TimeZone.utc_to_local(invite_time).date()
        # 最多计算到昨天
        end_date = local.date()

        # 从开始日期开始到昨天都需要计算
        for day in TimeZone.date_xrange(start_date, end_date):
            start_time, end_time = TimeZone.day_range(value=day)
            # 限制一下start_time
            start_time = start_time if start_time > invite_time else invite_time

            _count = express.find({
                "creator.id": shop_id,
                "times.sj_time": {
                    "$gte": start_time,
                    "$lte": end_time
                },
            }).count()

            if _count == 0:
                continue

            c = _count if _count < left else left

            money = c * 1.0
            # 先将时间加上本地tzinfo, 然后再转换时区, 直接指定tzinfo会出错, 差6分钟, 故意躲加1小时
            create_time = TimeZone.datetime_to_utc(
                TimeZone.naive_to_aware(
                    datetime(day.year, day.month, day.day, 1)))
            Rewards(m_type=m_type,
                    title="邀请客户",
                    desc="%s当日下单%s单" % (shop_name, c),
                    man=man,
                    money=money,
                    source={
                        "shop_id": shop_id,
                        "shop_name": shop_name
                    },
                    create_time=create_time).save()
            logging.info(
                "reward: m_type[%s], date[%s], man[%s], shop_id[%s], money[%s]",
                m_type, day, man['id'], shop_id, money)

            left -= c
            if left <= 0:
                break