Files
moadiran/Back/Services/servReport.cs

269 lines
67 KiB
C#
Raw Normal View History

2025-01-09 16:01:37 +03:30

using Shared;
using Shared.DTOs;
using SixLabors.ImageSharp.Formats;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
namespace Back.Services
{
public class servReport
{
string[] ones = { "", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", "نه" };
string[] tens = { "", "ده", "بیست", "سی", "چهل", "پنجاه", "شصت", "هفتاد", "هشتاد", "نود" };
string[] teens = { "ده", "یازده", "دوازده", "سیزده", "چهارده", "پانزده", "شانزده", "هفده", "هجده", "نوزده" };
string[] hundreds = { "", "صد", "دویست", "سیصد", "چهارصد", "پانصد", "ششصد", "هفتصد", "هشتصد", "نهصد" };
// تابع برای تبدیل اعداد به فارسی
static string ConvertToPersian(string number)
{
// دیکشنری برای تبدیل اعداد انگلیسی به فارسی
var persianDigits = new[] { '۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹' };
// تبدیل هر رقم انگلیسی به فارسی
char[] numberArray = number.ToCharArray();
for (int i = 0; i < numberArray.Length; i++)
{
if (Char.IsDigit(numberArray[i]))
{
int digit = numberArray[i] - '0'; // پیدا کردن معادل عددی
numberArray[i] = persianDigits[digit]; // تبدیل به معادل فارسی
}
}
return new string(numberArray);
}
// تابع برای جدا کردن سه‌رقمی
static string FormatWithCommas(decimal number)
{
return number.ToString("#,0", CultureInfo.InvariantCulture);
}
string ConvertToWords(decimal number)
{
if (number == 0)
return "صفر";
if (number < 0)
return "منفی " + ConvertToWords(-number);
string words = "";
long integerPart = (long)Math.Floor(number);
int fractionPart = (int)((number - integerPart) * 100);
if (integerPart / 1000000000 > 0)
{
words += ConvertToWords(integerPart / 1000000000) + " میلیارد ";
integerPart %= 1000000000;
}
if (integerPart / 1000000 > 0)
{
words += ConvertToWords(integerPart / 1000000) + " میلیون ";
integerPart %= 1000000;
}
if (integerPart / 1000 > 0)
{
words += ConvertToWords(integerPart / 1000) + " هزار ";
integerPart %= 1000;
}
if (integerPart / 100 > 0)
{
words += hundreds[integerPart / 100] + " ";
integerPart %= 100;
}
if (integerPart > 0)
{
if (words != "")
words += "و ";
if (integerPart < 10)
words += ones[integerPart];
else if (integerPart < 20)
words += teens[integerPart - 10];
else
{
words += tens[integerPart / 10];
if ((integerPart % 10) > 0)
words += " و " + ones[integerPart % 10];
}
}
if (fractionPart > 0)
{
if (words != "")
words += " و ";
words += ConvertToWords(fractionPart) + " صدم";
}
return words;
}
public async Task<string> CreateImage(InvoiceDTO invoice, string logoBase64="", string companyName="")
{
if (string.IsNullOrEmpty(logoBase64))
logoBase64 = "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
// مشخص کردن اندازه تصویر
int width = 900;
int height = 200 + (invoice.items.Count * 30) + 50; // افزایش ارتفاع برای فضای بیشتر در پایین صفحه
// ایجاد تصویر جدید
Bitmap bitmap = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bitmap);
// تنظیمات اولیه گرافیک
graphics.Clear(Color.White); // زمینه سفید
Font font = new Font("B Nazanin", 12); // استفاده از فونت فارسی
Font hfont = new Font("B Nazanin", 12, FontStyle.Bold); // for header
SolidBrush brush = new SolidBrush(Color.Black);
Pen pen = new Pen(Color.Black, 1); // قلم برای رسم خطوط جدول
// تنظیمات عنوان
string titleText = $"صورتحساب {invoice.invoiceType.GetEnumDisplayName()}";
Font titleFont = new Font("B Nazanin", 18, FontStyle.Bold); // فونت بزرگ‌تر و بولد
SizeF titleTextSize = graphics.MeasureString(titleText, titleFont);
int titleTextX = (width - (int)titleTextSize.Width) / 2; // وسط صفحه
int titleTextY = 20; // موقعیت عمودی (بالای صفحه)
graphics.DrawString(titleText, titleFont, Brushes.DarkBlue, titleTextX, titleTextY);
// بارگذاری لوگو از رشته Base64
byte[] logoBytes = Convert.FromBase64String(logoBase64);
using (MemoryStream ms = new MemoryStream(logoBytes))
{
Image logo = Image.FromStream(ms);
int logoWidth = 50; // عرض لوگو
int logoHeight = 50; // ارتفاع لوگو
int logoX = 60; // موقعیت افقی لوگو (سمت چپ)
int logoY = 70; // موقعیت عمودی لوگو (بعد از عنوان)
// رسم لوگو در سمت چپ بالای صفحه
graphics.DrawImage(logo, logoX, logoY, logoWidth, logoHeight);
// نوشتن متن "شرکت فرزان" در سمت راست بالای صفحه
//string companyName = "شرکت فرزان سیستم مانا";
Font companyFont = new Font("B Nazanin", 14, FontStyle.Bold); // فونت برای نام شرکت
SizeF textSize = graphics.MeasureString(companyName, companyFont);
int textX = width - (int)textSize.Width - 20; // موقعیت افقی متن (سمت راست)
int textY = logoY; // موقعیت عمودی متن (همسطح با لوگو)
graphics.DrawString(companyName, companyFont, Brushes.DarkGreen, textX, textY);
// نوشتن متن تاریخ در سمت چپ
string dateText = "تاریخ: " + ConvertToPersian(invoice.InvoiceDate);
Font dateFont = new Font("B Nazanin", 12); // فونت برای تاریخ
SizeF dateTextSize = graphics.MeasureString(dateText, dateFont);
int dateTextX = 20; // موقعیت افقی تاریخ (سمت چپ)
int dateTextY = logoY + logoHeight + 10; // فاصله بیشتر از "شرکت فرزان"
graphics.DrawString(dateText, dateFont, Brushes.Black, dateTextX, dateTextY);
// نوشتن متن "خریدار: مهدی ربیع نژاد" در پایین سمت راست
string buyerText = $"خریدار: {invoice.CustomerName}";
Font buyerFont = new Font("B Nazanin", 12); // فونت برای نام خریدار
SizeF buyerTextSize = graphics.MeasureString(buyerText, buyerFont);
int buyerTextX = width - (int)buyerTextSize.Width - 20; // موقعیت افقی (سمت راست)
// کاهش فاصله از "شرکت فرزان" برای "خریدار"
int buyerTextY = dateTextY - 30; // فاصله کمتر از نام شرکت
graphics.DrawString(buyerText, buyerFont, Brushes.Black, buyerTextX, buyerTextY);
}
// تنظیم موقعیت شروع برای نوشتن جدول
int x = 10;
int y = 170; // کاهش فاصله با تغییر مقدار y (در اینجا 200 به جای 240)
int rowHeight = 30;
// تغییر عرض ستون‌ها برای تنظیم فاصله
int columnWidth1 = 240; // ستون شناسه کالا
int columnWidth2 = 50; // ستون واحد
int columnWidth3 = 70; // ستون تعداد
int columnWidth4 = 100; // ستون مبلغ واحد
int columnWidth5 = 50; // ستون نرخ مالیات
int columnWidth6 = 120; // ستون مبلغ مالیات
int columnWidth7 = 100; // ستون تخفیف
int columnWidth8 = 130; // ستون مبلغ کل
// رسم هدر جدول با رنگ پس‌زمینه و تغییر رنگ متن
graphics.FillRectangle(Brushes.LightSteelBlue, x, y, width - 15, rowHeight); // رنگ پس‌زمینه هدر
graphics.DrawString("کالا", hfont, Brushes.White, x + (columnWidth1 - graphics.MeasureString("کالا", font).Width) / 2, y + 5);
graphics.DrawString("واحد", hfont, Brushes.White, x + columnWidth1 + (columnWidth2 - graphics.MeasureString("واحد", font).Width) / 2, y + 5);
graphics.DrawString("تعداد", hfont, Brushes.White, x + columnWidth1 + columnWidth2 + (columnWidth3 - graphics.MeasureString("تعداد", font).Width) / 2, y + 5);
graphics.DrawString("مبلغ واحد", hfont, Brushes.White, x + columnWidth1 + columnWidth2 + columnWidth3 + (columnWidth4 - graphics.MeasureString("مبلغ واحد", font).Width) / 2, y + 5);
graphics.DrawString("نرخ مالیات", hfont, Brushes.White, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + (columnWidth5 - graphics.MeasureString("نرخ مالیات", font).Width) / 2, y + 5);
graphics.DrawString("مبلغ مالیات", hfont, Brushes.White, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + columnWidth5 + (columnWidth6 - graphics.MeasureString("مبلغ مالیات", font).Width) / 2, y + 5);
graphics.DrawString("تخفیف", hfont, Brushes.White, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + columnWidth5 + columnWidth6 + (columnWidth7 - graphics.MeasureString("تخفیف", font).Width) / 2, y + 5);
graphics.DrawString("مبلغ کل", hfont, Brushes.White, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + columnWidth5 + columnWidth6 + columnWidth7 + (columnWidth8 - graphics.MeasureString("مبلغ کل", font).Width) / 2, y + 5);
y += rowHeight;
// رسم خطوط افقی
graphics.DrawLine(pen, x, y, width - 10, y);
// نوشتن داده‌ها در جدول
foreach (var product in invoice.items)
{
graphics.DrawString(product.sstt, font, brush, x + (columnWidth1 - graphics.MeasureString(product.sstt, font).Width) / 2, y + 5);
graphics.DrawString(product.mu, font, brush, x + columnWidth1 + (columnWidth2 - graphics.MeasureString(product.am.ToString().Split('٫')[0], font).Width) / 2, y + 5);
graphics.DrawString(ConvertToPersian(product.am.ToString().Split('٫')[0]), font, brush, x + columnWidth1 + columnWidth2 + (columnWidth3 - graphics.MeasureString(ConvertToPersian(product.am.ToString().Split('٫')[0].ToString()), font).Width) / 2, y + 5);
graphics.DrawString(ConvertToPersian(FormatWithCommas(product.fee)), font, brush, x + columnWidth1 + columnWidth2 + columnWidth3 + (columnWidth4 - graphics.MeasureString(ConvertToPersian(FormatWithCommas(product.fee)), font).Width) / 2, y + 5);
graphics.DrawString(ConvertToPersian(FormatWithCommas(product.vra.GetValueOrDefault())), font, brush, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + (columnWidth5 - graphics.MeasureString(ConvertToPersian(FormatWithCommas(product.vra.GetValueOrDefault())), font).Width) / 2, y + 5);
graphics.DrawString(ConvertToPersian(FormatWithCommas(product.vam.GetValueOrDefault())), font, brush, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + columnWidth5 + (columnWidth6 - graphics.MeasureString(ConvertToPersian(FormatWithCommas(product.vam.GetValueOrDefault())), font).Width) / 2, y + 5);
graphics.DrawString(ConvertToPersian(FormatWithCommas(product.dis.GetValueOrDefault())), font, brush, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + columnWidth5 + columnWidth6 + (columnWidth7 - graphics.MeasureString(ConvertToPersian(FormatWithCommas(product.dis.GetValueOrDefault())), font).Width) / 2, y + 5);
graphics.DrawString(ConvertToPersian(FormatWithCommas(product.tsstam.GetValueOrDefault())), font, brush, x + columnWidth1 + columnWidth2 + columnWidth3 + columnWidth4 + columnWidth5 + columnWidth6 + columnWidth7 + (columnWidth8 - graphics.MeasureString(ConvertToPersian(FormatWithCommas(product.tsstam.GetValueOrDefault())), font).Width) / 2, y + 5);
y += rowHeight;
// رسم خطوط افقی برای هر ردیف
graphics.DrawLine(pen, x, y, width - 10, y);
}
//-----------
// نوشتن متن "مبلع نهایی" در سمت راست بالای صفحه
string totalfactor = $"مبلع نهایی: {ConvertToWords(invoice.tbill.GetValueOrDefault())} ريال";
Font totalFont = new Font("B Nazanin", 12, FontStyle.Bold); // فونت برای نام شرکت
SizeF totaltextSize = graphics.MeasureString(totalfactor, totalFont);
int totalX = width - (int)totaltextSize.Width - 20;
int totalY = y; // موقعیت عمودی متن (همسطح با لوگو)
graphics.DrawString(totalfactor, totalFont, Brushes.Black, totalX, totalY);
// اضافه کردن توضیحات پایین صفحه در وسط
string descriptionText = $"توضیحات: {(string.IsNullOrEmpty(invoice.Des) ? "سامانه مودیران" :invoice.Des)}";
Font descriptionFont = new Font("B Nazanin", 12);
SizeF descriptionTextSize = graphics.MeasureString(descriptionText, descriptionFont);
int descriptionX = (width - (int)descriptionTextSize.Width) / 2;
int descriptionY = y + 20; // فاصله از جدول
graphics.DrawString(descriptionText, descriptionFont, Brushes.DarkRed, descriptionX, descriptionY);
string ret = "";
using (MemoryStream ms = new MemoryStream())
{
// Save the Bitmap to the memory stream
bitmap.Save(ms, ImageFormat.Png);
// Convert the memory stream to a byte array
byte[] imageBytes = ms.ToArray();
// Convert the byte array to a Base64 string
ret= Convert.ToBase64String(imageBytes);
}
// ذخیره تصویر به فرمت PNG
// bitmap.Save(filePath, ImageFormat.Png);
// آزادسازی منابع
graphics.Dispose();
bitmap.Dispose();
return ret;
}
}
}