feat : add print order , change question dialog

release
Amir Hossein Khademi 2024-03-03 11:42:11 +03:30
parent f92343d78f
commit 290d9bbaa8
17 changed files with 511 additions and 124 deletions

View File

@ -11,7 +11,12 @@ public class OrderBagController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetUserCurrentOrderBagAsync)
.WithDisplayName("GetUserCurrentOrderBagAsync")
.WithDisplayName("GetUserCurrentOrderBag")
.HasApiVersion(1.0);
group.MapPost("check", CheckOrderBagAsync)
.WithDisplayName("CheckOrderBag")
.AllowAnonymous()
.HasApiVersion(1.0);
group.MapPost("add", AddProductToBagAsync)
@ -22,6 +27,10 @@ public class OrderBagController : ICarterModule
.WithDisplayName("RemoveFromOrderBag")
.HasApiVersion(1.0);
group.MapPost("submit", SubmitOrderBagAsync)
.WithDisplayName("SubmitOrderBag")
.HasApiVersion(1.0);
group.MapPost("discount/{orderId}", AddDiscountToOrderBagAsync)
.WithDisplayName("AddDiscountToOrderBag")
@ -37,6 +46,12 @@ public class OrderBagController : ICarterModule
.HasApiVersion(1.0);
}
private async Task<IResult> SubmitOrderBagAsync([FromBody] List<OrderBagRequestDto> requestDtos, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new SubmitOrderBagCommand(requestDtos), cancellationToken));
private async Task<IResult> CheckOrderBagAsync([FromBody] List<CheckOrderBagRequestItem> request, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new CheckOrderBagCommand(OrderBag: request), cancellationToken));
public async Task<IResult> GetUserCurrentOrderBagAsync(IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetUserOrderBagQuery(), cancellationToken));

View File

@ -26,6 +26,7 @@ public class OrderController : ICarterModule
.HasApiVersion(1.0);
group.MapGet("{id}/invoice", GetOrderInvoiceAsync)
.WithDisplayName("GetOrderInvoice")
.AllowAnonymous()
.HasApiVersion(1.0);
}

View File

@ -1,4 +1,5 @@

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.RazorPages;
using NetinaShop.Core.EntityServices.Abstracts;
using NetinaShop.Repository.Abstracts;
@ -26,6 +27,14 @@ public class UserController : ICarterModule
.WithDisplayName("GetUser")
.HasApiVersion(1.0);
group.MapGet("/order", GetUserOrdersAsync)
.WithDisplayName("GetUserOrders")
.HasApiVersion(1.0);
group.MapGet("{id}/order", GetUserOrdersByIdAsync)
.WithDisplayName("GetUserOrders")
.HasApiVersion(1.0);
group.MapGet("/changelog", GetChangeLogAsync)
.WithDisplayName("GetChangeLog")
.HasApiVersion(1.0);
@ -40,6 +49,12 @@ public class UserController : ICarterModule
.HasApiVersion(1.0);
}
private async Task<IResult> GetUserOrdersAsync([FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetUserOrdersQuery(default), cancellationToken));
private async Task<IResult> GetUserOrdersByIdAsync(Guid id,[FromServices]IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetUserOrdersQuery(id), cancellationToken));
private async Task<IResult> GetChangeLogAsync(IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetAdminChangeLogAsync(cancellationToken));

View File

@ -134,7 +134,6 @@
<ItemGroup>
<Folder Include="wwwroot\assets\vendor\bootstrap\css\" />
<Folder Include="wwwroot\fonts\" />
</ItemGroup>
</Project>

View File

@ -1,8 +1,4 @@
using Autofac.Core;
using DinkToPdf.Contracts;
using DinkToPdf;
using NetinaShop.Repository.Behaviors;
using QuestPDF.Infrastructure;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
@ -44,8 +40,8 @@ builder.Services.AddCustomIdentity();
builder.Services.AddCustomDbContext(configuration);
builder.Services.AddMarten(configuration,builder.Environment);
builder.Services.AddCarter();
builder.Services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
QuestPDF.Settings.License = LicenseType.Community;
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("Ngo9BigBOggjHTQxAR8/V1NAaF1cXmhKYVtpR2Nbe05yflRGalxSVBYiSV9jS3pTdUViWHtfcHRWQGlcUQ==");
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>

View File

@ -0,0 +1,59 @@
using NetinaShop.Domain.Dtos.SmallDtos;
namespace NetinaShop.Core.EntityServices.OrderBagHandlers;
public class CheckOrderBagCommandHandler : IRequestHandler<CheckOrderBagCommand , List<CheckOrderBagResponseItem>>
{
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
public CheckOrderBagCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
}
public async Task<List<CheckOrderBagResponseItem>> Handle(CheckOrderBagCommand request, CancellationToken cancellationToken)
{
List<CheckOrderBagResponseItem> response = new List<CheckOrderBagResponseItem>();
foreach (var item in request.OrderBag)
{
var product = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking
.Where(p => p.Id == item.ProductId)
.Select(ProductMapper.ProjectToSDto)
.FirstOrDefaultAsync(cancellationToken);
if (product == null)
{
response.Add(new CheckOrderBagResponseItem
{
Count = item.Count,
IsEnable = false,
IsRemoved = true,
ProductId = item.ProductId,
Stock = 0
});
}
else
{
await _mediator.Send(new CalculateProductDiscountCommand(product), cancellationToken);
var res = new CheckOrderBagResponseItem
{
ProductId = item.ProductId,
CostWithDiscount = product.CostWithDiscount,
Cost = product.Cost,
DiscountPercent = product.DiscountPercent,
ProductName = product.PersianName,
Stock = product.Stock,
Count = item.Count,
IsEnable = product.IsEnable,
IsRemoved = false
};
response.Add(res);
}
}
return response;
}
}

View File

@ -0,0 +1,60 @@
namespace NetinaShop.Core.EntityServices.OrderBagHandlers;
public class SubmitOrderBagCommandHandler : IRequestHandler<SubmitOrderBagCommand,OrderSDto>
{
private readonly IMediator _mediator;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
public SubmitOrderBagCommandHandler(IMediator mediator, IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService)
{
_mediator = mediator;
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
}
public async Task<OrderSDto> Handle(SubmitOrderBagCommand request, CancellationToken cancellationToken)
{
if (_currentUserService.UserId == null)
throw new AppException("User id notfound", ApiResultStatusCode.BadRequest);
if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new AppException("User id wrong", ApiResultStatusCode.BadRequest);
var orderBag = await _mediator.Send(new GetUserOrderBagQuery(), cancellationToken);
foreach (var requestDto in request.RequestDtos)
{
var product = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking
.FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken);
if (product == null)
throw new AppException("Product not found ", ApiResultStatusCode.NotFound);
if (!product.IsEnable)
throw new AppException("Product is not enable", ApiResultStatusCode.BadRequest);
var productSDto = product.AdaptToSDto();
await _mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
orderBag.ChangeOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount,
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId, requestDto.Count);
}
foreach (var orderProduct in orderBag.OrderProducts.ToList())
{
if(request.RequestDtos.FirstOrDefault(op=>op.ProductId==orderProduct.ProductId)==null)
{
orderBag.OrderProducts.Remove(orderProduct);
_repositoryWrapper.SetRepository<OrderProduct>().Delete(orderProduct);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
}
}
_repositoryWrapper.SetRepository<Order>().Update(orderBag);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
var order = await _mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken);
return order.AdaptToSDto();
}
}

View File

@ -1,9 +1,8 @@
using DinkToPdf;
using DinkToPdf.Contracts;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using Unit = QuestPDF.Infrastructure.Unit;
using Syncfusion.Drawing;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf;
using Syncfusion.Pdf.Grid;
using NetinaShop.Domain.Dtos.LargDtos;
namespace NetinaShop.Core.EntityServices.OrderHandlers;
@ -11,118 +10,288 @@ public class GetOrderInvoiceCommandHandler : IRequestHandler<GetOrderInvoiceComm
{
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
private readonly IConverter _converter;
public GetOrderInvoiceCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator,IConverter converter)
private readonly PdfTrueTypeFont _gridFont;
private readonly PdfTrueTypeFont _gridBoldFont;
private readonly PdfStringFormat _stringFormat;
private readonly PdfTrueTypeFont _largeFont;
private readonly PdfTrueTypeFont _mediumFont;
private readonly PdfTrueTypeFont _smallFont;
private readonly PdfGridLayoutFormat _gridLayoutFormat;
private readonly PdfGridCellStyle _cellStyle;
private readonly PdfGridStyle _gridStyle;
public GetOrderInvoiceCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
_converter = converter;
var path = Directory.GetCurrentDirectory();
var settingsPath = Path.Combine(path, "wwwroot", "fonts", "iranyekanwebmediumfanum.ttf");
MemoryStream stream = new MemoryStream(File.ReadAllBytes(settingsPath));
_gridFont = new PdfTrueTypeFont(stream, 10, PdfFontStyle.Regular);
_gridBoldFont = new PdfTrueTypeFont(stream, 12, PdfFontStyle.Bold);
_stringFormat = new PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle);
_largeFont = new PdfTrueTypeFont(stream, 18);
_mediumFont = new PdfTrueTypeFont(stream, 12);
_smallFont = new PdfTrueTypeFont(stream, 10);
_gridLayoutFormat = new PdfGridLayoutFormat
{
Layout = PdfLayoutType.Paginate
};
_cellStyle = new PdfGridCellStyle
{
Font = _gridFont,
Borders =
{
All = PdfPens.Transparent
}
};
_gridStyle = new PdfGridStyle
{
CellPadding = new PdfPaddings(5, 5, 5, 5)
};
}
public async Task<byte[]> Handle(GetOrderInvoiceCommand request, CancellationToken cancellationToken)
{
var orderLDto = await _mediator.Send(new GetOrderLDtoQuery(request.OrderId), cancellationToken);
PdfDocument document = new PdfDocument();
PdfPage currentPage = document.Pages.Add();
SizeF clientSize = currentPage.Size;
//var textStyleWithFallback = TextStyle
// .Default
// .FontSize(18)
// .Fallback(y => y
// .FontFamily(Fonts.Arial)
// .SemiBold()
// .Underline(false)
// .BackgroundColor(Colors.Red.Lighten4));
var result = HeaderAndAddress(orderLDto, currentPage, clientSize);
//var pdf = Document.Create(container =>
//{
// container.Page(page =>
// {
// page.Size(PageSizes.A4);
// page.Margin(2,Unit.Centimetre);
// page.PageColor(Colors.White);
// page.DefaultTextStyle(x=>x.FontSize(14));
//Product Table
result = ProductTable(orderLDto, result, currentPage, clientSize);
// page.Header()
// .Text(text =>
// {
// text.DefaultTextStyle(textStyleWithFallback);
// text.Line("This is normal text.");
// text.EmptyLine();
//Cost Table
result = CostTable(orderLDto, result, currentPage, clientSize);
// text.Line("Following line should use font fallback:");
// text.Line("中文文本");
// text.EmptyLine();
//Dtail Table
result = DetailTable(orderLDto, result, currentPage, clientSize);
// text.Line("The following line contains a mix of known and unknown characters.");
// text.Line("Mixed line: This 中文 is 文文 a mixed 本 本 line 本 中文文本!");
// text.EmptyLine();
MemoryStream stream = new MemoryStream();
document.Save(stream);
document.Close(true);
stream.Position = 0;
return stream.ToArray();
}
// text.Span("Emojis work out of the box because of font fallback: 😊😅🥳👍❤😍👌");
// });
private PdfLayoutResult HeaderAndAddress(OrderLDto order, PdfPage currentPage, SizeF clientSize)
{
PdfStringFormat format = new PdfStringFormat();
format.TextDirection = PdfTextDirection.RightToLeft;
format.Alignment = PdfTextAlignment.Right;
// page.Content()
// .ContentFromRightToLeft()
// .Column(x =>
// {
// x.Spacing(20);
// x.Item().Text("فاکتور فروش ");
// });
// });
//}).GeneratePdf();
var sb = new StringBuilder();
sb.Append(@"
<html>
<head>
</head>
<body>
<div class='header'><h1>فاکتور فروش</h1></div>
<table align='center'>
<tr>
<th>Name</th>
<th>LastName</th>
<th>Age</th>
<th>Gender</th>
</tr>");
foreach (var emp in orderLDto.OrderProducts)
var headerText = new PdfTextElement($"فاکتور فروش {order.FactorCode}", _largeFont);
headerText.StringFormat = format;
var result = headerText.Draw(currentPage, new PointF(clientSize.Width - 100, 5));
var orderAtText = new PdfTextElement($"سفارش در : {order.OrderAt.ToPersianDateTime().ToLongDateString()} | {order.OrderAt:T}", _mediumFont);
orderAtText.StringFormat = format;
result = orderAtText.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Y + 30));
var nameText = new PdfTextElement($"{order.UserFullName}", _mediumFont);
nameText.StringFormat = format;
result = nameText.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Bottom));
var phoneText = new PdfTextElement($"{order.UserPhoneNumber}", _mediumFont);
phoneText.StringFormat = new PdfStringFormat(PdfTextAlignment.Left);
result = phoneText.Draw(currentPage, new PointF(0, result.Bounds.Y));
PdfPen pen = new PdfPen(PdfBrushes.Black, 1f);
PointF point1 = new PointF(0, result.Bounds.Bottom + 25);
PointF point2 = new PointF(clientSize.Width, result.Bounds.Bottom + 25);
currentPage.Graphics.DrawLine(pen, point1, point2);
var addressText = new PdfTextElement($"آدرس : {order.OrderDelivery.Address}", _mediumFont);
addressText.StringFormat = format;
result = addressText.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Y + 55));
var postalCode = new PdfTextElement($"استان : {order.OrderDelivery.Province} | شهر : {order.OrderDelivery.City} | کد پستی : {order.OrderDelivery.PostalCode} | پلاک : {order.OrderDelivery.Plaque}", _smallFont);
postalCode.StringFormat = format;
result = postalCode.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Bottom + 5));
var shippingMethod = new PdfTextElement($"روش ارسال : {order.OrderDelivery.ShippingMethod} ", _mediumFont);
shippingMethod.StringFormat = format;
result = shippingMethod.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Bottom + 5));
PointF pointB1 = new PointF(0, result.Bounds.Bottom + 15);
PointF pointB2 = new PointF(clientSize.Width, result.Bounds.Bottom + 15);
currentPage.Graphics.DrawLine(pen, pointB1, pointB2);
return result;
}
private PdfLayoutResult DetailTable(OrderLDto order, PdfLayoutResult result, PdfPage currentPage, SizeF clientSize)
{
PdfGrid detailGrid = new PdfGrid();
detailGrid.Style.Font = _gridFont;
detailGrid.Columns.Add(1);
detailGrid.Columns[0].Width = 150;
PdfGridCellStyle detailCellStyle = new PdfGridCellStyle();
detailCellStyle.Font = _gridBoldFont;
detailCellStyle.Borders.All = PdfPens.Transparent;
detailCellStyle.TextBrush = PdfBrushes.White;
detailCellStyle.BackgroundBrush = new PdfSolidBrush(new PdfColor(Color.Black));
foreach (var payment in order.Payments.Where(p=>p.Status==PaymentStatus.Paid))
{
sb.AppendFormat(@"<tr>
<td>{0}</td>
<td>{1}</td>
<td>{2}</td>
<td>{3}</td>
</tr>", emp.ProductName, emp.Count, emp.ProductFee, emp.ProductCost);
PdfGridRow paymentType = detailGrid.Rows.Add();
paymentType.Cells[0].Value = $"{payment.Amount:N0} ریال به صورت {payment.Type.ToDisplay()} پرداخت شده";
paymentType.Cells[0].StringFormat = _stringFormat;
paymentType.Cells[0].Style = _cellStyle;
}
sb.Append(@"
</table>
</body>
</html>");
PdfGridRow isPaid = detailGrid.Rows.Add();
isPaid.Cells[0].Value = order.IsPayed ? "پرداخت شده" : "پرداخت نشده";
isPaid.Cells[0].StringFormat = _stringFormat;
isPaid.Cells[0].Style = detailCellStyle;
var globalSettings = new GlobalSettings
{
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
Margins = new MarginSettings { Top = 10 },
DocumentTitle = "PDF Report",
Out = @"D:\PDFCreator\Employee_Report.pdf"
};
var objectSettings = new ObjectSettings
{
PagesCount = true,
HtmlContent = sb.ToString(),
WebSettings = { DefaultEncoding = "utf-8", UserStyleSheet = Path.Combine(Directory.GetCurrentDirectory(), "assets", "styles.css") },
HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
FooterSettings = { FontName = "Arial", FontSize = 9, Line = true, Center = "Report Footer" }
};
var pdf = new HtmlToPdfDocument()
{
GlobalSettings = globalSettings,
Objects = { objectSettings }
};
var file = _converter.Convert(pdf);
detailGrid.ApplyBuiltinStyle(PdfGridBuiltinStyle.GridTable1Light);
detailGrid.Style = _gridStyle;
result = detailGrid.Draw(currentPage, 0, result.Bounds.Top, 150, _gridLayoutFormat);
return result;
}
private PdfLayoutResult CostTable(OrderLDto order, PdfLayoutResult result, PdfPage currentPage, SizeF clientSize)
{
PdfGrid pricesGrid = new PdfGrid();
pricesGrid.Style.Font = _gridFont;
pricesGrid.Columns.Add(2);
pricesGrid.Columns[0].Width = 150;
pricesGrid.Columns[1].Width = 200;
PdfGridRow totalProductPriceRow = pricesGrid.Rows.Add();
totalProductPriceRow.Cells[1].Value = $"قیمت تمام شده محصولات";
totalProductPriceRow.Cells[1].StringFormat = _stringFormat;
totalProductPriceRow.Cells[1].Style = _cellStyle;
totalProductPriceRow.Cells[0].Value = $"{order.TotalProductsPrice:N0} ریال";
totalProductPriceRow.Cells[0].StringFormat = _stringFormat;
totalProductPriceRow.Cells[0].Style = _cellStyle;
PdfGridRow totalDeliveryPrice = pricesGrid.Rows.Add();
totalDeliveryPrice.Cells[1].Value = $"قیمت ارسال";
totalDeliveryPrice.Cells[1].StringFormat = _stringFormat;
totalDeliveryPrice.Cells[1].Style = _cellStyle;
totalDeliveryPrice.Cells[0].Value = $"{order.DeliveryPrice:N0} ریال";
totalDeliveryPrice.Cells[0].StringFormat = _stringFormat;
totalDeliveryPrice.Cells[0].Style = _cellStyle;
PdfGridRow discountPrice = pricesGrid.Rows.Add();
discountPrice.Cells[1].Value = $"تخفیف";
discountPrice.Cells[1].StringFormat = _stringFormat;
discountPrice.Cells[1].Style = _cellStyle;
discountPrice.Cells[0].Value = $"{order.DiscountPrice:N0} ریال";
discountPrice.Cells[0].StringFormat = _stringFormat;
discountPrice.Cells[0].Style = _cellStyle;
PdfGridRow taxesPrice = pricesGrid.Rows.Add();
taxesPrice.Cells[1].Value = $"مالیاتــــ";
taxesPrice.Cells[1].StringFormat = _stringFormat;
taxesPrice.Cells[1].Style = _cellStyle;
taxesPrice.Cells[0].Value = $"{order.TaxesPrice:N0} ریال";
taxesPrice.Cells[0].StringFormat = _stringFormat;
taxesPrice.Cells[0].Style = _cellStyle;
return file;
PdfGridRow totalPrice = pricesGrid.Rows.Add();
totalPrice.Cells[1].Value = $"مبلغ پرداختی";
totalPrice.Cells[1].StringFormat = _stringFormat;
totalPrice.Cells[1].Style = _cellStyle;
totalPrice.Cells[0].Value = $"{order.TotalPrice:N0} ریال";
totalPrice.Cells[0].StringFormat = _stringFormat;
totalPrice.Cells[0].Style = _cellStyle;
pricesGrid.ApplyBuiltinStyle(PdfGridBuiltinStyle.GridTable1Light);
pricesGrid.Style = _gridStyle;
result = pricesGrid.Draw(currentPage, clientSize.Width - 430, result.Bounds.Bottom + 15, 350, _gridLayoutFormat);
return result;
}
private PdfLayoutResult ProductTable(OrderLDto order , PdfLayoutResult result , PdfPage currentPage ,SizeF clientSize )
{
PdfGrid grid = new PdfGrid();
grid.Style.Font = _gridFont;
grid.Columns.Add(4);
grid.Columns[0].Width = 100;
grid.Columns[1].Width = 100;
grid.Columns[2].Width = 50;
grid.Headers.Add(1);
_stringFormat.TextDirection = PdfTextDirection.RightToLeft;
_stringFormat.WordWrap = PdfWordWrapType.Word;
PdfGridRow header = grid.Headers[0];
header.Cells[3].Value = "محصولات";
header.Cells[3].Style.Font = _gridBoldFont;
header.Cells[3].StringFormat = _stringFormat;
header.Cells[2].Value = "تعداد";
header.Cells[2].Style.Font = _gridBoldFont;
header.Cells[2].StringFormat = _stringFormat;
header.Cells[1].Value = "قیمت فی";
header.Cells[1].Style.Font = _gridBoldFont;
header.Cells[1].StringFormat = _stringFormat;
header.Cells[0].Value = "قیمت کل";
header.Cells[0].Style.Font = _gridBoldFont;
header.Cells[0].StringFormat = _stringFormat;
PdfGridCellStyle headerCellStyle = new PdfGridCellStyle();
headerCellStyle.Font = _gridFont;
headerCellStyle.Borders.All = PdfPens.Transparent;
headerCellStyle.TextBrush = PdfBrushes.White;
headerCellStyle.BackgroundBrush = new PdfSolidBrush(new PdfColor(Color.Black));
for (int i = 0; i < header.Cells.Count; i++)
{
PdfGridCell cell = header.Cells[i];
cell.Style = headerCellStyle;
}
foreach (var orderProduct in order.OrderProducts)
{
PdfGridRow row = grid.Rows.Add();
row.Cells[3].Value = orderProduct.ProductName;
row.Cells[3].StringFormat = _stringFormat;
row.Cells[3].Style = _cellStyle;
row.Cells[2].Value = orderProduct.Count.ToString();
row.Cells[2].StringFormat = _stringFormat;
row.Cells[2].Style = _cellStyle;
row.Cells[1].Value = $"{orderProduct.ProductFeeWithDiscount:N0} ریال";
row.Cells[1].StringFormat = _stringFormat;
row.Cells[1].Style = _cellStyle;
row.Cells[0].Value = $"{orderProduct.ProductCost:N0} ریال";
row.Cells[0].StringFormat = _stringFormat;
row.Cells[0].Style = _cellStyle;
}
grid.Style = _gridStyle;
grid.ApplyBuiltinStyle(PdfGridBuiltinStyle.GridTable1Light);
result = grid.Draw(currentPage, 0, result.Bounds.Bottom + 25, clientSize.Width, _gridLayoutFormat);
return result;
}
}

View File

@ -11,13 +11,10 @@
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" />
<PackageReference Include="Autofac.Extras.Quartz" Version="9.0.0" />
<PackageReference Include="DinkToPdf" Version="1.0.8" />
<PackageReference Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="QuestPDF" Version="2023.12.6" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.2" />
<PackageReference Include="Quartz" Version="3.8.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.7" />
<PackageReference Include="Syncfusion.Pdf.Net.Core" Version="24.2.8" />
</ItemGroup>

View File

@ -4,11 +4,13 @@ namespace NetinaShop.Domain.CommandQueries.Commands;
public sealed record CreateOrderCommand(string DiscountCode, List<OrderProductSDto> OrderProducts, OrderDeliverySDto OrderDelivery) : IRequest<OrderSDto>;
public sealed record CheckOrderBagCommand(List<CheckOrderBagRequestItem> OrderBag) : IRequest<List<CheckOrderBagResponseItem>>;
public sealed record AddToOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;
public sealed record RemoveFromOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;
public sealed record SubmitDiscountCommand(Guid OrderId,string DiscountCode) : IRequest<OrderSDto>;
public sealed record SubmitOrderDeliveryCommand(Guid AddressId, Guid OrderId, Guid ShippingId) : IRequest<OrderSDto>;
public sealed record SubmitOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;
public sealed record SubmitOrderPaymentCommand(Guid OrderId, OrderPaymentMethod PaymentMethod , bool HasPaid = false) : IRequest<SubmitOrderPaymentResponseDto>;

View File

@ -2,5 +2,6 @@
public sealed record GetOrderLDtoQuery(Guid Id) : IRequest<OrderLDto>;
public sealed record GetUserOrdersQuery(Guid UserId = default) : IRequest<List<OrderSDto>>;
public sealed record GetOrderQuery(Guid Id) : IRequest<Order>;
public sealed record GetOrdersQuery(OrderQueryDateFilter? DateFilter, OrderStatus? OrderStatus,long? SelectedDate, int Page = 0) : IRequest<List<OrderSDto>>;

View File

@ -0,0 +1,7 @@
namespace NetinaShop.Domain.Dtos.RequestDtos;
public class CheckOrderBagRequestItem
{
public Guid ProductId { get; set; }
public int Count { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace NetinaShop.Domain.Dtos.ResponseDtos;
public class CheckOrderBagResponseItem
{
public Guid ProductId { get; set; }
public string ProductName { get; set; } = string.Empty;
public int Count { get; set; }
public double Cost { get; set; }
public double CostWithDiscount { get; set; }
public double DiscountPercent { get; set; }
public bool IsEnable { get; set; }
public bool IsRemoved { get; set; }
public int Stock { get; set; }
}

View File

@ -20,5 +20,5 @@ public class OrderSDto : BaseDto<OrderSDto, Order>
public string DiscountCode { get; set; } = string.Empty;
public string UserFullName { get; set; } = string.Empty;
public string UserPhoneNumber { get; set; } = string.Empty;
public Guid UserId { get; internal set; }
public Guid UserId { get; set; }
}

View File

@ -12,7 +12,7 @@ public partial class Order
}
public void AddToOrderBag(Guid productId,double cost,double costWithDiscount,bool hasDiscount,double packingCost ,Guid categoryId , int count)
public void AddToOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost, Guid categoryId, int count)
{
var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
if (orderProduct == null)
@ -44,6 +44,21 @@ public partial class Order
}
}
public void ChangeOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost, Guid categoryId, int count)
{
var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
if (orderProduct != null)
{
if (orderProduct.Count > count)
RemoveFromOrderBag(productId, count);
else
AddToOrderBag(productId, cost, costWithDiscount, hasDiscount, packingCost, categoryId, count);
}
else
AddToOrderBag(productId, cost, costWithDiscount, hasDiscount, packingCost, categoryId, count);
}
public void SetDiscount(string discountCode)
=> DiscountCode = discountCode;
public void AddOrderProduct(OrderProduct orderProduct)
@ -111,17 +126,17 @@ public partial class Order
OrderDelivery = orderDelivery;
}
public void AddOrderDelivery(Guid addressId, double deliveryCost, Guid shippingId, Guid orderId,Guid orderDeliveryId)
public void AddOrderDelivery(Guid addressId, double deliveryCost, Guid shippingId, Guid orderId, Guid orderDeliveryId)
{
var orderDelivery = OrderDelivery.Create(addressId, deliveryCost, shippingId, orderId);
orderDelivery.Id = orderDeliveryId;
OrderDelivery = orderDelivery;
}
public void SetTotalPrice(double totalProductPrice,
double packingPrice,
double servicePrice,
public void SetTotalPrice(double totalProductPrice,
double packingPrice,
double servicePrice,
double deliveryPrice,
double productDiscountPrice,
double productDiscountPrice,
double discountCodePrice,
double taxesPrice)
{
@ -132,7 +147,7 @@ public partial class Order
TaxesPrice = taxesPrice;
DiscountCodePrice = discountCodePrice;
ProductDiscountPrice = productDiscountPrice;
DiscountPrice = productDiscountPrice+discountCodePrice;
DiscountPrice = productDiscountPrice + discountCodePrice;
TotalPrice = (totalProductPrice + packingPrice + servicePrice + deliveryPrice + taxesPrice) - DiscountPrice;
}
@ -140,14 +155,14 @@ public partial class Order
public partial class OrderProduct
{
public static OrderProduct Create(int count,
double productFee,
public static OrderProduct Create(int count,
double productFee,
double productFeeWithDiscount,
bool hasDiscount,
double packingFee,
OrderStatus orderProductStatus,
Guid productId,
Guid productCategoryId,
double packingFee,
OrderStatus orderProductStatus,
Guid productId,
Guid productCategoryId,
Guid orderId)
{
var productCost = count * productFeeWithDiscount;
@ -164,7 +179,7 @@ public partial class OrderProduct
public partial class OrderDelivery
{
public static OrderDelivery Create(Guid addressId,double deliveryCost, Guid shippingId, Guid orderId)
public static OrderDelivery Create(Guid addressId, double deliveryCost, Guid shippingId, Guid orderId)
{
return new OrderDelivery(addressId, deliveryCost, shippingId, orderId);
}

View File

@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore;
using NetinaShop.Domain.Entities.Orders;
namespace NetinaShop.Repository.Handlers.Orders;
public class GetUserOrdersQueryHandler : IRequestHandler<GetUserOrdersQuery, List<OrderSDto>>
{
private readonly ICurrentUserService _currentUserService;
private readonly IRepositoryWrapper _repositoryWrapper;
public GetUserOrdersQueryHandler(ICurrentUserService currentUserService,IRepositoryWrapper repositoryWrapper)
{
_currentUserService = currentUserService;
_repositoryWrapper = repositoryWrapper;
}
public async Task<List<OrderSDto>> Handle(GetUserOrdersQuery request, CancellationToken cancellationToken)
{
Guid userId = Guid.Empty;
if (request.UserId == default)
{
if (_currentUserService.UserId == null)
throw new AppException("Token is wrong", ApiResultStatusCode.UnAuthorized);
if (!Guid.TryParse(_currentUserService.UserId, out userId))
throw new AppException("Token is wrong", ApiResultStatusCode.UnAuthorized);
}
else
userId = request.UserId;
var orders = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.Where(o => o.UserId == userId)
.Select(OrderMapper.ProjectToSDto)
.ToListAsync(cancellationToken);
return orders;
}
}