44 Table of Figures Figure 1: Questionnaire about the business application 1...Figure 2: Questionnaire about the business application 2...Figure 3: Questionnaire about the business appli
Chapter 1: Peer Review and Feedback Analysis (P4)
Format questionnaire to reviews the business application, problem definition statement, proposed solution
We've devised an online survey aimed at gathering user feedback post-launch, focusing on their liv experience with the website This survey serves to pinpoint any encountered navigational challenges a solicit recommendations for enhancing the user experience
The survey will cover aspects such as website layout, functionality, and overall user satisfaction, employin uncomplicated questions accessible to all visitors
Our goal is to gather user insights to enhance the website's user-friendliness All comments received will b carefully reviewed and factored into future updates or improvements
Our primary objective is to ensure a seamless user experience, striving to identify issues and impleme necessary improvements through this questionnaire
Figure 1: Questionnaire about the business application (1)
Figure 2: Questionnaire about the business application (2)
Figure 3: Questionnaire about the business application (3)
Collect review feedbacks
1 Is it realistic for us to not show every product on the fron page?
2 How probable is it that you will share your app with friends?
3 Do you enjoy the user interface of our website?
4 How fast does our payment usually take?
5 Does our registration system work properly and provide correct page when logged in?
6 What is the typical time it takes for a webpage to fully load?
7 Rate our system from 1 to 10 A selection from 1 to 10
Table 1: The result of survey Feedback:
After collating feedback from our colleagues and authorized individuals who have interacted with or been given permission to use our products, the rating for each response stands as follows:
1 Is it realistic for us to not show every product on the fro page?
76.2% of our feedback choose Ye 23.8% of our feedback choose N
2 How probable is it that you will share your app with friends?
35.7% of our feedback choose Very likely
31% of our feedback choose Not likely
33.3% of our feedback choose May be
3 Do you enjoy the user interface of our website? 78.6% of our feedback choose Ye
4 How fast does our payment usually take?
47.6% of our feedback choose A few seconds
21.4% of our feedback choose O minute
21.4% of our feedback choose More than one minute 9.5% of our feedback choose No clear
5 Does our registration system work properly and provid the correct page when logged in?
83.3% of our feedback choose Ye 16.7% of our feedback choose N
6 What is the typical time it takes for a webpage to fully load?
61.9% of our feedback choose A few seconds
23.8% of our feedback choose About a minute
14.3% of our feedback choose More than a minute
7 Rate our system from 1 to 10
26.2% of our feedback choose 10 23.8% of our feedback choose 9
21.4% of our feedback choose 8 14.3% of our feedback choose 7
9.5% of our feedback choose 6 4.8% of our feedback choose 5 Table 2: Feedback
Chapter 2: Application Development (P5)
Folder structure of the application
To access the configuration file for the login and registration page, examine the Areas folder Here are the designated locations for various components within the application: g p pp
- The Controllers directory will accommodate all controller classes intended for the application's management and operation
- Within the Data directory, the ApplicationDbContext file assumes responsibility for the creation and maintenance of the database
- The Models directory is specifically allocated for housing all models utilized throughout the application's functionality
- The Utils directory is designated to house constant values corresponding to each distinct user role
- The ViewModels directory is dedicated to preserving models that contain requisite data for displaying pertinent application information
Source code samples of the application
Upon the initial login by the user, the homepage will integrate a specialized function expressly crafted to exhibit information concerning the availability of books This functionality will showcase an extensive inventory comprising all available books, thereby facilitating customers' effortless selection processes public async Task BookProduct()
{ var book = await context.Books.ToListAsync(); return View(book);
} public async Task BookProductDetail(int id)
{ var book = await context.Books.FirstOrDefaultAsync(x => x.BookId == id);
ViewBag.Category_id = new SelectList(context.Categories, "CategoryId" "Name", );
ViewBag.Company_id = new SelectList(context.PublicCompanies, "PublishingCompanyId",
}; return await Task.Run(() => View("BookProductDetail", viewmodel)); } return RedirectToAction("BookProduct");
The described function empowers clients to incorporate desired books into their basket, wherein th selected items within the cart are securely stored within individual customer accounts public async Task AddToCart(int id)
{ book var await context.Books.FirstOrDefaultAsync(x => x.BookId == id); if (book != null) { var cart_item = new Cart() {
BookId = book.BookId, Book = book,
Quantity = 1 }; cart_item.Total = cart_item.Quantity * cart_item.Book.Price; foreach (var item in context.Carts.Include(_ => _.Book).ToList()) { if (item.BookId == cart_item.BookId) { return RedirectToAction("CartIndex");
} } await context.Carts.AddAsync(cart_item); await context.SaveChangesAsync();
Thread.Sleep(2500); return RedirectToAction("BookProduct", "Book");
- The new feature enables customers to effortlessly transfer books from their shopping cart to the order list.- This action triggers a status change, ensuring the items are securely linked to the customer's account.- The ordered books are then conveniently accessible through the dedicated Order list.
{ var identity = (ClaimsIdentity)User.Identity; var claims = identity.FindFirst(ClaimTypes.NameIdentifier); var user = await context.ApplicationUsers.FindAsync(claims.Value); var customer = new Customer()
(!context.Customers.Contains(customer)) if
{ await context.Customers.AddAsync(customer); await context.SaveChangesAsync();
}; await context.Orders.AddAsync(order); await context.SaveChangesAsync(); var order_list = await context.Carts.Include(x => x.Book).ToListAsync(); foreach (var book order_list) in
{ var book_object = await context.Carts.Include(x => x.Book).FirstOrDefaultAsync(x => x.BookId == book.BookId); var orderDetail = new OrderDetail()
}; await context.AddAsync(orderDetail); await context.SaveChangesAsync();
} foreach (var book in order_list)
{ context.Carts.Remove(book); await context.SaveChangesAsync();
} foreach (var order_book order_list) in
{ var stored_book = await context.Books.FirstOrDefaultAsync(x => x.BookId = order_book.BookId); int book_quantity_inStored = stored_book.Quantity; book_quantity_inStored -= order_book.Quantity; stored_book.Quantity = book_quantity_inStored;
{ context.Books.Remove(stored_book);
} await context.SaveChangesAsync(); return RedirectToAction("BookProduct", "Book");
Below is a function that allows StoreOwner to display category information
[ p ] public async Task CategoryApproved()
{ var category = await context.Categories.ToListAsync(); return View(category);
The feature enabling the Store Owner to generate a new category is outlined below Upon the establishment of this category, the system will trigger a notification to the administrator, informing them of the newly created category
[HttpPost] //dữ liệu t máy khách(client) lên máy chừ ủ(server) để ử x lý. public async Task CreateCategory(AddCategoryViewModel CategoryModel) { var category = new Category()
}; await context.Categories.AddAsync(category); await context.SaveChangesAsync(); return RedirectToAction("CategoryIndex");
Figure 9: Category (2) The following function grants the StoreOwner the capability to modify category details
[HttpGet] public async Task ViewCategory(int id)
{ var category = await context.Categories.FirstOrDefaultAsync(x => x.CategoryId == id);
}; return await Task.Run(() => View("ViewCategory", viewmodel)); //truyền đối tượng viewmodel
Figure 10: Category (3) Here is a function that grants the StoreOwner the ability to remove category information
[HttpPost] public async Task DeleteCategory(UpdateCategoryView model)//tham số { var category = await context.Categories.FindAsync(model.CategoryId);
{ context.Categories.Remove(category); await context.SaveChangesAsync(); return RedirectToAction("CategoryIndex");
The function provided below facilitates the StoreOwner in accessing and displaying Publishing Company information within the system
[HttpGet] public async Task CompanyIndex()
{ company var await context.PublicCompanies.ToListAsync(); return View(company);
The function illustrating the capability for the Store Owner to create a new Publishing Company is outlined below
[HttpPost] public async Task CreatePublishCompany(AddCompanyViewModel CompanyModel)
{ Name = CompanyModel.Name, Adress = CompanyModel.Adress,
}; await context.PublicCompanies.AddAsync(company); await context.SaveChangesAsync(); return RedirectToAction("CompanyIndex");
Figure 13: PulishingCompany (2) Here's a function enabling the StoreOwner to modify Publishing Company information
[HttpPost] public async Task ViewCompany(UpdateCompany model)
{ company var await context.PublicCompanies.FindAsync(model.PublishingCompanyId); if (company != null) { company.Name = model.Name; company.Adress = model.Adress; await context.SaveChangesAsync(); return RedirectToAction("CompanyIndex");
Figure 14: PublishCompany (3) The function described below enables the StoreOwner to remove Publishing Company information [HttpPost] public async Task DeleteCompany(UpdateCompany model) { var company = await context.PublicCompanies.FindAsync(model.PublishingCompanyId); if (company != null) { context.PublicCompanies.Remove(company); await context.SaveChangesAsync(); return RedirectToAction("CompanyIndex");
The following function enables the StoreOwner to access and exhibit information regarding books available within the system
[HttpGet] public async Task BookIndex()
{ var book = await context.Books.Include(_ => _.Category).Include(_ =>
_.PublishCompany).ToListAsync(); return View(book);
The function presented below empowers the StoreOwner to generate new information entries for books within the system public async Task CreateBook(AddBookViewModel BookModel)
ViewBag.Category_id = new SelectList(context.Categories, "CategoryId" "Name", ,
ViewBag.Company_id = new SelectList(context.PublicCompanies, "PublishingCompanyId",
"Name", BookModel.PublishCompanyId); string uniqueFileName = UploadedFile(BookModel); var book = new Book()
//lay các thu c tính raộ
PublishCompanyId = BookModel.PublishCompanyId, Category = BookModel.Category,
}; foreach (var bookitem context.Books.ToList()) in
(book.Name == bookitem.Name) if
{ var NewQuantity = bookitem.Quantity.ToString(); var StoredQuantity = book.Quantity.ToString(); int ToStoredQuantity = int.Parse(StoredQuantity) + int.Parse(NewQuantity); //số lượng sách bookitem.Quantity = ToStoredQuantity; bookitem.UpdateDate = book.UpdateDate; await context.SaveChangesAsync(); return RedirectToAction("BookIndex");
} context.Books.Attach(book); //đính kèm context.Entry(book).State = EntityState.Added; await context.Books.AddAsync(book); await context.SaveChangesAsync(); return RedirectToAction("BookIndex");
The provided function grants the StoreOwner the capability to modify existing book information within the system public async Task ViewBook(UpdateBookView model)
ViewBag.Category_id = new SelectList(context.Categories, "CategoryId" "Name", , model.CategoryId);
ViewBag.Company_id = new SelectList(context.PublicCompanies, "PublishingCompanyId", g p y_ ( p g p y
"Name", model.PublishCompanyId);//render du lieu ra view var book = await context.Books.FirstOrDefaultAsync(x => x.BookId == model.BookId); string change_img = UploadedFile(model);
{ book.Name = model.Name; book.Quantity = model.Quantity; book.Price = model.Price; book.Description = model.Description; book.UpdateDate = model.UpdateDate; book.Author = model.Author;
} book.CategoryId = model.CategoryId; book.PublishCompanyId = model.PublishCompanyId; await context.SaveChangesAsync();
{ return NotFound("Book Not Found");
} await context.SaveChangesAsync(); return RedirectToAction("BookIndex");
The function outlined below provides the StoreOwner with the ability to remove book information from the system public async Task DeleteBook(UpdateBookView model)
{ var book = await context.Books.FindAsync(model.BookId);
{ context.Books.Remove(book); await context.SaveChangesAsync(); return RedirectToAction("BookIndex");
The following function equips the StoreOwner with the ability to search for book information based on the book's name within the system public async Task SearchBook(string Search)
{ var search_list = new List();
Upon successful registration and subsequent login as a customer, the screen will display the registered Gmail account information, affirming the successful login process
Following a successful login as a customer, the Shop screen will be presented, showcasing a variety of products, particularly books, for customers to browse through and purchase
The displayed shopping cart page exhibits the products that the customer has added from the system's home page
The displayed page contains the detailed information regarding the confirmed Order that the customer proceeded with from the shopping cart page
Below is the screen after logging in as a Storeowner The Gmail account information will be displayed on the screen to confirm the successful login
Upon logging in as a Storeowner, the screen will display the Gmail account information to confirm the successful login process
The provided page serves as the management interface for Store Owners, enabling actions such as displaying the book list, creating new entries, accessing book details, performing edits, and deleting book within the system
The presented page serves as the interface for Store Owners to oversee Categories, facilitating actions such as displaying the category list, creating new categories, and performing edits to existing categories within the system
The provided page serves as the interface for Store Owners to manage Publishing Companies, enabling actions such as displaying the list of Publishing Companies, creating new entries, and performing edits to existing Publishing Company information within the system
Upon successful login as an admin, the screen will confirm the login by displaying the Gmail account information.
Below is the page that the Admin uses to manage customer account including displaying the list of customer account, remove customer account, and reset password
Empowering admins with comprehensive account management capabilities, this interface grants the authority to view all customer accounts, seamlessly remove unwanted ones, and ensure secure access by resetting passwords.
The provided page acts as the interface for the Admin to oversee the comprehensive list of accepted Categories managed by Store Owners, allowing actions such as deleting specific Categories within the system
Collaborative work requires effective source code management, and the team opted for GitHub as the solution after careful consideration Our team selected GitHub for the following reasons
Here is the interface of GitHub, showcasing all the necessary features for efficient source code handling.
GitHub
Collaborative work requires effective source code management, and the team opted for GitHub as the solution after careful consideration Our team selected GitHub for the following reasons
Here is the interface of GitHub, showcasing all the necessary features for efficient source code handling.
Chapter 3: Application Evaluation (P6)
Review the performance of the application
No Decription Expect result Actual result Status
1 Register Register page of the website
2 Login Login page of the website
3 Home Home page of the website
4 Book Book page of the website
Category page of the website
6 Add Category Add Category page of the website
Update Category page of the website
8 Delete Category Delete Category page of the website
9 Book (StoreOwner) Book (StoreOwner) page of the website
Add Book (StoreOwner) page of the website
11 Update Book Update Book Figure 42 Pass p
(StoreOwner) (StoreOwner) page of the website
Delete Book (StoreOwner) page of the website
13 Order (StoreOwner) Order (StoreOwner) page of the website
Category Approval (Admin) page of the website
Category Reject (Admin) page of the website
Manage StoreOwner Account (Admin) page of the website
Manage Customer Account (Admin) page of the website
18 Search Search Book Figure 48 Pass
Conclusion
After project completion, feedback will be provided, categorized into two sections: input from our team and input from customers
The FPT Book Store system meets the initial requirements, offering seamless operation and adherence to established protocols Customers can effortlessly establish and manage accounts using the login and registration functions Additionally, they can explore and select books, simplifying the ordering process.
However, from the consumer perspective, there's substantial room for improvement within the system Several anticipated features typically found on a bookstore website are missing Consequently, custome have created a Google Form detailing their suggestions and requirements to propose enhancements instance, they've noted issues such as the inability to complete payment after placing an order, a desire a suggestion feature in the search field, delays in book display times on the screen, and confusion arisi