[ python分组groups使用 ]


PYTHON中分组groups

from itertools import groupby
def get_cm_months_report(start_date, end_date):
    """上一次Check out时间和最近一次Check in时间,并且相减。取所有小于等于365天的单据。
    """
    csv_header = [
        "Serial Number",
        "Stock Code",
        "Group",
        "Last Check Out Date",
        "Check In Date",
    ]
    csv_fields = [
        "serial_number",
        "stock_code",
        "group",
        "last_check_out",
        "check_in_date",
    ]


    status_list = [RepairOrder.STATUS.CHECKED_IN, RepairOrder.STATUS.IN_PROCESS, RepairOrder.STATUS.WAITING_FOR_ENDORSEMENT, RepairOrder.STATUS.WAITING_FOR_SIC, RepairOrder.STATUS.WAITING_FOR_JOB_COMPLETED, RepairOrder.STATUS.COMPLETE, RepairOrder.STATUS.FORCE_COMPLETE]
    cm_repair_order_id_list = RepairOrder.objects.filter(mtce_type=RepairOrder.MTCE_TYPE.CM,status__in=status_list, deleted=False).values_list("id", flat=True)

    repair_order_part_query = RepairOrderPart.objects.filter(repair_order_id__in=cm_repair_order_id_list).order_by("stock_code", "serial_no", "-last_check_in")

    new_repair_order_part_list: list[CmMonthsDict] = [] 

    # 根据 (stock_code, serial_no) 分组
    repair_order_parts_grouped = groupby(repair_order_part_query, key= lambda x: (x.stock_code, x.serial_no))

    # 迭代处理每个分组
    new_repair_order_part_list = []
    for (stock_code, serial_no),group in repair_order_parts_grouped:
        group = list(group)  # 转换成列表以便处理
        if len(group) >= 2:
            last_check_in = group[0].last_check_in
            last_check_out = group[1].last_check_out
            if last_check_out and last_check_in and group[0].last_check_out == None:
                days_diff = abs((last_check_in - last_check_out).days)
                if days_diff <= 365:
                    new_repair_order_part_list.append({
                        "serial_number": serial_no,
                        "stock_code": stock_code,
                        "group": group[0].repair_order.workgroup,
                        "last_check_out": last_check_out,
                        "check_in_date": last_check_in,
                    })

    # 过滤check_in日期
    if start_date:
        start_date = timezone.make_aware(datetime.strptime(start_date, "%Y/%m/%d"), timezone.get_current_timezone()) 
        new_repair_order_part_list = [part for part in new_repair_order_part_list if part["check_in_date"] > start_date]

    if end_date:
        end_date = timezone.make_aware(datetime.strptime(end_date, "%Y/%m/%d"), timezone.get_current_timezone()) + timedelta(days=1)
        new_repair_order_part_list = [part for part in new_repair_order_part_list if part["check_in_date"] < end_date]

    for index, data in enumerate(new_repair_order_part_list):
        new_repair_order_part_list[index]["check_in_date"] = timezone.localtime(data["check_in_date"]).strftime("%Y/%m/%d %H:%M:%S")
        new_repair_order_part_list[index]["last_check_out"] = timezone.localtime(data["last_check_out"]).strftime("%Y/%m/%d %H:%M:%S")

    # 写入csv
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="CM Months Report.csv"'
    writer = csv.writer(response)
    writer.writerow(csv_header) 

    for obj in new_repair_order_part_list:
        row = (str(obj[field]) for field in csv_fields)
        writer.writerow(row)
    return r