191 lines
6.8 KiB
C#
191 lines
6.8 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using StopShopping.EF;
|
|
using StopShopping.Services.Extensions;
|
|
using StopShopping.Services.Models;
|
|
using StopShopping.Services.Models.Req;
|
|
using StopShopping.Services.Models.Resp;
|
|
|
|
namespace StopShopping.Services.Implementions;
|
|
|
|
public class RequestService : IRequestService
|
|
{
|
|
public RequestService(
|
|
StopShoppingContext dbContext,
|
|
IClaimsService claimsService,
|
|
ISerialNoGenerator serialNoGenerator)
|
|
{
|
|
_dbContext = dbContext;
|
|
_claimService = claimsService;
|
|
_serialNoGenerator = serialNoGenerator;
|
|
}
|
|
|
|
private readonly StopShoppingContext _dbContext;
|
|
private readonly IClaimsService _claimService;
|
|
private readonly ISerialNoGenerator _serialNoGenerator;
|
|
|
|
public async Task<ApiResponse> PublishRequestAsync(CreateRequestParams model)
|
|
{
|
|
var serialNo = _serialNoGenerator.GenerateRequestNo();
|
|
var userId = _claimService.GetCurrentUserId()!.Value;
|
|
|
|
EF.Models.Request req = new()
|
|
{
|
|
CategoryId = model.CategoryId,
|
|
Deadline = DateOnly.Parse(model.Deadline),
|
|
Description = model.Description,
|
|
Name = model.Name,
|
|
PublisherId = userId,
|
|
SerialNo = serialNo,
|
|
Status = (short)RequestStatus.Publish,
|
|
};
|
|
|
|
await _dbContext.Requests.AddAsync(req);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
return ApiResponse.Succed();
|
|
}
|
|
|
|
public async Task<ApiResponse<PagedResult<Request>>> SearchAsync(RequestSearchParams model)
|
|
{
|
|
return await DoSearchAsync(model, null);
|
|
}
|
|
|
|
public async Task<ApiResponse<PagedResult<Request>>> RequestOrderSearchAsync(RequestSearchWithStatusParams model)
|
|
{
|
|
return await DoSearchAsync(model, UserRoles.Buyer);
|
|
}
|
|
|
|
public async Task<ApiResponse<PagedResult<Request>>> ReplyOrderSearchAsync(RequestSearchWithStatusParams model)
|
|
{
|
|
return await DoSearchAsync(model, UserRoles.Seller);
|
|
}
|
|
|
|
public async Task<ApiResponse> DeleteRequestAsync(RequestIdParams model)
|
|
{
|
|
var userId = _claimService.GetCurrentUserId()!.Value;
|
|
|
|
var request = await _dbContext.Requests
|
|
.Include(r => r.Replies)
|
|
.Where(r => r.Id == model.RequestId && !r.Deleted)
|
|
.FirstOrDefaultAsync();
|
|
|
|
if (null == request)
|
|
return ApiResponse.Failed("此需求已不存在,请刷新重试");
|
|
|
|
var status = (RequestStatus)request.Status;
|
|
if (status.CanDelete())
|
|
return ApiResponse.Failed("此需求状态已改变,请刷新重试");
|
|
|
|
request.Deleted = true;
|
|
request.Status = (short)RequestStatus.Completed;
|
|
|
|
foreach (var reply in request.Replies)
|
|
{
|
|
reply.Rejected = true;
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
return ApiResponse.Succed();
|
|
}
|
|
|
|
private async Task<ApiResponse<PagedResult<Request>>> DoSearchAsync<T>(T model, UserRoles? userRoles)
|
|
where T : RequestSearchParams, new()
|
|
{
|
|
var qry = _dbContext.Requests
|
|
.AsNoTracking()
|
|
.Where(q => !q.Deleted);
|
|
|
|
if (model is RequestSearchWithStatusParams statusParams)
|
|
{
|
|
if (statusParams.Status != RequestStatus.All)
|
|
qry = qry.Where(q => q.Status == (short)statusParams.Status);
|
|
}
|
|
else
|
|
{
|
|
qry = qry.Where(q => q.Status == (short)RequestStatus.Publish
|
|
|| q.Status == (short)RequestStatus.Replied);
|
|
}
|
|
|
|
if (model.CategoryId > 0)
|
|
{
|
|
string categoryPath = $"/{model.CategoryId.Value}/";
|
|
qry = qry.Where(q =>
|
|
_dbContext.Categories
|
|
.Where(c => c.Path.StartsWith(categoryPath) && !c.Deleted)
|
|
.Select(c => c.Id)
|
|
.Contains(q.CategoryId));
|
|
}
|
|
if (!string.IsNullOrEmpty(model.Keyword))
|
|
{
|
|
qry = qry.Where(q =>
|
|
q.Name.Contains(model.Keyword)
|
|
|| (q.Description != null && q.Description.Contains(model.Keyword))
|
|
|| q.SerialNo.Contains(model.Keyword));
|
|
}
|
|
|
|
if (userRoles.HasValue)
|
|
{
|
|
var userId = _claimService.GetCurrentUserId()!.Value;
|
|
qry = userRoles.Value switch
|
|
{
|
|
UserRoles.Seller => qry.Where(q => q.Replies.Any(r => r.UserId == userId)),
|
|
UserRoles.Buyer => qry.Where(q => q.PublisherId == userId),
|
|
_ => qry
|
|
};
|
|
}
|
|
|
|
var firstOrderBy = model.OrderBys!.First();
|
|
var included = qry
|
|
.Include(r => r.Publisher).AsNoTracking()
|
|
.Include(r => r.Category).AsNoTracking()
|
|
.Select(r => new
|
|
{
|
|
ReplyAmount = r.Replies.Count,
|
|
r
|
|
});
|
|
|
|
var ordered = firstOrderBy switch
|
|
{
|
|
RequestOrderBys.PublishTime => included.OrderBy(q => q.r.PublishTime),
|
|
RequestOrderBys.PublishTimeDesc => included.OrderByDescending(q => q.r.PublishTime),
|
|
RequestOrderBys.CategoryId => included.OrderBy(q => q.r.CategoryId),
|
|
RequestOrderBys.CategoryIdDesc => included.OrderByDescending(q => q.r.CategoryId),
|
|
RequestOrderBys.ReplyAmount => included.OrderBy(q => q.ReplyAmount),
|
|
RequestOrderBys.ReplyAmountDesc => included.OrderByDescending(q => q.ReplyAmount),
|
|
_ => included.OrderBy(q => q.r.PublishTime)
|
|
};
|
|
|
|
foreach (var orderBy in model.OrderBys!.Skip(1))
|
|
{
|
|
ordered = orderBy switch
|
|
{
|
|
RequestOrderBys.PublishTime => ordered!.ThenBy(q => q.r.PublishTime),
|
|
RequestOrderBys.PublishTimeDesc => ordered!.ThenByDescending(q => q.r.PublishTime),
|
|
RequestOrderBys.CategoryId => ordered!.ThenBy(q => q.r.CategoryId),
|
|
RequestOrderBys.CategoryIdDesc => ordered!.ThenByDescending(q => q.r.CategoryId),
|
|
RequestOrderBys.ReplyAmount => ordered!.ThenBy(q => q.ReplyAmount),
|
|
RequestOrderBys.ReplyAmountDesc => ordered!.ThenByDescending(q => q.ReplyAmount),
|
|
_ => ordered!.ThenBy(q => q.r.PublishTime)
|
|
};
|
|
}
|
|
|
|
var paged = await ordered.Select(r => new Request
|
|
{
|
|
CategoryId = r.r.Category.Id,
|
|
CategoryName = r.r.Category.Name,
|
|
Deadline = r.r.Deadline.ToFormatted(),
|
|
Description = r.r.Description,
|
|
Id = r.r.Id,
|
|
Name = r.r.Name,
|
|
Publisher = r.r.Publisher.NickName,
|
|
PublishTime = r.r.PublishTime.ToFormatted(),
|
|
ReplyAmount = r.ReplyAmount,
|
|
SerialNo = r.r.SerialNo,
|
|
Status = (RequestStatus)r.r.Status,
|
|
|
|
}).ToAsyncEnumerable().ToPagedAsync(model.PageIndex, model.PageSize);
|
|
|
|
return new ApiResponse<PagedResult<Request>>(paged);
|
|
}
|
|
} |