From ddc434d63e764c3ffc69428b045efeaf1fef5cc7 Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sun, 3 Aug 2025 13:56:59 +0330 Subject: [PATCH] create my_products_stat_excel --- .idea/Rasaddam_Backend.iml | 2 +- .idea/misc.xml | 2 +- .../services/excel/excel_processing.py | 156 +++++++++++++++++- common/helper_excel.py | 13 +- 4 files changed, 163 insertions(+), 10 deletions(-) diff --git a/.idea/Rasaddam_Backend.iml b/.idea/Rasaddam_Backend.iml index 168bde0..c5d6090 100644 --- a/.idea/Rasaddam_Backend.iml +++ b/.idea/Rasaddam_Backend.iml @@ -14,7 +14,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 296aa57..29f5506 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index 4c71d14..16a171d 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -10,7 +10,7 @@ from rest_framework.decorators import action from apps.core.mixins.search_mixin import ExcelDynamicSearchMixin from apps.product import models as product_models from apps.product.web.api.v1.serializers import quota_distribution_serializers as distribution_serializers -from apps.product.web.api.v1.serializers.product_serializers import IncentivePlanSerializer +from apps.product.web.api.v1.serializers.product_serializers import IncentivePlanSerializer, ProductStatsSerializer from apps.product.web.api.v1.serializers.quota_serializers import QuotaSerializer from common.helper_excel import create_header, excel_description, create_header_freez, create_value, shamsi_date, \ convert_str_to_date @@ -688,3 +688,157 @@ class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): 'utf-8') response.write(output.getvalue()) return response + + # noqa # گزارش گیری + @action( + methods=['get'], + detail=False, + url_path='my_products_stat_excel', + url_name='my_products_stat_excel', + name='my_products_stat_excel' + ) + def my_products_stat_excel(self, request): + search_fields_quota = [ + "registerer_organization__name", + "quota_id", + "product__name", + "sale_type", + "sale_unit__unit", + "group", + ] + + queryset = product_models.Quota.objects.all() + serializer_class = QuotaSerializer + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + queryset = product_models.ProductStats.objects.all() + organization = get_organization_by_user(request.user) + product_stats = queryset.filter(organization=organization).order_by('-modify_date') + ser_data = ProductStatsSerializer(product_stats, many=True).data + + excel_options = [ + "ردیف", + "محصول", + "تعداد طرح ها", + "طرح های فعال (کیلوگرم)", + "طرح های بایگانی شده (کیلوگرم)", + "وزن کل طرح ها (کیلوگرم)", + "باقیمانده وزن طرح ها (کیلوگرم)", + "باقیمانده وزن توزیع ها (کیلوگرم)", + "توزیع دریافتی (کیلوگرم)", + "توزیع ارسال شده (کیلوگرم)", + "حجم توزیع دریافتی (کیلوگرم)", + "حجم توزیع ارسالی", + "کل وزن ورودی به انبار (کیلوگرم)", + "وزن فروش رفته (کیلوگرم)" + ] + + header_list = [ + "تعداد طرح ها", + "طرح های فعال", + "طرح های بایگانی شده", + "وزن کل طرح ها", + "باقیمانده وزن طرح ها", + "باقیمانده وزن توزیع ها", + "توزیع دریافتی", + "توزیع ارسال شده", + "حجم توزیع دریافتی", + "حجم توزیع ارسالی", + "کل وزن ورودی به انبار", + "وزن فروش رفته" + + ] + + create_header(worksheet, header_list, 3, 2, height=28, border_style='thin') + excel_description(worksheet, 'A1', + 'گزارش گیری', row2='B2', + size=11) + create_header_freez(worksheet, excel_options, 1, 6, 7, height=28, width=20) + + l = 7 + m = 1 + if ser_data: + for data in ser_data: + list1 = [ + m, + (data.get('product') or {}).get('name') or '-', + data.get('quotas_number') or 0, + data.get('active_quotas_weight') or 0, + data.get('closed_quotas_weight') or 0, + data.get('total_quota_weight') or 0, + data.get('total_quota_remaining') or 0, + data.get('total_remaining_distribution_weight') or 0, + data.get('received_distribution_weight') or 0, + data.get('given_distribution_weight') or 0, + data.get('received_distribution_number') or 0, + data.get('given_distribution_number') or 0, + data.get('total_warehouse_entry') or 0, + data.get('total_sold') or 0, + ] + create_value(worksheet, list1, l, 1, height=25, m=m) + l += 1 + m += 1 + + quotas_number = sum((data.get('quotas_number') or 0 for data in ser_data)) + active_quotas_weight = sum((data.get('active_quotas_weight') or 0 for data in ser_data)) + closed_quotas_weight = sum((data.get('closed_quotas_weight') or 0 for data in ser_data)) + total_quota_weight = sum((data.get('total_quota_weight') or 0 for data in ser_data)) + total_quota_remaining = sum((data.get('total_quota_remaining') or 0 for data in ser_data)) + total_remaining_distribution_weight = sum( + (data.get('total_remaining_distribution_weight') or 0 for data in ser_data)) + received_distribution_weight = sum((data.get('received_distribution_weight') or 0 for data in ser_data)) + given_distribution_weight = sum((data.get('given_distribution_weight') or 0 for data in ser_data)) + received_distribution_number = sum((data.get('received_distribution_number') or 0 for data in ser_data)) + given_distribution_number = sum((data.get('given_distribution_number') or 0 for data in ser_data)) + total_warehouse_entry = sum((data.get('total_warehouse_entry') or 0 for data in ser_data)) + total_sold = sum((data.get('total_sold') or 0 for data in ser_data)) + + value_list = [ + quotas_number, + active_quotas_weight, + closed_quotas_weight, + total_quota_weight, + total_quota_remaining, + total_remaining_distribution_weight, + received_distribution_weight, + given_distribution_weight, + received_distribution_number, + given_distribution_number, + total_warehouse_entry, + total_sold + ] + create_value(worksheet, value_list, 3, 3, border_style='thin') + + list2 = [ + 'مجموع==>', + '', + quotas_number, + active_quotas_weight, + closed_quotas_weight, + total_quota_weight, + total_quota_remaining, + total_remaining_distribution_weight, + received_distribution_weight, + given_distribution_weight, + received_distribution_number, + given_distribution_number, + total_warehouse_entry, + total_sold + + + ] + create_value(worksheet, list2, l + 2, 1, color='gray') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="fگزارش گیری.xlsx"'.encode( # noqa + 'utf-8') + response.write(output.getvalue()) + return response diff --git a/common/helper_excel.py b/common/helper_excel.py index e5da0a9..8556969 100644 --- a/common/helper_excel.py +++ b/common/helper_excel.py @@ -139,6 +139,11 @@ def create_value(worksheet, list, l, num, border_style=None, m=None, height=None for item in range(len(list)): cell = worksheet.cell(row=l, column=item + num, value=list[item]) cell.alignment = Alignment_CELL + if height is not None: + worksheet.row_dimensions[l].height = height + + if width is not None: + worksheet.column_dimensions[openpyxl.utils.get_column_letter(item + num)].width = width if border_style: cell.border = openpyxl.styles.Border( @@ -162,9 +167,6 @@ def create_value(worksheet, list, l, num, border_style=None, m=None, height=None else: cell.fill = PatternFill(start_color="FAF0E7", fill_type="solid") - if height is not None: - worksheet.row_dimensions[l + 1].height = height - if item_num is not None and item == item_num: if item_color: cell.fill = item_color @@ -174,9 +176,6 @@ def create_value(worksheet, list, l, num, border_style=None, m=None, height=None if different_cell is not None and list[different_cell] == different_value: cell.fill = RED_CELL - if width is not None: - worksheet.column_dimensions[openpyxl.utils.get_column_letter(item + num)].width = width - def merge_cells(worksheet, l, s, cell1=None, cell2=None, lst=None): if lst is not None: @@ -311,4 +310,4 @@ def convert_str_to_date(string): try: return datetime.strptime(string, '%Y-%m-%d').date() except ValueError: - return None \ No newline at end of file + return None