File size: 5,882 Bytes
da13799
 
068485b
4433399
068485b
 
 
 
 
861f0db
068485b
ccc2569
068485b
 
 
 
 
 
 
da13799
068485b
da13799
068485b
 
 
 
861f0db
068485b
861f0db
 
 
 
 
 
 
 
 
 
 
068485b
 
 
 
861f0db
 
 
068485b
 
 
 
ccc2569
 
 
 
 
 
 
 
 
068485b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b866d20
068485b
 
 
 
 
861f0db
 
 
 
 
 
 
 
 
 
068485b
 
 
 
 
 
 
 
861f0db
 
 
068485b
 
 
 
 
b866d20
068485b
 
 
 
 
 
 
 
 
 
 
861f0db
 
 
 
 
 
 
 
 
 
 
068485b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
861f0db
b866d20
861f0db
068485b
 
 
 
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
using DbConnect.Data;
using DbConnect.Entities;
using Microsoft.EntityFrameworkCore;
using LibraryManagement.Shared.Models;

namespace Backend.Features.Books
{
    public interface IBookService
    {
        Task<IEnumerable<BookDto>> GetAllBooksAsync(int? categoryId = null);
        Task<BookDto?> GetBookByIdAsync(int id);
        Task<IEnumerable<BookDto>> GetBooksByIdsAsync(List<int> ids);
        Task<BookDto> CreateBookAsync(BookCreateRequest request);
        Task<BookDto?> UpdateBookAsync(int id, BookUpdateRequest request);
        Task<bool> DeleteBookAsync(int id);
    }

    public class BookService : IBookService
    {
        private readonly AppDbContext _context;

        public BookService(AppDbContext context)
        {
            _context = context;
        }

        public async Task<IEnumerable<BookDto>> GetAllBooksAsync(int? categoryId = null)
        {
            var query = _context.Books
                .Include(b => b.Categories)
                .Where(b => b.IsActive);

            if (categoryId.HasValue)
            {
                query = query.Where(b => b.Categories.Any(c => c.Id == categoryId.Value));
            }

            var books = await query.ToListAsync();
            return books.Select(b => MapToDto(b));
        }

        public async Task<BookDto?> GetBookByIdAsync(int id)
        {
            var book = await _context.Books
                .Include(b => b.Categories)
                .FirstOrDefaultAsync(b => b.Id == id);
            if (book == null || !book.IsActive) return null;
            return MapToDto(book);
        }

        public async Task<IEnumerable<BookDto>> GetBooksByIdsAsync(List<int> ids)
        {
            var books = await _context.Books
                .Include(b => b.Categories)
                .Where(b => ids.Contains(b.Id) && b.IsActive)
                .ToListAsync();
            return books.Select(b => MapToDto(b));
        }

        public async Task<BookDto> CreateBookAsync(BookCreateRequest request)
        {
            if (await _context.Books.AnyAsync(b => b.Isbn == request.Isbn))
            {
                throw new Exception("A book with this ISBN already exists.");
            }

            var book = new Book
            {
                Title = request.Title,
                Isbn = request.Isbn,
                Author = request.Author,
                Description = request.Description,
                TotalCopies = request.TotalCopies,
                AvailableCopies = request.TotalCopies,
                CoverUrl = request.CoverUrl,
                Status = request.TotalCopies > 0 ? "Available" : "Out Of Stock",
                IsActive = true,
                CreatedAt = DateTime.UtcNow
            };

            // Attach selected categories
            if (request.CategoryIds != null && request.CategoryIds.Any())
            {
                var categories = await _context.Categories
                    .Where(c => request.CategoryIds.Contains(c.Id))
                    .ToListAsync();
                foreach (var cat in categories)
                    book.Categories.Add(cat);
            }

            _context.Books.Add(book);
            await _context.SaveChangesAsync();

            return MapToDto(book);
        }

        public async Task<BookDto?> UpdateBookAsync(int id, BookUpdateRequest request)
        {
            var book = await _context.Books
                .Include(b => b.Categories)
                .FirstOrDefaultAsync(b => b.Id == id);
            if (book == null || !book.IsActive) return null;

            book.Title = request.Title;
            book.Author = request.Author;
            book.Description = request.Description;
            book.CoverUrl = request.CoverUrl;
            
            // Basic logic to sync availability when total copies change
            int difference = request.TotalCopies - book.TotalCopies;
            book.TotalCopies = request.TotalCopies;
            book.AvailableCopies += difference;

            if (book.AvailableCopies < 0) book.AvailableCopies = 0;
            book.Status = book.AvailableCopies > 0 ? "Available" : "Out Of Stock";
            
            book.UpdatedAt = DateTime.UtcNow;

            // Sync categories: replace existing with new selection
            book.Categories.Clear();
            if (request.CategoryIds != null && request.CategoryIds.Any())
            {
                var categories = await _context.Categories
                    .Where(c => request.CategoryIds.Contains(c.Id))
                    .ToListAsync();
                foreach (var cat in categories)
                    book.Categories.Add(cat);
            }

            await _context.SaveChangesAsync();
            return MapToDto(book);
        }

        public async Task<bool> DeleteBookAsync(int id)
        {
            var book = await _context.Books.FindAsync(id);
            if (book == null) return false;

            book.IsActive = false;
            book.UpdatedAt = DateTime.UtcNow;

            await _context.SaveChangesAsync();
            return true;
        }

        private static BookDto MapToDto(Book book)
        {
            return new BookDto
            {
                Id = book.Id,
                Title = book.Title,
                Isbn = book.Isbn,
                Author = book.Author,
                Status = book.Status,
                IsActive = book.IsActive,
                Description = book.Description,
                TotalCopies = book.TotalCopies,
                AvailableCopies = book.AvailableCopies,
                CreatedAt = book.CreatedAt,
                UpdatedAt = book.UpdatedAt,
                CoverUrl = book.CoverUrl,
                Categories = book.Categories.Select(c => new BookCategoryDto { Id = c.Id, Name = c.Name }).ToList()
            };
        }
    }
}