Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 9m50s
Build and Deploy to Production / build-and-deploy (push) Successful in 9m50s
This commit is contained in:
+2
-2
@@ -163,10 +163,10 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
||||
request.UserId
|
||||
);
|
||||
|
||||
// در فعالسازی اجباری، اگر PackagePurchaseMethod تنظیم نشده، مقدار DirectPurchase بگذار
|
||||
// در فعالسازی اجباری ادمین، اگر روش خرید تنظیم نشده، دستی در نظر بگیر
|
||||
if (user.PackagePurchaseMethod == PackagePurchaseMethod.None)
|
||||
{
|
||||
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
|
||||
user.PackagePurchaseMethod = PackagePurchaseMethod.Manual;
|
||||
_context.Users.Update(user);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace CMSMicroservice.Application.Common;
|
||||
|
||||
/// <summary>
|
||||
/// نام نمایشی کاربر برای گزارشها؛ اگر نام خالی باشد موبایل یا شناسه.
|
||||
/// </summary>
|
||||
public static class UserDisplayName
|
||||
{
|
||||
public static string From(string? firstName, string? lastName, string? mobile, long userId)
|
||||
{
|
||||
var name = string.Join(" ",
|
||||
new[] { firstName, lastName }.Where(s => !string.IsNullOrWhiteSpace(s)));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
return name;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(mobile))
|
||||
return mobile.Trim();
|
||||
|
||||
return userId > 0 ? $"کاربر {userId}" : "—";
|
||||
}
|
||||
|
||||
public static string From(Domain.Entities.User? user)
|
||||
{
|
||||
if (user is null)
|
||||
return string.Empty;
|
||||
|
||||
return From(user.FirstName, user.LastName, user.Mobile, user.Id);
|
||||
}
|
||||
}
|
||||
+5
@@ -35,6 +35,11 @@ public class UpdateOrderStatusCommandHandler : IRequestHandler<UpdateOrderStatus
|
||||
order.TrackingCode = request.TrackingCode;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(request.AdminNotes))
|
||||
{
|
||||
order.DeliveryDescription = request.AdminNotes;
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new UpdateOrderStatusResponseDto
|
||||
|
||||
+36
-12
@@ -1,3 +1,4 @@
|
||||
using CMSMicroservice.Application.Common;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
using MediatR;
|
||||
@@ -80,16 +81,40 @@ public class GetAllDiscountOrdersQueryHandler : IRequestHandler<GetAllDiscountOr
|
||||
// Apply pagination
|
||||
var pagination = request.PaginationQuery ?? new PaginationState { PageNumber = 1, PageSize = 20 };
|
||||
|
||||
var orders = await query
|
||||
var rows = await query
|
||||
.OrderByDescending(o => o.Created)
|
||||
.Skip((pagination.PageNumber - 1) * pagination.PageSize)
|
||||
.Take(pagination.PageSize)
|
||||
.Select(o => new AdminOrderDto
|
||||
.Select(o => new
|
||||
{
|
||||
o.Id,
|
||||
o.UserId,
|
||||
FirstName = o.User.FirstName,
|
||||
LastName = o.User.LastName,
|
||||
Mobile = o.User.Mobile,
|
||||
o.TotalAmount,
|
||||
o.DiscountBalanceUsed,
|
||||
o.GatewayAmountPaid,
|
||||
o.VatAmount,
|
||||
o.PaymentStatus,
|
||||
o.PaymentDate,
|
||||
o.DeliveryStatus,
|
||||
ShippingAddress = o.UserAddress.Address,
|
||||
ReceiverName = o.UserAddress.Title,
|
||||
o.TrackingCode,
|
||||
AdminNote = o.DeliveryDescription,
|
||||
o.Created,
|
||||
o.LastModified,
|
||||
ItemsCount = o.OrderDetails.Count
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var orders = rows.Select(o => new AdminOrderDto
|
||||
{
|
||||
Id = o.Id,
|
||||
UserId = o.UserId,
|
||||
UserFullName = (o.User.FirstName ?? "") + " " + (o.User.LastName ?? ""),
|
||||
UserMobile = o.User.Mobile,
|
||||
UserFullName = UserDisplayName.From(o.FirstName, o.LastName, o.Mobile, o.UserId),
|
||||
UserMobile = o.Mobile,
|
||||
TotalAmount = o.TotalAmount,
|
||||
DiscountBalanceUsed = o.DiscountBalanceUsed,
|
||||
GatewayAmountPaid = o.GatewayAmountPaid,
|
||||
@@ -97,17 +122,16 @@ public class GetAllDiscountOrdersQueryHandler : IRequestHandler<GetAllDiscountOr
|
||||
PaymentStatus = o.PaymentStatus,
|
||||
PaymentDate = o.PaymentDate,
|
||||
DeliveryStatus = o.DeliveryStatus,
|
||||
DeliveryDate = null, // TODO: Add DeliveryDate to DiscountOrder if needed
|
||||
ShippingAddress = o.UserAddress.Address,
|
||||
ReceiverName = o.UserAddress.Title,
|
||||
ReceiverMobile = o.User.Mobile,
|
||||
DeliveryDate = null,
|
||||
ShippingAddress = o.ShippingAddress,
|
||||
ReceiverName = o.ReceiverName,
|
||||
ReceiverMobile = o.Mobile,
|
||||
TrackingCode = o.TrackingCode,
|
||||
AdminNote = o.DeliveryDescription,
|
||||
AdminNote = o.AdminNote,
|
||||
Created = o.Created,
|
||||
LastModified = o.LastModified,
|
||||
ItemsCount = o.OrderDetails.Count
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
ItemsCount = o.ItemsCount
|
||||
}).ToList();
|
||||
|
||||
return new GetAllDiscountOrdersResponseDto
|
||||
{
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ public class UserAddressDto
|
||||
public string Title { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
/// <summary>شماره تماس سفارشدهنده (موبایل کاربر) برای برچسب پست</summary>
|
||||
public string? Phone { get; set; }
|
||||
}
|
||||
|
||||
public class OrderItemDto
|
||||
|
||||
+3
-1
@@ -25,6 +25,7 @@ public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, Order
|
||||
|
||||
var order = await query
|
||||
.Include(o => o.UserAddress)
|
||||
.Include(o => o.User)
|
||||
.Include(o => o.OrderDetails)
|
||||
.ThenInclude(od => od.Product)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
@@ -50,7 +51,8 @@ public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, Order
|
||||
{
|
||||
Title = order.UserAddress.Title,
|
||||
Address = order.UserAddress.Address,
|
||||
PostalCode = order.UserAddress.PostalCode
|
||||
PostalCode = order.UserAddress.PostalCode,
|
||||
Phone = order.User?.Mobile
|
||||
},
|
||||
Items = order.OrderDetails.Select(od => new OrderItemDto
|
||||
{
|
||||
|
||||
+12
-2
@@ -150,8 +150,18 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
|
||||
|
||||
await _context.UserWalletHistories.AddAsync(walletLog, cancellationToken);
|
||||
|
||||
// 9. تنظیم روش خرید پکیج
|
||||
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
|
||||
// 9. تنظیم روش خرید پکیج + ثبت ledger خرید دستی
|
||||
user.PackagePurchaseMethod = PackagePurchaseMethod.Manual;
|
||||
|
||||
_context.UserPackagePurchases.Add(new UserPackagePurchase
|
||||
{
|
||||
UserId = request.UserId,
|
||||
PackageId = package.Id,
|
||||
PurchaseMethod = PackagePurchaseMethod.Manual,
|
||||
PurchasedAt = DateTime.Now,
|
||||
Amount = balanceAmount,
|
||||
TransactionId = transaction.Id
|
||||
});
|
||||
|
||||
// 10. ذخیره همه تغییرات
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler<Proc
|
||||
};
|
||||
await _context.UserWalletHistories.AddAsync(balanceLog, cancellationToken);
|
||||
|
||||
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
|
||||
user.PackagePurchaseMethod = PackagePurchaseMethod.Manual;
|
||||
// 10. بهروزرسانی ManualPayment با TransactionId
|
||||
manualPayment.TransactionId = transaction.Id;
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
+4
-1
@@ -1,3 +1,4 @@
|
||||
using CMSMicroservice.Application.Common;
|
||||
using CMSMicroservice.Application.Common.Exceptions;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
@@ -50,8 +51,10 @@ public class GetCustomerOrderQueryHandler : IRequestHandler<GetCustomerOrderQuer
|
||||
DeliveryStatus = order.DeliveryStatus,
|
||||
TrackingCode = order.TrackingCode ?? "",
|
||||
DeliveryDescription = order.DeliveryDescription ?? "",
|
||||
UserFullName = $"{order.User?.FirstName ?? ""} {order.User?.LastName ?? ""}".Trim(),
|
||||
UserFullName = UserDisplayName.From(order.User),
|
||||
UserNationalCode = order.User?.NationalCode ?? "",
|
||||
PostalCode = order.UserAddress?.PostalCode ?? "",
|
||||
UserMobile = order.User?.Mobile ?? "",
|
||||
VatAmount = order.OrderVAT?.VATAmount ?? 0,
|
||||
VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
|
||||
FactorDetails = order.FactorDetails?.Select(fd => new FactorDetailDto
|
||||
|
||||
+2
@@ -20,6 +20,8 @@ public class GetCustomerOrderResponseDto
|
||||
public string DeliveryDescription { get; set; }
|
||||
public string UserFullName { get; set; }
|
||||
public string UserNationalCode { get; set; }
|
||||
public string PostalCode { get; set; } = string.Empty;
|
||||
public string UserMobile { get; set; } = string.Empty;
|
||||
public long VatAmount { get; set; }
|
||||
public double VatPercentage { get; set; }
|
||||
}
|
||||
|
||||
+2
@@ -113,6 +113,7 @@ public class GetCustomerOrderHistoryQueryHandler : IRequestHandler<GetCustomerOr
|
||||
DeliveryStatus.Delivered => 4,
|
||||
DeliveryStatus.Cancelled => 5,
|
||||
DeliveryStatus.Returned => 6,
|
||||
DeliveryStatus.ReadyForOfficePickup => 7,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
@@ -127,6 +128,7 @@ public class GetCustomerOrderHistoryQueryHandler : IRequestHandler<GetCustomerOr
|
||||
DeliveryStatus.Delivered => "تحویل داده شد",
|
||||
DeliveryStatus.Cancelled => "لغو شده",
|
||||
DeliveryStatus.Returned => "مرجوع شده",
|
||||
DeliveryStatus.ReadyForOfficePickup => "آماده تحویل در دفتر",
|
||||
_ => "نامشخص"
|
||||
};
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
using CMSMicroservice.Application.Common;
|
||||
using CMSMicroservice.Application.Common.Extensions;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
@@ -72,7 +73,7 @@ public class GetCustomerOrdersQueryHandler : IRequestHandler<GetCustomerOrdersQu
|
||||
DeliveryStatus = order.DeliveryStatus,
|
||||
TrackingCode = order.TrackingCode ?? "",
|
||||
DeliveryDescription = order.DeliveryDescription ?? "",
|
||||
UserFullName = $"{order.User?.FirstName ?? ""} {order.User?.LastName ?? ""}".Trim(),
|
||||
UserFullName = UserDisplayName.From(order.User),
|
||||
UserNationalCode = order.User?.NationalCode ?? "",
|
||||
VatAmount = order.OrderVAT?.VATAmount ?? 0,
|
||||
VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||
|
||||
public record GetCustomerPackagePurchaseRollupQuery : IRequest<GetCustomerPackagePurchaseRollupResponseDto>
|
||||
{
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
public GetCustomerPackagePurchaseRollupFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerPackagePurchaseRollupFilter
|
||||
{
|
||||
public long? UserId { get; set; }
|
||||
public PackagePurchaseMethod? PurchaseMethod { get; set; }
|
||||
public DateTime? PurchasedFrom { get; set; }
|
||||
public DateTime? PurchasedTo { get; set; }
|
||||
}
|
||||
|
||||
public class GetCustomerPackagePurchaseRollupResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; } = new();
|
||||
public List<CustomerPackagePurchaseRollupModel> Models { get; set; } = new();
|
||||
}
|
||||
|
||||
public class CustomerPackagePurchaseRollupModel
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string UserMobile { get; set; } = string.Empty;
|
||||
|
||||
public long FirstPackageId { get; set; }
|
||||
public string FirstPackageName { get; set; } = string.Empty;
|
||||
public long FirstAmount { get; set; }
|
||||
public DateTime FirstPurchasedAt { get; set; }
|
||||
|
||||
public long LastPackageId { get; set; }
|
||||
public string LastPackageName { get; set; } = string.Empty;
|
||||
public long LastAmount { get; set; }
|
||||
public DateTime LastPurchasedAt { get; set; }
|
||||
public PackagePurchaseMethod LastPurchaseMethod { get; set; }
|
||||
|
||||
public int PurchaseCount { get; set; }
|
||||
public long TotalAmount { get; set; }
|
||||
|
||||
public int DayaCount { get; set; }
|
||||
public long DayaAmount { get; set; }
|
||||
public int ManualCount { get; set; }
|
||||
public long ManualAmount { get; set; }
|
||||
public int GatewayCount { get; set; }
|
||||
public long GatewayAmount { get; set; }
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||
|
||||
public class GetCustomerPackagePurchaseRollupQueryHandler
|
||||
: IRequestHandler<GetCustomerPackagePurchaseRollupQuery, GetCustomerPackagePurchaseRollupResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetCustomerPackagePurchaseRollupQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerPackagePurchaseRollupResponseDto> Handle(
|
||||
GetCustomerPackagePurchaseRollupQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var filter = request.Filter;
|
||||
var pagination = request.PaginationState ?? new PaginationState { PageNumber = 1, PageSize = 20 };
|
||||
if (pagination.PageNumber < 1) pagination.PageNumber = 1;
|
||||
// PageSize == 0 → خروجی کامل (بدون صفحهبندی)، مثلاً Excel
|
||||
var exportAll = pagination.PageSize == 0;
|
||||
if (!exportAll && pagination.PageSize < 1) pagination.PageSize = 20;
|
||||
|
||||
// خرید معتبر: بدون تراکنش یا تراکنش موفق
|
||||
var purchases = _context.UserPackagePurchases
|
||||
.AsNoTracking()
|
||||
.Include(x => x.User)
|
||||
.Include(x => x.Package)
|
||||
.Include(x => x.Transaction)
|
||||
.Where(x => x.TransactionId == null
|
||||
|| (x.Transaction != null && x.Transaction.PaymentStatus == PaymentStatus.Success));
|
||||
|
||||
if (filter?.UserId is > 0)
|
||||
purchases = purchases.Where(x => x.UserId == filter.UserId.Value);
|
||||
|
||||
if (filter?.PurchaseMethod != null)
|
||||
purchases = purchases.Where(x => x.PurchaseMethod == filter.PurchaseMethod.Value);
|
||||
|
||||
if (filter?.PurchasedFrom != null)
|
||||
purchases = purchases.Where(x => x.PurchasedAt >= filter.PurchasedFrom.Value);
|
||||
|
||||
if (filter?.PurchasedTo != null)
|
||||
purchases = purchases.Where(x => x.PurchasedAt <= filter.PurchasedTo.Value);
|
||||
|
||||
var rows = await purchases
|
||||
.Select(x => new
|
||||
{
|
||||
x.UserId,
|
||||
FirstName = x.User != null ? x.User.FirstName : null,
|
||||
LastName = x.User != null ? x.User.LastName : null,
|
||||
Mobile = x.User != null ? x.User.Mobile : null,
|
||||
x.PackageId,
|
||||
PackageName = x.Package != null ? x.Package.Title : null,
|
||||
x.Amount,
|
||||
x.PurchasedAt,
|
||||
x.PurchaseMethod
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var grouped = rows
|
||||
.GroupBy(x => x.UserId)
|
||||
.Select(g =>
|
||||
{
|
||||
var ordered = g.OrderBy(x => x.PurchasedAt).ThenBy(x => x.PackageId).ToList();
|
||||
var first = ordered.First();
|
||||
var last = ordered.Last();
|
||||
var userName = string.Join(" ",
|
||||
new[] { first.FirstName, first.LastName }.Where(s => !string.IsNullOrWhiteSpace(s))).Trim();
|
||||
|
||||
return new CustomerPackagePurchaseRollupModel
|
||||
{
|
||||
UserId = g.Key,
|
||||
UserName = string.IsNullOrWhiteSpace(userName)
|
||||
? (!string.IsNullOrWhiteSpace(first.Mobile) ? first.Mobile! : $"کاربر {g.Key}")
|
||||
: userName,
|
||||
UserMobile = first.Mobile ?? string.Empty,
|
||||
|
||||
FirstPackageId = first.PackageId,
|
||||
FirstPackageName = first.PackageName ?? string.Empty,
|
||||
FirstAmount = first.Amount,
|
||||
FirstPurchasedAt = first.PurchasedAt,
|
||||
|
||||
LastPackageId = last.PackageId,
|
||||
LastPackageName = last.PackageName ?? string.Empty,
|
||||
LastAmount = last.Amount,
|
||||
LastPurchasedAt = last.PurchasedAt,
|
||||
LastPurchaseMethod = last.PurchaseMethod,
|
||||
|
||||
PurchaseCount = ordered.Count,
|
||||
TotalAmount = ordered.Sum(x => x.Amount),
|
||||
|
||||
DayaCount = ordered.Count(x => x.PurchaseMethod == PackagePurchaseMethod.DayaLoan),
|
||||
DayaAmount = ordered.Where(x => x.PurchaseMethod == PackagePurchaseMethod.DayaLoan).Sum(x => x.Amount),
|
||||
ManualCount = ordered.Count(x => x.PurchaseMethod == PackagePurchaseMethod.Manual),
|
||||
ManualAmount = ordered.Where(x => x.PurchaseMethod == PackagePurchaseMethod.Manual).Sum(x => x.Amount),
|
||||
GatewayCount = ordered.Count(x => x.PurchaseMethod == PackagePurchaseMethod.DirectPurchase),
|
||||
GatewayAmount = ordered.Where(x => x.PurchaseMethod == PackagePurchaseMethod.DirectPurchase).Sum(x => x.Amount)
|
||||
};
|
||||
})
|
||||
.OrderByDescending(x => x.LastPurchasedAt)
|
||||
.ToList();
|
||||
|
||||
var totalCount = grouped.Count;
|
||||
var pageNumber = exportAll ? 1 : pagination.PageNumber;
|
||||
var pageSize = exportAll ? totalCount : pagination.PageSize;
|
||||
var totalPage = exportAll || pageSize <= 0
|
||||
? (totalCount > 0 ? 1 : 0)
|
||||
: (int)Math.Ceiling(totalCount / (double)pageSize);
|
||||
|
||||
var pageModels = exportAll
|
||||
? grouped
|
||||
: grouped
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToList();
|
||||
|
||||
return new GetCustomerPackagePurchaseRollupResponseDto
|
||||
{
|
||||
MetaData = new MetaData
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = totalCount,
|
||||
TotalPage = totalPage,
|
||||
HasPrevious = !exportAll && pageNumber > 1,
|
||||
HasNext = !exportAll && pageNumber < totalPage
|
||||
},
|
||||
Models = pageModels
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -15,5 +15,7 @@ public enum DeliveryStatus
|
||||
Returned = 4,
|
||||
// لغو شده
|
||||
Cancelled = 5,
|
||||
// آماده تحویل حضوری در دفتر
|
||||
ReadyForOfficePickup = 6,
|
||||
}
|
||||
|
||||
|
||||
@@ -18,5 +18,10 @@ public enum PackagePurchaseMethod
|
||||
/// <summary>
|
||||
/// از طریق پرداخت مستقیم درگاه بانکی
|
||||
/// </summary>
|
||||
DirectPurchase = 2
|
||||
DirectPurchase = 2,
|
||||
|
||||
/// <summary>
|
||||
/// ثبت دستی توسط ادمین
|
||||
/// </summary>
|
||||
Manual = 3
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.0.205</Version>
|
||||
<Version>0.0.208</Version>
|
||||
<DebugType>None</DebugType>
|
||||
<DebugSymbols>False</DebugSymbols>
|
||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||
|
||||
@@ -118,6 +118,8 @@ enum DeliveryStatus
|
||||
DELIVERY_SHIPPED = 2;
|
||||
DELIVERY_DELIVERED = 3;
|
||||
DELIVERY_CANCELLED = 4;
|
||||
DELIVERY_READY_FOR_OFFICE = 5;
|
||||
DELIVERY_RETURNED = 6;
|
||||
}
|
||||
|
||||
// Get Order By Id
|
||||
|
||||
@@ -102,6 +102,10 @@ enum DeliveryStatus
|
||||
DeliveryStatus_Delivered = 3;
|
||||
// مرجوع شده
|
||||
DeliveryStatus_Returned = 4;
|
||||
// لغو شده
|
||||
DeliveryStatus_Cancelled = 5;
|
||||
// آماده تحویل حضوری در دفتر
|
||||
DeliveryStatus_ReadyForOfficePickup = 6;
|
||||
}
|
||||
enum TransactionType
|
||||
{
|
||||
|
||||
@@ -220,6 +220,9 @@ message GetUserOrderResponse
|
||||
google.protobuf.StringValue user_national_code = 16;
|
||||
// اطلاعات مالیات بر ارزش افزوده
|
||||
OrderVATInfo vat_info = 17;
|
||||
// اطلاعات پستی برای برچسب کارتن
|
||||
google.protobuf.StringValue postal_code = 18;
|
||||
google.protobuf.StringValue user_mobile = 19;
|
||||
}
|
||||
|
||||
// اطلاعات مالیات بر ارزش افزوده
|
||||
|
||||
@@ -21,6 +21,11 @@ service UserPackagePurchaseContract
|
||||
get: "/UserPackagePurchase/GetSummary"
|
||||
};
|
||||
};
|
||||
rpc GetCustomerPackagePurchaseRollup(GetCustomerPackagePurchaseRollupRequest) returns (GetCustomerPackagePurchaseRollupResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/UserPackagePurchase/GetCustomerRollup"
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message GetAllUserPackagePurchaseByFilterRequest
|
||||
@@ -73,3 +78,51 @@ message GetUserPackagePurchaseSummaryResponse
|
||||
int64 total_count = 1;
|
||||
int64 total_amount = 2;
|
||||
}
|
||||
|
||||
message GetCustomerPackagePurchaseRollupRequest
|
||||
{
|
||||
messages.PaginationState pagination_state = 1;
|
||||
GetCustomerPackagePurchaseRollupFilter filter = 2;
|
||||
}
|
||||
|
||||
message GetCustomerPackagePurchaseRollupFilter
|
||||
{
|
||||
google.protobuf.Int64Value user_id = 1;
|
||||
google.protobuf.Int32Value purchase_method = 2;
|
||||
google.protobuf.Timestamp purchased_from = 3;
|
||||
google.protobuf.Timestamp purchased_to = 4;
|
||||
}
|
||||
|
||||
message GetCustomerPackagePurchaseRollupResponse
|
||||
{
|
||||
messages.MetaData meta_data = 1;
|
||||
repeated CustomerPackagePurchaseRollupModel models = 2;
|
||||
}
|
||||
|
||||
message CustomerPackagePurchaseRollupModel
|
||||
{
|
||||
int64 user_id = 1;
|
||||
string user_name = 2;
|
||||
string user_mobile = 3;
|
||||
|
||||
int64 first_package_id = 4;
|
||||
string first_package_name = 5;
|
||||
int64 first_amount = 6;
|
||||
google.protobuf.Timestamp first_purchased_at = 7;
|
||||
|
||||
int64 last_package_id = 8;
|
||||
string last_package_name = 9;
|
||||
int64 last_amount = 10;
|
||||
google.protobuf.Timestamp last_purchased_at = 11;
|
||||
int32 last_purchase_method = 12;
|
||||
|
||||
int32 purchase_count = 13;
|
||||
int64 total_amount = 14;
|
||||
|
||||
int32 daya_count = 15;
|
||||
int64 daya_amount = 16;
|
||||
int32 manual_count = 17;
|
||||
int64 manual_amount = 18;
|
||||
int32 gateway_count = 19;
|
||||
int64 gateway_amount = 20;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using CMSMicroservice.Domain.Enums;
|
||||
using Mapster;
|
||||
using AppUp = CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
using AppUpSummary = CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetUserPackagePurchaseSummary;
|
||||
using AppRollup = CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||
using ProtoUp = CMSMicroservice.Protobuf.Protos.UserPackagePurchase;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||
@@ -49,5 +50,41 @@ public class UserPackagePurchaseProfile : IRegister
|
||||
config.NewConfig<AppUpSummary.GetUserPackagePurchaseSummaryResponseDto, ProtoUp.GetUserPackagePurchaseSummaryResponse>()
|
||||
.Map(dest => dest.TotalCount, src => src.TotalCount)
|
||||
.Map(dest => dest.TotalAmount, src => src.TotalAmount);
|
||||
|
||||
config.NewConfig<ProtoUp.GetCustomerPackagePurchaseRollupRequest, AppRollup.GetCustomerPackagePurchaseRollupQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoUp.GetCustomerPackagePurchaseRollupFilter, AppRollup.GetCustomerPackagePurchaseRollupFilter>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.PurchaseMethod, src => src.PurchaseMethod == null ? null : (PackagePurchaseMethod?)src.PurchaseMethod)
|
||||
.Map(dest => dest.PurchasedFrom, src => src.PurchasedFrom != null ? src.PurchasedFrom.ToDateTime() : (DateTime?)null)
|
||||
.Map(dest => dest.PurchasedTo, src => src.PurchasedTo != null ? src.PurchasedTo.ToDateTime() : (DateTime?)null);
|
||||
|
||||
config.NewConfig<AppRollup.GetCustomerPackagePurchaseRollupResponseDto, ProtoUp.GetCustomerPackagePurchaseRollupResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppRollup.CustomerPackagePurchaseRollupModel, ProtoUp.CustomerPackagePurchaseRollupModel>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.UserName, src => src.UserName)
|
||||
.Map(dest => dest.UserMobile, src => src.UserMobile)
|
||||
.Map(dest => dest.FirstPackageId, src => src.FirstPackageId)
|
||||
.Map(dest => dest.FirstPackageName, src => src.FirstPackageName)
|
||||
.Map(dest => dest.FirstAmount, src => src.FirstAmount)
|
||||
.Map(dest => dest.FirstPurchasedAt, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.FirstPurchasedAt, DateTimeKind.Utc)))
|
||||
.Map(dest => dest.LastPackageId, src => src.LastPackageId)
|
||||
.Map(dest => dest.LastPackageName, src => src.LastPackageName)
|
||||
.Map(dest => dest.LastAmount, src => src.LastAmount)
|
||||
.Map(dest => dest.LastPurchasedAt, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.LastPurchasedAt, DateTimeKind.Utc)))
|
||||
.Map(dest => dest.LastPurchaseMethod, src => (int)src.LastPurchaseMethod)
|
||||
.Map(dest => dest.PurchaseCount, src => src.PurchaseCount)
|
||||
.Map(dest => dest.TotalAmount, src => src.TotalAmount)
|
||||
.Map(dest => dest.DayaCount, src => src.DayaCount)
|
||||
.Map(dest => dest.DayaAmount, src => src.DayaAmount)
|
||||
.Map(dest => dest.ManualCount, src => src.ManualCount)
|
||||
.Map(dest => dest.ManualAmount, src => src.ManualAmount)
|
||||
.Map(dest => dest.GatewayCount, src => src.GatewayCount)
|
||||
.Map(dest => dest.GatewayAmount, src => src.GatewayAmount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,20 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
||||
|
||||
public override async Task<UpdateOrderStatusResponse> UpdateOrderStatus(UpdateOrderStatusRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<UpdateOrderStatusRequest, UpdateOrderStatusCommand, UpdateOrderStatusResponse>(request, context);
|
||||
// Proto DeliveryStatus ≠ Domain DeliveryStatus — نگاشت صریح لازم است
|
||||
var command = new UpdateOrderStatusCommand
|
||||
{
|
||||
OrderId = request.OrderId,
|
||||
DeliveryStatus = MapProtoDeliveryToDomain(request.DeliveryStatus),
|
||||
TrackingCode = request.TrackingCode,
|
||||
AdminNotes = request.AdminNotes
|
||||
};
|
||||
var result = await _sender.Send(command, context.CancellationToken);
|
||||
return new UpdateOrderStatusResponse
|
||||
{
|
||||
Success = result.Success,
|
||||
Message = result.Message ?? string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
public override async Task<GetOrderByIdResponse> GetOrderById(GetOrderByIdRequest request, ServerCallContext context)
|
||||
@@ -141,6 +154,8 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
||||
Address = result.Address.Address ?? "",
|
||||
PostalCode = result.Address.PostalCode ?? ""
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(result.Address.Phone))
|
||||
response.Address.Phone = result.Address.Phone;
|
||||
}
|
||||
|
||||
foreach (var item in result.Items)
|
||||
@@ -197,9 +212,98 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<GetAllDiscountOrdersResponse> GetAllDiscountOrders(GetAllDiscountOrdersRequest request, ServerCallContext context)
|
||||
public override async Task<GetAllDiscountOrdersResponse> GetAllDiscountOrders(
|
||||
GetAllDiscountOrdersRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<GetAllDiscountOrdersRequest, GetAllDiscountOrdersQuery, GetAllDiscountOrdersResponse>(request, context);
|
||||
// Proto PaymentStatus ≠ Domain PaymentStatus (مقادیر int متفاوت) — Adapt خام باعث باگ لیست/فیلتر میشود
|
||||
if (request.PaymentStatus is 3) // PAYMENT_REFUNDED — در دامنه وجود ندارد
|
||||
{
|
||||
return new GetAllDiscountOrdersResponse
|
||||
{
|
||||
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||
{
|
||||
TotalCount = 0,
|
||||
PageSize = request.PageSize > 0 ? request.PageSize : 20,
|
||||
CurrentPage = request.PageNumber > 0 ? request.PageNumber : 1,
|
||||
TotalPage = 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var query = new GetAllDiscountOrdersQuery
|
||||
{
|
||||
PaginationQuery = new Application.Common.Models.PaginationState
|
||||
{
|
||||
PageNumber = request.PageNumber > 0 ? request.PageNumber : 1,
|
||||
PageSize = request.PageSize > 0 ? request.PageSize : 20
|
||||
},
|
||||
UserId = request.UserId,
|
||||
UserMobile = request.UserMobile,
|
||||
TrackingCode = request.TrackingCode,
|
||||
FromDate = request.FromDate?.ToDateTime(),
|
||||
ToDate = request.ToDate?.ToDateTime(),
|
||||
MinAmount = request.MinAmount,
|
||||
MaxAmount = request.MaxAmount
|
||||
};
|
||||
|
||||
if (request.PaymentStatus is int paymentStatus)
|
||||
query.PaymentStatus = MapProtoPaymentFilterToDomain(paymentStatus);
|
||||
|
||||
if (request.DeliveryStatus is int deliveryStatus)
|
||||
query.DeliveryStatus = MapProtoDeliveryFilterToDomain(deliveryStatus);
|
||||
|
||||
var result = await _sender.Send(query, context.CancellationToken);
|
||||
|
||||
var response = new GetAllDiscountOrdersResponse
|
||||
{
|
||||
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||
{
|
||||
TotalCount = result.MetaData.TotalCount,
|
||||
PageSize = result.MetaData.PageSize,
|
||||
CurrentPage = result.MetaData.CurrentPage,
|
||||
TotalPage = result.MetaData.TotalPage,
|
||||
HasPrevious = result.MetaData.HasPrevious,
|
||||
HasNext = result.MetaData.HasNext
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var o in result.Models)
|
||||
{
|
||||
var model = new CMSMicroservice.Protobuf.Protos.DiscountOrder.AdminOrderDto
|
||||
{
|
||||
Id = o.Id,
|
||||
UserId = o.UserId,
|
||||
UserFullName = o.UserFullName ?? string.Empty,
|
||||
UserMobile = o.UserMobile ?? string.Empty,
|
||||
TotalAmount = o.TotalAmount,
|
||||
DiscountBalanceUsed = o.DiscountBalanceUsed,
|
||||
GatewayAmountPaid = o.GatewayAmountPaid,
|
||||
VatAmount = o.VatAmount,
|
||||
PaymentStatus = MapPaymentStatus(o.PaymentStatus),
|
||||
DeliveryStatus = MapDeliveryStatus(o.DeliveryStatus),
|
||||
ItemsCount = o.ItemsCount,
|
||||
Created = Timestamp.FromDateTime(DateTime.SpecifyKind(o.Created, DateTimeKind.Utc))
|
||||
};
|
||||
|
||||
if (o.PaymentDate.HasValue)
|
||||
model.PaymentDate = Timestamp.FromDateTime(DateTime.SpecifyKind(o.PaymentDate.Value, DateTimeKind.Utc));
|
||||
if (o.LastModified.HasValue)
|
||||
model.LastModified = Timestamp.FromDateTime(DateTime.SpecifyKind(o.LastModified.Value, DateTimeKind.Utc));
|
||||
if (!string.IsNullOrWhiteSpace(o.ShippingAddress))
|
||||
model.ShippingAddress = o.ShippingAddress;
|
||||
if (!string.IsNullOrWhiteSpace(o.ReceiverName))
|
||||
model.ReceiverName = o.ReceiverName;
|
||||
if (!string.IsNullOrWhiteSpace(o.ReceiverMobile))
|
||||
model.ReceiverMobile = o.ReceiverMobile;
|
||||
if (!string.IsNullOrWhiteSpace(o.TrackingCode))
|
||||
model.TrackingCode = o.TrackingCode;
|
||||
if (!string.IsNullOrWhiteSpace(o.AdminNote))
|
||||
model.AdminNote = o.AdminNote;
|
||||
|
||||
response.Models.Add(model);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<GetDiscountSalesReportResponse> GetDiscountSalesReport(GetDiscountSalesReportRequest request, ServerCallContext context)
|
||||
@@ -359,14 +463,50 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
||||
_ => CMSMicroservice.Protobuf.Protos.DiscountOrder.PaymentStatus.PaymentPending
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// فیلتر UI/proto → دامنه: PENDING=0, COMPLETED=1, FAILED=2
|
||||
/// </summary>
|
||||
private static DomainEnums.PaymentStatus MapProtoPaymentFilterToDomain(int protoPaymentStatus) => protoPaymentStatus switch
|
||||
{
|
||||
1 => DomainEnums.PaymentStatus.Success, // PAYMENT_COMPLETED
|
||||
2 => DomainEnums.PaymentStatus.Reject, // PAYMENT_FAILED
|
||||
_ => DomainEnums.PaymentStatus.Pending // PAYMENT_PENDING (0) و پیشفرض
|
||||
};
|
||||
|
||||
private static DeliveryStatus MapDeliveryStatus(DomainEnums.DeliveryStatus status) => status switch
|
||||
{
|
||||
DomainEnums.DeliveryStatus.None => DeliveryStatus.DeliveryPending,
|
||||
DomainEnums.DeliveryStatus.Pending => DeliveryStatus.DeliveryProcessing,
|
||||
DomainEnums.DeliveryStatus.InTransit => DeliveryStatus.DeliveryShipped,
|
||||
DomainEnums.DeliveryStatus.Delivered => DeliveryStatus.DeliveryDelivered,
|
||||
DomainEnums.DeliveryStatus.Returned => DeliveryStatus.DeliveryCancelled,
|
||||
DomainEnums.DeliveryStatus.Cancelled => DeliveryStatus.DeliveryCancelled,
|
||||
DomainEnums.DeliveryStatus.ReadyForOfficePickup => DeliveryStatus.DeliveryReadyForOffice,
|
||||
DomainEnums.DeliveryStatus.Returned => DeliveryStatus.DeliveryReturned,
|
||||
_ => DeliveryStatus.DeliveryPending
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// فیلتر UI/proto → دامنه DeliveryStatus
|
||||
/// </summary>
|
||||
private static DomainEnums.DeliveryStatus MapProtoDeliveryFilterToDomain(int protoDeliveryStatus) => protoDeliveryStatus switch
|
||||
{
|
||||
1 => DomainEnums.DeliveryStatus.Pending, // DELIVERY_PROCESSING
|
||||
2 => DomainEnums.DeliveryStatus.InTransit, // DELIVERY_SHIPPED
|
||||
3 => DomainEnums.DeliveryStatus.Delivered, // DELIVERY_DELIVERED
|
||||
4 => DomainEnums.DeliveryStatus.Cancelled, // DELIVERY_CANCELLED
|
||||
5 => DomainEnums.DeliveryStatus.ReadyForOfficePickup, // DELIVERY_READY_FOR_OFFICE
|
||||
6 => DomainEnums.DeliveryStatus.Returned, // DELIVERY_RETURNED
|
||||
_ => DomainEnums.DeliveryStatus.None // DELIVERY_PENDING (0)
|
||||
};
|
||||
|
||||
private static DomainEnums.DeliveryStatus MapProtoDeliveryToDomain(DeliveryStatus status) => status switch
|
||||
{
|
||||
DeliveryStatus.DeliveryProcessing => DomainEnums.DeliveryStatus.Pending,
|
||||
DeliveryStatus.DeliveryShipped => DomainEnums.DeliveryStatus.InTransit,
|
||||
DeliveryStatus.DeliveryDelivered => DomainEnums.DeliveryStatus.Delivered,
|
||||
DeliveryStatus.DeliveryCancelled => DomainEnums.DeliveryStatus.Cancelled,
|
||||
DeliveryStatus.DeliveryReadyForOffice => DomainEnums.DeliveryStatus.ReadyForOfficePickup,
|
||||
DeliveryStatus.DeliveryReturned => DomainEnums.DeliveryStatus.Returned,
|
||||
_ => DomainEnums.DeliveryStatus.None
|
||||
};
|
||||
}
|
||||
|
||||
@@ -121,7 +121,9 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
TrackingCode = result.TrackingCode,
|
||||
DeliveryDescription = result.DeliveryDescription,
|
||||
UserFullName = result.UserFullName,
|
||||
UserNationalCode = result.UserNationalCode
|
||||
UserNationalCode = result.UserNationalCode,
|
||||
PostalCode = result.PostalCode,
|
||||
UserMobile = result.UserMobile
|
||||
};
|
||||
|
||||
// VAT Info
|
||||
@@ -789,7 +791,9 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
TrackingCode = result.TrackingCode,
|
||||
DeliveryDescription = result.DeliveryDescription,
|
||||
UserFullName = result.UserFullName,
|
||||
UserNationalCode = result.UserNationalCode
|
||||
UserNationalCode = result.UserNationalCode,
|
||||
PostalCode = result.PostalCode,
|
||||
UserMobile = result.UserMobile
|
||||
};
|
||||
|
||||
// VAT Info
|
||||
@@ -1054,6 +1058,7 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
|
||||
Domain.Enums.DeliveryStatus.Delivered => "تحویل داده شده",
|
||||
Domain.Enums.DeliveryStatus.Returned => "مرجوع شده",
|
||||
Domain.Enums.DeliveryStatus.Cancelled => "لغو شده",
|
||||
Domain.Enums.DeliveryStatus.ReadyForOfficePickup => "آماده تحویل در دفتر",
|
||||
_ => status.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using CMSMicroservice.Protobuf.Protos.UserPackagePurchase;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
using CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetUserPackagePurchaseSummary;
|
||||
using CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
@@ -18,4 +19,8 @@ public class UserPackagePurchaseService : UserPackagePurchaseContract.UserPackag
|
||||
public override Task<GetUserPackagePurchaseSummaryResponse> GetUserPackagePurchaseSummary(
|
||||
GetUserPackagePurchaseSummaryRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetUserPackagePurchaseSummaryRequest, GetUserPackagePurchaseSummaryQuery, GetUserPackagePurchaseSummaryResponse>(request, context);
|
||||
|
||||
public override Task<GetCustomerPackagePurchaseRollupResponse> GetCustomerPackagePurchaseRollup(
|
||||
GetCustomerPackagePurchaseRollupRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetCustomerPackagePurchaseRollupRequest, GetCustomerPackagePurchaseRollupQuery, GetCustomerPackagePurchaseRollupResponse>(request, context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user