Files
caliverse_server/BrokerApiCore/Repository/PlanetItemExchangeOrderRepo.cs
2025-05-01 07:23:28 +09:00

290 lines
9.4 KiB
C#

using Microsoft.EntityFrameworkCore;
using ServerBase;
namespace BrokerApiCore;
public class PlanetItemExchangeOrderRepo
{
private readonly MetaverseBrokerDbContext m_db_context;
public PlanetItemExchangeOrderRepo(MetaverseBrokerDbContext dbContext)
{
m_db_context = dbContext;
}
//================================================================================
// 교환 주문을 추가한다.
// 트랜잭션을 사용한다.
//================================================================================
public async Task<Result> add(PlanetItemExchangeOrder order, CancellationToken cancellationToken = default)
{
try
{
m_db_context.PlanetItemExchangeOrders.Add(order);
await m_db_context.SaveChangesAsync(cancellationToken);
}
catch (Exception e)
{
return new Result { ErrorCode = ServerErrorCode.RdbError, ResultString = e.Message };
}
return new Result();
}
// public async Task<Result> add(PlanetItemExchangeOrder order,
// CancellationToken cancellationToken = default)
// {
// var result = new Result();
//
// // 실행 전략 생성
// var strategy = m_db_context.Database.CreateExecutionStrategy();
//
// // 실행 전략을 사용하여 트랜잭션 작업을 실행
// await strategy.ExecuteAsync(async () =>
// {
// // 트랜잭션 시작
// await using var transaction = await m_db_context.Database.BeginTransactionAsync(cancellationToken);
// try
// {
// var order_date_utc = order.CreatedAt.ToUniversalTime().Date; // UTC 기준 주문일의 자정(00:00:00)
//
// // 단일 쿼리로 total_exchange_count와 user_exchange_count를 함께 조회
// var exchange_counts = await m_db_context.PlanetItemExchangeOrders
// .Where(x => x.PlanetId == order.PlanetId &&
// x.ExchangeMetaId == order.ExchangeMetaId &&
// x.CreatedAt >= order_date_utc && x.CreatedAt < order_date_utc.AddDays(1))
// .GroupBy(x => 1)
// .Select(g => new
// {
// TotalCount = g.Sum(x => x.ExchangeMetaAmount),
// UserCount = g.Where(x => x.UserGuid == order.UserGuid).Sum(x => x.ExchangeMetaAmount)
// })
// .FirstOrDefaultAsync(cancellationToken);
//
// var total_exchange_count = exchange_counts?.TotalCount ?? 0;
// var user_exchange_count = exchange_counts?.UserCount ?? 0;
//
// if (total_exchange_count + order.ExchangeMetaAmount > dailyLimit)
// {
// result.setFail(ServerErrorCode.ExchangeTotalOrderDailyLimitExceeded,
// $"일일 총 구매 제한 초과 => {order.ExchangeMetaId} Total exchange count {total_exchange_count} + order amount {order.ExchangeMetaAmount} > daily total limit {dailyLimit}");
// return;
// }
//
// if (user_exchange_count + order.ExchangeMetaAmount > dailyUserLimit)
// {
// result.setFail(ServerErrorCode.ExchangeUserOrderDailyLimitExceeded,
// $"일일 개인 구매 제한 초과 => {order.ExchangeMetaId} User exchange count {user_exchange_count} + order amount {order.ExchangeMetaAmount} > daily user limit {dailyUserLimit}");
// return;
// }
//
// m_db_context.PlanetItemExchangeOrders.Add(order);
// m_
//
// await m_db_context.SaveChangesAsync(cancellationToken);
// await transaction.CommitAsync(cancellationToken);
// }
// catch (Exception e)
// {
// result.setFail(ServerErrorCode.InternalServerError, e.Message);
// }
// });
//
// return result;
// }
public async Task<Result> delete(PlanetItemExchangeOrder order, CancellationToken cancellationToken = default)
{
var result = new Result();
try
{
m_db_context.PlanetItemExchangeOrders.Remove(order);
await m_db_context.SaveChangesAsync(cancellationToken);
}
catch (Exception e)
{
result.setFail(ServerErrorCode.InternalServerError, e.Message);
}
return result;
}
//================================================================================
// 교환 주문을 비동기로 업데이트한다.
// OrderId를 키로 사용한다.
// OrderType과 OrderCompletedAt만 업데이트한다.
//================================================================================
public async Task<(Result, PlanetItemExchangeOrder?)> findAndUpdateStatus(string orderId,
ExchangeOrderStatus orderStatus,
CancellationToken cancellationToken = default)
{
var result = new Result();
try
{
var order = await m_db_context.PlanetItemExchangeOrders.Where(x => x.OrderId == orderId)
.FirstOrDefaultAsync(cancellationToken);
if (order == null)
{
result.setFail(ServerErrorCode.ExchangeOrderIdNotFound, $"Order not found: {orderId}");
return (result, null);
}
order.OrderStatus = orderStatus;
order.CompletedAt = DateTime.UtcNow;
m_db_context.PlanetItemExchangeOrders.Attach(order);
m_db_context.Entry(order).Property(x => x.OrderStatus).IsModified = true;
m_db_context.Entry(order).Property(x => x.CompletedAt).IsModified = true;
await m_db_context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
return (new Result(), order);
}
catch (Exception e)
{
// await transaction.RollbackAsync(cancellationToken).ConfigureAwait(false);
return (new Result { ResultString = e.Message }, null);
}
}
public async Task<(Result, PlanetItemExchangeOrder?)> findOne(string orderId,
ExchangeOrderStatus orderStatus,
CancellationToken cancellationToken = default)
{
try
{
var order = await m_db_context.PlanetItemExchangeOrders
.Where(x => x.OrderId == orderId && x.OrderStatus == orderStatus)
.FirstOrDefaultAsync(cancellationToken);
return (new Result(), order);
}
catch (Exception e)
{
return (new Result { ErrorCode = ServerErrorCode.RdbError, ResultString = e.Message }, null);
}
}
// public async Task<Result> updateForPending(SapphireExchangeOrder order,
// CancellationToken cancellationToken = default)
// {
// // await using var transaction = await m_db_context.Database.BeginTransactionAsync(cancellationToken);
// try
// {
// m_db_context.SapphireExchangeOrders.Attach(order);
// m_db_context.Entry(order).Property(x => x.OrderStatus).IsModified = true;
// await m_db_context.SaveChangesAsync(cancellationToken);
// // await transaction.CommitAsync(cancellationToken);
// return new Result();
// }
// catch (Exception e)
// {
// // await transaction.RollbackAsync(cancellationToken);
// return new Result { ResultString = e.Message };
// }
// }
//==========================================================================
//SELECT *
// FROM `sapphire_exchange_order`
// WHERE `PlanetId` = @planetId
// AND `UserGuid` = @userGuid
// AND (@orderStatus IS NULL OR `OrderStatus` = @orderStatus)
// ORDER BY `CreatedAt` ASC
// LIMIT @pageSize OFFSET @offset;
//==========================================================================
public async Task<(Result, IEnumerable<PlanetItemExchangeOrder>?, int)> findList(
string planetId,
string metaId,
string seasonId,
string userGuid,
ExchangeOrderStatus? orderStatus = null,
int pageIndex = 1,
int pageSize = 20,
string sortOrder = "asc",
CancellationToken cancellationToken = default)
{
var result = new Result();
try
{
var query = m_db_context.PlanetItemExchangeOrders.AsQueryable();
if (!string.IsNullOrEmpty(planetId))
{
query = query.Where(x => x.PlanetId == planetId);
}
if (!string.IsNullOrEmpty(metaId))
{
query = query.Where(x => x.ExchangeMetaId == metaId);
}
if (!string.IsNullOrEmpty(seasonId))
{
query = query.Where(x => x.SeasonId == seasonId);
}
if (!string.IsNullOrEmpty(userGuid))
{
query = query.Where(x => x.UserGuid == userGuid);
}
if (orderStatus.HasValue)
{
query = query.Where(x => x.OrderStatus == orderStatus);
}
query = sortOrder.ToLower() == "desc"
? query.OrderByDescending(o => o.CreatedAt)
: query.OrderBy(o => o.CreatedAt);
var orders = await query
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.ToArrayAsync(cancellationToken);
var total_count = await query.CountAsync(cancellationToken);
return (result, orders, total_count);
}
catch (Exception e)
{
result.setFail(ServerErrorCode.RdbError, e.Message);
return (result, null, 0);
}
}
//================================================================================
// 사파이어 교환 주문 목록을 비동기로 조회한다.
// OrderType과 PlanetId로 검색한다.
// Result, IEnumerable<>를 반환한다.
// 조건에 맞는 값이 없다면 빈 배열을 반환한다.
//================================================================================
public async Task<PaginatedList<PlanetItemExchangeOrder>> findPlanetItemExchangeOrders(int pageIndex, int pageSize)
{
var query = m_db_context.Set<PlanetItemExchangeOrder>().AsNoTracking();
var count = await query.CountAsync();
var items = await query
.OrderBy(o => o.CreatedAt)
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return new PaginatedList<PlanetItemExchangeOrder>(items, count, pageIndex, pageSize);
}
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }
public int TotalCount { get; private set; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalCount = count;
this.AddRange(items);
}
public bool HasPreviousPage => PageIndex > 1;
public bool HasNextPage => PageIndex < TotalPages;
}
}