From 11e302e65254c2ba90c539ffd5b970adf57ff7eb Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:17:24 +0700 Subject: [PATCH 01/13] Add LaundryStore, Wallet Service --- .../Entity/LaundryStore.cs | 3 +- .../Entity/Staff_Trip.cs | 2 +- .../Entity/TimeSchedule.cs | 4 +- .../Interface/ILaundryStoreRepository.cs | 8 +++ .../Interface/ITimeScheduleRepository.cs | 3 +- .../Interface/ITransactionRepository.cs | 8 +++ .../Interface/IWalletRepository.cs | 8 +++ .../Interface/ILaundryStoreService.cs | 9 +++ .../Interface/ITimeScheduleService.cs | 9 ++- .../Interface/ITransactionService.cs | 12 ++++ .../Interface/IWalletService.cs | 12 ++++ .../TimeScheduleMapperProfile.cs | 3 +- .../WalletMapperProfile.cs | 4 +- .../Repository/LaundryStoreRepository.cs | 14 +++++ .../Repository/TimeScheduleRepository.cs | 1 + .../Repository/TransactionRepository.cs | 14 +++++ .../Repository/WalletRepository.cs | 14 +++++ .../SWD-Laundry-Backend.Service.csproj | 1 + .../Services/BuildingService.cs | 1 + .../Services/LaundryStoreService.cs | 56 +++++++++++++++++++ .../Services/TimeScheduleService.cs | 11 ++-- .../Services/TransactionService.cs | 43 ++++++++++++++ .../Services/WalletService.cs | 53 ++++++++++++++++++ .../Controllers/BuildingController.cs | 9 +-- .../Controllers/TimeScheduleController.cs | 1 + .../Controllers/WalletController.cs | 34 +++++++++++ .../Extensions/AutoMapperExtension.cs | 14 ++--- 27 files changed, 317 insertions(+), 34 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Interface/ILaundryStoreRepository.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Interface/ITransactionRepository.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Interface/IWalletRepository.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Interface/ITransactionService.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs create mode 100644 src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs create mode 100644 src/SWD-Laundry-Backend.Service/Services/TransactionService.cs create mode 100644 src/SWD-Laundry-Backend.Service/Services/WalletService.cs create mode 100644 src/SWD-Laundry-Backend/Controllers/WalletController.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs index 27fed5b..78f6b88 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; namespace SWD_Laundry_Backend.Contract.Repository.Entity; @@ -21,7 +20,7 @@ public class LaundryStore : BaseEntity public ApplicationUser ApplicationUser { get; set; } - public List Orders{ get; set; } + public List Orders { get; set; } #endregion Relationship } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs index db749de..746076d 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs @@ -22,7 +22,7 @@ public class Staff_Trip : BaseEntity public Building Building { get; set; } public Staff Staff { get; set; } - public TimeSchedule TimeSchedule { get; set; } + public LaundryStore TimeSchedule { get; set; } #endregion Relationship diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs index b5ebd26..e7dc903 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs @@ -1,6 +1,6 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; + using SWD_Laundry_Backend.Core.Enum; - +namespace SWD_Laundry_Backend.Contract.Repository.Entity; #nullable disable public class TimeSchedule : BaseEntity diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Interface/ILaundryStoreRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Interface/ILaundryStoreRepository.cs new file mode 100644 index 0000000..76ea065 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Interface/ILaundryStoreRepository.cs @@ -0,0 +1,8 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Contract.Repository.Interface; + +public interface ILaundryStoreRepository : IRepository +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITimeScheduleRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITimeScheduleRepository.cs index 69c5674..a7f4370 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITimeScheduleRepository.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITimeScheduleRepository.cs @@ -1,4 +1,5 @@ -using SWD_Laundry_Backend.Contract.Repository.Infrastructure; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; namespace SWD_Laundry_Backend.Contract.Repository.Interface; diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITransactionRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITransactionRepository.cs new file mode 100644 index 0000000..e24ebcc --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Interface/ITransactionRepository.cs @@ -0,0 +1,8 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Contract.Repository.Interface; + +public interface ITransactionRepository : IRepository +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Interface/IWalletRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Interface/IWalletRepository.cs new file mode 100644 index 0000000..482b7be --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Interface/IWalletRepository.cs @@ -0,0 +1,8 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Contract.Repository.Interface; + +public interface IWalletRepository : IRepository +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs new file mode 100644 index 0000000..a41551e --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs @@ -0,0 +1,9 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Contract.Service.Interface; + +public interface ILaundryStoreService : ICreateAble, IGetAble, IUpdateAble +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/ITimeScheduleService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/ITimeScheduleService.cs index 2d2c4ae..9b55115 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Interface/ITimeScheduleService.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/ITimeScheduleService.cs @@ -1,8 +1,13 @@ -using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; using SWD_Laundry_Backend.Core.Models; namespace SWD_Laundry_Backend.Contract.Service.Interface; -public interface ITimeScheduleService : ICreateAble, IGetAble, IUpdateAble, IDeleteAble +public interface ITimeScheduleService : + ICreateAble, + IGetAble, + IUpdateAble, + IDeleteAble { } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/ITransactionService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/ITransactionService.cs new file mode 100644 index 0000000..0d830a0 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/ITransactionService.cs @@ -0,0 +1,12 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Contract.Service.Interface; + +public interface ITransactionService : + ICreateAble, + IGetAble, + IUpdateAble +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs new file mode 100644 index 0000000..85ba7e6 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs @@ -0,0 +1,12 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Contract.Service.Interface; + +public interface IWalletService : + ICreateAble, + IGetAble, + IUpdateAble +{ +} diff --git a/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs index fd305c3..d0b894f 100644 --- a/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Core.Models; namespace SWD_Laundry_Backend.Mapper; @@ -7,6 +8,6 @@ public class TimeScheduleMapperProfile : Profile { public TimeScheduleMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs index b4d8b3e..f61c151 100644 --- a/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs @@ -10,6 +10,4 @@ public WalletMapperProfile() { CreateMap().ReverseMap(); } - -} - +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs new file mode 100644 index 0000000..b4ea692 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs @@ -0,0 +1,14 @@ +using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Repository.Repository; + +[ScopedDependency(ServiceType = typeof(ILaundryStoreRepository))] +public class LaundryStoreRepository : Repository, ILaundryStoreRepository +{ + public LaundryStoreRepository(AppDbContext dbContext) : base(dbContext) + { + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/TimeScheduleRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/TimeScheduleRepository.cs index 52aed7c..b75d557 100644 --- a/src/SWD-Laundry-Backend.Repository/Repository/TimeScheduleRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Repository/TimeScheduleRepository.cs @@ -1,4 +1,5 @@ using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Interface; using SWD_Laundry_Backend.Repository.Infrastructure; diff --git a/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs new file mode 100644 index 0000000..fb38a70 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs @@ -0,0 +1,14 @@ +using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Repository.Repository; + +[ScopedDependency(ServiceType = typeof(ITransactionRepository))] +public class TransactionRepository : Repository, ITransactionRepository +{ + public TransactionRepository(AppDbContext dbContext) : base(dbContext) + { + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs new file mode 100644 index 0000000..e5bc24c --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs @@ -0,0 +1,14 @@ +using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Repository.Repository; + +[ScopedDependency(ServiceType = typeof(IWalletRepository))] +public class WalletRepository : Repository, IWalletRepository +{ + public WalletRepository(AppDbContext dbContext) : base(dbContext) + { + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj b/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj index a17de4e..27da04e 100644 --- a/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj +++ b/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj @@ -9,6 +9,7 @@ + diff --git a/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs b/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs index 746ce5e..d23d8db 100644 --- a/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs @@ -7,6 +7,7 @@ using SWD_Laundry_Backend.Core.Models; namespace SWD_Laundry_Backend.Service.Services; + [ScopedDependency(ServiceType = typeof(IBuidingService))] public class BuildingService : Base_Service.Service, IBuidingService { diff --git a/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs b/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs new file mode 100644 index 0000000..aba619b --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs @@ -0,0 +1,56 @@ + +using Invedia.DI.Attributes; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + + +namespace SWD_Laundry_Backend.Service.Services; + +//[ScopedDependency(ServiceType = typeof(ILaundryStoreService))] +public class LaundryStoreService : Base_Service.Service, ILaundryStoreService +{ + private readonly ILaundryStoreRepository _repository; + private readonly AutoMapper.Mapper _mapper; + + public LaundryStoreService(ILaundryStoreRepository repository, AutoMapper.Mapper mapper) + { + _repository = repository; + _mapper = mapper; + } + + public async Task CreateAsync(LaundryStoreModel model, CancellationToken cancellationToken = default) + { + var query = await _repository.AddAsync(_mapper.Map(model), cancellationToken); + var objectId = query.Id; + return objectId; + } + + public async Task> GetAllAsync(CancellationToken cancellationToken = default) + { + var list = await _repository.GetAsync(cancellationToken: cancellationToken); + return await list.ToListAsync(cancellationToken); + } + + public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + { + var query = await _repository.GetAsync(c => c.Id == id, cancellationToken); + var obj = await query.FirstOrDefaultAsync(); + return obj; + } + + public async Task UpdateAsync(string id, LaundryStoreModel model, CancellationToken cancellationToken = default) + { + var numberOfRows = await _repository.UpdateAsync(x => x.Id == id, + x => x + .SetProperty(x => x.StartTime, model.StartTime) + .SetProperty(x => x.EndTime, model.EndTime) + .SetProperty(x => x.Address, model.Address) + .SetProperty(x => x.Status, model.Status) + , cancellationToken); + + return numberOfRows; + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Service/Services/TimeScheduleService.cs b/src/SWD-Laundry-Backend.Service/Services/TimeScheduleService.cs index a1d9c15..46fee3b 100644 --- a/src/SWD-Laundry-Backend.Service/Services/TimeScheduleService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/TimeScheduleService.cs @@ -1,8 +1,7 @@ using AutoMapper; -using Invedia.Core.ObjUtils; using Invedia.DI.Attributes; using Microsoft.EntityFrameworkCore; - +using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Interface; using SWD_Laundry_Backend.Contract.Service.Interface; using SWD_Laundry_Backend.Core.Models; @@ -10,7 +9,7 @@ namespace SWD_Laundry_Backend.Service.Services; [ScopedDependency(ServiceType = typeof(ITimeScheduleService))] -internal class TimeScheduleService : Base_Service.Service, ITimeScheduleService +public class TimeScheduleService : Base_Service.Service, ITimeScheduleService { private readonly ITimeScheduleRepository _repository; private readonly IMapper _mapper; @@ -36,8 +35,8 @@ public async Task DeleteAsync(string id, CancellationToken cancellationToke public async Task> GetAllAsync(CancellationToken cancellationToken = default) { - var timescheduleList = await _repository.GetAsync( cancellationToken: cancellationToken); - return await timescheduleList.ToListAsync(cancellationToken); + var list = await _repository.GetAsync(cancellationToken: cancellationToken); + return await list.ToListAsync(cancellationToken); } public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) @@ -55,7 +54,7 @@ public async Task UpdateAsync(string id, TimeScheduleModel model, Cancellat .SetProperty(x => x.EndTime, model.EndTime) .SetProperty(x => x.DayOfWeek, model.DayOfWeek) .SetProperty(x => x.TimeFrame, model.TimeFrame) - ,cancellationToken); + , cancellationToken); return numberOfRows; } diff --git a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs new file mode 100644 index 0000000..fffbb26 --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs @@ -0,0 +1,43 @@ +using AutoMapper; +using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Service.Services; + +//[ScopedDependency(ServiceType = typeof(ITransactionService))] +public class TransactionService : Base_Service.Service, ITransactionService +{ + private readonly ITransactionRepository _repository; + private readonly AutoMapper.Mapper _mapper; + + public TransactionService(ITransactionRepository repository, AutoMapper.Mapper mapper) + { + _repository = repository; + _mapper = mapper; + } + + public async Task CreateAsync(TransactionModel model, CancellationToken cancellationToken = default) + { + var query = await _repository.AddAsync(_mapper.Map(model), cancellationToken); + var objectId = query.Id; + return objectId; + } + + public Task> GetAllAsync(CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(string id, TransactionModel model, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Service/Services/WalletService.cs b/src/SWD-Laundry-Backend.Service/Services/WalletService.cs new file mode 100644 index 0000000..044369d --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Services/WalletService.cs @@ -0,0 +1,53 @@ +using AutoMapper; +using Invedia.DI.Attributes; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Service.Services; + +//[ScopedDependency(ServiceType = typeof(IWalletService))] + +public class WalletService : Base_Service.Service, IWalletService +{ + private readonly IWalletRepository _repository; + private readonly AutoMapper.Mapper _mapper; + + public WalletService(IWalletRepository repository, AutoMapper.Mapper mapper) + { + _repository = repository; + _mapper = mapper; + } + + public async Task CreateAsync(WalletModel model, CancellationToken cancellationToken = default) + { + var query = await _repository.AddAsync(_mapper.Map(model), cancellationToken); + var objectId = query.Id; + return objectId; + } + + public async Task> GetAllAsync(CancellationToken cancellationToken = default) + { + var list = await _repository.GetAsync(cancellationToken: cancellationToken); + return await list.ToListAsync(cancellationToken); + } + + public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + { + var query = await _repository.GetAsync(c => c.Id == id, cancellationToken); + var obj = await query.FirstOrDefaultAsync(); + return obj; + } + + public async Task UpdateAsync(string id, WalletModel model, CancellationToken cancellationToken = default) + { + var numberOfRows = await _repository.UpdateAsync(x => x.Id == id, + x => x + .SetProperty(x => x.Balance, model.Balance) + , cancellationToken); + + return numberOfRows; + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend/Controllers/BuildingController.cs b/src/SWD-Laundry-Backend/Controllers/BuildingController.cs index a1b3184..ba787ee 100644 --- a/src/SWD-Laundry-Backend/Controllers/BuildingController.cs +++ b/src/SWD-Laundry-Backend/Controllers/BuildingController.cs @@ -4,6 +4,7 @@ using SWD_Laundry_Backend.Core.Models; namespace SWD_Laundry_Backend.Controllers; + [ApiController] public class BuildingController : ApiControllerBase { @@ -29,7 +30,6 @@ public async Task GetAll() { return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } - } [HttpGet("{id}")] @@ -69,7 +69,6 @@ public async Task Create(BuildingModel model) { return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } - } [HttpPut("{id}")] @@ -82,7 +81,7 @@ public async Task Update(string id, BuildingModel model) try { var result = await _buildingService.UpdateAsync(id, model); - if(result == 0) + if (result == 0) { return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); } @@ -92,7 +91,6 @@ public async Task Update(string id, BuildingModel model) { return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } - } [HttpDelete("{id}")] @@ -116,5 +114,4 @@ public async Task Delete(string id) return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } } - -} +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs b/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs index 574b050..016a8af 100644 --- a/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs +++ b/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Service.Interface; using SWD_Laundry_Backend.Core.Models; diff --git a/src/SWD-Laundry-Backend/Controllers/WalletController.cs b/src/SWD-Laundry-Backend/Controllers/WalletController.cs new file mode 100644 index 0000000..23f6fa7 --- /dev/null +++ b/src/SWD-Laundry-Backend/Controllers/WalletController.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Controllers; + +[ApiController] +public class WalletController : ApiControllerBase +{ + private readonly IWalletService _service; + + public WalletController(IWalletService service) + { + _service = service; + } + + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetAll() + { + try + { + var result = await _service.GetAllAsync(); + return Ok(new BaseResponseModel?>(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } +} diff --git a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs index 0b9ca96..4d775ee 100644 --- a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs +++ b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs @@ -2,27 +2,21 @@ namespace SWD_Laundry_Backend.Extensions; - public static class AutoMapperExtension { public static IServiceCollection AddAutoMapperServices(this IServiceCollection services) { - services.AddAutoMapper(cfg => - { + services.AddAutoMapper(cfg => + { cfg.AddProfile(); - + cfg.AddProfile(); cfg.AddProfile(); cfg.AddProfile(); cfg.AddProfile(); cfg.AddProfile(); cfg.AddProfile(); cfg.AddProfile(); - - cfg.AddProfile(); }); return services; } -} - - - +} \ No newline at end of file From 3e5b59555f20e3e13f38c87363953334b1f4978c Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:28:34 +0700 Subject: [PATCH 02/13] Fix --- .../Interface/ILaundryStoreService.cs | 2 +- .../Repository/LaundryStoreRepository.cs | 3 ++- .../Repository/TransactionRepository.cs | 3 ++- .../Repository/WalletRepository.cs | 3 ++- .../Services/LaundryStoreService.cs | 13 +++++++++---- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs index a41551e..239b68a 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/ILaundryStoreService.cs @@ -4,6 +4,6 @@ namespace SWD_Laundry_Backend.Contract.Service.Interface; -public interface ILaundryStoreService : ICreateAble, IGetAble, IUpdateAble +public interface ILaundryStoreService : ICreateAble, IGetAble, IUpdateAble, IDeleteAble { } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs index b4ea692..e3a1acb 100644 --- a/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Repository/LaundryStoreRepository.cs @@ -1,5 +1,6 @@ using Invedia.DI.Attributes; using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; using SWD_Laundry_Backend.Contract.Repository.Interface; using SWD_Laundry_Backend.Repository.Infrastructure; @@ -8,7 +9,7 @@ namespace SWD_Laundry_Backend.Repository.Repository; [ScopedDependency(ServiceType = typeof(ILaundryStoreRepository))] public class LaundryStoreRepository : Repository, ILaundryStoreRepository { - public LaundryStoreRepository(AppDbContext dbContext) : base(dbContext) + public LaundryStoreRepository(AppDbContext dbContext, ICacheLayer cachelayer) : base(dbContext, cachelayer) { } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs index fb38a70..d8c9b5b 100644 --- a/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Repository/TransactionRepository.cs @@ -1,5 +1,6 @@ using Invedia.DI.Attributes; using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; using SWD_Laundry_Backend.Contract.Repository.Interface; using SWD_Laundry_Backend.Repository.Infrastructure; @@ -8,7 +9,7 @@ namespace SWD_Laundry_Backend.Repository.Repository; [ScopedDependency(ServiceType = typeof(ITransactionRepository))] public class TransactionRepository : Repository, ITransactionRepository { - public TransactionRepository(AppDbContext dbContext) : base(dbContext) + public TransactionRepository(AppDbContext dbContext, ICacheLayer cachelayer) : base(dbContext, cachelayer) { } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs index e5bc24c..32c5288 100644 --- a/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Repository/WalletRepository.cs @@ -1,5 +1,6 @@ using Invedia.DI.Attributes; using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; using SWD_Laundry_Backend.Contract.Repository.Interface; using SWD_Laundry_Backend.Repository.Infrastructure; @@ -8,7 +9,7 @@ namespace SWD_Laundry_Backend.Repository.Repository; [ScopedDependency(ServiceType = typeof(IWalletRepository))] public class WalletRepository : Repository, IWalletRepository { - public WalletRepository(AppDbContext dbContext) : base(dbContext) + public WalletRepository(AppDbContext dbContext, ICacheLayer cachelayer) : base(dbContext, cachelayer) { } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs b/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs index aba619b..99e3865 100644 --- a/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs @@ -1,4 +1,4 @@ - +using AutoMapper; using Invedia.DI.Attributes; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Contract.Repository.Entity; @@ -9,13 +9,13 @@ namespace SWD_Laundry_Backend.Service.Services; -//[ScopedDependency(ServiceType = typeof(ILaundryStoreService))] +[ScopedDependency(ServiceType = typeof(ILaundryStoreService))] public class LaundryStoreService : Base_Service.Service, ILaundryStoreService { private readonly ILaundryStoreRepository _repository; - private readonly AutoMapper.Mapper _mapper; + private readonly IMapper _mapper; - public LaundryStoreService(ILaundryStoreRepository repository, AutoMapper.Mapper mapper) + public LaundryStoreService(ILaundryStoreRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; @@ -28,6 +28,11 @@ public async Task CreateAsync(LaundryStoreModel model, CancellationToken return objectId; } + public Task DeleteAsync(string id, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + public async Task> GetAllAsync(CancellationToken cancellationToken = default) { var list = await _repository.GetAsync(cancellationToken: cancellationToken); From 2fc3c66416f60653d76f9707f2256046d4cc6e06 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:34:38 +0700 Subject: [PATCH 03/13] Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6f06060..dc88f54 100644 --- a/.gitignore +++ b/.gitignore @@ -237,3 +237,5 @@ _Pvt_Extensions /.mfractor src/WebUI/ClientApp/package-lock.json /src/WebUI/appsettings.json +src/SWD-Laundry-Backend/appsettings.Development.json +src/SWD-Laundry-Backend/appsettings.Development.json From a0031d27fedaa2a13e103b2ca8d7db1eb9cf9a87 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:35:47 +0700 Subject: [PATCH 04/13] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index dc88f54..c851094 100644 --- a/.gitignore +++ b/.gitignore @@ -239,3 +239,4 @@ src/WebUI/ClientApp/package-lock.json /src/WebUI/appsettings.json src/SWD-Laundry-Backend/appsettings.Development.json src/SWD-Laundry-Backend/appsettings.Development.json +src/SWD-Laundry-Backend/appsettings.Development.json From 7105af450160a486bfba06b53a6e9dfc86b00af6 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:04:39 +0700 Subject: [PATCH 05/13] Fix Controller --- .../Services/TransactionService.cs | 29 ++++-- .../Controllers/LaundryStoreController.cs | 98 +++++++++++++++++++ .../Controllers/TimeScheduleController.cs | 22 +++++ .../Controllers/WalletController.cs | 63 ++++++++++++ 4 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs diff --git a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs index fffbb26..a057251 100644 --- a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs @@ -1,5 +1,5 @@ using AutoMapper; -using Invedia.DI.Attributes; +using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Interface; using SWD_Laundry_Backend.Contract.Service.Interface; @@ -11,9 +11,9 @@ namespace SWD_Laundry_Backend.Service.Services; public class TransactionService : Base_Service.Service, ITransactionService { private readonly ITransactionRepository _repository; - private readonly AutoMapper.Mapper _mapper; + private readonly IMapper _mapper; - public TransactionService(ITransactionRepository repository, AutoMapper.Mapper mapper) + public TransactionService(ITransactionRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; @@ -26,18 +26,29 @@ public async Task CreateAsync(TransactionModel model, CancellationToken return objectId; } - public Task> GetAllAsync(CancellationToken cancellationToken = default) + public async Task> GetAllAsync(CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + var list = await _repository.GetAsync(cancellationToken: cancellationToken); + return await list.ToListAsync(cancellationToken); } - public Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + var query = await _repository.GetAsync(c => c.Id == id, cancellationToken); + var obj = await query.FirstOrDefaultAsync(); + return obj; } - public Task UpdateAsync(string id, TransactionModel model, CancellationToken cancellationToken = default) + public async Task UpdateAsync(string id, TransactionModel model, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + var numberOfRows = await _repository.UpdateAsync(x => x.Id == id, + x => x + .SetProperty(x => x.Amount, model.Amount) + .SetProperty(x => x.TransactionType, model.TransactionType) + .SetProperty(x => x.PaymentMethod, model.PaymentMethod) + .SetProperty(x => x.Description, model.Description) + , cancellationToken); + + return numberOfRows; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs new file mode 100644 index 0000000..9abf2ab --- /dev/null +++ b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs @@ -0,0 +1,98 @@ +using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; +using SWD_Laundry_Backend.Service.Services; + +namespace SWD_Laundry_Backend.Controllers; + +[ApiController] +public class LaundryStoreController : ApiControllerBase +{ + private readonly LaundryStoreService _service; + + public LaundryStoreController(LaundryStoreService service) + { + _service = service; + } + + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetAll() + { + try + { + var result = await _service.GetAllAsync(); + return Ok(new BaseResponseModel?>(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetById(string id) + { + try + { + var result = await _service.GetByIdAsync(id); + if (result == null) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Create(LaundryStoreModel model) + { + try + { + var result = await _service.CreateAsync(model); + return Ok(new BaseResponseModel + (StatusCodes.Status201Created, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel + (StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPut("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Update(string id, LaundryStoreModel model) + { + try + { + var result = await _service.UpdateAsync(id, model); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } +} diff --git a/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs b/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs index 016a8af..a382a75 100644 --- a/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs +++ b/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs @@ -72,4 +72,26 @@ public async Task Create(TimeScheduleModel model) (StatusCodes.Status500InternalServerError, e.Message)); } } + + [HttpPut("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Update(string id, TimeScheduleModel model) + { + try + { + var result = await _service.UpdateAsync(id, model); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend/Controllers/WalletController.cs b/src/SWD-Laundry-Backend/Controllers/WalletController.cs index 23f6fa7..52d38f9 100644 --- a/src/SWD-Laundry-Backend/Controllers/WalletController.cs +++ b/src/SWD-Laundry-Backend/Controllers/WalletController.cs @@ -31,4 +31,67 @@ public async Task GetAll() return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } } + + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetById(string id) + { + try + { + var result = await _service.GetByIdAsync(id); + if (result == null) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Create(WalletModel model) + { + try + { + var result = await _service.CreateAsync(model); + return Ok(new BaseResponseModel + (StatusCodes.Status201Created, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel + (StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPut("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Update(string id, WalletModel model) + { + try + { + var result = await _service.UpdateAsync(id, model); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } } From 7862ef0ca506861b5253527e4a6fb7abe0806990 Mon Sep 17 00:00:00 2001 From: Nero Date: Wed, 4 Oct 2023 17:07:52 +0700 Subject: [PATCH 06/13] Update TransactionService.cs --- .../Services/TransactionService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs index a057251..7f95523 100644 --- a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs @@ -7,7 +7,7 @@ namespace SWD_Laundry_Backend.Service.Services; -//[ScopedDependency(ServiceType = typeof(ITransactionService))] +[ScopedDependency(ServiceType = typeof(ITransactionService))] public class TransactionService : Base_Service.Service, ITransactionService { private readonly ITransactionRepository _repository; @@ -51,4 +51,4 @@ public async Task UpdateAsync(string id, TransactionModel model, Cancellati return numberOfRows; } -} \ No newline at end of file +} From a36616310fa82ad5503ecaf87a0c7a170c8d075c Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Thu, 5 Oct 2023 00:20:38 +0700 Subject: [PATCH 07/13] Add StaffTripService --- Script.sql | Bin 1548058 -> 567644 bytes .../Entity/Staff.cs | 3 - .../Entity/Staff_Trip.cs | 14 +-- .../Entity/TimeSchedule.cs | 2 +- .../Interface/IStaffTripRepository.cs | 12 +++ .../Interface/IStaffTripService.cs | 13 +++ .../Models/StaffModel.cs | 12 +++ .../Models/StaffTripModel.cs | 8 +- .../Repository/StaffTripRepository.cs | 19 ++++ .../Services/StaffTripService.cs | 76 ++++++++++++++ .../Services/TransactionService.cs | 1 + .../Controllers/StaffTripController.cs | 97 ++++++++++++++++++ 12 files changed, 239 insertions(+), 18 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Interface/IStaffTripRepository.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Interface/IStaffTripService.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/StaffModel.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Repository/StaffTripRepository.cs create mode 100644 src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs create mode 100644 src/SWD-Laundry-Backend/Controllers/StaffTripController.cs diff --git a/Script.sql b/Script.sql index 4202993595fdfa8287bd412ed0aebf0576a692f0..1409611d8ba48ff2244810915ceace79813e73d7 100644 GIT binary patch delta 275 zcmbQWFYeAIrG^&97N#xCt74`*1Ty(;FGyf+5t|&q=(F7_n`IjF^bcOle$(9?*yE<1 zWnQ=az#^75rs)eViUv$ymB9IDdO!w?!1j{atW8YQFBkw7hRL!gO&929Ua>tvjvc5{ zp^kms^n$5;tF~9vvrk}}e&7huV7`g$bC|)lO+WTmAPy`)Z8kT{_IXPRe^Y{SK7HuW~ delta 150892 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 T_4j1`J$3!tf8)*n;I{t{{|lqu diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs index 8c7fea3..e081943 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs @@ -8,9 +8,6 @@ public class Staff : BaseEntity { - //public DateTime Dob { get; set; } - //public string Address { get; set; } - //public double Salary { get; set; } #region Relationship diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs index 746076d..0c01dfe 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs @@ -9,7 +9,8 @@ public class Staff_Trip : BaseEntity { public int TripCollect { get; set; } = 0; - #region Relationship + public TripType TripType { get; set; } + [ForeignKey("Staff")] public string StaffID { get; set; } @@ -20,15 +21,8 @@ public class Staff_Trip : BaseEntity [ForeignKey("Building")] public string BuildingID { get; set; } + public Building Building { get; set; } public Staff Staff { get; set; } - public LaundryStore TimeSchedule { get; set; } - - #endregion Relationship - - #region Special Attribute - - public TripType TripType { get; set; } - - #endregion Special Attribute + public TimeSchedule TimeSchedule { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs index e7dc903..c2732a9 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs @@ -12,7 +12,7 @@ public class TimeSchedule : BaseEntity public DayOfWeek DayOfWeek { get; set; } public TimeFrame TimeFrame { get; set; } - public List Staff_Trip { get; set; } + //public List Staff_Trip { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Interface/IStaffTripRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Interface/IStaffTripRepository.cs new file mode 100644 index 0000000..484012f --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Interface/IStaffTripRepository.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Contract.Repository.Interface; +public interface IStaffTripRepository : IRepository +{ +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/IStaffTripService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/IStaffTripService.cs new file mode 100644 index 0000000..8897283 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/IStaffTripService.cs @@ -0,0 +1,13 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Contract.Service.Interface; + +public interface IStaffTripService : + ICreateAble, + IGetAble, + IUpdateAble, + IDeleteAble +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/StaffModel.cs b/src/SWD-Laundry-Backend.Core/Models/StaffModel.cs new file mode 100644 index 0000000..685b8d6 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/StaffModel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Core.Models; +public class StaffModel +{ + public string? Name { get; set; } + public string? WalletBalance { get; set; } +} diff --git a/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs b/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs index 4dffb42..0ae7873 100644 --- a/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs +++ b/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs @@ -5,9 +5,9 @@ namespace SWD_Laundry_Backend.Core.Models; public class StaffTripModel { public int TripCollect { get; set; } = 0; - - public BuildingModel? Building { get; set; } // Name of the associated building - public string? StaffName { get; set; } // Name of the associated staff - public TimeScheduleModel? TimeSchedule { get; set; } // Name of the associated time schedule + + public string? BuildingID { get; set; } + public string? TimeScheduleID { get; set; } + public string? StaffID { get; set; } public TripType TripType { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Repository/StaffTripRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/StaffTripRepository.cs new file mode 100644 index 0000000..4764e7b --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Repository/StaffTripRepository.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Repository.Repository; +[ScopedDependency(ServiceType = typeof(IStaffTripRepository))] +public class StaffTripRepository : Repository, IStaffTripRepository +{ + public StaffTripRepository(AppDbContext dbContext, ICacheLayer cacheLayer) : base(dbContext, cacheLayer) + { + } +} diff --git a/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs b/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs new file mode 100644 index 0000000..a88fddd --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs @@ -0,0 +1,76 @@ +using System.Linq.Expressions; +using AutoMapper; +using Invedia.DI.Attributes; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Service.Services; + +[ScopedDependency(ServiceType = typeof(IStaffTripService))] +public class StaffTripService : Base_Service.Service, IStaffTripService +{ + private readonly Expression>[]? items = + { + p => p.Staff, + p => p.Building, + p => p.TimeSchedule + }; + + private readonly IStaffTripRepository _repository; + private readonly IMapper _mapper; + + public StaffTripService(IStaffTripRepository staffTripRepository, IMapper mapper) + { + _repository = staffTripRepository; + _mapper = mapper; + } + + public async Task CreateAsync(StaffTripModel model, CancellationToken cancellationToken = default) + { + var query = await _repository.AddAsync(_mapper.Map(model), cancellationToken); + var objectId = query.Id; + return objectId; + } + + public async Task DeleteAsync(string id, CancellationToken cancellationToken = default) + { + var numberOfRows = await _repository.DeleteAsync(x => x.Id == id, cancellationToken: cancellationToken); + return numberOfRows; + } + + public async Task> GetAllAsync(CancellationToken cancellationToken = default) + { + var list = await _repository.GetAsync( + cancellationToken: cancellationToken, + includes: items); + return await list.ToListAsync(cancellationToken); + } + + public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + { + var query = await _repository.GetAsync( + c => c.Id == id, + cancellationToken: cancellationToken, + includes: items); + + var obj = await query.FirstOrDefaultAsync(); + return obj; + } + + public async Task UpdateAsync(string id, StaffTripModel model, CancellationToken cancellationToken = default) + { + var numberOfRows = await _repository.UpdateAsync(x => x.Id == id, + x => x + .SetProperty(x => x.TripCollect, model.TripCollect) + .SetProperty(x => x.TripType, model.TripType) + .SetProperty(x => x.TimeScheduleID, model.TimeScheduleID) + .SetProperty(x => x.BuildingID, model.BuildingID) + .SetProperty(x => x.StaffID, model.StaffID) + , cancellationToken); + + return numberOfRows; + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs index 7f95523..663f39f 100644 --- a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Invedia.DI.Attributes; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Interface; diff --git a/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs b/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs new file mode 100644 index 0000000..256e3a9 --- /dev/null +++ b/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs @@ -0,0 +1,97 @@ +using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Controllers; + +[ApiController] +public class StaffTripController : ApiControllerBase +{ + private readonly IStaffTripService _service; + + public StaffTripController(IStaffTripService service) + { + _service = service; + } + + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetAll() + { + try + { + var result = await _service.GetAllAsync(); + return Ok(new BaseResponseModel?>(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetById(string id) + { + try + { + var result = await _service.GetByIdAsync(id); + if (result == null) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Create(StaffTripModel model) + { + try + { + var result = await _service.CreateAsync(model); + return Ok(new BaseResponseModel + (StatusCodes.Status201Created, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel + (StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPut("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Update(string id, StaffTripModel model) + { + try + { + var result = await _service.UpdateAsync(id, model); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } +} From 7690ae473333c3480e1255f3df81cdf01f649cce Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:10:05 +0700 Subject: [PATCH 08/13] Update mapper --- src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/LaundryStoreMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/OrderHistoryMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/OrderMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/StaffTripMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/TransactionMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs | 2 +- src/SWD-Laundry-Backend.Service/Services/TransactionService.cs | 1 + 9 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs index a4bad90..247219f 100644 --- a/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs @@ -8,6 +8,6 @@ public class BuildingMapperProfile : Profile { public BuildingMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } diff --git a/src/SWD-Laundry-Backend.Mapper/LaundryStoreMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/LaundryStoreMapperProfile.cs index 29bc761..3195614 100644 --- a/src/SWD-Laundry-Backend.Mapper/LaundryStoreMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/LaundryStoreMapperProfile.cs @@ -8,6 +8,6 @@ public class LaundryStoreMapperProfile : Profile { public LaundryStoreMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/OrderHistoryMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/OrderHistoryMapperProfile.cs index 751fa5f..3281d59 100644 --- a/src/SWD-Laundry-Backend.Mapper/OrderHistoryMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/OrderHistoryMapperProfile.cs @@ -8,6 +8,6 @@ public class OrderHistoryMapperProfile : Profile { public OrderHistoryMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/OrderMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/OrderMapperProfile.cs index bde1e6e..f6b24e9 100644 --- a/src/SWD-Laundry-Backend.Mapper/OrderMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/OrderMapperProfile.cs @@ -8,6 +8,6 @@ public class OrderMapperProfile : Profile { public OrderMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/StaffTripMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/StaffTripMapperProfile.cs index a0cc3c5..341f7a1 100644 --- a/src/SWD-Laundry-Backend.Mapper/StaffTripMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/StaffTripMapperProfile.cs @@ -8,6 +8,6 @@ public class StaffTripMapperProfile : Profile { public StaffTripMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs index d0b894f..e0fb90c 100644 --- a/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs @@ -8,6 +8,6 @@ public class TimeScheduleMapperProfile : Profile { public TimeScheduleMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/TransactionMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/TransactionMapperProfile.cs index 23ed873..2d3aad7 100644 --- a/src/SWD-Laundry-Backend.Mapper/TransactionMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/TransactionMapperProfile.cs @@ -8,6 +8,6 @@ public class TransactionMapperProfile : Profile { public TransactionMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs index f61c151..e4e7b25 100644 --- a/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs +++ b/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs @@ -8,6 +8,6 @@ public class WalletMapperProfile : Profile { public WalletMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ForMember(x => x.Id, opt => opt.Ignore()).ReverseMap(); } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs index 7f95523..663f39f 100644 --- a/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/TransactionService.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Invedia.DI.Attributes; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Interface; From af021ab72bdf0fe4e4a9ce9a04e141a1c575dc8a Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:12:46 +0700 Subject: [PATCH 09/13] Optimize Database --- .../Entity/Building.cs | 5 - .../Entity/Customer.cs | 17 +- .../Entity/LaundryStore.cs | 7 +- .../Entity/Order.cs | 22 +- .../Entity/OrderHistory.cs | 15 +- .../Entity/Payment.cs | 6 +- .../Entity/Staff.cs | 9 +- .../Entity/Staff_Trip.cs | 3 +- .../Entity/TimeSchedule.cs | 10 +- .../Entity/Transaction.cs | 16 +- .../Entity/Wallet.cs | 10 +- ...=> 20231004172440_UpdateStaff.Designer.cs} | 81 +- ...base7.cs => 20231004172440_UpdateStaff.cs} | 2 +- ...231004174024_UpdateTransaction.Designer.cs | 822 ++++++++++++++++++ .../20231004174024_UpdateTransaction.cs | 78 ++ .../Migrations/AppDbContextModelSnapshot.cs | 171 ++-- .../Services/WalletService.cs | 7 +- .../Controllers/LaundryStoreController.cs | 10 +- 18 files changed, 1043 insertions(+), 248 deletions(-) rename src/SWD-Laundry-Backend.Repository/Migrations/{20231002072614_UpdateDatbase7.Designer.cs => 20231004172440_UpdateStaff.Designer.cs} (98%) rename src/SWD-Laundry-Backend.Repository/Migrations/{20231002072614_UpdateDatbase7.cs => 20231004172440_UpdateStaff.cs} (96%) create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.Designer.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs index 9b769ef..51bed1f 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs @@ -6,9 +6,4 @@ public class Building : BaseEntity public string Name { get; set; } public string Address { get; set; } public string Description { get; set; } - - #region Relationship - public List Customers { get; set; } - public List Staff_Trips { get; set; } - #endregion } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs index 317f843..24b2928 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; namespace SWD_Laundry_Backend.Contract.Repository.Entity; @@ -8,27 +7,15 @@ namespace SWD_Laundry_Backend.Contract.Repository.Entity; public class Customer : BaseEntity { - //public string Name { get; set; } - //public string Address { get; set; } - - #region Relationship - [ForeignKey("Building")] public string BuildingID { get; set; } [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } + ////=========================== public Building Building { get; set; } public ApplicationUser ApplicationUser { get; set; } - public virtual List Order { get; set; } - - #endregion Relationship - - #region Special Attribute - - - - #endregion Special Attribute + //public virtual List Order { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs index 78f6b88..1282675 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs @@ -13,14 +13,11 @@ public class LaundryStore : BaseEntity public DateTime EndTime { get; set; } public bool Status { get; set; } - #region Relationship - + ////=========================== [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } public ApplicationUser ApplicationUser { get; set; } - public List Orders { get; set; } - - #endregion Relationship + //public List Orders { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs index 6cb3ee9..232e1e5 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs @@ -9,14 +9,17 @@ public class Order : BaseEntity public DateTime OrderDate { get; set; } public TimeFrame DeliveryTimeFrame { get; set; } public DateTime ExpectedFinishDate { get; set; } + + public OrderType OrderType { get; set; } + public PaymentType PaymentType { get; set; } + public string Address { get; set; } // Address = Customer's building location public short Amount { get; set; } public double TotalPrice { get; set; } - #region Relationship - - [ForeignKey("Customer")] + ////=========================== + [ForeignKey(nameof(Customer))] public string CustomerID { get; set; } [ForeignKey(nameof(LaundryStore))] @@ -31,15 +34,6 @@ public class Order : BaseEntity public Staff Staff { get; set; } public LaundryStore LaundryStore { get; set; } - public List Payments { get; set; } - public List OrderHistories { get; set; } - - #endregion Relationship - - #region Special Attribute - - public OrderType OrderType { get; set; } - public PaymentType PaymentType { get; set; } - - #endregion Special Attribute + //public List Payments { get; set; } + //public List OrderHistories { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs index 2f68205..1e41b38 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs @@ -9,20 +9,13 @@ public class OrderHistory : BaseEntity public string Title { get; set; } public string Message { get; set; } - #region Relationship + public OrderStatus OrderStatus { get; set; } + public DeliveryStatus DeliveryStatus { get; set; } + public LaundryStatus LaundryStatus { get; set; } + ////=========================== [ForeignKey("Order")] public string OrderID { get; set; } public Order Order { get; set; } - - #endregion Relationship - - #region Special attributes - - public OrderStatus OrderStatus { get; set; } - public DeliveryStatus DeliveryStatus { get; set; } - public LaundryStatus LaundryStatus { get; set; } - - #endregion Special attributes } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs index cc1ace4..2cbba7c 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs @@ -7,13 +7,9 @@ public class Payment : BaseEntity { public double Price { get; set; } - #region Relationship - + ////=========================== [ForeignKey(nameof(Order))] public string OrderId { get; set; } - public Transaction Transaction { get; set; } public Order Orders { get; set; } - - #endregion Relationship } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs index e081943..2a4d649 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs @@ -2,21 +2,14 @@ using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; - - #nullable disable public class Staff : BaseEntity { - - #region Relationship - [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } public ApplicationUser ApplicationUser { get; set; } - public List Staff_Trips { get; set; } - - #endregion Relationship + //public List Staff_Trips { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs index 0c01dfe..0dcda0b 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs @@ -11,7 +11,7 @@ public class Staff_Trip : BaseEntity public TripType TripType { get; set; } - + ////=========================== [ForeignKey("Staff")] public string StaffID { get; set; } @@ -21,6 +21,7 @@ public class Staff_Trip : BaseEntity [ForeignKey("Building")] public string BuildingID { get; set; } + ////=========================== public Building Building { get; set; } public Staff Staff { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs index c2732a9..67d696b 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs @@ -1,5 +1,5 @@ - -using SWD_Laundry_Backend.Core.Enum; +using SWD_Laundry_Backend.Core.Enum; + namespace SWD_Laundry_Backend.Contract.Repository.Entity; #nullable disable @@ -8,11 +8,7 @@ public class TimeSchedule : BaseEntity public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } - #region Special Attribute - public DayOfWeek DayOfWeek { get; set; } public TimeFrame TimeFrame { get; set; } - //public List Staff_Trip { get; set; } - - #endregion Special Attribute + //public virtual List Staff_Trip { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs index 6f01340..9ae6dff 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs @@ -9,20 +9,16 @@ public class Transaction : BaseEntity public string PaymentMethod { get; set; } public int Amount { get; set; } public string Description { get; set; } + public AllowedTransactionType TransactionType { get; set; } - #region Relationship - + ////=========================== [ForeignKey(nameof(Wallet))] public string WalletID { get; set; } public Wallet Wallet { get; set; } - public List Payments { get; set; } - - #endregion Relationship - - #region Special Attribute - - public AllowedTransactionType TransactionType { get; set; } - #endregion Special Attribute + [ForeignKey(nameof(Payment))] + public string PaymentID { get; set; } + public Payment Payment { get; set; } + //public List Payments { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs index 09b0e5a..6d8ee2c 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs @@ -1,5 +1,4 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; -using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; namespace SWD_Laundry_Backend.Contract.Repository.Entity; #nullable disable @@ -8,11 +7,6 @@ public class Wallet : BaseEntity { public double Balance { get; set; } - #region Relationship - - public List Transactions { get; set; } - public ApplicationUser ApplicationUser { get; set; } - - #endregion Relationship + //public List Transactions { get; set; } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231004172440_UpdateStaff.Designer.cs similarity index 98% rename from src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs rename to src/SWD-Laundry-Backend.Repository/Migrations/20231004172440_UpdateStaff.Designer.cs index bac6672..80c85ab 100644 --- a/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231004172440_UpdateStaff.Designer.cs @@ -12,8 +12,8 @@ namespace SWD_Laundry_Backend.Repository.Migrations { [DbContext(typeof(AppDbContext))] - [Migration("20231002072614_UpdateDatbase7")] - partial class UpdateDatbase7 + [Migration("20231004172440_UpdateStaff")] + partial class UpdateStaff { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -519,6 +519,40 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Staff_Trips"); }); + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => { b.Property("Id") @@ -610,40 +644,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Staffs"); }); - modelBuilder.Entity("TimeSchedule", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedTime") - .HasColumnType("datetimeoffset"); - - b.Property("DayOfWeek") - .HasColumnType("int"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastUpdatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastUpdatedTime") - .HasColumnType("datetimeoffset"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TimeSchedules"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -783,8 +783,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .WithMany("Staff_Trips") .HasForeignKey("StaffID"); - b.HasOne("TimeSchedule", "TimeSchedule") - .WithMany("Staff_Trip") + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.TimeSchedule", "TimeSchedule") + .WithMany() .HasForeignKey("TimeScheduleID"); b.Navigation("Building"); @@ -852,11 +852,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Navigation("Staff_Trips"); }); - - modelBuilder.Entity("TimeSchedule", b => - { - b.Navigation("Staff_Trip"); - }); #pragma warning restore 612, 618 } } diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231004172440_UpdateStaff.cs similarity index 96% rename from src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs rename to src/SWD-Laundry-Backend.Repository/Migrations/20231004172440_UpdateStaff.cs index c34a2c0..98bfa96 100644 --- a/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231004172440_UpdateStaff.cs @@ -6,7 +6,7 @@ namespace SWD_Laundry_Backend.Repository.Migrations { /// - public partial class UpdateDatbase7 : Migration + public partial class UpdateStaff : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.Designer.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.Designer.cs new file mode 100644 index 0000000..a69a51f --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.Designer.cs @@ -0,0 +1,822 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SWD_Laundry_Backend.Repository.Infrastructure; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20231004174024_UpdateTransaction")] + partial class UpdateTransaction + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.HasIndex("BuildingID"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.HasIndex("WalletID") + .IsUnique() + .HasFilter("[WalletID] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("CustomerID") + .HasColumnType("nvarchar(450)"); + + b.Property("DeliveryTimeFrame") + .HasColumnType("int"); + + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStoreID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderDate") + .HasColumnType("datetime2"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("PaymentType") + .HasColumnType("int"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TotalPrice") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreID"); + + b.HasIndex("StaffID"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DeliveryStatus") + .HasColumnType("int"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStatus") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("OrderID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderStatus") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrderID"); + + b.ToTable("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TimeScheduleID") + .HasColumnType("nvarchar(450)"); + + b.Property("TripCollect") + .HasColumnType("int"); + + b.Property("TripType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BuildingID"); + + b.HasIndex("StaffID"); + + b.HasIndex("TimeScheduleID"); + + b.ToTable("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("PaymentID") + .HasColumnType("nvarchar(450)"); + + b.Property("PaymentMethod") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionType") + .HasColumnType("int"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentID"); + + b.HasIndex("WalletID"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Balance") + .HasColumnType("float"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Wallets"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany() + .HasForeignKey("BuildingID"); + + b.Navigation("ApplicationUser"); + + b.Navigation("Building"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", "LaundryStore") + .WithMany() + .HasForeignKey("LaundryStoreID"); + + b.HasOne("Staff", "Staff") + .WithMany() + .HasForeignKey("StaffID"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Order") + .WithMany() + .HasForeignKey("OrderID"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Orders") + .WithMany() + .HasForeignKey("OrderId"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany() + .HasForeignKey("BuildingID"); + + b.HasOne("Staff", "Staff") + .WithMany() + .HasForeignKey("StaffID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.TimeSchedule", "TimeSchedule") + .WithMany() + .HasForeignKey("TimeScheduleID"); + + b.Navigation("Building"); + + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", "Payment") + .WithMany() + .HasForeignKey("PaymentID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithMany() + .HasForeignKey("WalletID"); + + b.Navigation("Payment"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("Staff", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Navigation("ApplicationUser"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.cs new file mode 100644 index 0000000..7605e82 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231004174024_UpdateTransaction.cs @@ -0,0 +1,78 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + /// + public partial class UpdateTransaction : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Payments_Transaction_TransactionId", + table: "Payments"); + + migrationBuilder.DropIndex( + name: "IX_Payments_TransactionId", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "TransactionId", + table: "Payments"); + + migrationBuilder.AddColumn( + name: "PaymentID", + table: "Transaction", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Transaction_PaymentID", + table: "Transaction", + column: "PaymentID"); + + migrationBuilder.AddForeignKey( + name: "FK_Transaction_Payments_PaymentID", + table: "Transaction", + column: "PaymentID", + principalTable: "Payments", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Transaction_Payments_PaymentID", + table: "Transaction"); + + migrationBuilder.DropIndex( + name: "IX_Transaction_PaymentID", + table: "Transaction"); + + migrationBuilder.DropColumn( + name: "PaymentID", + table: "Transaction"); + + migrationBuilder.AddColumn( + name: "TransactionId", + table: "Payments", + type: "nvarchar(450)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Payments_TransactionId", + table: "Payments", + column: "TransactionId"); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Transaction_TransactionId", + table: "Payments", + column: "TransactionId", + principalTable: "Transaction", + principalColumn: "Id"); + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs index d5d09ce..420dd39 100644 --- a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs +++ b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs @@ -183,7 +183,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Buildings", (string)null); + b.ToTable("Buildings"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => @@ -215,7 +215,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("BuildingID"); - b.ToTable("Customers", (string)null); + b.ToTable("Customers"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => @@ -332,7 +332,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.ToTable("LaundryStores", (string)null); + b.ToTable("LaundryStores"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => @@ -393,7 +393,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("StaffID"); - b.ToTable("Orders", (string)null); + b.ToTable("Orders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => @@ -435,7 +435,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("OrderID"); - b.ToTable("OrderHistories", (string)null); + b.ToTable("OrderHistories"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => @@ -461,16 +461,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Price") .HasColumnType("float"); - b.Property("TransactionId") - .HasColumnType("nvarchar(450)"); - b.HasKey("Id"); b.HasIndex("OrderId"); - b.HasIndex("TransactionId"); - - b.ToTable("Payments", (string)null); + b.ToTable("Payments"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => @@ -513,7 +508,41 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TimeScheduleID"); - b.ToTable("Staff_Trips", (string)null); + b.ToTable("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => @@ -539,6 +568,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastUpdatedTime") .HasColumnType("datetimeoffset"); + b.Property("PaymentID") + .HasColumnType("nvarchar(450)"); + b.Property("PaymentMethod") .HasColumnType("nvarchar(max)"); @@ -550,9 +582,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); + b.HasIndex("PaymentID"); + b.HasIndex("WalletID"); - b.ToTable("Transaction", (string)null); + b.ToTable("Transaction"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => @@ -577,7 +611,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Wallets", (string)null); + b.ToTable("Wallets"); }); modelBuilder.Entity("Staff", b => @@ -604,41 +638,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.ToTable("Staffs", (string)null); - }); - - modelBuilder.Entity("TimeSchedule", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedTime") - .HasColumnType("datetimeoffset"); - - b.Property("DayOfWeek") - .HasColumnType("int"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastUpdatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastUpdatedTime") - .HasColumnType("datetimeoffset"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TimeSchedules", (string)null); + b.ToTable("Staffs"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -699,7 +699,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") - .WithMany("Customers") + .WithMany() .HasForeignKey("BuildingID"); b.Navigation("ApplicationUser"); @@ -728,11 +728,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => { b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", "Customer") - .WithMany("Order") + .WithMany() .HasForeignKey("CustomerID"); b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", "LaundryStore") - .WithMany("Orders") + .WithMany() .HasForeignKey("LaundryStoreID"); b.HasOne("Staff", "Staff") @@ -749,7 +749,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => { b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Order") - .WithMany("OrderHistories") + .WithMany() .HasForeignKey("OrderID"); b.Navigation("Order"); @@ -758,30 +758,24 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => { b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Orders") - .WithMany("Payments") + .WithMany() .HasForeignKey("OrderId"); - b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", "Transaction") - .WithMany("Payments") - .HasForeignKey("TransactionId"); - b.Navigation("Orders"); - - b.Navigation("Transaction"); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => { b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") - .WithMany("Staff_Trips") + .WithMany() .HasForeignKey("BuildingID"); b.HasOne("Staff", "Staff") - .WithMany("Staff_Trips") + .WithMany() .HasForeignKey("StaffID"); - b.HasOne("TimeSchedule", "TimeSchedule") - .WithMany("Staff_Trip") + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.TimeSchedule", "TimeSchedule") + .WithMany() .HasForeignKey("TimeScheduleID"); b.Navigation("Building"); @@ -793,10 +787,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", "Payment") + .WithMany() + .HasForeignKey("PaymentID"); + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") - .WithMany("Transactions") + .WithMany() .HasForeignKey("WalletID"); + b.Navigation("Payment"); + b.Navigation("Wallet"); }); @@ -809,50 +809,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApplicationUser"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => - { - b.Navigation("Customers"); - - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => - { - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => - { - b.Navigation("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => - { - b.Navigation("OrderHistories"); - - b.Navigation("Payments"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => - { - b.Navigation("Payments"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => { b.Navigation("ApplicationUser"); - - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("Staff", b => - { - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("TimeSchedule", b => - { - b.Navigation("Staff_Trip"); }); #pragma warning restore 612, 618 } diff --git a/src/SWD-Laundry-Backend.Service/Services/WalletService.cs b/src/SWD-Laundry-Backend.Service/Services/WalletService.cs index 044369d..9cb2f2a 100644 --- a/src/SWD-Laundry-Backend.Service/Services/WalletService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/WalletService.cs @@ -8,14 +8,13 @@ namespace SWD_Laundry_Backend.Service.Services; -//[ScopedDependency(ServiceType = typeof(IWalletService))] - +[ScopedDependency(ServiceType = typeof(IWalletService))] public class WalletService : Base_Service.Service, IWalletService { private readonly IWalletRepository _repository; - private readonly AutoMapper.Mapper _mapper; + private readonly IMapper _mapper; - public WalletService(IWalletRepository repository, AutoMapper.Mapper mapper) + public WalletService(IWalletRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; diff --git a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs index 9abf2ab..7606d51 100644 --- a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs +++ b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs @@ -9,9 +9,9 @@ namespace SWD_Laundry_Backend.Controllers; [ApiController] public class LaundryStoreController : ApiControllerBase { - private readonly LaundryStoreService _service; + private readonly ILaundryStoreService _service; - public LaundryStoreController(LaundryStoreService service) + public LaundryStoreController(ILaundryStoreService service) { _service = service; } @@ -20,7 +20,7 @@ public LaundryStoreController(LaundryStoreService service) [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesDefaultResponseType] - public async Task GetAll() + public async Task ViewLaundryStoreList() { try { @@ -38,7 +38,7 @@ public async Task GetAll() [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesDefaultResponseType] - public async Task GetById(string id) + public async Task ViewLaundryStoreInformation(string id) { try { @@ -79,7 +79,7 @@ public async Task Create(LaundryStoreModel model) [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesDefaultResponseType] - public async Task Update(string id, LaundryStoreModel model) + public async Task EditLaundryStoreInformation(string id, LaundryStoreModel model) { try { From 4e07a982d45c7058ae504765dcdaac80f31a6df0 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:15:12 +0700 Subject: [PATCH 10/13] new Data --- Script.sql | Bin 567644 -> 572398 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Script.sql b/Script.sql index 1409611d8ba48ff2244810915ceace79813e73d7..bfae50638536d3cbac3c255f8394a447edbc217a 100644 GIT binary patch delta 1761 zcma)5e`r-@82-+EuiwEX<7zR4T+PjzUe@LQJa?0fWrJ#6ZgZH3i{VVkjk^^p3vHCb zWeXWnJF>SVY%9n=5)E$bi|`KzDk~~nu;F5@xx#2@EjF{is^^^h?Z+S6K@Q(J=X<~B zdEe)K&U?mxDE;GJ>G7tF~m$wZL%u<>^f0iEMRG)lE ztv@TDv-rYr-JqV1zMI00dL=%|AevyieCHcE^lq!oLThx^v!83+@u3R^fa}pL&-VvvUEw#wC zUmQhQr@zG-&!C+qaac5qBRGwT=#n}LeKZ=XaZKLnU+}{tQ{uDZO6J0?hxmC9(6@K4OC*EbR^sUhAlPl`3;CW z3KI?hz9{+yaR`DBLvj;5TxyL9-G*ciTs8b^>W=Kxg+p_Y*fIk(TmM>^l-FNH@cOLm zP-o}lCZqRHc`!dhdo2t_0?s-jE!bs27`~J%FM)j$afo$?qHHHbv|=5?T9oMcoq=pe zde~n3*hV!uC#9iI4UlEn0Ymc1k7Xe}FKXx8O zg#IU*`9_Y4RKZ7-(uC0m{AvF5KmW1>rvj!w%_Wqxxa;4^OAcnQ}#YoAbT@^zrmDh;tI9T6Fki4 zrdE{raF_z>@vj$3w4X-<75^^#rFpQ-Y*m@>s7BeT7>T-z9*pq_bxM~@&psvFn<3&o_+k-*%?j6dm?yWYr^YtG8dfroQTF%>X4m@oZ@E+S=-!)X|$6BR^3gxfe OT{Cy3nz?Ica{mJdQY9Av delta 935 zcmZXSQD{d`Tx)VJLlW}-d}yw zpUFyD(^IhBWB(`yq*6w9mlR2*R1|wSw+|C0s-1(wl><21f)v|rR@p1#MI9iI+bq-Z zMF^2+5U?%Y?8CYLYHoai5JwJS+(5L-AZq%%@Hd#HL=;{8$cs}3B6HP`HREN;X%CY~ zX6GMAI^#7)K&IINvr0Z0ZCo738NFCwt(|%37-sdvGX@%0PZ+15wc8YenA24^XGik^ z(M2enJaxJwM3Zv<3_dd|UOntmn|@BtP2;qYW?l#?{Cc?e0!EB9d{T64t!m>E7L7D^ z1(1DFd}##v&|lg3HN0$~oVeZ$S=fU^)L6hWMV3M3@&YbfxKW0nYiT%%;_Tw#WLG#} zS%LUdLh^vWTrov^9g1{1)(*UNR98j{a^;)5bh1CC@?Rm2SMLFA+;q w$ZZoPtxR`q*zsVo7lo`2Otl-N9q5(F{}_C{>M);g4pUw7S Date: Thu, 5 Oct 2023 07:13:24 +0700 Subject: [PATCH 11/13] Update respone --- .../Interface/IWalletService.cs | 1 + .../Enum/AllowedTransactionType.cs | 8 ++--- .../Enum/OrderStatus.cs | 8 ++--- .../Enum/OrderType.cs | 4 +-- .../Enum/PaymentType.cs | 8 ++--- src/SWD-Laundry-Backend.Core/Enum/TripType.cs | 10 ++++-- .../Models/BaseResponseModels.cs | 5 ++- .../SWD-Laundry-Backend.Core.csproj | 1 + .../Utils/CoreHelper.cs | 24 +++++++++++++- .../Utils/EnumConverter.cs | 20 ++++++++++++ .../Utils/ObjHelper.cs | 4 +-- .../Utils/StringEnumConverterPair.cs | 29 +++++++++++++++++ .../Services/LaundryStoreService.cs | 4 +-- .../Services/StaffTripService.cs | 2 +- .../Services/WalletService.cs | 6 ++++ .../Controllers/LaundryStoreController.cs | 22 +++++++++++++ .../Controllers/StaffTripController.cs | 22 +++++++++++++ .../Controllers/TimeScheduleController.cs | 22 +++++++++++++ .../Controllers/WalletController.cs | 24 +++++++++++++- .../Controllers/WeatherForecastController.cs | 31 ------------------- src/SWD-Laundry-Backend/Program.cs | 11 +++++++ src/SWD-Laundry-Backend/WeatherForecast.cs | 12 ------- 22 files changed, 210 insertions(+), 68 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Core/Utils/EnumConverter.cs create mode 100644 src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs delete mode 100644 src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs delete mode 100644 src/SWD-Laundry-Backend/WeatherForecast.cs diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs index 85ba7e6..240b306 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/IWalletService.cs @@ -7,6 +7,7 @@ namespace SWD_Laundry_Backend.Contract.Service.Interface; public interface IWalletService : ICreateAble, IGetAble, + IDeleteAble, IUpdateAble { } diff --git a/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs b/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs index 4d2e176..febeabc 100644 --- a/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs +++ b/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs @@ -1,8 +1,8 @@ namespace SWD_Laundry_Backend.Core.Enum; public enum AllowedTransactionType { - Deposit = 1, - Withdraw = 2, - Debt = 3, - Paid = 4 + Deposit = 0, + Withdraw = 1, + Debt = 2, + Paid = 3 } diff --git a/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs b/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs index db7cc71..587fb7b 100644 --- a/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs +++ b/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs @@ -1,8 +1,8 @@ namespace SWD_Laundry_Backend.Core.Enum; public enum OrderStatus { - Preparing = 1, - Processing = 2, - Completed = 3, - Cancelled = 4 + Preparing = 0, + Processing = 1, + Completed = 2, + Cancelled = 3 } diff --git a/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs b/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs index c95ec26..c6e11cf 100644 --- a/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs +++ b/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs @@ -1,6 +1,6 @@ namespace SWD_Laundry_Backend.Core.Enum; public enum OrderType { - OneWay = 1, - TwoWay = 2 + OneWay = 0, + TwoWay = 1 } diff --git a/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs b/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs index 478b06d..d2d9e6f 100644 --- a/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs +++ b/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs @@ -1,8 +1,8 @@ namespace SWD_Laundry_Backend.Core.Enum; public enum PaymentType { - Cash = 1, - CreditCard = 2, - DebitCard = 3, - EWallet = 4 + Cash = 0, + CreditCard = 1, + DebitCard = 2, + EWallet = 3 } diff --git a/src/SWD-Laundry-Backend.Core/Enum/TripType.cs b/src/SWD-Laundry-Backend.Core/Enum/TripType.cs index b5075df..2a73ee1 100644 --- a/src/SWD-Laundry-Backend.Core/Enum/TripType.cs +++ b/src/SWD-Laundry-Backend.Core/Enum/TripType.cs @@ -1,7 +1,11 @@ -namespace SWD_Laundry_Backend.Core.Enum; +using Newtonsoft.Json; +using SWD_Laundry_Backend.Core.Utils; +namespace SWD_Laundry_Backend.Core.Enum; + +//[JsonConverter(typeof(EnumConverter))] public enum TripType { - Collect_From_Customer = 0, - Delivery_To_Customer = 1, + CollectFromCustomer = 0, + DeliveryToCustomer = 1, } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs index 2950328..0301fd4 100644 --- a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs +++ b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs @@ -1,8 +1,11 @@ -namespace SWD_Laundry_Backend.Core.Models; +using SWD_Laundry_Backend.Core.Utils; + +namespace SWD_Laundry_Backend.Core.Models; public class BaseResponseModel { public T? Data { get; set; } public object? AdditionalData { get; set; } + public object EnumData { get; set; } = CoreHelper.GetAllEnums(); public string? Message { get; set; } public int StatusCode { get; set; } diff --git a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj index 0828a68..191fd7a 100644 --- a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj +++ b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj @@ -14,6 +14,7 @@ + diff --git a/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs b/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs index b60efd4..d7efa68 100644 --- a/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs +++ b/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs @@ -1,4 +1,6 @@ -using Microsoft.AspNetCore.Http; +using System.Reflection; +using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Http; using SWD_Laundry_Backend.Core.Constant; using TimeZoneConverter; @@ -29,4 +31,24 @@ public static TimeZoneInfo GetTimeZoneInfo(string timeZoneId) } public static HttpContext? Current => _contextAccessor?.HttpContext; + + public static string ToSentenceCase(this string str) + { + return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1])); + } + + public static object GetAllEnums() + { + return Assembly.GetExecutingAssembly() + .GetTypes() + .Where(t => t.IsEnum) + .ToDictionary(t => t.Name, t => + System.Enum.GetNames(t) + .Zip(System.Enum.GetValues(t).Cast(), (Key, Value) => new + { + Name = Key, + Value, + DisplayName = ToSentenceCase(Key) + })); + } } diff --git a/src/SWD-Laundry-Backend.Core/Utils/EnumConverter.cs b/src/SWD-Laundry-Backend.Core/Utils/EnumConverter.cs new file mode 100644 index 0000000..fa25c27 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Utils/EnumConverter.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; + +namespace SWD_Laundry_Backend.Core.Utils; +public class EnumConverter : JsonConverter where T : System.Enum +{ + public override T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer) + => throw new NotImplementedException(); + + public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer) + { + var nameAndValue = new { + Name = value.ToString("g"), + Value = value.ToString("d"), + DisplayName = CoreHelper.ToSentenceCase(value.ToString("g")) + }; + var semiJson = JObject.FromObject(nameAndValue); + semiJson.WriteTo(writer); + } +} diff --git a/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs b/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs index ed7ca72..3489d01 100644 --- a/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs +++ b/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs @@ -9,10 +9,10 @@ public static string ToJsonString(object obj) JObject? jObject = obj as JObject; if (jObject != null) { - return jObject.ToString(Formatting.None); + return jObject.ToString(Formatting.Indented); } - return JsonConvert.SerializeObject(obj, Formatting.None); + return JsonConvert.SerializeObject(obj, Formatting.Indented); } public static T? Clone(T obj) diff --git a/src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs b/src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs new file mode 100644 index 0000000..cb09071 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs @@ -0,0 +1,29 @@ +using Newtonsoft.Json; + +namespace SWD_Laundry_Backend.Core.Utils; +public class StringEnumConverterPair : JsonConverter +{ + + + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + writer.WriteStartObject(); + writer.WritePropertyName("name"); + writer.WriteValue(value.ToString()); + writer.WritePropertyName("value"); + writer.WriteValue(Convert.ChangeType(value, typeof(int))); + writer.WriteEndObject(); + } + + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) + { + // ill leave this up to your imagination + throw new NotImplementedException(); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(System.Enum); + } + +} diff --git a/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs b/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs index 99e3865..5890991 100644 --- a/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/LaundryStoreService.cs @@ -35,13 +35,13 @@ public Task DeleteAsync(string id, CancellationToken cancellationToken = de public async Task> GetAllAsync(CancellationToken cancellationToken = default) { - var list = await _repository.GetAsync(cancellationToken: cancellationToken); + var list = await _repository.GetAsync(cancellationToken: cancellationToken, includes: x => x.ApplicationUser); return await list.ToListAsync(cancellationToken); } public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) { - var query = await _repository.GetAsync(c => c.Id == id, cancellationToken); + var query = await _repository.GetAsync(c => c.Id == id, cancellationToken, x => x.ApplicationUser); var obj = await query.FirstOrDefaultAsync(); return obj; } diff --git a/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs b/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs index a88fddd..0e68081 100644 --- a/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/StaffTripService.cs @@ -56,7 +56,7 @@ public async Task> GetAllAsync(CancellationToken cancell cancellationToken: cancellationToken, includes: items); - var obj = await query.FirstOrDefaultAsync(); + var obj = await query.FirstOrDefaultAsync(cancellationToken: cancellationToken); return obj; } diff --git a/src/SWD-Laundry-Backend.Service/Services/WalletService.cs b/src/SWD-Laundry-Backend.Service/Services/WalletService.cs index 9cb2f2a..5056252 100644 --- a/src/SWD-Laundry-Backend.Service/Services/WalletService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/WalletService.cs @@ -27,6 +27,12 @@ public async Task CreateAsync(WalletModel model, CancellationToken cance return objectId; } + public async Task DeleteAsync(string id, CancellationToken cancellationToken = default) + { + int i = await _repository.DeleteAsync(x => x.Id == id, cancellationToken: cancellationToken); + return i; + } + public async Task> GetAllAsync(CancellationToken cancellationToken = default) { var list = await _repository.GetAsync(cancellationToken: cancellationToken); diff --git a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs index 7606d51..16482a8 100644 --- a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs +++ b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs @@ -95,4 +95,26 @@ public async Task EditLaundryStoreInformation(string id, LaundryS return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Delete(string id) + { + try + { + var result = await _service.DeleteAsync(id); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } } diff --git a/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs b/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs index 256e3a9..85e6316 100644 --- a/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs +++ b/src/SWD-Laundry-Backend/Controllers/StaffTripController.cs @@ -94,4 +94,26 @@ public async Task Update(string id, StaffTripModel model) return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Delete(string id) + { + try + { + var result = await _service.DeleteAsync(id); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } } diff --git a/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs b/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs index a382a75..3c9ef5c 100644 --- a/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs +++ b/src/SWD-Laundry-Backend/Controllers/TimeScheduleController.cs @@ -94,4 +94,26 @@ public async Task Update(string id, TimeScheduleModel model) return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); } } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Delete(string id) + { + try + { + var result = await _service.DeleteAsync(id); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend/Controllers/WalletController.cs b/src/SWD-Laundry-Backend/Controllers/WalletController.cs index 52d38f9..9dec75a 100644 --- a/src/SWD-Laundry-Backend/Controllers/WalletController.cs +++ b/src/SWD-Laundry-Backend/Controllers/WalletController.cs @@ -82,7 +82,29 @@ public async Task Update(string id, WalletModel model) { try { - var result = await _service.UpdateAsync(id, model); + var result = await _service.UpdateAsync(id, model ); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Delete(string id) + { + try + { + var result = await _service.DeleteAsync(id); if (result == 0) { return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); diff --git a/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs b/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs deleted file mode 100644 index a37e97d..0000000 --- a/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace SWD_Laundry_Backend.Controllers; -[ApiController] -public class WeatherForecastController : ApiControllerBase -{ - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - private readonly ILogger _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } -} - diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index 00cdfd9..3b63476 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -1,3 +1,5 @@ +using System.Text.Json; +using System.Text.Json.Serialization; using System.Text.RegularExpressions; using Invedia.DI; using Microsoft.AspNetCore.Authentication.JwtBearer; @@ -6,12 +8,18 @@ using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; using Serilog; using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; using SWD_Laundry_Backend.Core.Config; +using SWD_Laundry_Backend.Core.Enum; +using SWD_Laundry_Backend.Core.Utils; using SWD_Laundry_Backend.Extensions; using SWD_Laundry_Backend.Repository.Infrastructure; + namespace SWD_Laundry_Backend; public class Program @@ -39,6 +47,9 @@ public static void Main(string[] args) builder.Services.AddControllers(options => { options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer())); + }).AddNewtonsoftJson(options => + { + options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/src/SWD-Laundry-Backend/WeatherForecast.cs b/src/SWD-Laundry-Backend/WeatherForecast.cs deleted file mode 100644 index 205d2ab..0000000 --- a/src/SWD-Laundry-Backend/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SWD_Laundry_Backend; - -public class WeatherForecast -{ - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } -} From ce633e3ab438e9868991f4ecfe8121bd032f31e0 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Thu, 5 Oct 2023 08:48:01 +0700 Subject: [PATCH 12/13] update --- .../Models/BaseResponseModels.cs | 3 +- .../Utils/CoreHelper.cs | 10 ++----- .../Utils/StringEnumConverterPair.cs | 29 ------------------- .../ValueObject/EnumObject.cs | 18 ++++++++++++ .../Controllers/LaundryStoreController.cs | 1 - 5 files changed, 23 insertions(+), 38 deletions(-) delete mode 100644 src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs create mode 100644 src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs diff --git a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs index 0301fd4..9476fde 100644 --- a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs +++ b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs @@ -1,11 +1,12 @@ using SWD_Laundry_Backend.Core.Utils; +using SWD_Laundry_Backend.Core.ValueObject; namespace SWD_Laundry_Backend.Core.Models; public class BaseResponseModel { public T? Data { get; set; } public object? AdditionalData { get; set; } - public object EnumData { get; set; } = CoreHelper.GetAllEnums(); + public Dictionary EnumData { get; set; } = CoreHelper.GetAllEnums(); public string? Message { get; set; } public int StatusCode { get; set; } diff --git a/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs b/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs index d7efa68..0e275a7 100644 --- a/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs +++ b/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs @@ -2,6 +2,7 @@ using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; using SWD_Laundry_Backend.Core.Constant; +using SWD_Laundry_Backend.Core.ValueObject; using TimeZoneConverter; namespace SWD_Laundry_Backend.Core.Utils; @@ -37,18 +38,13 @@ public static string ToSentenceCase(this string str) return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1])); } - public static object GetAllEnums() + public static Dictionary GetAllEnums() { return Assembly.GetExecutingAssembly() .GetTypes() .Where(t => t.IsEnum) .ToDictionary(t => t.Name, t => System.Enum.GetNames(t) - .Zip(System.Enum.GetValues(t).Cast(), (Key, Value) => new - { - Name = Key, - Value, - DisplayName = ToSentenceCase(Key) - })); + .Zip(System.Enum.GetValues(t).Cast(), (Key, Value) => new EnumObject(Key, value: Value, ToSentenceCase(Key))).ToArray()); } } diff --git a/src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs b/src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs deleted file mode 100644 index cb09071..0000000 --- a/src/SWD-Laundry-Backend.Core/Utils/StringEnumConverterPair.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; - -namespace SWD_Laundry_Backend.Core.Utils; -public class StringEnumConverterPair : JsonConverter -{ - - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - writer.WriteStartObject(); - writer.WritePropertyName("name"); - writer.WriteValue(value.ToString()); - writer.WritePropertyName("value"); - writer.WriteValue(Convert.ChangeType(value, typeof(int))); - writer.WriteEndObject(); - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - // ill leave this up to your imagination - throw new NotImplementedException(); - } - - public override bool CanConvert(Type objectType) - { - return objectType == typeof(System.Enum); - } - -} diff --git a/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs b/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs new file mode 100644 index 0000000..8fdc05f --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs @@ -0,0 +1,18 @@ +namespace SWD_Laundry_Backend.Core.ValueObject; +public record EnumObject +{ + private string _key; + private int _value; + private string _v; + + public EnumObject(string key, int value, string v) + { + _key = key; + _value = value; + _v = v; + } + + public string name { get; set; } + public int value { get; set; } + public string displayName { get; set; } +} diff --git a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs index 16482a8..1ed3bf3 100644 --- a/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs +++ b/src/SWD-Laundry-Backend/Controllers/LaundryStoreController.cs @@ -2,7 +2,6 @@ using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Service.Interface; using SWD_Laundry_Backend.Core.Models; -using SWD_Laundry_Backend.Service.Services; namespace SWD_Laundry_Backend.Controllers; From 54bc6c9dcc9e0baec8bdd8201f8b9643947e50f5 Mon Sep 17 00:00:00 2001 From: Nero <67089844+k-nero@users.noreply.github.com> Date: Thu, 5 Oct 2023 09:03:00 +0700 Subject: [PATCH 13/13] Hot fix enum --- .../ValueObject/EnumObject.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs b/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs index 8fdc05f..5e47dd2 100644 --- a/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs +++ b/src/SWD-Laundry-Backend.Core/ValueObject/EnumObject.cs @@ -1,15 +1,12 @@ namespace SWD_Laundry_Backend.Core.ValueObject; public record EnumObject -{ - private string _key; - private int _value; - private string _v; +{ public EnumObject(string key, int value, string v) { - _key = key; - _value = value; - _v = v; + name = key; + value = value; + displayName = v; } public string name { get; set; }