diff --git a/.idea/Rasaddam_Backend.iml b/.idea/Rasaddam_Backend.iml
index 997031e..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 61a9313..29f5506 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/apps/log/middlewares.py b/apps/log/middlewares.py
index cddd35c..85a9efb 100644
--- a/apps/log/middlewares.py
+++ b/apps/log/middlewares.py
@@ -38,7 +38,7 @@ class SaveLog:
'method': request.method,
'remote_address': self.get_client_ip(request),
'exec_time': _t,
- 'body_response': response.content.decode('utf-8'),
+ # 'body_response': response.content.decode('utf-8'),
'body_request': request.POST,
'client_ip': self.get_client_ip(request),
'browser_info': request.META['HTTP_USER_AGENT'],
diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py
new file mode 100644
index 0000000..e69de29
diff --git a/apps/warehouse/services/excel/__init__.py b/apps/warehouse/services/excel/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/apps/warehouse/services/excel/excel_processing.py b/apps/warehouse/services/excel/excel_processing.py
new file mode 100644
index 0000000..ab1bb15
--- /dev/null
+++ b/apps/warehouse/services/excel/excel_processing.py
@@ -0,0 +1,85 @@
+from io import BytesIO
+
+from django.http import HttpResponse
+from django.views.decorators.csrf import csrf_exempt
+from openpyxl import Workbook
+from openpyxl.styles import Alignment
+from rest_framework import viewsets
+from rest_framework.decorators import action, api_view, permission_classes
+from rest_framework.permissions import AllowAny , IsAuthenticated
+
+from apps.warehouse import models as warehouse_models
+from apps.warehouse.web.api.v1 import serializers as warehouse_serializers
+from common.helper_excel import create_header, excel_description, create_header_freez, create_value
+
+
+@api_view(["GET"])
+@permission_classes([IsAuthenticated])
+@csrf_exempt
+def warehouse_excel(request):
+
+ excel_options = [
+ 'ردیف',
+ 'وضعیت',
+ 'ثبت کننده',
+ 'تاریخ ثبت',
+ 'مرغدار',
+ 'کشتارگاه',
+ 'حجم',
+ 'حجم کم شده از سالن مرغدار',
+ 'وزن تقریبی کشتار(کیلوگرم)',
+ 'حجم سفارشات دریافتی توسط کشتارگاه',
+ 'اختلاف کشتار(حجم)',
+
+ ]
+
+
+ output = BytesIO()
+ workbook = Workbook()
+ worksheet = workbook.active
+ worksheet.sheet_view.rightToLeft = True
+ worksheet.insert_rows(1)
+ cell = worksheet.cell(row=1, column=1)
+ cell.alignment = Alignment(horizontal='center', vertical='center')
+
+ header_list = [
+ 'حجم',
+ 'حجم کم شده از سالن مرغدار',
+ 'وزن تقریبی کشتار(کیلوگرم)',
+ 'حجم سفارشات دریافتی توسط کشتارگاه',
+ 'اختلاف کشتار(حجم)',
+
+ ]
+
+ create_header(worksheet, header_list, 5, 2, height=20)
+
+ excel_description(worksheet, 'B1', f'اختلاف کشتار ', color='red', row2='C3')
+
+ create_header_freez(worksheet, excel_options, 1, 6, 7, height=22)
+
+ l = 5
+ m = 1
+
+
+
+ list2 = [
+ 'مجموع==>',
+ '',
+ '',
+ '',
+ '',
+ '',
+
+
+ ]
+ create_value(worksheet, list2, l + 3, 1, color='green')
+ workbook.save(output)
+ output.seek(0)
+
+ response = HttpResponse(
+ content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+ response[
+ 'Content-Disposition'] = f'attachment; filename="اختلاف کشتار.xlsx"'.encode(
+ 'utf-8')
+ response.write(output.getvalue())
+ return response
diff --git a/apps/warehouse/services/excel/urls.py b/apps/warehouse/services/excel/urls.py
new file mode 100644
index 0000000..a46e8bd
--- /dev/null
+++ b/apps/warehouse/services/excel/urls.py
@@ -0,0 +1,11 @@
+from django.urls import path, include
+from rest_framework.routers import DefaultRouter
+from apps.warehouse.services.excel import excel_processing as excel
+from apps.warehouse.services.excel.excel_processing import warehouse_excel
+
+router = DefaultRouter()
+
+urlpatterns = [
+ path('', include(router.urls)),
+ path('warehouse_excel/', warehouse_excel),
+]
diff --git a/apps/warehouse/urls.py b/apps/warehouse/urls.py
index 1f09e14..b3c94c9 100644
--- a/apps/warehouse/urls.py
+++ b/apps/warehouse/urls.py
@@ -3,5 +3,7 @@ from django.urls import path, include
urlpatterns = [
- path('web/api/', include('apps.warehouse.web.api.v1.urls'))
+ path('web/api/', include('apps.warehouse.web.api.v1.urls')),
+ path('excel/', include('apps.warehouse.services.excel.urls')),
+
]
diff --git a/common/helper_excel.py b/common/helper_excel.py
new file mode 100644
index 0000000..e7d4e4a
--- /dev/null
+++ b/common/helper_excel.py
@@ -0,0 +1,294 @@
+from datetime import datetime
+from io import BytesIO
+
+import jdatetime
+import openpyxl
+from django.http import HttpResponse
+from openpyxl import Workbook
+from openpyxl.chart import LineChart, Reference, BarChart
+from openpyxl.styles import PatternFill, Alignment, Font
+from openpyxl.utils import get_column_letter
+
+blue_fill = PatternFill(start_color="277358", fill_type="solid")
+Alignment_CELL = Alignment(horizontal='center', vertical='center', wrap_text=True)
+red_font = Font(color="C00000", bold=True)
+GREEN_CELL = PatternFill(start_color="00B050", fill_type="solid")
+RED_CELL = PatternFill(start_color="FCDFDC", fill_type="solid")
+YELLOW_CELL = PatternFill(start_color="FFFF00", fill_type="solid")
+ORANGE_CELL = PatternFill(start_color="FFC000", fill_type="solid")
+BLUE_CELL = PatternFill(start_color="538DD5", fill_type="solid")
+LIGHT_GREEN_CELL = PatternFill(start_color="92D050", fill_type="solid")
+VERY_LIGHT_GREEN_CELL = PatternFill(start_color="5AFC56", fill_type="solid")
+
+
+def shamsi_date(date, in_value=None):
+ if in_value:
+ sh_date = jdatetime.date.fromgregorian(
+ year=date.year,
+ month=date.month,
+ day=date.day
+ )
+ else:
+ gh_date = jdatetime.date.fromgregorian(
+ year=date.year,
+ month=date.month,
+ day=date.day
+ ).strftime('%Y-%m-%d')
+ reversed_date = reversed(gh_date.split("-"))
+ separate = "-"
+ sh_date = separate.join(reversed_date)
+ return sh_date
+
+
+def create_header(worksheet, list, num, row, height=None, width=None, color=None, text_color=None, border_style=None):
+ for col_num, option in enumerate(list, num):
+ cell = worksheet.cell(row=row, column=col_num, value=option)
+ col_letter = get_column_letter(col_num)
+ cell.alignment = Alignment_CELL
+ if color is not None:
+ if color == 'green':
+ cell.fill = GREEN_CELL
+ elif color == 'orange':
+ cell.fill = ORANGE_CELL
+ elif color == 'blue':
+ cell.fill = BLUE_CELL
+ else:
+ cell.fill = PatternFill(start_color=color, fill_type="solid")
+ else:
+ cell.fill = blue_fill
+ if text_color is not None:
+ cell.font = Font(size=9, bold=True, color=text_color)
+ else:
+ cell.font = Font(size=9, bold=True, color='D9FFFFFF')
+ if height is not None:
+ worksheet.row_dimensions[row].height = height
+ if width is not None:
+ worksheet.column_dimensions[col_letter].width = width
+ if border_style is not None:
+ cell.border = openpyxl.styles.Border(
+ left=openpyxl.styles.Side(style=border_style),
+ right=openpyxl.styles.Side(style=border_style),
+ top=openpyxl.styles.Side(style=border_style),
+ bottom=openpyxl.styles.Side(style=border_style)
+ )
+
+
+def create_header_freez(worksheet, list, num, row, header_row, height=None, width=None, len_with=None,
+ different_cell=None):
+ for col_num, option in enumerate(list, num):
+ col_letter = get_column_letter(col_num)
+ cell = worksheet.cell(row=row, column=col_num, value=option)
+ cell.alignment = Alignment_CELL
+ cell.fill = blue_fill
+ cell.font = Font(size=10, bold=True, color='D9FFFFFF')
+
+ if height is not None:
+ worksheet.row_dimensions[row].height = height
+ if len(option) > worksheet.column_dimensions[col_letter].width:
+ worksheet.column_dimensions[col_letter].width = len(option) + 2
+ if width is not None:
+ worksheet.column_dimensions[col_letter].width = width
+ if len_with is not None:
+ if len(option) > worksheet.column_dimensions[col_letter].width:
+ worksheet.column_dimensions[col_letter].width = len(option) + 3
+ if different_cell is not None:
+ if option == different_cell:
+ cell.fill = PatternFill(start_color="C00000", fill_type="solid")
+ worksheet.freeze_panes = worksheet[f'A{header_row}']
+ max_col = worksheet.max_column
+ range_str = f'A{header_row - 1}:{get_column_letter(max_col)}{worksheet.max_row}'
+ worksheet.auto_filter.ref = range_str
+
+
+def excel_description(worksheet, row1, description, size=None, color=None, my_color=None, row2=None):
+ worksheet[row1] = description
+ worksheet[row1].alignment = Alignment_CELL
+ if size is not None:
+ worksheet[row1].font = Font(size=size)
+ if color is not None:
+ worksheet[row1].font = red_font
+ if my_color is not None:
+ worksheet[row1].font = PatternFill(start_color=my_color, fill_type="solid")
+
+ if row2 is not None:
+ merge_range = f'{row1}:{row2}'
+ worksheet.merge_cells(merge_range)
+
+
+def create_value(worksheet, list, l, num, border_style=None, m=None, height=None, color=None, width=None,
+ different_cell=None, different_value=None, item_num=None, item_color=None):
+ color_dict = {
+ 'green': GREEN_CELL,
+ 'yellow': YELLOW_CELL,
+ 'blue': BLUE_CELL,
+ 'red': RED_CELL,
+ 'light_green': LIGHT_GREEN_CELL,
+ 'very_light_green': VERY_LIGHT_GREEN_CELL
+ }
+
+ for item in range(len(list)):
+ cell = worksheet.cell(row=l, column=item + num, value=list[item])
+ cell.alignment = Alignment_CELL
+
+ if border_style:
+ cell.border = openpyxl.styles.Border(
+ left=openpyxl.styles.Side(style=border_style),
+ right=openpyxl.styles.Side(style=border_style),
+ top=openpyxl.styles.Side(style=border_style),
+ bottom=openpyxl.styles.Side(style=border_style)
+ )
+
+ value = list[item]
+ if isinstance(value, (int, float)) and value != 0:
+ cell.number_format = '#,###'
+ else:
+ cell.value = value
+
+ cell.font = Font(size=10, bold=True)
+
+ if m is not None and m % 2 != 0:
+ cell.fill = PatternFill(start_color="D6F6FE", 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
+ elif color in color_dict:
+ cell.fill = color_dict[color]
+
+ 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:
+ for col in lst:
+ rng = f'{col}{l}:{col}{l + s}'
+ worksheet.merge_cells(rng)
+ worksheet[col + f'{l}'].alignment = Alignment_CELL
+ else:
+ for col in range(ord(f'{cell1}'), ord(f'{cell2}') + 1):
+ rng = f'{chr(col)}{l}:{chr(col)}{l + s}'
+ worksheet.merge_cells(rng)
+ worksheet[chr(col) + f'{l}'].alignment = Alignment_CELL
+
+
+def add_header(worksheet):
+ worksheet.oddHeader.center.text = "سامانه رصدیار"
+ worksheet.oddHeader.center.size = 14 # تنظیم اندازه فونت
+ worksheet.oddHeader.center.font = "Arial,Bold" # تنظیم فونت و ضخامت
+
+ # همچنین میتوانید از هدرهای چپ و راست هم استفاده کنید
+ # worksheet.oddHeader.right.text = f"تاریخ: {shamsi_now_date}"
+
+
+def cell_color_changer(worksheet, row, start_index, end_index, custom_color):
+ for item in range(start_index, end_index):
+ cell = worksheet.cell(row=row, column=item)
+ cell.fill = PatternFill(start_color=custom_color, fill_type="solid")
+
+
+def start_excel():
+ output = BytesIO()
+ workbook = Workbook()
+ worksheet = workbook.active
+ worksheet.sheet_view.rightToLeft = True
+ worksheet.insert_rows(1)
+ return workbook, worksheet, output
+
+
+def close_excel(name):
+ workbook, worksheet, output = start_excel()
+ workbook.save(output)
+ output.seek(0)
+
+ response = HttpResponse(
+ content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+ response[
+ 'Content-Disposition'] = f'attachment; filename="{name}.xlsx"'.encode(
+ 'utf-8')
+ response.write(output.getvalue())
+ return response
+
+
+def add_chart(
+ worksheet,
+ chart_type,
+ data_columns,
+ category_column,
+ start_row,
+ end_row,
+ chart_position,
+ chart_title,
+ x_axis_title,
+ y_axis_title,
+ chart_width=25, # عرض نمودار پیشفرض (واحد: cm)
+ chart_height=15
+):
+ """
+ افزودن نمودار به صفحه اکسل.
+
+ ورودی:
+ worksheet (openpyxl.Worksheet): صفحه اکسل.
+ chart_type (str): نوع نمودار ("line" یا "bar").
+ data_columns (list): لیستی از ستونهای داده.
+ category_column (int): ستون دستهبندیها.
+ start_row (int): ردیف شروع دادهها.
+ end_row (int): ردیف پایان دادهها.
+ chart_position (str): محل قرار گرفتن نمودار.
+ chart_title (str): عنوان نمودار.
+ x_axis_title (str): عنوان محور X.
+ y_axis_title (str): عنوان محور Y.
+ chart_width (float): عرض نمودار (واحد: cm).
+ chart_height (float): ارتفاع نمودار (واحد: cm).
+ """
+
+ if chart_type == 'line':
+ chart = LineChart()
+ chart.style = 20
+ elif chart_type == 'bar':
+ chart = BarChart()
+ else:
+ raise ValueError("chart_type باید 'line' یا 'bar' باشد.")
+
+ chart.title = chart_title
+ chart.y_axis.title = y_axis_title
+ chart.x_axis.title = x_axis_title
+ chart.width = chart_width
+ chart.height = chart_height
+
+ categories = Reference(worksheet, min_col=category_column, min_row=start_row, max_row=end_row)
+ data = Reference(worksheet, min_col=data_columns, min_row=start_row - 1, max_row=end_row)
+ chart.add_data(data, titles_from_data=True)
+ chart.set_categories(categories)
+ for series in chart.series:
+ series.graphicalProperties.line.solidFill = "277358"
+ series.graphicalProperties.line.width = 30000
+
+ worksheet.add_chart(chart, chart_position)
+ # example
+ # add_chart(
+ # worksheet=worksheet,
+ # chart_type='line',
+ # data_columns=7, # ستون وزن وارد شده
+ # category_column=2, # ستون نام سردخانهها
+ # start_row=7,
+ # end_row=l + 1,
+ # chart_position="A12",
+ # chart_title="نمودار تغییرات وزن در سردخانهها",
+ # x_axis_title="سردخانهها",
+ # y_axis_title="وزن (کیلوگرم)"
+ # )
+
+
+def to_locale_str(a):
+ return "{:,}".format(int(a))
+
+
+def convert_str_to_date(string):
+ return datetime.strptime(str(string), '%Y-%m-%d').date()