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

View File

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

View File

@ -1,4 +1,5 @@
 
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using NetinaShop.Core.EntityServices.Abstracts; using NetinaShop.Core.EntityServices.Abstracts;
using NetinaShop.Repository.Abstracts; using NetinaShop.Repository.Abstracts;
@ -26,6 +27,14 @@ public class UserController : ICarterModule
.WithDisplayName("GetUser") .WithDisplayName("GetUser")
.HasApiVersion(1.0); .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) group.MapGet("/changelog", GetChangeLogAsync)
.WithDisplayName("GetChangeLog") .WithDisplayName("GetChangeLog")
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -40,6 +49,12 @@ public class UserController : ICarterModule
.HasApiVersion(1.0); .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) private async Task<IResult> GetChangeLogAsync(IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetAdminChangeLogAsync(cancellationToken)); => TypedResults.Ok(await userService.GetAdminChangeLogAsync(cancellationToken));

View File

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

View File

@ -1,8 +1,4 @@
using Autofac.Core;
using DinkToPdf.Contracts;
using DinkToPdf;
using NetinaShop.Repository.Behaviors; using NetinaShop.Repository.Behaviors;
using QuestPDF.Infrastructure;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
@ -44,8 +40,8 @@ builder.Services.AddCustomIdentity();
builder.Services.AddCustomDbContext(configuration); builder.Services.AddCustomDbContext(configuration);
builder.Services.AddMarten(configuration,builder.Environment); builder.Services.AddMarten(configuration,builder.Environment);
builder.Services.AddCarter(); 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 => 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 Syncfusion.Drawing;
using DinkToPdf.Contracts; using Syncfusion.Pdf.Graphics;
using QuestPDF.Fluent; using Syncfusion.Pdf;
using QuestPDF.Helpers; using Syncfusion.Pdf.Grid;
using QuestPDF.Infrastructure; using NetinaShop.Domain.Dtos.LargDtos;
using Unit = QuestPDF.Infrastructure.Unit;
namespace NetinaShop.Core.EntityServices.OrderHandlers; namespace NetinaShop.Core.EntityServices.OrderHandlers;
@ -11,118 +10,288 @@ public class GetOrderInvoiceCommandHandler : IRequestHandler<GetOrderInvoiceComm
{ {
private readonly IRepositoryWrapper _repositoryWrapper; private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator; 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; _repositoryWrapper = repositoryWrapper;
_mediator = mediator; _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) public async Task<byte[]> Handle(GetOrderInvoiceCommand request, CancellationToken cancellationToken)
{ {
var orderLDto = await _mediator.Send(new GetOrderLDtoQuery(request.OrderId), 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 var result = HeaderAndAddress(orderLDto, currentPage, clientSize);
// .Default
// .FontSize(18)
// .Fallback(y => y
// .FontFamily(Fonts.Arial)
// .SemiBold()
// .Underline(false)
// .BackgroundColor(Colors.Red.Lighten4));
//var pdf = Document.Create(container => //Product Table
//{ result = ProductTable(orderLDto, result, currentPage, clientSize);
// container.Page(page =>
// {
// page.Size(PageSizes.A4);
// page.Margin(2,Unit.Centimetre);
// page.PageColor(Colors.White);
// page.DefaultTextStyle(x=>x.FontSize(14));
// page.Header()
// .Text(text =>
// {
// text.DefaultTextStyle(textStyleWithFallback);
// text.Line("This is normal text."); //Cost Table
// text.EmptyLine(); result = CostTable(orderLDto, result, currentPage, clientSize);
// text.Line("Following line should use font fallback:"); //Dtail Table
// text.Line("中文文本"); result = DetailTable(orderLDto, result, currentPage, clientSize);
// text.EmptyLine();
// text.Line("The following line contains a mix of known and unknown characters."); MemoryStream stream = new MemoryStream();
// text.Line("Mixed line: This 中文 is 文文 a mixed 本 本 line 本 中文文本!"); document.Save(stream);
// text.EmptyLine(); 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(); var headerText = new PdfTextElement($"فاکتور فروش {order.FactorCode}", _largeFont);
sb.Append(@" headerText.StringFormat = format;
<html> var result = headerText.Draw(currentPage, new PointF(clientSize.Width - 100, 5));
<head>
</head> var orderAtText = new PdfTextElement($"سفارش در : {order.OrderAt.ToPersianDateTime().ToLongDateString()} | {order.OrderAt:T}", _mediumFont);
<body> orderAtText.StringFormat = format;
<div class='header'><h1>فاکتور فروش</h1></div> result = orderAtText.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Y + 30));
<table align='center'>
<tr> var nameText = new PdfTextElement($"{order.UserFullName}", _mediumFont);
<th>Name</th> nameText.StringFormat = format;
<th>LastName</th> result = nameText.Draw(currentPage, new PointF(clientSize.Width - 100, result.Bounds.Bottom));
<th>Age</th>
<th>Gender</th> var phoneText = new PdfTextElement($"{order.UserPhoneNumber}", _mediumFont);
</tr>"); phoneText.StringFormat = new PdfStringFormat(PdfTextAlignment.Left);
foreach (var emp in orderLDto.OrderProducts) 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> PdfGridRow paymentType = detailGrid.Rows.Add();
<td>{0}</td> paymentType.Cells[0].Value = $"{payment.Amount:N0} ریال به صورت {payment.Type.ToDisplay()} پرداخت شده";
<td>{1}</td> paymentType.Cells[0].StringFormat = _stringFormat;
<td>{2}</td> paymentType.Cells[0].Style = _cellStyle;
<td>{3}</td>
</tr>", emp.ProductName, emp.Count, emp.ProductFee, emp.ProductCost);
} }
sb.Append(@" PdfGridRow isPaid = detailGrid.Rows.Add();
</table> isPaid.Cells[0].Value = order.IsPayed ? "پرداخت شده" : "پرداخت نشده";
</body> isPaid.Cells[0].StringFormat = _stringFormat;
</html>"); isPaid.Cells[0].Style = detailCellStyle;
var globalSettings = new GlobalSettings detailGrid.ApplyBuiltinStyle(PdfGridBuiltinStyle.GridTable1Light);
{ detailGrid.Style = _gridStyle;
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait, result = detailGrid.Draw(currentPage, 0, result.Bounds.Top, 150, _gridLayoutFormat);
PaperSize = PaperKind.A4, return result;
Margins = new MarginSettings { Top = 10 }, }
DocumentTitle = "PDF Report",
Out = @"D:\PDFCreator\Employee_Report.pdf" private PdfLayoutResult CostTable(OrderLDto order, PdfLayoutResult result, PdfPage currentPage, SizeF clientSize)
}; {
var objectSettings = new ObjectSettings PdfGrid pricesGrid = new PdfGrid();
{ pricesGrid.Style.Font = _gridFont;
PagesCount = true, pricesGrid.Columns.Add(2);
HtmlContent = sb.ToString(), pricesGrid.Columns[0].Width = 150;
WebSettings = { DefaultEncoding = "utf-8", UserStyleSheet = Path.Combine(Directory.GetCurrentDirectory(), "assets", "styles.css") }, pricesGrid.Columns[1].Width = 200;
HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
FooterSettings = { FontName = "Arial", FontSize = 9, Line = true, Center = "Report Footer" } PdfGridRow totalProductPriceRow = pricesGrid.Rows.Add();
}; totalProductPriceRow.Cells[1].Value = $"قیمت تمام شده محصولات";
var pdf = new HtmlToPdfDocument() totalProductPriceRow.Cells[1].StringFormat = _stringFormat;
{ totalProductPriceRow.Cells[1].Style = _cellStyle;
GlobalSettings = globalSettings,
Objects = { objectSettings } totalProductPriceRow.Cells[0].Value = $"{order.TotalProductsPrice:N0} ریال";
}; totalProductPriceRow.Cells[0].StringFormat = _stringFormat;
var file = _converter.Convert(pdf); 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" Version="5.0.0" />
<PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" /> <PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" />
<PackageReference Include="Autofac.Extras.Quartz" Version="9.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="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="SixLabors.ImageSharp" Version="3.1.2" />
<PackageReference Include="Quartz" Version="3.8.0" /> <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> </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 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 AddToOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;
public sealed record RemoveFromOrderBagCommand(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 SubmitDiscountCommand(Guid OrderId,string DiscountCode) : IRequest<OrderSDto>;
public sealed record SubmitOrderDeliveryCommand(Guid AddressId, Guid OrderId, Guid ShippingId) : 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>; 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 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 GetOrderQuery(Guid Id) : IRequest<Order>;
public sealed record GetOrdersQuery(OrderQueryDateFilter? DateFilter, OrderStatus? OrderStatus,long? SelectedDate, int Page = 0) : IRequest<List<OrderSDto>>; 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 DiscountCode { get; set; } = string.Empty;
public string UserFullName { get; set; } = string.Empty; public string UserFullName { get; set; } = string.Empty;
public string UserPhoneNumber { 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); var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
if (orderProduct == null) 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) public void SetDiscount(string discountCode)
=> DiscountCode = discountCode; => DiscountCode = discountCode;
public void AddOrderProduct(OrderProduct orderProduct) public void AddOrderProduct(OrderProduct orderProduct)
@ -111,17 +126,17 @@ public partial class Order
OrderDelivery = orderDelivery; 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); var orderDelivery = OrderDelivery.Create(addressId, deliveryCost, shippingId, orderId);
orderDelivery.Id = orderDeliveryId; orderDelivery.Id = orderDeliveryId;
OrderDelivery = orderDelivery; OrderDelivery = orderDelivery;
} }
public void SetTotalPrice(double totalProductPrice, public void SetTotalPrice(double totalProductPrice,
double packingPrice, double packingPrice,
double servicePrice, double servicePrice,
double deliveryPrice, double deliveryPrice,
double productDiscountPrice, double productDiscountPrice,
double discountCodePrice, double discountCodePrice,
double taxesPrice) double taxesPrice)
{ {
@ -132,7 +147,7 @@ public partial class Order
TaxesPrice = taxesPrice; TaxesPrice = taxesPrice;
DiscountCodePrice = discountCodePrice; DiscountCodePrice = discountCodePrice;
ProductDiscountPrice = productDiscountPrice; ProductDiscountPrice = productDiscountPrice;
DiscountPrice = productDiscountPrice+discountCodePrice; DiscountPrice = productDiscountPrice + discountCodePrice;
TotalPrice = (totalProductPrice + packingPrice + servicePrice + deliveryPrice + taxesPrice) - DiscountPrice; TotalPrice = (totalProductPrice + packingPrice + servicePrice + deliveryPrice + taxesPrice) - DiscountPrice;
} }
@ -140,14 +155,14 @@ public partial class Order
public partial class OrderProduct public partial class OrderProduct
{ {
public static OrderProduct Create(int count, public static OrderProduct Create(int count,
double productFee, double productFee,
double productFeeWithDiscount, double productFeeWithDiscount,
bool hasDiscount, bool hasDiscount,
double packingFee, double packingFee,
OrderStatus orderProductStatus, OrderStatus orderProductStatus,
Guid productId, Guid productId,
Guid productCategoryId, Guid productCategoryId,
Guid orderId) Guid orderId)
{ {
var productCost = count * productFeeWithDiscount; var productCost = count * productFeeWithDiscount;
@ -164,7 +179,7 @@ public partial class OrderProduct
public partial class OrderDelivery 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); 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;
}
}