diff --git a/NetinaShop.Api/Controller/OrderBagController.cs b/NetinaShop.Api/Controller/OrderBagController.cs index 82dd010..4795ecb 100644 --- a/NetinaShop.Api/Controller/OrderBagController.cs +++ b/NetinaShop.Api/Controller/OrderBagController.cs @@ -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 SubmitOrderBagAsync([FromBody] List requestDtos, IMediator mediator, CancellationToken cancellationToken) + => TypedResults.Ok(await mediator.Send(new SubmitOrderBagCommand(requestDtos), cancellationToken)); + + private async Task CheckOrderBagAsync([FromBody] List request, IMediator mediator, CancellationToken cancellationToken) + => TypedResults.Ok(await mediator.Send(new CheckOrderBagCommand(OrderBag: request), cancellationToken)); + public async Task GetUserCurrentOrderBagAsync(IMediator mediator, CancellationToken cancellationToken) => TypedResults.Ok(await mediator.Send(new GetUserOrderBagQuery(), cancellationToken)); diff --git a/NetinaShop.Api/Controller/OrderController.cs b/NetinaShop.Api/Controller/OrderController.cs index d5514d8..24444b2 100644 --- a/NetinaShop.Api/Controller/OrderController.cs +++ b/NetinaShop.Api/Controller/OrderController.cs @@ -26,6 +26,7 @@ public class OrderController : ICarterModule .HasApiVersion(1.0); group.MapGet("{id}/invoice", GetOrderInvoiceAsync) .WithDisplayName("GetOrderInvoice") + .AllowAnonymous() .HasApiVersion(1.0); } diff --git a/NetinaShop.Api/Controller/UserController.cs b/NetinaShop.Api/Controller/UserController.cs index 83653a6..b08a2df 100644 --- a/NetinaShop.Api/Controller/UserController.cs +++ b/NetinaShop.Api/Controller/UserController.cs @@ -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 GetUserOrdersAsync([FromServices] IMediator mediator, CancellationToken cancellationToken) + => TypedResults.Ok(await mediator.Send(new GetUserOrdersQuery(default), cancellationToken)); + + private async Task GetUserOrdersByIdAsync(Guid id,[FromServices]IMediator mediator, CancellationToken cancellationToken) + => TypedResults.Ok(await mediator.Send(new GetUserOrdersQuery(id), cancellationToken)); + private async Task GetChangeLogAsync(IUserService userService, CancellationToken cancellationToken) => TypedResults.Ok(await userService.GetAdminChangeLogAsync(cancellationToken)); diff --git a/NetinaShop.Api/NetinaShop.Api.csproj b/NetinaShop.Api/NetinaShop.Api.csproj index e796a7a..b05d873 100644 --- a/NetinaShop.Api/NetinaShop.Api.csproj +++ b/NetinaShop.Api/NetinaShop.Api.csproj @@ -134,7 +134,6 @@ - diff --git a/NetinaShop.Api/Program.cs b/NetinaShop.Api/Program.cs index eb0128a..9f4fc16 100644 --- a/NetinaShop.Api/Program.cs +++ b/NetinaShop.Api/Program.cs @@ -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(builder => diff --git a/NetinaShop.Api/wwwroot/fonts/iranyekanwebmediumfanum.ttf b/NetinaShop.Api/wwwroot/fonts/iranyekanwebmediumfanum.ttf new file mode 100644 index 0000000..551a67f Binary files /dev/null and b/NetinaShop.Api/wwwroot/fonts/iranyekanwebmediumfanum.ttf differ diff --git a/NetinaShop.Core/EntityServices/OrderBagHandlers/CheckOrderBagCommandHandler.cs b/NetinaShop.Core/EntityServices/OrderBagHandlers/CheckOrderBagCommandHandler.cs new file mode 100644 index 0000000..b23c497 --- /dev/null +++ b/NetinaShop.Core/EntityServices/OrderBagHandlers/CheckOrderBagCommandHandler.cs @@ -0,0 +1,59 @@ +using NetinaShop.Domain.Dtos.SmallDtos; + +namespace NetinaShop.Core.EntityServices.OrderBagHandlers; + +public class CheckOrderBagCommandHandler : IRequestHandler> +{ + private readonly IRepositoryWrapper _repositoryWrapper; + private readonly IMediator _mediator; + + public CheckOrderBagCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator) + { + _repositoryWrapper = repositoryWrapper; + _mediator = mediator; + } + public async Task> Handle(CheckOrderBagCommand request, CancellationToken cancellationToken) + { + List response = new List(); + + foreach (var item in request.OrderBag) + { + var product = await _repositoryWrapper.SetRepository() + .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; + } +} \ No newline at end of file diff --git a/NetinaShop.Core/EntityServices/OrderBagHandlers/SubmitOrderBagCommandHandler.cs b/NetinaShop.Core/EntityServices/OrderBagHandlers/SubmitOrderBagCommandHandler.cs new file mode 100644 index 0000000..56a8e87 --- /dev/null +++ b/NetinaShop.Core/EntityServices/OrderBagHandlers/SubmitOrderBagCommandHandler.cs @@ -0,0 +1,60 @@ +namespace NetinaShop.Core.EntityServices.OrderBagHandlers; + +public class SubmitOrderBagCommandHandler : IRequestHandler +{ + 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 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() + .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().Delete(orderProduct); + await _repositoryWrapper.SaveChangesAsync(cancellationToken); + } + } + + _repositoryWrapper.SetRepository().Update(orderBag); + await _repositoryWrapper.SaveChangesAsync(cancellationToken); + + var order = await _mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken); + + return order.AdaptToSDto(); + } +} \ No newline at end of file diff --git a/NetinaShop.Core/EntityServices/OrderHandlers/GetOrderInvoiceCommandHandler.cs b/NetinaShop.Core/EntityServices/OrderHandlers/GetOrderInvoiceCommandHandler.cs index cec54e5..00eb6f5 100644 --- a/NetinaShop.Core/EntityServices/OrderHandlers/GetOrderInvoiceCommandHandler.cs +++ b/NetinaShop.Core/EntityServices/OrderHandlers/GetOrderInvoiceCommandHandler.cs @@ -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 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(@" - - - - -

فاکتور فروش

- - - - - - - "); - 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(@" - - - - - ", 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(@" -
NameLastNameAgeGender
{0}{1}{2}{3}
- - "); + 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; } } \ No newline at end of file diff --git a/NetinaShop.Core/NetinaShop.Core.csproj b/NetinaShop.Core/NetinaShop.Core.csproj index 2e7cbc1..8695861 100644 --- a/NetinaShop.Core/NetinaShop.Core.csproj +++ b/NetinaShop.Core/NetinaShop.Core.csproj @@ -11,13 +11,10 @@ - - - - + diff --git a/NetinaShop.Domain/CommandQueries/Commands/OrderBagCommands.cs b/NetinaShop.Domain/CommandQueries/Commands/OrderBagCommands.cs index 2c61a92..98e4022 100644 --- a/NetinaShop.Domain/CommandQueries/Commands/OrderBagCommands.cs +++ b/NetinaShop.Domain/CommandQueries/Commands/OrderBagCommands.cs @@ -4,11 +4,13 @@ namespace NetinaShop.Domain.CommandQueries.Commands; public sealed record CreateOrderCommand(string DiscountCode, List OrderProducts, OrderDeliverySDto OrderDelivery) : IRequest; +public sealed record CheckOrderBagCommand(List OrderBag) : IRequest>; public sealed record AddToOrderBagCommand(List RequestDtos) : IRequest; public sealed record RemoveFromOrderBagCommand(List RequestDtos) : IRequest; public sealed record SubmitDiscountCommand(Guid OrderId,string DiscountCode) : IRequest; public sealed record SubmitOrderDeliveryCommand(Guid AddressId, Guid OrderId, Guid ShippingId) : IRequest; +public sealed record SubmitOrderBagCommand(List RequestDtos) : IRequest; public sealed record SubmitOrderPaymentCommand(Guid OrderId, OrderPaymentMethod PaymentMethod , bool HasPaid = false) : IRequest; diff --git a/NetinaShop.Domain/CommandQueries/Queries/OrderQueries.cs b/NetinaShop.Domain/CommandQueries/Queries/OrderQueries.cs index ab14aa9..8666859 100644 --- a/NetinaShop.Domain/CommandQueries/Queries/OrderQueries.cs +++ b/NetinaShop.Domain/CommandQueries/Queries/OrderQueries.cs @@ -2,5 +2,6 @@ public sealed record GetOrderLDtoQuery(Guid Id) : IRequest; +public sealed record GetUserOrdersQuery(Guid UserId = default) : IRequest>; public sealed record GetOrderQuery(Guid Id) : IRequest; public sealed record GetOrdersQuery(OrderQueryDateFilter? DateFilter, OrderStatus? OrderStatus,long? SelectedDate, int Page = 0) : IRequest>; \ No newline at end of file diff --git a/NetinaShop.Domain/Dtos/RequestDtos/CheckOrderBagRequestItem.cs b/NetinaShop.Domain/Dtos/RequestDtos/CheckOrderBagRequestItem.cs new file mode 100644 index 0000000..ecbea23 --- /dev/null +++ b/NetinaShop.Domain/Dtos/RequestDtos/CheckOrderBagRequestItem.cs @@ -0,0 +1,7 @@ +namespace NetinaShop.Domain.Dtos.RequestDtos; + +public class CheckOrderBagRequestItem +{ + public Guid ProductId { get; set; } + public int Count { get; set; } +} \ No newline at end of file diff --git a/NetinaShop.Domain/Dtos/ResponseDtos/CheckOrderBagResponseItem.cs b/NetinaShop.Domain/Dtos/ResponseDtos/CheckOrderBagResponseItem.cs new file mode 100644 index 0000000..803303e --- /dev/null +++ b/NetinaShop.Domain/Dtos/ResponseDtos/CheckOrderBagResponseItem.cs @@ -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; } +} \ No newline at end of file diff --git a/NetinaShop.Domain/Dtos/SmallDtos/OrderSDto.cs b/NetinaShop.Domain/Dtos/SmallDtos/OrderSDto.cs index 967a046..8f53f8a 100644 --- a/NetinaShop.Domain/Dtos/SmallDtos/OrderSDto.cs +++ b/NetinaShop.Domain/Dtos/SmallDtos/OrderSDto.cs @@ -20,5 +20,5 @@ public class OrderSDto : BaseDto 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; } } diff --git a/NetinaShop.Domain/Entities/Orders/Order.Aggregate.cs b/NetinaShop.Domain/Entities/Orders/Order.Aggregate.cs index 7bba6d3..4ced9ae 100644 --- a/NetinaShop.Domain/Entities/Orders/Order.Aggregate.cs +++ b/NetinaShop.Domain/Entities/Orders/Order.Aggregate.cs @@ -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); } diff --git a/NetinaShop.Repository/Handlers/Orders/GetUserOrdersQueryHandler.cs b/NetinaShop.Repository/Handlers/Orders/GetUserOrdersQueryHandler.cs new file mode 100644 index 0000000..b44fee7 --- /dev/null +++ b/NetinaShop.Repository/Handlers/Orders/GetUserOrdersQueryHandler.cs @@ -0,0 +1,37 @@ +using Microsoft.EntityFrameworkCore; +using NetinaShop.Domain.Entities.Orders; + +namespace NetinaShop.Repository.Handlers.Orders; + +public class GetUserOrdersQueryHandler : IRequestHandler> +{ + private readonly ICurrentUserService _currentUserService; + private readonly IRepositoryWrapper _repositoryWrapper; + + public GetUserOrdersQueryHandler(ICurrentUserService currentUserService,IRepositoryWrapper repositoryWrapper) + { + _currentUserService = currentUserService; + _repositoryWrapper = repositoryWrapper; + } + public async Task> 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() + .TableNoTracking + .Where(o => o.UserId == userId) + .Select(OrderMapper.ProjectToSDto) + .ToListAsync(cancellationToken); + + return orders; + } +} \ No newline at end of file