Пример #1
0
 def expire_at_today(self, key, hour=0):
     from tools_lib.common_util.archived.gtz import TimeZone
     tomorrow = TimeZone.increment_days(TimeZone.local_now())
     self.expireat(
         key,
         TimeZone.increment_hours(
             TimeZone.transfer_datetime_to_beginning(tomorrow), hour))
Пример #2
0
 def expire_at_this_end_of_month(self, key):
     # 本月月底过期
     from tools_lib.common_util.archived.gtz import TimeZone
     local_now = TimeZone.local_now()
     end_of_this_month = TimeZone.utc_to_local(
         TimeZone.month_range(local_now.year, local_now.month)[1])
     self.expireat(key, end_of_this_month)
     self.delete()
Пример #3
0
def redirect_song_export_express(creator_id, start_time, end_time):
    """
    [HTTPRequest]SONG导出运单信息
    :param creator: 下单者id,商户id
    :param start_time: 起始时间
    :param end_time: 终止时间
    """
    url = settings.BL_DAS_API_PREFIX + "/express/export/song"
    url = url_concat(
        url, {
            "shop_id": creator_id,
            "start_time": TimeZone.datetime_to_str(start_time),
            "end_time": TimeZone.datetime_to_str(end_time)
        })
    return HTTPRequest(url, method="GET", **timeouts)
Пример #4
0
 def get(self):
     """
     导出运单
     """
     try:
         data = self.get_query_args()
         creator_id = data["shop_id"]
         start_time = TimeZone.str_to_datetime(data["start_time"])
         end_time = TimeZone.str_to_datetime(data["end_time"])
     except:
         self.resp_error("参数错误")
         return
     yield self.resp_redirect(
         express.redirect_song_export_express(creator_id,
                                              start_time=start_time,
                                              end_time=end_time))
Пример #5
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)
Пример #6
0
def sign_in():
    sign_in = client['profile']['sign_in']
    start, end = TimeZone.day_range(value=TimeZone.local_now())
    pprint(
        "姓名",
        "电话",
        "时间",
        "地址",
        "POI",
        "经度",
        "维度",
    )
    for doc in sign_in.find({"create_time": {"$gte": start, "$lte": end}}):
        pprint(doc['name'], doc['tel'],
               TimeZone.utc_to_local(doc['create_time']), doc['loc']['addr'],
               doc['loc']['name'], doc['loc']['lng'], doc['loc']['lat'])
Пример #7
0
 def schedule(self, scheduled_time):
     """
     定时发送
     :param scheduled_time:
     :return: schedule token for cancelling
     """
     json_data = {
         "type": conf.MQ_TYPE_SCHEDULE,
         "scheduled_time": TimeZone.datetime_to_str(scheduled_time),
         "data": self
     }
     return self._send(json.dumps(json_data))
Пример #8
0
def get_zj_statistics(start_date, end_date):
    url = IP_PORT_API + "/shop/flow/complex_query"
    query = {
        "filter_col": ["shop_id", "type", "sum(cash) as total", "create_time"],
        "query": {
            "op":
            "AND",
            "exprs": [{
                "create_time": {
                    ">=": TimeZone.date_to_str(start_date),
                    "<": TimeZone.date_to_str(end_date)
                }
            }, {
                "type": {
                    "in": ["TOP_UP", "PAY"]
                }
            }, {
                "is_not": 1,
                "shop_name": {
                    "like": "%测试%"
                }
            }]
        },
        "group_by": "shop_id,type",
        "count": 3000
    }

    resp = requests.post(url, json=query)
    if resp.status_code != 200:
        return 0, 0
    top_up = 0
    pay = 0
    for item in resp.json():
        if item['type'] == "PAY":
            pay += float(item['total'])
        elif item['type'] == "TOP_UP":
            top_up += float(item['total'])

    return top_up, pay
Пример #9
0
def modify_sj_time(expr_cursor):
    i = 0
    for doc in expr_cursor:
        i += 1
        times = []
        _times = []
        for k, t in list(doc['times'].items()):
            if k != 'sj_time':
                times.append(t)

        times = sorted(times)
        for t in times:
            _times.append(TimeZone.datetime_to_str(t, pattern='%H:%M'))

        sj_time = min(times)
        result = mc.update_one({'_id': doc['_id']},
                               {'$set': {
                                   'times.sj_time': sj_time
                               }})
        print(('%s, %s, min%s => [%s], %s, %s' %
               (i, doc['number'], _times,
                TimeZone.datetime_to_str(sj_time, pattern='%H:%M'),
                result.matched_count, result.modified_count)))
Пример #10
0
def api_deliveryman_sign_in():
    """
    派件系人员签到
    :param man_id: 根据 id 查出 name, tel, avatar
    :param loc: {name, addr, lng, lat}
    :param device: {mac_id, ...}
    :return: 失败返回400和message
    """
    params = ctx.request.input()
    # ==> 根据id拿基本信息
    man = Man.objects(id=params.man_id).first()
    # ==> 检查今日签到次数
    now = TimeZone.local_now()
    start_time, _end_time = TimeZone.day_range(value=now)
    start_time = TimeZone.datetime_to_str(start_time)
    sign_in_count = SignIn.objects(**{
        'man_id': params.man_id,
        'create_time__gte': start_time
    }).count()
    if sign_in_count >= 50:
        logging.warn("Man[%s][%s] try to sign in over 10 times." %
                     (params.man_id, man.name))
        raise ValueError("一天最多签到10次")
    # ==> 记录这次签到
    name = man.name if man.name else ''
    avatar = man.avatar if man.avatar else ''
    SignIn(man_id=params.man_id,
           name=name,
           tel=man.tel,
           avatar=avatar,
           loc=params.loc,
           device=params.device,
           create_time=now).save(force_insert=True)
    return {
        'create_time': TimeZone.datetime_to_str(now,
                                                pattern='%Y-%m-%dT%H:%M:%S')
    }
Пример #11
0
 def format_response(self):
     return {
         "cli": self.channel_leancloud_id,
         "name": self.name,
         "description": self.description,
         "icon": get_image_url(self.icon),
         "sticky": self.sticky,
         "top": self.top,
         "talkable": self.talkable,
         "disabled": self.disabled,
         "manager": self.manager,
         "answerer": self.answerer,
         "subscriber_condition": self.subscriber_condition,
         "create_time": TimeZone.datetime_to_str(self.create_time)
     }
Пример #12
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)
Пример #13
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())
Пример #14
0
    def get(self):
        # 商户名,商户注册电话,余额,当日消费,当日10:00前下单,当日10:00~14:00下单,当日14:00之后下单,当日待取件,总计待妥投
        try:
            data = Schema({
                "date": schema_date,
            }).validate(self.get_query_args())
            date = data['date']
        except SchemaError:
            self.resp_error('参数[date]解析失败')
            return
        middle = {}
        # 1. 商户名,商户注册电话,当日消费,当日10:00前下单,当日10:00~14:00下单,当日14:00之后下单
        start_time, end_time = TimeZone.day_range(value=date)
        pipeline = [
            # 取今天的所有有效运单
            {
                "$match": {
                    "create_time": {
                        "$gt": start_time,
                        "$lt": end_time
                    },
                    "status.sub_status": {"$ne": ExprState.SUB_STATUS_CANCEL}
                }
            },
            # 按照[商户,小时]分组
            {
                "$group": {
                    "_id": {
                        "creator_id": "$creator.id",
                        "hour": {"$hour": {"$add": ['$create_time', 28800000]}},
                    },
                    "tel": {"$first": "$creator.tel"},
                    "name": {"$first": "$creator.name"},
                    "expr_count": {"$sum": 1},
                    # 暂时除了pre_created的运单才算是消费了
                    "expense": {"$sum": {"$cond": [{"$ne": ["$status.status", "PRE_CREATED"]}, "$fee.fh", 0]}}
                }
            },
            # 根据[商户,小时]分组计算10:00前,10:00~14:00,14:00后下单数量
            {
                "$group": {
                    "_id": {
                        "creator_id": "$_id.creator_id",
                    },
                    "tel": {"$first": "$tel"},
                    "name": {"$first": "$name"},
                    "expense": {"$sum": "$expense"},
                    "count_before_10am": {"$sum": {"$cond": [{"$lt": ["$_id.hour", 10]}, "$expr_count", 0]}},
                    "count_10am_to_2pm": {"$sum": {
                        "$cond": [{"$and": [{"$gte": ["$_id.hour", 10]}, {"$lt": ["$_id.hour", 14]}]}, "$expr_count",
                                  0]}},
                    "count_after_2pm": {"$sum": {"$cond": [{"$gte": ["$_id.hour", 14]}, "$expr_count", 0]}},
                    "count_all": {"$sum": "$expr_count"}
                }
            },
            {
                "$sort": {
                    "count_all": -1,
                }
            }
        ]
        result = yield self.async_fetch(redirect_aggregation(pipeline=pipeline))
        content = result.content
        # 从这里拿到所有的商户id
        creator_ids = []
        for c in content:
            creator_id = c['_id']['creator_id']
            tel = c['tel']
            name = c['name']
            expense = c['expense']
            # 10点之前下单数量
            count0 = c['count_before_10am']
            # 10-14点下单数量
            count1 = c['count_10am_to_2pm']
            # 14点之后下单数量
            count2 = c['count_after_2pm']
            # 当日总计下单量
            _count_all = c['count_all']
            # print("[%s] %s+%s+%s=%s 消費:%s" % (name, count0, count1, count2, _count_all, expense))
            creator_ids.append(creator_id)
            middle[creator_id] = dict(name=name, tel=tel, expense=expense, count_before_10am=count0,
                                      count_10am_to_2pm=count1, count_after_2pm=count2, count_all=_count_all)

        # 2. 当日待取件, 当日待妥投
        pipeline = [
            # 取今天在<creator_ids>里面的所有运单
            {
                "$match": {
                    "create_time": {
                        "$gt": start_time,
                        "$lt": end_time
                    },
                    "creator.id": {
                        "$in": creator_ids
                    }
                }
            },
            # 按照[商户,状态条件]分组
            {
                "$group": {
                    "_id": {
                        "creator_id": "$creator.id",
                    },
                    "count_created": {"$sum": {"$cond": [{"$eq": ["$status.status", "PRE_CREATED"]}, 1, 0]}},
                    "count_sending": {"$sum": {"$cond": [{"$eq": ["$status.status", "SENDING"]}, 1, 0]}},
                    "count_all": {"$sum": 1}
                }
            },
            {
                "$sort": {
                    "count_all": -1,
                }
            }
        ]
        result = yield self.async_fetch(redirect_aggregation(pipeline=pipeline))
        for c in result.content:
            creator_id = c['_id']['creator_id']
            # 待取貨
            count0 = c['count_created']
            # 派件中
            count1 = c['count_sending']
            # 当日总计下单量
            _count_all = c['count_all']
            # print("[%s] 待取貨:%s 派件中:%s 總計:%s" % (name, count0, count1, _count_all))
            middle[creator_id]['count_created'] = count0
            middle[creator_id]['count_sending'] = count1

        # 3. 拿余额
        balances = yield multi_shop_balance(creator_ids)

        # 4. 拼结果
        fin = []
        for cid in creator_ids:
            middle[cid]['id'] = cid
            middle[cid]['balance'] = balances[cid]
            fin.append(middle[cid])
        self.resp(fin)
Пример #15
0
def api_retrieve_man_info(what):
    what = str(what).upper().strip()
    request = ctx.request.input()
    # 如果传入what,by不是允许的值,直接报错
    if what not in WHATS:
        raise ValueError("WHAT[%s] should be in WHATS%s." %
                         (what, list(WHATS.keys())))
    params = set([str(k).lower().strip() for k in request])
    bys = set(BYS.keys())
    by = params.intersection(bys)
    if not by:
        raise ValueError("BY%s should be in BYS%s." %
                         (list(params), list(bys)))
    by_key = next(iter(by))
    by_val = request[by_key]
    if by_key == 'id' and by_val and len(by_val) != 24:
        raise ValueError('find man with id=%s, id should be of length 24.' %
                         by_val)
    # 判断是要什么类型的返回
    if what == WHATS.BASIC:
        excludes = ('accounts', 'create_time', 'my_man')
        man = Man.objects(**{by_key: by_val}).exclude(*excludes).first()
        if not man:
            raise ValueError("Can't find man with[%s]=[%s]." %
                             (by_key, by_val))
        packed = ManLogic.pack_man(man, excludes=excludes)
        ret_cnt = ('familiars', 'pick_up_locations')
        for k in ret_cnt:
            if k in packed:
                packed[k] = len(packed[k]) if packed[k] else 0
        return packed
    elif what == WHATS.ACCOUNT_LIST:
        man = Man.objects(**{by_key: by_val}).only('accounts').first()
        return man.accounts
    elif what == WHATS.FAMILIAR_LIST:
        man = Man.objects(**{by_key: by_val}).only('familiars').first()
        return man.familiars
    elif what == WHATS.STATUS:
        man = Man.objects(**{by_key: by_val}).only('status').first()
        return man.status
    elif what == WHATS.MAN_LIST:
        man = Man.objects(**{by_key: by_val}).only('my_man').first()
        if man and man.my_man:
            only = ('status', 'id', 'name', 'tel', 'avatar')
            my_man = {m['id']: m['bind_time'] for m in man.my_man}
            mans = Man.objects(id__in=list(my_man.keys())).only(*only)
            ret = []
            for m in mans:
                packed_man = ManLogic.pack_man(m, only=only)
                packed_man['bind_time'] = my_man[str(m.pk)]
                ret.append(packed_man)
            return ret
        else:
            return []
    elif what == WHATS.CODE:
        # 取header里面的app-name, 没给的话就给man
        app_name = ctx.request.header('app-name', 'man')
        man_id = by_val
        code = shortuuid.ShortUUID().random(length=8)
        # role是区域经理app端header里面的app-name
        key = key_man_code.format(role=app_name, content=code)
        # 存放: 二维码(360秒): get <app-name>:code:fe11ad907e2fa779ed2f363ef589d3f9 => 56f1028b2d50c07c80914393
        redis_client.setex(key, man_id, 360)
        logging.info('Setting Code [%s] => [%s].' % (key, man_id))
        return key
    elif what == WHATS.PICKUP_LIST:
        man = Man.objects(**{by_key: by_val}).only('pick_up_locations').first()
        return man.pick_up_locations
    elif what == WHATS.SIGN_IN_COUNT:
        # 获取人员名字
        man = Man.objects(id=by_val).only('name').first()
        name = man.name if man.name else ''
        # 获取今天凌晨以后的签到记录次数
        now = TimeZone.local_now()
        start_time, _end_time = TimeZone.day_range(value=now)
        start_time = TimeZone.datetime_to_str(start_time)
        sign_in_count = SignIn.objects(**{
            by_key: by_val,
            'create_time__gte': start_time
        }).count()
        return dict(name=name,
                    sign_in_count=sign_in_count,
                    server_time=TimeZone.datetime_to_str(
                        now, pattern='%Y-%m-%dT%H:%M:%S'))
Пример #16
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('操作失败')
Пример #17
0
        for data_record in data:
            try:
                baidu_push_v3(channel_id=data_record['channel_id'],
                              msg=json.dumps(data_record.get('msg', ''),
                                             ensure_ascii=False),
                              device_type=PLATFORM_ANDROID)
            except:
                pass
    except:
        print((traceback.format_exc()))
    finally:
        pass


if __name__ == '__main__':
    print(('[{current_time}] starting server ...'.format(
        current_time=TimeZone.local_now())))

    connection = pika.BlockingConnection(
        pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()

    channel.exchange_declare(exchange=EXCHANGE_PUSH_MSG, type=TYPE_FANOUT)
    result = channel.queue_declare(exclusive=True)
    queue_name = result.method.queue

    channel.queue_bind(exchange=EXCHANGE_PUSH_MSG, queue=queue_name)
    channel.basic_consume(callback, queue=queue_name, no_ack=True)
    channel.start_consuming()
Пример #18
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)))
Пример #19
0
def op_data():
    logging.info("op_data start...")

    man_conn = mongodb_client['profile']['man']
    shop_conn = mongodb_client['profile']['shop']
    express = mongodb_client['aeolus']['express']

    opdata = OpData.objects.order_by("-create_time").first()

    start_date = date(2016, 5, 20)
    if opdata:
        start_date = TimeZone.increment_days(
            TimeZone.utc_to_local(opdata.create_time), 1).date()
    end_date = TimeZone.local_now().date()

    for day in TimeZone.date_xrange(start_date, end_date):
        start_time, end_time = TimeZone.day_range(value=day)

        logging.info("op data %s", day)
        data = {}
        # ============= 资金 ==============
        data['zj_top_up'], data['zj_pay'] = get_zj_statistics(
            day, TimeZone.increment_days(day))

        # ============= 订单 ==============
        data['dd_count'] = express.find({
            "create_time": {
                "$gte": start_time,
                "$lte": end_time
            }
        }).count()
        data['dd_sj_count'] = express.find({
            "times.zj_time": {
                "$gte": start_time,
                "$lte": end_time
            }
        }).count()
        data['dd_tt_count'] = express.find({
            "times.parttime_tt_time": {
                "$gte": start_time,
                "$lte": end_time
            }
        }).count()
        data['dd_error_count'] = express.find({
            "times.yc_time": {
                "$gte": start_time,
                "$lte": end_time
            }
        }).count()

        # ============= 客户 ==============
        data['sh_register'] = shop_conn.find({
            "create_time": {
                "$gte": start_time,
                "$lte": end_time
            }
        }).count()
        data['sh_order'] = 0
        result = express.aggregate([{
            "$match": {
                "create_time": {
                    "$gte": start_time,
                    "$lte": end_time
                }
            }
        }, {
            "$group": {
                "_id": "$creator.id",
            }
        }, {
            "$group": {
                "_id": "sum",
                "count": {
                    "$sum": 1
                }
            }
        }])
        for doc in result:
            data['sh_order'] += doc['count']

        # ============== 人力 ===============
        data['hr_on_job'] = man_conn.find({
            "job_description": "parttime",
            "status": "STATUS_WORKING"
        }).count()
        data['hr_active'] = 0
        # 在规定时间内收件的人
        result = express.aggregate([{
            "$match": {
                "times.sj_time": {
                    "$gte": start_time,
                    "$lte": end_time
                }
            }
        }, {
            "$project": {
                "man": {
                    "$arrayElemAt": ["$watchers", 0]
                }
            }
        }, {
            "$group": {
                "_id": "$man.id"
            }
        }])
        active_list = [_['_id'] for _ in result]

        result = express.aggregate([{
            "$match": {
                "times.parttime_tt_time": {
                    "$gte": start_time,
                    "$lte": end_time
                }
            }
        }, {
            "$group": {
                "_id": "$assignee.id",
            }
        }])
        # 在规定时间内妥投的人
        active_list2 = [_['_id'] for _ in result]
        temp = set(active_list + active_list2)
        data['hr_active'] = len(temp)

        # 司机出勤
        man_list = man_conn.find({"tel": {"$in": driver_list}})
        node_conn = psycopg2.connect(cursor_factory=psycopg2.extras.DictCursor,
                                     database="tlbs",
                                     **CONFIG_POSTGRESQL)
        cursor = node_conn.cursor()
        data['cl_depart'] = 0
        man_id_list = [str(_['_id']) for _ in man_list]

        for man_id in man_id_list:
            local = arrow.get(day, "local")
            cursor.execute(
                """SELECT count(*)
                from trans.bs_trans_deliver_sign_record
                where deliver_id = %s and create_time >= %s and create_time <= %s
                """, (man_id, local.floor("day").strftime(TIME_PATTERN),
                      local.ceil("day").strftime(TIME_PATTERN)))

            doc = cursor.fetchone()
            if doc and int(doc[0]) > 0:
                data['cl_depart'] += 1
        cursor.execute(
            """
            SELECT count(*)
            FROM trans.bs_trans_bind_node_info
            WHERE deliver_id = ANY(%s)
            """, (man_id_list, ))
        doc = cursor.fetchone()
        if not doc:
            data['cl_shift'] = 0
        else:
            data['cl_shift'] = int(doc[0])

        # =======================================
        create_time = TimeZone.datetime_to_utc(
            TimeZone.naive_to_aware(datetime(day.year, day.month, day.day, 1)))

        data["create_time"] = create_time
        OpData(**data).save()

    logging.info("op_data end...")
Пример #20
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
Пример #21
0
            if k != 'sj_time':
                times.append(t)

        times = sorted(times)
        for t in times:
            _times.append(TimeZone.datetime_to_str(t, pattern='%H:%M'))

        sj_time = min(times)
        result = mc.update_one({'_id': doc['_id']},
                               {'$set': {
                                   'times.sj_time': sj_time
                               }})
        print(('%s, %s, min%s => [%s], %s, %s' %
               (i, doc['number'], _times,
                TimeZone.datetime_to_str(sj_time, pattern='%H:%M'),
                result.matched_count, result.modified_count)))


if __name__ == '__main__':
    pool = Pool(4)
    cursor = mc.find({
        'times.sj_time': {
            '$exists': True
        },
        'create_time': {
            '$gte': TimeZone.str_to_datetime("2016-05-01T00:00:00.000+0800")
        }
    })
    modify_sj_time(expr_cursor=cursor)
    # pool.map(modify_sj_time, [cursor])
Пример #22
0
 def get(self):
     now = TimeZone.utc_now()
     self.write_response(content=TimeZone.datetime_to_str(now))
Пример #23
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
Пример #24
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)))
Пример #25
0
    def get(self):
        """
            @api {get} /express/yun/op_data 风云 - 运营数据
            @apiName yun_op_data
            @apiGroup app_fe
            @apiVersion 0.0.1

            @apiParam (query param) {string} date 一个月中的某一天

            @apiSuccessExample 成功返回示例
            HTTP/1.1 200 OK
            [
                {
                "hr_break": 0,
                "zj_pay": 0,
                "create_time": "2016-05-19T17:00:00Z",
                "cl_shift": 0,
                "dd_error_count": 1,
                "sh_valid": 0,
                "hr_invite": 0,
                "sh_register": 0,
                "sh_order": 0,
                "zj_cash_back": 0,
                "dd_count": 0,
                "hr_interview": 0,
                "zj_top_up": 0,
                "sh_complain": 0,
                "hr_consulting": 0,
                "hr_entry": 0,
                "hr_active": 0,
                "dd_tt_count": 0,
                "hr_leave": 0,
                "cl_late": 0,
                "dd_sj_count": 0,
                "hr_on_job": 2,
                "cl_depart": 0,
                "sh_visit": 0
                },
                ...
            ]
            @apiUse bad_response
        """
        try:
            data = Schema({
                "date": schema_date
            }).validate(self.get_query_args())
        except:
            self.resp_args_error()
            return

        start, end = TimeZone.month_range(value=data['date'])

        query = {
            "create_time__gte": start,
            "create_time__lte": end,
            "excludes": ["id"]
        }

        resp = yield self.async_fetch(bl_data.redirect_op_data_search(query))

        content = resp.content

        total = dict()
        for _ in content:
            for (k, v) in list(_.items()):
                if k in total:
                    total[k] += v
                else:
                    total[k] = v

        total['create_time'] = "总计"
        content.insert(0, total)
        self.resp(content=content)