File size: 8,042 Bytes
8edbc20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
using AutoMapper;
using Backend_Teamwork.src.Entities;
using Backend_Teamwork.src.Repository;
using Backend_Teamwork.src.Utils;
using static Backend_Teamwork.src.DTO.OrderDTO;

namespace Backend_Teamwork.src.Services.order
{
    public class OrderService : IOrderService
    {
        private readonly OrderRepository _orderRepository;
        private readonly IMapper _mapper;

        private readonly ArtworkRepository _artworkRepository;

        public OrderService(
            OrderRepository OrderRepository,
            IMapper mapper,
            ArtworkRepository artworkRepository
        )
        {
            _orderRepository = OrderRepository;
            _mapper = mapper;
            _artworkRepository = artworkRepository;
        }

        //-----------------------------------------------------

        // Retrieves all orders (Only Admin)
        public async Task<List<OrderReadDto>> GetAllAsync()
        {
            var OrderList = await _orderRepository.GetAllAsync();
            if (OrderList.Count == 0)
            {
                throw CustomException.NotFound($"Orders not found");
            }
            return _mapper.Map<List<Order>, List<OrderReadDto>>(OrderList);
        }

        // Retrieves all orders
        public async Task<List<OrderReadDto>> GetAllAsync(Guid id)
        {
            if (id == Guid.Empty)
            {
                throw CustomException.BadRequest("Invalid order ID");
            }
            var orders = await _orderRepository.GetOrdersByUserIdAsync(id);
            if (orders == null || !orders.Any())
            {
                throw CustomException.NotFound($"No orders found for user with id: {id}");
            }
            return _mapper.Map<List<Order>, List<OrderReadDto>>(orders);
        }

        //-----------------------------------------------------

        // Creates a new order
        public async Task<OrderReadDto> CreateOneAsync(Guid userId, OrderCreateDto createDto)
        {
            // Validate the createDto object
            if (
                createDto == null
                || createDto.OrderDetails == null
                || !createDto.OrderDetails.Any()
            )
            {
                throw CustomException.BadRequest(
                    "Invalid order data or no artworks provided in the order."
                );
            }

            decimal totalAmount = 0; // Initialize total amount

            // Process each artwork in the order
            foreach (var orderDetail in createDto.OrderDetails)
            {
                // Fetch the artwork by its ID
                var artwork = await _artworkRepository.GetByIdAsync(orderDetail.ArtworkId); // Using ArtworkId

                // Validate if the artwork exists
                if (artwork == null)
                {
                    throw CustomException.NotFound(
                        $"Artwork with ID: {orderDetail.ArtworkId} not found."
                    );
                }

                // Check if there is enough stock for the requested quantity
                if (artwork.Quantity < orderDetail.Quantity)
                {
                    throw CustomException.BadRequest(
                        $"Artwork {artwork.Title} does not have enough stock. Requested: {orderDetail.Quantity}, Available: {artwork.Quantity}."
                    );
                }

                // Reduce artwork stock
                artwork.Quantity -= orderDetail.Quantity;

                // Update the artwork quantity in the repository
                await _artworkRepository.UpdateOneAsync(artwork);

                // Calculate the total amount for this order detail
                decimal detailAmount = artwork.Price * orderDetail.Quantity;

                // Add this amount to the total amount
                totalAmount += detailAmount;
            }

            // Set the order creation time
            createDto.CreatedAt = DateTime.UtcNow;

            var newOrder = _mapper.Map<OrderCreateDto, Order>(createDto);

            // Set the user ID on the new order
            newOrder.UserId = userId;
            newOrder.TotalAmount = totalAmount;

            // Save the order to the repository
            var createdOrder = await _orderRepository.CreateOneAsync(newOrder);

            // Return the created order as a DTO
            return _mapper.Map<Order, OrderReadDto>(createdOrder);
        }

        //-----------------------------------------------------

        // Retrieves a order by their ID (Only Admin)
        public async Task<OrderReadDto> GetByIdAsync(Guid id)
        {
            if (id == Guid.Empty)
            {
                throw CustomException.BadRequest("Invalid order ID");
            }
            var foundOrder = await _orderRepository.GetByIdAsync(id);
            if (foundOrder == null)
            {
                throw CustomException.NotFound($"Order with ID {id} not found.");
            }
            return _mapper.Map<Order, OrderReadDto>(foundOrder);
        }

        // Retrieves a order by their ID
        public async Task<OrderReadDto> GetByIdAsync(Guid id, Guid userId)
        {
            if (id == Guid.Empty)
            {
                throw CustomException.BadRequest("Invalid order ID");
            }
            var foundOrder = await _orderRepository.GetByIdAsync(id);
            if (foundOrder == null)
            {
                throw CustomException.NotFound($"Order with ID {id} not found.");
            }
            if (foundOrder.UserId != userId)
            {
                throw CustomException.Forbidden("You are not authorized to view this order.");
            }

            return _mapper.Map<Order, OrderReadDto>(foundOrder);
        }

        //-----------------------------------------------------

        // Deletes a order by their ID
        public async Task<bool> DeleteOneAsync(Guid id)
        {
            var foundOrder = await _orderRepository.GetByIdAsync(id);
            if (foundOrder == null)
            {
                throw CustomException.NotFound($"Order with ID {id} not found.");
            }
            return await _orderRepository.DeleteOneAsync(foundOrder);
        }

        // Updates a order by their ID
        public async Task<bool> UpdateOneAsync(Guid id, OrderUpdateDto updateDto)
        {
            var foundOrder = await _orderRepository.GetByIdAsync(id);
            if (foundOrder == null)
            {
                throw CustomException.NotFound($"Order with ID {id} not found.");
            }

            // Map the update DTO to the existing Order entity
            _mapper.Map(updateDto, foundOrder);
            return await _orderRepository.UpdateOneAsync(foundOrder);
        }

        public async Task<List<OrderReadDto>> GetOrdersByPage(PaginationOptions paginationOptions)
        {
            // Validate pagination options
            if (paginationOptions.PageSize <= 0)
            {
                throw CustomException.BadRequest("Page Size should be greater than 0.");
            }

            if (paginationOptions.PageNumber < 0)
            {
                throw CustomException.BadRequest("Page Number should be 0 or greater.");
            }
            var OrderList = await _orderRepository.GetAllAsync(paginationOptions);
            if (OrderList == null || !OrderList.Any())
            {
                throw CustomException.NotFound("Orders not found");
            }
            return _mapper.Map<List<Order>, List<OrderReadDto>>(OrderList);
        }

        public async Task<List<OrderReadDto>> SortOrdersByDate()
        {
            var orders = await _orderRepository.GetAllAsync();
            if (orders.Count == 0)
            {
                throw CustomException.NotFound("Orders not found");
            }
            var sortedOrders=orders.OrderBy(x => x.CreatedAt).ToList();
            return _mapper.Map<List<Order>, List<OrderReadDto>>(sortedOrders);
        }
    }
}