Beispiel #1
0
    def logs(self, ltype, lid):
        """

        :param ltype:
        :param lid:
        :return:
        """
        if ltype == 'express':
            logistics = Logistic.objects(id=lid).first().express_tracking
            return self.render('admin/logistic/express.html',
                               logistics=logistics)
        elif ltype == 'logistic':
            logistics = LogisticLog.objects(logistic_id=lid,
                                            log_type__ne='API')
            user = lambda i: getattr(User.objects(id=i).first(), 'name', ''
                                     ) if i and i != 'system' else i
            return self.render('admin/logistic/logs.html',
                               logistics=logistics,
                               user=user)
        elif ltype == 'print':
            logistic = Logistic.objects(id=lid).first()
            if logistic.is_closed:
                return Response('this logistics id has been closed.')
            return self.render('admin/logistic/print_page.html',
                               logistic=logistic)
Beispiel #2
0
    def logistics_delay(self, status=None, delay_type=None):
        """
        物流延迟
        :param status:
        :param delay_type:
        :return:
        """
        utcnow = datetime.datetime.utcnow()
        if status:
            items_range = request.headers.get('Range', '0-9')
            start, end = items_range.split('-')
            per_page = int(end) - int(start) + 1

            query = restruct_query(request.args)
            tracking_no = query.pop('tracking_no', '')
            date_field = LogisticDetail.attr_by_log_status[status]
            delay_days = datetime.timedelta(days=delay_status_by_date[status])
            query.update({
                'detail__%s__lt' % date_field: utcnow - delay_days,
                'detail__status': status,
            })
            logistic = Logistic.objects(is_closed=False, **query).order_by(
                'detail__%s' % date_field)

            if tracking_no:
                logistic = logistic.filter(
                    Q(detail__us_tracking_no=tracking_no)
                    | Q(detail__cn_tracking_no=tracking_no))
            if delay_type:
                logistic = logistic.filter(
                    detail__delay_details__reason__contains=delay_type)

            data = logistic[int(start):int(end)]
            data = [to_json(l) for l in data]
            resp = make_response(json_util.dumps(data), 200)
            resp.headers['Accept_Range'] = 'items'
            resp.headers['Content_Range'] = '%s-%s/%s' % (start, end,
                                                          logistic.count())
            resp.headers['Content_Type'] = 'application/json'
            return resp

        data = {}
        for status in [
                'PAYMENT_RECEIVED', 'PROCESSING', 'SHIPPING', 'PORT_ARRIVED'
        ]:
            logistic = Logistic.objects(is_closed=False)
            date_field = LogisticDetail.attr_by_log_status[status]
            delay_days = datetime.timedelta(days=delay_status_by_date[status])
            query = {
                'detail__%s__lt' % date_field: utcnow - delay_days,
                'detail__status': status,
            }
            count = logistic.filter(**query).count()
            data.update({status: count})

        return jsonify(results=data)
Beispiel #3
0
    def logistics(self):
        """
        物流
        :return:
        """
        items_range = request.headers.get('Range', '0-9')
        start, end = items_range.split('-')
        per_page = int(end) - int(start) + 1
        query = restruct_query(request.args)
        tracking_no = query.pop('tracking_no', '')
        include_closed = query.get('include_closed') and query.pop(
            'include_closed')
        try:
            if include_closed:
                logistic = Logistic.objects(**query)
            else:
                logistic = Logistic.objects(is_closed=False, **query)
            if tracking_no:
                logistic = logistic.filter(
                    Q(detail__us_tracking_no=tracking_no)
                    | Q(detail__cn_tracking_no=tracking_no))

            if request.args.get('status'):
                logistic = logistic.order_by('detail__%s' %
                                             LogisticDetail.attr_by_log_status[
                                                 request.args.get('status')])
        except:
            pass

        if query.get('receiver'):
            address = Address.objects(
                receiver=query.get('receiver')).distinct('id')
            orders = Order.commodities(address__in=address)
            logistic = list(
                chain.from_iterable(order.logistics for order in orders))
        if query.get('order_id'):
            orders = Order.commodities(short_id=int(query.get('order_id')))
            logistic = list(
                chain.from_iterable(order.logistics for order in orders))

        try:
            logistic_size = logistic.count()
        except:
            logistic_size = len(logistic)

        data = logistic[int(start):int(end)]
        data = [to_json(l) for l in data]
        resp = make_response(json_util.dumps(data), 200)
        resp.headers['Accept_Range'] = 'items'
        resp.headers['Content_Range'] = '%s-%s/%s' % (start, end,
                                                      logistic_size)
        resp.headers['Content_Type'] = 'application/json'
        return resp
Beispiel #4
0
    def split_entries(self):
        """

        :return:
        """
        entries = request.json.get('selected')
        if not entries:
            return jsonify(message='Failed', desc='please select entries.')

        lids = []
        entry_ids = []
        for e in entries:
            l = e.split(':')
            lids.append(l[1])
            entry_ids.append(l[0])

        logistic = [Logistic.objects(id=lid).first() for lid in set(lids)]

        entry_lst = []
        for i in entry_ids:
            e = OrderEntry.objects(id=str(i)).first()
            entry_lst.append(e)

        entries_groups = map(
            lambda lo: filter(lambda e: e in lo.entries, entry_lst), logistic)

        for logistic, lst in zip(logistic, entries_groups):
            logistic.fork_by_entries([e.id for e in lst])

        return jsonify(message='OK', oid=logistic.order.short_id)
Beispiel #5
0
    def close(self, lid):
        """

        :param lid:
        :return:
        """
        logistic = Logistic.objects(id=lid).first()
        logistic.close('closed by %s' % current_user.name)
        return jsonify(message='OK')
Beispiel #6
0
    def logistics_irregular(self, process_status=None, irr_type=None):
        """

        :param process_status:
        :param irr_type:
        :return:
        """
        utcnow = datetime.datetime.utcnow()
        if process_status:
            items_range = request.headers.get('Range', '0-9')
            start, end = items_range.split('-')
            query = restruct_query(request.args)
            tracking_no = query.pop('tracking_no', '')
            logistic = Logistic.objects(
                detail__irregular_details__process_status=process_status,
                **query).order_by('-detail.irregular_details.created_at')
            if irr_type:
                logistic = logistic.filter(
                    detail__irregular_details__irr_type=irr_type).order_by(
                        '-detail.irregular_details.created_at')

            if tracking_no:
                logistic = logistic.filter(
                    Q(detail__us_tracking_no=tracking_no)
                    | Q(detail__cn_tracking_no=tracking_no))

            data = logistic[int(start):int(end)]
            data = [to_json(l) for l in data]
            resp = make_response(json_util.dumps(data), 200)
            resp.headers['Accept-Range'] = 'items'
            resp.headers['Content-Range'] = '%s-%s/%s' % (start, end,
                                                          logistic.count())
            resp.headers['Content_Type'] = 'application/json'
            return resp

        data = {}
        for status in ['WAITTING_PROCESS', 'PROCESSING', 'PROCESSED']:
            logistic = Logistic.objects(
                detail__irregular_details_process_status=status)
            data.udpate({status: logistic.count()})

        return jsonify(results=data)
Beispiel #7
0
def logistic_provider_dispatcher(order):
    """

    :param order:
    :return:
    """
    Logistic.create(order)
    for logistic in order.logistics:
        if len(logistic.entries) > 1:
            logs = LogisticSpliter(log=logistic).do()
            if len(logs) > 1:
                logistic.close(reason='close by auto spliter')

    order.reload()
    for logistic in order.logistics:
        if order.order_type == ORDER_TYPE.TRANSFER:
            logistic.detail.route = order.order_type
        logistic.save()

    return order
Beispiel #8
0
    def back_status(self):
        lid = request.args.get('lid')
        status = request.args.get('status')

        logistic = Logistic.objects(id=lid).first()
        logistic.detail.status = status
        setattr(logistic.detail, LogisticDetail.attr_by_log_status[status],
                datetime.datetime.utcnow())
        logistic.save()
        order = logistic.order
        order.update_logistic_status()
        return jsonify(message='OK')
Beispiel #9
0
    def create(self):
        try:
            log = Logistic(detail=self.log.detail)
        except:
            log = Logistic(detail=LogisticDetail())

        log.order = self.order
        log.entries = list(self.entries)
        self.order.logistics.append(log)
        if not self.debug:
            log.detail.partner = Partner.objects().first()
            log.detail.partner_tracking_no = generate_uid()
            log.save()
            self.order.save()
        return log
Beispiel #10
0
def get_logistic(logistic_id):
    """

    :param logistic_id:
    :return:
    """
    logistic = Logistic.objects(id=logistic_id).first_or_404()
    express = logistic.express_tracking
    logistic_obj = {'id': str(logistic.id)}
    logistic_obj['entries'] = [
        json_templ.entry_json(entry) for entry in logistic.entries
    ]
    logistic_obj['status'] = logistic.detail.status
    logistic_obj['data'] = logistic.to_json()
    logistic_obj['history'] = logistic.shipping_history
    logistic_obj['tracking'] = express.history if express else ''
    logistic_obj['address'] = logistic.order.address.to_json()
    logistic_obj['payment_status'] = logistic.order.goods_payment.status
    return jsonify(message='OK', logistic=logistic_obj)
Beispiel #11
0
def update_logistic_received_status(state, com, num, data):
    """
    更新物流状态
    :param state:
    :param com:
    :param num:
    :param data:
    :return:
    """
    latest_time = datetime.strptime(data[0]['time'], '%Y-%m-%d %H:%M:%S')
    first_time = datetime.strptime(data[-1]['time'], '%Y-%m-%d %H:%M:%S')
    check = (state == '3')

    for logistic in Logistic.objects(detail__cn_tracking_no=num):
        if not check and logistic.status != LOG_STATUS.SHIPPING:
            logistic.update_logistic({
                'status':
                LOG_STATUS.SHIPPING,
                'shipping_date':
                to_utc(first_time).replace(tzinfo=None),
                'modified_by':
                'kuaidi100'
            })
        elif not check and 'ISC' in data[0][
                'ISC'] and logistic.detail.status != LOG_STATUS.PORT_ARRIVED:
            logistic.update_logistic({
                'status':
                LOG_STATUS.PORT_ARRIVED,
                'received_date':
                to_utc(latest_time).replace(tzinfo=None),
                'modified_by':
                'kuaidi100',
            })
        elif check and logistic.detail.status != LOG_STATUS.RECEIVED:
            logistic.update_logistic({
                'status':
                LOG_STATUS.RECEIVED,
                'received_date':
                to_utc(latest_time).replace(tzinfo=None),
                'modified_by':
                'kuaidi100',
            })
Beispiel #12
0
    def merge(self):
        """

        :return:
        """
        lids = request.json.get('lids')
        if not lids:
            return jsonify(message='Failed', desc='error')

        logistic = [Logistic.objects(id=lid).first() for lid in lids]
        if not type(logistic) is list:
            return jsonify(message='Failed',
                           desc='please select more than 2 logistics')

        start = 0
        for index in range(len(logistic) - 1):
            if logistic[index + 1].detail.cn_tracking_no != logistic[
                    start].detail.cn_tracking_no or logistic[
                        index + 1].order != logistic[0].order:
                return jsonify(message='Failed',
                               desc='CTN and OrderID should be the same')

        for index in range(len(logistic) - 1):
            map(lambda e: logistic[index + 1].entries.append(e),
                logistic[index].entries)
            logistic[index].entries = []
            logistic[index].save()
            logistic[index].close('merged with %s' % logistic[index + 1].id,
                                  datetime.datetime.utcnow())
            logistic[index].save()

            if index + 1 == len(logistic) - 1:
                comment = LogisticRemark(content='合并单',
                                         creator=current_user.name)
                logistic[index + 1].detail.remarks.append(comment)
                logistic[index + 1].save()

        return jsonify(message='OK', lid=str(logistic[index + 1].id))
Beispiel #13
0
    def split_quantity(self):
        """

        :return:
        """
        lid = request.json.get('lid')
        eid = request.json.get('eid')
        quantity = request.json.get('quantity')

        logistic = Logistic.objects(id=lid).first()
        entry = OrderEntry.objects(id=eid).first()

        if entry.quantity > 1 and entry.quantity - int(
                quantity) >= 1 and entry and logistic:
            entry.quantity -= int(quantity)
            entry.update_snapshot()
            entry.update_amount()

            new_entry = deepcopy(entry)
            new_entry.__class__ = OrderEntry
            new_entry.id = None
            new_entry.quantity = int(quantity)
            new_entry.update_snapshot()
            new_entry.update_amount()
            new_entry.save()
            logistic.entries.append(new_entry)
            logistic.save()
            order = logistic.order
            order.entries.append(new_entry)
            order.save()
        else:
            return jsonify(message='Failed', desc='quantity error')
        return jsonify(message='OK',
                       entries=[
                           json.loads(json_util.dumps(entry_to_json(entry)))
                           for entry in logistic.entries
                       ])
Beispiel #14
0
def check_kuaidi():
    logistics = Logistic.objects(is_closed=False, detail__cn_tracking_no__ne='', detail__cn_logistic_name__ne='',
                                 detail__status__in=['SHIPPING', 'PORT_ARRIVED'])
    for logistic in logistics:
        jobs.express.kuai_request(logistic.detail.cn_logistic_name, logistic.detail.cn_logistic_no)
Beispiel #15
0
    def download(self):
        """

        :return:
        """
        FIELDS = [
            '包裹ID', 'IMG NO', 'CTN', '下单日期', '订单ID', '订单短号', '收件人', '手机号',
            '合作物流商', 'remark', '下单备注', '估重', '渠道'
        ]

        now = datetime.datetime.now()

        status = request.args.get('status')
        query = restruct_query(request.args)
        delay_export = query.get('delay_export') and query.pop('delay_export')
        delay_type = query.get('delay_type') and query.pop('delay_type')

        try:
            logistics = Logistic.objects(is_closed=False, **query)
            if status:
                logistics = logistics.order_by(
                    'detail__%s' % LogisticDetail.attr_by_log_status[status])
        except:
            pass

        if delay_export:
            date_field = LogisticDetail.attr_by_log_status[status]
            delay_days = datetime.timedelta(days=delay_status_by_date[status])
            query = {
                'detail__%s__lt' % date_field:
                datetime.datetime.utcnow() - delay_days,
                'detail__status': status,
            }
            logistics = logistics.filter(**query).order_by('detail__%s' %
                                                           date_field)
            if delay_type:
                logistics = logistics.filter(
                    detail__delay_details__reason__contains=delay_type)

        if query.get('receiver'):
            addresses = Address.objects(
                receiver=query.get('receiver')).distince('id')
            orders = Order.commodities(address__in=addresses)
            logistics = list(
                chain.from_iterable(order.logistics for order in orders))

        if query.get('order_id'):
            orders = Order.commodities(short_id=int(query.get('order_id')))
            logistics = list(
                chain.from_iterable(order.logistics for order in orders))

        def generate():
            yield ','.join(st for st in FIELDS) + '\n'
            for logistic in logistics:
                yield ','.join([
                    str(logistic.id),
                    logistic.detail.partner_tracking_no,
                    logistic.detail.carrier_tracking_no,
                    logistic.detail.cn_tracking_no,
                    logistic.detail.cn_logistic_name,
                    format_date(logistic.detail_payment_received_date),
                    str(logistic.order.id),
                    str(logistic.order.short_id),
                    logistic.order.address.receiver,
                    logistic.order.address.mobile_number,
                    format_date(logistic.detail.processing_date),
                    format_date(logistic.detail.shipping_date),
                    format_date(logistic.detail.port_arrived_date),
                    format_date(logistic.detail.received_date),
                    format_date(logistic.detail.modified),
                    logistic.detail.partner.name
                    if logistic.detail.partner else '',
                    ';'.join([r.content for r in logistic.detail.remarks]),
                    logistic.detail.extra or '',
                    str(logistic.estimated_weight),
                    logistic.detail.channel,
                ]) + '\n'

        return Response(generate(),
                        minetype='text/csv',
                        headers={
                            'Content_Disposition':
                            'attachment;filename=%s %s.csv' %
                            (format_date(now, '%Y-%m-%d'), 'dumps_file')
                        })