Skip to content

Commit c09abf9

Browse files
DangDang
authored andcommitted
update
1 parent 4acfacf commit c09abf9

File tree

32 files changed

+230
-209
lines changed

32 files changed

+230
-209
lines changed

VehicleShowroomManagement/src/Application/Features/Orders/Commands/UpdateOrderStatus/UpdateOrderStatusCommandHandler.cs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
using MediatR;
2-
using VehicleShowroomManagement.Application.Common.Interfaces;
3-
using VehicleShowroomManagement.Domain.Entities;
4-
51
namespace VehicleShowroomManagement.Application.Features.Orders.Commands.UpdateOrderStatus
62
{
73
/// <summary>
@@ -12,15 +8,23 @@ namespace VehicleShowroomManagement.Application.Features.Orders.Commands.UpdateO
128
/// </summary>
139
public class UpdateOrderStatusCommandHandler(
1410
IRepository<Order> orderRepository,
15-
IRepository<Vehicle> vehicleRepository) : IRequestHandler<UpdateOrderStatusCommand, Unit>
11+
IRepository<Vehicle> vehicleRepository,
12+
IUnitOfWork unitOfWork) : IRequestHandler<UpdateOrderStatusCommand, Unit>
1613
{
1714
public async Task<Unit> Handle(UpdateOrderStatusCommand request, CancellationToken cancellationToken)
1815
{
19-
var order = await orderRepository.GetByIdAsync(request.OrderId, cancellationToken);
20-
if (order == null) return Unit.Value;
21-
22-
order.UpdateStatus(request.Status);
23-
await orderRepository.UpdateAsync(order, cancellationToken);
16+
await unitOfWork.BeginTransactionAsync(cancellationToken);
17+
try
18+
{
19+
var order = await orderRepository.GetByIdAsync(request.OrderId, cancellationToken);
20+
if (order == null)
21+
{
22+
await unitOfWork.RollbackTransactionAsync(cancellationToken);
23+
return Unit.Value;
24+
}
25+
26+
order.UpdateStatus(request.Status);
27+
await orderRepository.UpdateAsync(order, cancellationToken);
2428

2529
// Business Logic: Update vehicle status based on order status
2630
if (!string.IsNullOrEmpty(order.VehicleId))
@@ -45,11 +49,22 @@ public async Task<Unit> Handle(UpdateOrderStatusCommand request, CancellationTok
4549
// When order is cancelled, make vehicle available again
4650
vehicle.UpdateStatus(VehicleStatus.Available);
4751
await vehicleRepository.UpdateAsync(vehicle, cancellationToken);
52+
53+
// Clear vehicle assignment from order
54+
order.ClearVehicle();
55+
await orderRepository.UpdateAsync(order, cancellationToken);
4856
}
4957
}
5058
}
5159

52-
return Unit.Value;
60+
await unitOfWork.CommitTransactionAsync(cancellationToken);
61+
return Unit.Value;
62+
}
63+
catch
64+
{
65+
await unitOfWork.RollbackTransactionAsync(cancellationToken);
66+
throw;
67+
}
5368
}
5469
}
5570
}

VehicleShowroomManagement/src/Application/Features/Orders/Queries/GetOrders/GetOrdersQueryHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ public async Task<OrdersResponse> Handle(GetOrdersQuery request, CancellationTok
4545
SalePrice = order.SalePrice,
4646
VehicleId = order.VehicleId,
4747
AppointmentDate = order.AppointmentDate,
48-
Status = order.Status.ToString(),
48+
Status = ((int)order.Status).ToString(),
49+
StatusCode = (int)order.Status,
50+
StatusName = order.Status.ToString(),
4951
CreatedAt = order.CreatedAt,
5052
UpdatedAt = order.UpdatedAt
5153
}).ToList();

VehicleShowroomManagement/src/Application/Features/Orders/Queries/GetOrders/OrderDto.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class OrderDto
1414
public DateTime? AppointmentDate { get; set; }
1515
public string? Note { get; set; }
1616
public string Status { get; set; } = string.Empty;
17+
public int StatusCode { get; set; }
18+
public string StatusName { get; set; } = string.Empty;
1719
public DateTime CreatedAt { get; set; }
1820
public DateTime UpdatedAt { get; set; }
1921
}

VehicleShowroomManagement/src/Application/Features/ServiceOrders/Commands/UpdateStatus/UpdateServiceOrderStatusCommand.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ namespace VehicleShowroomManagement.Application.Features.ServiceOrders.Commands.
99
/// </summary>
1010
public record UpdateServiceOrderStatusCommand(
1111
string ServiceOrderId,
12-
ServiceOrderStatus Status,
13-
string? LicensePlate = null)
12+
ServiceOrderStatus Status)
1413
: IRequest<UpdateServiceOrderStatusResult>;
1514
}
1615

VehicleShowroomManagement/src/Application/Features/ServiceOrders/Commands/UpdateStatus/UpdateServiceOrderStatusCommandHandler.cs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,40 @@ public class UpdateServiceOrderStatusCommandHandler(
1414
IRepository<ServiceOrder> serviceOrderRepository,
1515
IRepository<Order> orderRepository,
1616
IRepository<Vehicle> vehicleRepository,
17-
IMediator mediator) : IRequestHandler<UpdateServiceOrderStatusCommand, UpdateServiceOrderStatusResult>
17+
IMediator mediator,
18+
IUnitOfWork unitOfWork) : IRequestHandler<UpdateServiceOrderStatusCommand, UpdateServiceOrderStatusResult>
1819
{
1920

2021
public async Task<UpdateServiceOrderStatusResult> Handle(UpdateServiceOrderStatusCommand request, CancellationToken cancellationToken)
2122
{
22-
// Fetch service order
23-
var serviceOrder = await serviceOrderRepository.GetByIdAsync(request.ServiceOrderId, cancellationToken) ?? throw new ArgumentException("Service order not found");
24-
25-
// Update status using domain method
26-
serviceOrder.UpdateStatus(request.Status);
27-
await serviceOrderRepository.UpdateAsync(serviceOrder, cancellationToken);
28-
29-
// Update license plate if provided (for any status)
30-
if (!string.IsNullOrWhiteSpace(request.LicensePlate))
23+
await unitOfWork.BeginTransactionAsync(cancellationToken);
24+
try
3125
{
32-
var order = await orderRepository.GetByIdAsync(serviceOrder.OrderId, cancellationToken);
33-
if (order != null && !string.IsNullOrEmpty(order.VehicleId))
26+
// Fetch service order
27+
var serviceOrder = await serviceOrderRepository.GetByIdAsync(request.ServiceOrderId, cancellationToken) ?? throw new ArgumentException("Service order not found");
28+
29+
// Enforce preconditions for certain transitions
30+
if (request.Status == ServiceOrderStatus.Completed && serviceOrder.Type == ServiceType.PreDelivery)
3431
{
35-
var vehicles = await vehicleRepository.FindAsync(v => v.VehicleId == order.VehicleId, cancellationToken);
36-
var vehicle = vehicles.FirstOrDefault();
37-
if (vehicle != null)
32+
// Ensure related order exists and is Confirmed before completing pre-delivery service
33+
var relatedOrder = await orderRepository.GetByIdAsync(serviceOrder.OrderId, cancellationToken) ?? throw new ArgumentException("Related order not found");
34+
if (relatedOrder.Status != OrderStatus.Confirmed)
3835
{
39-
vehicle.SetLicensePlate(request.LicensePlate);
40-
await vehicleRepository.UpdateAsync(vehicle, cancellationToken);
36+
throw new InvalidOperationException("Order must be Confirmed before completing PreDelivery service order");
4137
}
4238
}
43-
}
39+
40+
// Update status using domain method
41+
serviceOrder.UpdateStatus(request.Status);
42+
await serviceOrderRepository.UpdateAsync(serviceOrder, cancellationToken);
4443

4544
var result = new UpdateServiceOrderStatusResult
4645
{
4746
Success = true,
4847
Message = "Service order status updated successfully"
4948
};
5049

51-
// Business Logic: Handle different status updates
50+
// Business Logic: Handle different status updates
5251
if (request.Status == ServiceOrderStatus.Cancelled)
5352
{
5453
// For cancelled service orders, no impact on Order/Vehicle status
@@ -104,7 +103,14 @@ public async Task<UpdateServiceOrderStatusResult> Handle(UpdateServiceOrderStatu
104103
result.BillingDocumentId = billingDocumentId;
105104
}
106105

107-
return result;
106+
await unitOfWork.CommitTransactionAsync(cancellationToken);
107+
return result;
108+
}
109+
catch
110+
{
111+
await unitOfWork.RollbackTransactionAsync(cancellationToken);
112+
throw;
113+
}
108114
}
109115
}
110116
}

VehicleShowroomManagement/src/Application/obj/VehicleShowroomManagement.Application.csproj.nuget.dgspec.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,6 @@
8787
"target": "Package",
8888
"version": "[13.0.0, )"
8989
},
90-
"MediatR.Extensions.Autofac.DependencyInjection": {
91-
"target": "Package",
92-
"version": "[13.1.0, )"
93-
},
9490
"Microsoft.AspNetCore.Http.Abstractions": {
9591
"target": "Package",
9692
"version": "[2.2.0, )"

VehicleShowroomManagement/src/Application/obj/project.assets.json

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -263,23 +263,6 @@
263263
}
264264
}
265265
},
266-
"MediatR.Extensions.Autofac.DependencyInjection/13.1.0": {
267-
"type": "package",
268-
"dependencies": {
269-
"Autofac": "8.4.0",
270-
"MediatR": "13.0.0"
271-
},
272-
"compile": {
273-
"lib/netstandard2.0/MediatR.Extensions.Autofac.DependencyInjection.dll": {
274-
"related": ".pdb"
275-
}
276-
},
277-
"runtime": {
278-
"lib/netstandard2.0/MediatR.Extensions.Autofac.DependencyInjection.dll": {
279-
"related": ".pdb"
280-
}
281-
}
282-
},
283266
"Microsoft.AspNetCore.Http.Abstractions/2.2.0": {
284267
"type": "package",
285268
"dependencies": {
@@ -2310,20 +2293,6 @@
23102293
"mediatr.contracts.nuspec"
23112294
]
23122295
},
2313-
"MediatR.Extensions.Autofac.DependencyInjection/13.1.0": {
2314-
"sha512": "5qXLkLSFailx1fSRkwOAmPl3uEu21IR7KZrFirf6ODxl3Xlf+msOkvhLGyfjmeS0doIKLdx2Gsg4XBotLJUffg==",
2315-
"type": "package",
2316-
"path": "mediatr.extensions.autofac.dependencyinjection/13.1.0",
2317-
"files": [
2318-
".nupkg.metadata",
2319-
".signature.p7s",
2320-
"icon.png",
2321-
"lib/netstandard2.0/MediatR.Extensions.Autofac.DependencyInjection.dll",
2322-
"lib/netstandard2.0/MediatR.Extensions.Autofac.DependencyInjection.pdb",
2323-
"mediatr.extensions.autofac.dependencyinjection.13.1.0.nupkg.sha512",
2324-
"mediatr.extensions.autofac.dependencyinjection.nuspec"
2325-
]
2326-
},
23272296
"Microsoft.AspNetCore.Http.Abstractions/2.2.0": {
23282297
"sha512": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
23292298
"type": "package",
@@ -6413,7 +6382,6 @@
64136382
"FluentValidation >= 11.9.2",
64146383
"MailKit >= 4.8.0",
64156384
"MediatR >= 13.0.0",
6416-
"MediatR.Extensions.Autofac.DependencyInjection >= 13.1.0",
64176385
"Microsoft.AspNetCore.Http.Abstractions >= 2.2.0",
64186386
"Microsoft.Extensions.Configuration.Abstractions >= 8.0.0",
64196387
"Microsoft.Extensions.DependencyInjection.Abstractions >= 8.0.2",
@@ -6513,10 +6481,6 @@
65136481
"target": "Package",
65146482
"version": "[13.0.0, )"
65156483
},
6516-
"MediatR.Extensions.Autofac.DependencyInjection": {
6517-
"target": "Package",
6518-
"version": "[13.1.0, )"
6519-
},
65206484
"Microsoft.AspNetCore.Http.Abstractions": {
65216485
"target": "Package",
65226486
"version": "[2.2.0, )"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"restore":{"projectUniqueName":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Application\\VehicleShowroomManagement.Application.csproj","projectName":"VehicleShowroomManagement.Application","projectPath":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Application\\VehicleShowroomManagement.Application.csproj","outputPath":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Application\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"],"originalTargetFrameworks":["net8.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"C:\\Program Files\\dotnet\\library-packs":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Domain\\VehicleShowroomManagement.Domain.csproj":{"projectPath":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Domain\\VehicleShowroomManagement.Domain.csproj"}}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"},"SdkAnalysisLevel":"9.0.300"}"frameworks":{"net8.0":{"targetAlias":"net8.0","dependencies":{"AutoMapper":{"target":"Package","version":"[12.0.1, )"},"Autofac":{"target":"Package","version":"[8.4.0, )"},"BCrypt.Net-Next":{"target":"Package","version":"[4.0.3, )"},"ClosedXML":{"target":"Package","version":"[0.104.2, )"},"CloudinaryDotNet":{"target":"Package","version":"[1.26.2, )"},"FluentValidation":{"target":"Package","version":"[11.9.2, )"},"MailKit":{"target":"Package","version":"[4.8.0, )"},"MediatR":{"target":"Package","version":"[13.0.0, )"},"MediatR.Extensions.Autofac.DependencyInjection":{"target":"Package","version":"[13.1.0, )"},"Microsoft.AspNetCore.Http.Abstractions":{"target":"Package","version":"[2.2.0, )"},"Microsoft.Extensions.Configuration.Abstractions":{"target":"Package","version":"[8.0.0, )"},"Microsoft.Extensions.DependencyInjection.Abstractions":{"target":"Package","version":"[8.0.2, )"},"Microsoft.Extensions.Logging.Abstractions":{"target":"Package","version":"[8.0.2, )"},"Microsoft.IdentityModel.Tokens":{"target":"Package","version":"[8.1.2, )"},"MimeKit":{"target":"Package","version":"[4.8.0, )"},"MongoDB.Driver":{"target":"Package","version":"[2.29.0, )"},"RazorEngineCore":{"target":"Package","version":"[2024.4.1, )"},"System.IdentityModel.Tokens.Jwt":{"target":"Package","version":"[8.1.2, )"}},"imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"}}
1+
"restore":{"projectUniqueName":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Application\\VehicleShowroomManagement.Application.csproj","projectName":"VehicleShowroomManagement.Application","projectPath":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Application\\VehicleShowroomManagement.Application.csproj","outputPath":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Application\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"],"originalTargetFrameworks":["net8.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"C:\\Program Files\\dotnet\\library-packs":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Domain\\VehicleShowroomManagement.Domain.csproj":{"projectPath":"c:\\Users\\Admin\\Documents\\GitHub\\Eproject3\\VehicleShowroomManagement\\src\\Domain\\VehicleShowroomManagement.Domain.csproj"}}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"},"SdkAnalysisLevel":"9.0.300"}"frameworks":{"net8.0":{"targetAlias":"net8.0","dependencies":{"AutoMapper":{"target":"Package","version":"[12.0.1, )"},"Autofac":{"target":"Package","version":"[8.4.0, )"},"BCrypt.Net-Next":{"target":"Package","version":"[4.0.3, )"},"ClosedXML":{"target":"Package","version":"[0.104.2, )"},"CloudinaryDotNet":{"target":"Package","version":"[1.26.2, )"},"FluentValidation":{"target":"Package","version":"[11.9.2, )"},"MailKit":{"target":"Package","version":"[4.8.0, )"},"MediatR":{"target":"Package","version":"[13.0.0, )"},"Microsoft.AspNetCore.Http.Abstractions":{"target":"Package","version":"[2.2.0, )"},"Microsoft.Extensions.Configuration.Abstractions":{"target":"Package","version":"[8.0.0, )"},"Microsoft.Extensions.DependencyInjection.Abstractions":{"target":"Package","version":"[8.0.2, )"},"Microsoft.Extensions.Logging.Abstractions":{"target":"Package","version":"[8.0.2, )"},"Microsoft.IdentityModel.Tokens":{"target":"Package","version":"[8.1.2, )"},"MimeKit":{"target":"Package","version":"[4.8.0, )"},"MongoDB.Driver":{"target":"Package","version":"[2.29.0, )"},"RazorEngineCore":{"target":"Package","version":"[2024.4.1, )"},"System.IdentityModel.Tokens.Jwt":{"target":"Package","version":"[8.1.2, )"}},"imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
17608043218808836
1+
17608652202497872

0 commit comments

Comments
 (0)