feat: Implement file management and authorization features
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m9s
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m9s
- Add RequiresPermissionAttribute for gRPC method access control. - Create IFileManagementService interface for file upload and management. - Implement AddProductImageCommand and handler for adding product images. - Implement CreateNewProductsCommand and handler for creating new products with image uploads. - Implement DeleteProductsCommand and handler for deleting products and their associations. - Implement RemoveProductImageCommand and handler for removing product images from galleries. - Implement UpdateProductsCommand and handler for updating product details and images. - Create GetProductGalleryQuery and handler for retrieving product galleries. - Implement PermissionService for role-based access control using JWT claims. - Implement FileManagementService for handling file uploads and image optimization. - Define gRPC service and messages for file management in fms.proto. - Add FluentValidation for request validation in various commands. - Create PermissionInterceptor for enforcing permissions on gRPC methods.
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
using CMSMicroservice.Application.Common.Authorization;
|
||||
using CMSMicroservice.Protobuf.Protos.UserOrder;
|
||||
using CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrders;
|
||||
using CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrder;
|
||||
using CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrderHistory;
|
||||
using CMSMicroservice.Application.OrderManagementCQ.Commands.UpdateOrderStatus;
|
||||
using CMSMicroservice.Application.OrderManagementCQ.Commands.CancelOrderByAdmin;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using CMSMicroservice.Domain.Entities.Order;
|
||||
@@ -15,6 +18,7 @@ using CMSMicroservice.Protobuf.Protos;
|
||||
using MediatR;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
@@ -30,21 +34,68 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
_context = context;
|
||||
_currentUserService = currentUserService;
|
||||
}
|
||||
[RequiresPermission(PermissionNames.OrdersCreate)]
|
||||
public override async Task<CreateNewUserOrderResponse> CreateNewUserOrder(CreateNewUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var order = new UserOrder
|
||||
{
|
||||
Amount = request.Amount,
|
||||
PackageId = request.PackageId > 0 ? request.PackageId : null,
|
||||
TransactionId = request.TransactionId,
|
||||
PaymentStatus = request.HasPaymentStatus
|
||||
? (Domain.Enums.PaymentStatus)(int)request.PaymentStatus
|
||||
: Domain.Enums.PaymentStatus.Pending,
|
||||
PaymentDate = request.PaymentDate?.ToDateTime(),
|
||||
UserId = request.UserId,
|
||||
UserAddressId = request.UserAddressId,
|
||||
PaymentMethod = request.HasPaymentMethod
|
||||
? (Domain.Enums.PaymentMethod)(int)request.PaymentMethod
|
||||
: null,
|
||||
DeliveryStatus = Domain.Enums.DeliveryStatus.Pending
|
||||
};
|
||||
|
||||
_context.UserOrders.Add(order);
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
|
||||
return new CreateNewUserOrderResponse { Id = order.Id };
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersUpdate)]
|
||||
public override async Task<Google.Protobuf.WellKnownTypes.Empty> UpdateUserOrder(UpdateUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var order = await _context.UserOrders.FindAsync(new object[] { request.Id }, context.CancellationToken);
|
||||
if (order == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "سفارش یافت نشد"));
|
||||
|
||||
if (request.Amount != null) order.Amount = request.Amount.Value;
|
||||
if (request.PackageId != null) order.PackageId = request.PackageId.Value;
|
||||
if (request.TransactionId != null) order.TransactionId = request.TransactionId.Value;
|
||||
if (request.HasPaymentStatus) order.PaymentStatus = (Domain.Enums.PaymentStatus)(int)request.PaymentStatus;
|
||||
if (request.PaymentDate != null) order.PaymentDate = request.PaymentDate.ToDateTime();
|
||||
if (request.UserId != null) order.UserId = request.UserId.Value;
|
||||
if (request.UserAddressId != null) order.UserAddressId = request.UserAddressId.Value;
|
||||
if (request.HasPaymentMethod) order.PaymentMethod = (Domain.Enums.PaymentMethod)(int)request.PaymentMethod;
|
||||
if (request.HasDeliveryStatus) order.DeliveryStatus = (Domain.Enums.DeliveryStatus)(int)request.DeliveryStatus;
|
||||
if (request.TrackingCode != null) order.TrackingCode = request.TrackingCode;
|
||||
if (request.DeliveryDescription != null) order.DeliveryDescription = request.DeliveryDescription;
|
||||
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
return new Google.Protobuf.WellKnownTypes.Empty();
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersDelete)]
|
||||
public override async Task<Google.Protobuf.WellKnownTypes.Empty> DeleteUserOrder(DeleteUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var order = await _context.UserOrders.FindAsync(new object[] { request.Id }, context.CancellationToken);
|
||||
if (order == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "سفارش یافت نشد"));
|
||||
|
||||
order.IsDeleted = true;
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
return new Google.Protobuf.WellKnownTypes.Empty();
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersView)]
|
||||
public override async Task<GetUserOrderResponse> GetUserOrder(GetUserOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
var query = new GetCustomerOrderQuery
|
||||
@@ -108,6 +159,7 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
return response;
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersView)]
|
||||
public override async Task<GetAllUserOrderByFilterResponse> GetAllUserOrderByFilter(GetAllUserOrderByFilterRequest request, ServerCallContext context)
|
||||
{
|
||||
// Admin API - can view all orders or filter by specific user
|
||||
@@ -342,29 +394,176 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
};
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersCancel)]
|
||||
public override async Task<CancelOrderResponse> CancelOrder(CancelOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var command = new CancelOrderByAdminCommand
|
||||
{
|
||||
OrderId = request.OrderId,
|
||||
CancelReason = request.CancelReason,
|
||||
RefundToWallet = request.RefundPayment
|
||||
};
|
||||
|
||||
await _sender.Send(command, context.CancellationToken);
|
||||
|
||||
return new CancelOrderResponse
|
||||
{
|
||||
OrderId = request.OrderId,
|
||||
Status = (CMSMicroservice.Protobuf.Protos.DeliveryStatus)(int)Domain.Enums.DeliveryStatus.Cancelled,
|
||||
Message = "سفارش با موفقیت لغو شد",
|
||||
RefundProcessed = request.RefundPayment
|
||||
};
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersUpdate)]
|
||||
public override async Task<UpdateOrderStatusResponse> UpdateOrderStatus(UpdateOrderStatusRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var order = await _context.UserOrders.FindAsync(new object[] { request.OrderId }, context.CancellationToken);
|
||||
if (order == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "سفارش یافت نشد"));
|
||||
|
||||
var oldStatus = (int)order.DeliveryStatus;
|
||||
|
||||
var command = new Application.OrderManagementCQ.Commands.UpdateOrderStatus.UpdateOrderStatusCommand
|
||||
{
|
||||
OrderId = request.OrderId,
|
||||
NewStatus = (Domain.Enums.DeliveryStatus)request.NewStatus
|
||||
};
|
||||
|
||||
await _sender.Send(command, context.CancellationToken);
|
||||
|
||||
return new UpdateOrderStatusResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = "وضعیت سفارش با موفقیت تغییر کرد",
|
||||
OldStatus = oldStatus,
|
||||
NewStatus = request.NewStatus
|
||||
};
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.ReportsView)]
|
||||
public override async Task<GetOrdersByDateRangeResponse> GetOrdersByDateRange(GetOrdersByDateRangeRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var pageNumber = request.PageNumber > 0 ? request.PageNumber : 1;
|
||||
var pageSize = request.PageSize > 0 ? request.PageSize : 20;
|
||||
|
||||
var query = _context.UserOrders
|
||||
.Include(o => o.User)
|
||||
.Include(o => o.FactorDetails)
|
||||
.Where(o => !o.IsDeleted);
|
||||
|
||||
if (request.StartDate != null)
|
||||
query = query.Where(o => o.Created >= request.StartDate.ToDateTime());
|
||||
if (request.EndDate != null)
|
||||
query = query.Where(o => o.Created <= request.EndDate.ToDateTime());
|
||||
if (request.Status != null)
|
||||
query = query.Where(o => (int)o.DeliveryStatus == request.Status.Value);
|
||||
if (request.UserId != null)
|
||||
query = query.Where(o => o.UserId == request.UserId.Value);
|
||||
|
||||
var totalCount = await query.CountAsync(context.CancellationToken);
|
||||
|
||||
var orders = await query
|
||||
.OrderByDescending(o => o.Created)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(o => new OrderSummaryDto
|
||||
{
|
||||
OrderId = o.Id,
|
||||
OrderNumber = $"ORD-{o.Id:D6}",
|
||||
UserId = o.UserId,
|
||||
UserFullName = o.User != null ? (o.User.FirstName + " " + o.User.LastName) : string.Empty,
|
||||
TotalAmount = o.Amount,
|
||||
Status = (int)o.DeliveryStatus,
|
||||
StatusName = o.DeliveryStatus.ToString(),
|
||||
ItemsCount = o.FactorDetails.Count,
|
||||
CreatedAt = Timestamp.FromDateTime(DateTime.SpecifyKind(o.Created, DateTimeKind.Utc))
|
||||
})
|
||||
.ToListAsync(context.CancellationToken);
|
||||
|
||||
return new GetOrdersByDateRangeResponse
|
||||
{
|
||||
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = totalCount,
|
||||
TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize),
|
||||
HasPrevious = pageNumber > 1,
|
||||
HasNext = pageNumber * pageSize < totalCount
|
||||
},
|
||||
Orders = { orders }
|
||||
};
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersUpdate)]
|
||||
public override async Task<ApplyDiscountToOrderResponse> ApplyDiscountToOrder(ApplyDiscountToOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var order = await _context.UserOrders.FindAsync(new object[] { request.OrderId }, context.CancellationToken);
|
||||
if (order == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "سفارش یافت نشد"));
|
||||
|
||||
if (order.PaymentStatus == Domain.Enums.PaymentStatus.Success)
|
||||
return new ApplyDiscountToOrderResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = "امکان اعمال تخفیف برای سفارش پرداخت شده وجود ندارد"
|
||||
};
|
||||
|
||||
var originalAmount = order.Amount;
|
||||
var discountAmount = Math.Min(request.DiscountAmount, originalAmount);
|
||||
order.Amount = originalAmount - discountAmount;
|
||||
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
|
||||
return new ApplyDiscountToOrderResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = $"تخفیف {discountAmount:N0} تومان با موفقیت اعمال شد",
|
||||
OriginalAmount = originalAmount,
|
||||
DiscountAmount = discountAmount,
|
||||
FinalAmount = order.Amount
|
||||
};
|
||||
}
|
||||
|
||||
[RequiresPermission(PermissionNames.OrdersView)]
|
||||
public override async Task<CalculateOrderPVResponse> CalculateOrderPV(CalculateOrderPVRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "Method not implemented yet"));
|
||||
var order = await _context.UserOrders
|
||||
.Include(o => o.FactorDetails)
|
||||
.ThenInclude(fd => fd.Product)
|
||||
.Where(o => o.Id == request.OrderId && !o.IsDeleted)
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (order == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "سفارش یافت نشد"));
|
||||
|
||||
var products = new List<ProductPVDto>();
|
||||
long totalPV = 0;
|
||||
|
||||
foreach (var fd in order.FactorDetails.Where(f => !f.IsDeleted))
|
||||
{
|
||||
// PV = UnitPrice * Count (simplified - can be customized)
|
||||
long unitPV = fd.UnitPrice;
|
||||
long itemPV = unitPV * fd.Count;
|
||||
totalPV += itemPV;
|
||||
|
||||
products.Add(new ProductPVDto
|
||||
{
|
||||
ProductId = fd.ProductId,
|
||||
ProductTitle = fd.Product?.Title ?? string.Empty,
|
||||
Quantity = fd.Count,
|
||||
UnitPv = unitPV,
|
||||
TotalPv = itemPV
|
||||
});
|
||||
}
|
||||
|
||||
return new CalculateOrderPVResponse
|
||||
{
|
||||
OrderId = request.OrderId,
|
||||
TotalPv = totalPV,
|
||||
Products = { products }
|
||||
};
|
||||
}
|
||||
|
||||
// ============= Customer-specific Methods =============
|
||||
@@ -518,13 +717,53 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
|
||||
public override async Task<CustomerCancelOrderResponse> CustomerCancelOrder(CustomerCancelOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
// Mock Customer order cancellation with realistic Persian response
|
||||
var order = await _context.UserOrders
|
||||
.Where(o => o.Id == request.OrderId && !o.IsDeleted)
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (order == null)
|
||||
return new CustomerCancelOrderResponse { Success = false, Message = "سفارش یافت نشد" };
|
||||
|
||||
if (order.DeliveryStatus != Domain.Enums.DeliveryStatus.Pending)
|
||||
return new CustomerCancelOrderResponse { Success = false, Message = "فقط سفارشهای در انتظار قابل لغو هستند" };
|
||||
|
||||
var refundAmount = order.Amount;
|
||||
|
||||
order.DeliveryStatus = Domain.Enums.DeliveryStatus.Cancelled;
|
||||
|
||||
// Refund to wallet if payment was from wallet
|
||||
if (order.PaymentStatus == Domain.Enums.PaymentStatus.Success && order.PaymentMethod == Domain.Enums.PaymentMethod.Wallet)
|
||||
{
|
||||
var wallet = await _context.UserWallets
|
||||
.Where(w => w.UserId == order.UserId)
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (wallet != null)
|
||||
{
|
||||
wallet.Balance += refundAmount;
|
||||
_context.UserWalletChangeLogs.Add(new UserWalletChangeLog
|
||||
{
|
||||
WalletId = wallet.Id,
|
||||
CurrentBalance = wallet.Balance,
|
||||
ChangeValue = refundAmount,
|
||||
CurrentNetworkBalance = wallet.NetworkBalance,
|
||||
ChangeNerworkValue = 0,
|
||||
CurrentDiscountBalance = wallet.DiscountBalance,
|
||||
ChangeDiscountValue = 0,
|
||||
IsIncrease = true,
|
||||
RefrenceId = order.TransactionId ?? 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
|
||||
return new CustomerCancelOrderResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = "سفارش شما با موفقیت لغو شد",
|
||||
RefundAmount = 180000,
|
||||
RefundTransactionId = "REF" + DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||||
RefundAmount = refundAmount,
|
||||
RefundTransactionId = $"REF{order.Id}"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -574,105 +813,105 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
|
||||
public override async Task<CustomerTrackOrderResponse> CustomerTrackOrder(CustomerTrackOrderRequest request, ServerCallContext context)
|
||||
{
|
||||
// Mock Customer order tracking with detailed Persian information
|
||||
var statusHistory = new List<OrderStatusHistory>
|
||||
var order = await _context.UserOrders
|
||||
.Include(o => o.FactorDetails)
|
||||
.Include(o => o.Package)
|
||||
.Where(o => o.Id == request.OrderId && !o.IsDeleted)
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (order == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "سفارش یافت نشد"));
|
||||
|
||||
var orderModel = new Protobuf.Protos.UserOrder.CustomerOrderModel
|
||||
{
|
||||
new OrderStatusHistory
|
||||
{
|
||||
Status = OrderStatusEnum.OrderStatusPending,
|
||||
StatusMessage = "در انتظار تایید",
|
||||
ChangedAt = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-5)),
|
||||
ChangedBy = "سیستم"
|
||||
},
|
||||
new OrderStatusHistory
|
||||
{
|
||||
Status = OrderStatusEnum.OrderStatusConfirmed,
|
||||
StatusMessage = "تایید شده",
|
||||
ChangedAt = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-4)),
|
||||
ChangedBy = "کارشناس فروش"
|
||||
},
|
||||
new OrderStatusHistory
|
||||
{
|
||||
Status = OrderStatusEnum.OrderStatusProcessing,
|
||||
StatusMessage = "در حال آمادهسازی",
|
||||
ChangedAt = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-3)),
|
||||
ChangedBy = "انبار"
|
||||
},
|
||||
new OrderStatusHistory
|
||||
{
|
||||
Status = OrderStatusEnum.OrderStatusShipped,
|
||||
StatusMessage = "ارسال شده",
|
||||
ChangedAt = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-2)),
|
||||
ChangedBy = "پست پیشتاز"
|
||||
}
|
||||
Id = order.Id,
|
||||
Amount = order.Amount,
|
||||
PackageId = order.PackageId ?? 0,
|
||||
PackageName = order.Package?.Title ?? string.Empty,
|
||||
Status = (OrderStatusEnum)(int)order.DeliveryStatus,
|
||||
StatusMessage = GetDeliveryStatusPersian(order.DeliveryStatus),
|
||||
OrderDate = Timestamp.FromDateTime(DateTime.SpecifyKind(order.Created, DateTimeKind.Utc)),
|
||||
TrackingCode = order.TrackingCode ?? string.Empty,
|
||||
ItemsCount = order.FactorDetails.Count(f => !f.IsDeleted),
|
||||
CanCancel = order.DeliveryStatus == Domain.Enums.DeliveryStatus.Pending,
|
||||
CanReorder = order.DeliveryStatus == Domain.Enums.DeliveryStatus.Delivered
|
||||
};
|
||||
|
||||
var deliverySteps = new List<DeliveryStep>
|
||||
var response = new CustomerTrackOrderResponse
|
||||
{
|
||||
new DeliveryStep
|
||||
{
|
||||
StepName = "دریافت از فروشنده",
|
||||
StepDescription = "بسته از فروشنده دریافت شد",
|
||||
StepTime = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-2)),
|
||||
IsCompleted = true
|
||||
},
|
||||
new DeliveryStep
|
||||
{
|
||||
StepName = "مرکز پردازش تهران",
|
||||
StepDescription = "بسته در مرکز پردازش تهران",
|
||||
StepTime = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-1)),
|
||||
IsCompleted = true
|
||||
},
|
||||
new DeliveryStep
|
||||
{
|
||||
StepName = "در حال ارسال",
|
||||
StepDescription = "بسته در حال ارسال به آدرس مقصد",
|
||||
StepTime = Timestamp.FromDateTime(DateTime.UtcNow.AddHours(-8)),
|
||||
IsCompleted = false
|
||||
}
|
||||
};
|
||||
|
||||
return new CustomerTrackOrderResponse
|
||||
{
|
||||
Order = new Protobuf.Protos.UserOrder.CustomerOrderModel
|
||||
{
|
||||
Id = request.OrderId,
|
||||
Amount = 180000,
|
||||
PackageId = 1,
|
||||
PackageName = "پکیج ویژه",
|
||||
Status = OrderStatusEnum.OrderStatusShipped,
|
||||
StatusMessage = "در حال ارسال",
|
||||
OrderDate = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-5)),
|
||||
TrackingCode = "TRK" + request.OrderId.ToString("000"),
|
||||
ItemsCount = 4,
|
||||
CanCancel = false,
|
||||
CanReorder = true
|
||||
},
|
||||
StatusHistory = { statusHistory },
|
||||
Order = orderModel,
|
||||
DeliveryInfo = new DeliveryTrackingInfo
|
||||
{
|
||||
TrackingCode = "TRK" + request.OrderId.ToString("000"),
|
||||
TrackingCode = order.TrackingCode ?? string.Empty,
|
||||
CourierName = "پست پیشتاز",
|
||||
EstimatedDelivery = "فردا تا ساعت 18:00",
|
||||
CurrentLocation = "مرکز پخش منطقه 5 تهران",
|
||||
DeliverySteps = { deliverySteps }
|
||||
EstimatedDelivery = order.DeliveryDescription ?? string.Empty,
|
||||
CurrentLocation = string.Empty
|
||||
}
|
||||
};
|
||||
|
||||
// Add current status to history
|
||||
response.StatusHistory.Add(new OrderStatusHistory
|
||||
{
|
||||
Status = (OrderStatusEnum)(int)order.DeliveryStatus,
|
||||
StatusMessage = GetDeliveryStatusPersian(order.DeliveryStatus),
|
||||
ChangedAt = order.LastModified.HasValue
|
||||
? Timestamp.FromDateTime(DateTime.SpecifyKind(order.LastModified.Value, DateTimeKind.Utc))
|
||||
: Timestamp.FromDateTime(DateTime.SpecifyKind(order.Created, DateTimeKind.Utc)),
|
||||
ChangedBy = "سیستم"
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<CustomerReorderResponse> CustomerReorderPreviousOrder(CustomerReorderRequest request, ServerCallContext context)
|
||||
{
|
||||
// Mock Customer reorder functionality
|
||||
var newOrderId = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
var totalAmount = request.UseCurrentPrices ? 280000 : 250000;
|
||||
var originalOrder = await _context.UserOrders
|
||||
.Include(o => o.FactorDetails)
|
||||
.ThenInclude(fd => fd.Product)
|
||||
.Where(o => o.Id == request.OriginalOrderId && !o.IsDeleted)
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (originalOrder == null)
|
||||
return new CustomerReorderResponse { Success = false, Message = "سفارش اصلی یافت نشد" };
|
||||
|
||||
var userId = originalOrder.UserId;
|
||||
|
||||
// Add items from old order to cart
|
||||
foreach (var fd in originalOrder.FactorDetails.Where(f => !f.IsDeleted))
|
||||
{
|
||||
var existingCartItem = await _context.UserCarts
|
||||
.Where(c => c.UserId == userId && c.ProductId == fd.ProductId && !c.IsDeleted)
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (existingCartItem != null)
|
||||
{
|
||||
existingCartItem.Count += fd.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
_context.UserCarts.Add(new UserCart
|
||||
{
|
||||
UserId = userId,
|
||||
ProductId = fd.ProductId,
|
||||
Count = fd.Count
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
|
||||
// Calculate total with current prices
|
||||
long totalAmount = originalOrder.FactorDetails
|
||||
.Where(f => !f.IsDeleted)
|
||||
.Sum(fd => request.UseCurrentPrices && fd.Product != null
|
||||
? fd.Product.Price * fd.Count
|
||||
: fd.UnitPrice * fd.Count);
|
||||
|
||||
return new CustomerReorderResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = request.UseCurrentPrices ?
|
||||
"سفارش مجدد با قیمتهای جدید ثبت شد" :
|
||||
"سفارش مجدد با قیمتهای قبلی ثبت شد",
|
||||
NewOrderId = newOrderId,
|
||||
Message = "محصولات به سبد خرید اضافه شدند",
|
||||
NewOrderId = 0, // Cart items added, no order created yet
|
||||
TotalAmount = totalAmount
|
||||
};
|
||||
}
|
||||
@@ -687,4 +926,17 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
IsEnabled = true
|
||||
});
|
||||
}
|
||||
|
||||
// ============= Helper Methods =============
|
||||
|
||||
private static string GetDeliveryStatusPersian(Domain.Enums.DeliveryStatus status) => status switch
|
||||
{
|
||||
Domain.Enums.DeliveryStatus.None => "نامشخص",
|
||||
Domain.Enums.DeliveryStatus.Pending => "در انتظار ارسال",
|
||||
Domain.Enums.DeliveryStatus.InTransit => "در حال ارسال",
|
||||
Domain.Enums.DeliveryStatus.Delivered => "تحویل داده شده",
|
||||
Domain.Enums.DeliveryStatus.Returned => "مرجوع شده",
|
||||
Domain.Enums.DeliveryStatus.Cancelled => "لغو شده",
|
||||
_ => status.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user