Core Technologies
- Backend Language: Java
- Framework: Spring Boot
- Frontend Stack: JavaScript, Vue.js, CSS3
- Development Tools: IntelliJ IDEA / Eclipse / Visual Studio Code
- Database: MySQL 5.7 or 8.0
- DB Management: Navicat / phpStudy
- JDK Version: 1.8
- Build Tool: Apache Maven 3.8.1
The system employs a B/S architecture, leveraging Java for business logic and MySQL for persistent storage, enabling efficient operation of homestay reservation workflows.
Functional Modules
Public-Facing Interface
Visitors accessing the root URL encounter the landing page containing navigation links: Home, Room Listings, Nearby Amenities, Announcements, Feedback & Complaints, Admin Portal, and Live Support.
Unregistered users can sign up by providing:
- Username
- Password & confirmation
- Full name
- Gender
- Profile picture (optional)
- Mobile number
- ID number
- Membership tier
Registered users log in via username and password. Authenticated users may browse rooms by entering a room name in the search bar. Each listing shows:
- Room name
- Floor location
- Category
- Image gallery
- Included facilities
- Price per night
- Availability status
- Service highlights
- Contact number
Actions available: make a reservation, bookmark, or post a review.
Similarly, amenities can be searched by name; each result displays:
- Facility name
- Photo
- Type
- Location
- External link
- Services offered
- Registration date
Bookmarking is supported for later reference.
The user profile section allows editing personal data and managing bookmarks.
Member Dashboard
After authentication, members access their workspace comprising:
- Personal dashboard
- Reservation history management
- Stay records handling
- Review management
Members track past and upcoming bookings, update personal details, and manage saved items.
Administrator Console
Administrators sign in using designated credentials and role selection. Once authenticated, they control:
- Member tier definitions
- Member accounts
- Room categories
- Room inventory
- Nearby facility registry
- Reservation logs
- Check-in logs
- Reviews and ratings
- Complaint handling
- System-wide configurations (e.g., banners, announcements, support info)
Key Administrative Operations
- Member Control: View, add, or remove member entries including username, full name, gender, photo, phone, ID, membership level, and discount rate.
- Room Inventory: Add, edit, query, or delete room entries covering name, floor, category, images, amenities, price, status, features, and booking contact.
- Facility Registry: Manage amenity records—name, image, type, location, external URL, services, registration date—with options to add or remove.
- Check-In Records: Browse, query, or purge check-in logs detailing reservation ID, room name, image, total cost, guest count, duration, processing date, remarks, and associated username.
- System Settings: Maintain sections like live chat, about page, carousel slides, platform introduction, and announcement board with create, read, update, delete capabilities.
Sample Backend Logic (Refactored)
@RestController
@RequestMapping("/api/user")
public class AccountController {
private final AccountService accountService;
private final AuthTokenManager authManager;
public AccountController(AccountService svc, AuthTokenManager mgr) {
this.accountService = svc;
this.authManager = mgr;
}
@PostMapping("/signin")
public ResponseData signIn(@RequestParam String uname,
@RequestParam String pwd,
@RequestParam String captcha,
HttpServletRequest req) {
UserRecord record = accountService.findByUsername(uname);
if (record == null || !record.getPwdHash().equals(pwd)) {
return ResponseData.fail("Invalid credentials");
}
String jwt = authManager.createToken(record.getId(), uname, "user", record.getRole());
return ResponseData.success(Map.of(
"token", jwt,
"role", record.getRole(),
"uid", record.getId()
));
}
@PostMapping("/signup")
public ResponseData signUp(@RequestBody UserRecord newUser) {
boolean exists = accountService.existsByUsername(newUser.getUsername());
if (exists) {
return ResponseData.fail("Username already taken");
}
accountService.addUser(newUser);
return ResponseData.success();
}
@GetMapping("/signout")
public ResponseData signOut(HttpServletRequest req) {
req.getSession().invalidate();
return ResponseData.success("Signed out successfully");
}
@GetMapping("/changePwd")
public ResponseData changePassword(@RequestParam String oldPwd,
@RequestParam String newPwd,
HttpServletRequest req) {
Integer uid = (Integer) req.getSession().getAttribute("uid");
UserRecord user = accountService.fetchById(uid);
if (!oldPwd.equals(user.getPwdHash())) {
return ResponseData.fail("Old password mismatch");
}
if (newPwd.equals(user.getPwdHash())) {
return ResponseData.fail("New password must differ from old one");
}
user.setPwdHash(newPwd);
accountService.updateUser(user);
return ResponseData.success();
}
@PostMapping("/resetPwd")
public ResponseData resetPassword(@RequestParam String uname) {
UserRecord user = accountService.findByUsername(uname);
if (user == null) {
return ResponseData.fail("Account not found");
}
user.setPwdHash("123456");
accountService.updateUser(user);
return ResponseData.success("Password reset to 123456");
}
@GetMapping("/list")
public ResponseData listUsers(@RequestParam Map<String, Object> criteria) {
PageResult<UserRecord> page = accountService.searchUsers(criteria);
return ResponseData.success(page);
}
@GetMapping("/item/{uid}")
public ResponseData fetchUser(@PathVariable Integer uid) {
UserRecord user = accountService.fetchById(uid);
return ResponseData.success(user);
}
@GetMapping("/current")
public ResponseData getCurrentUser(HttpServletRequest req) {
Integer uid = (Integer) req.getSession().getAttribute("uid");
UserRecord user = accountService.fetchById(uid);
return ResponseData.success(user);
}
@PostMapping("/add")
public ResponseData addUser(@RequestBody UserRecord user) {
if (accountService.existsByUsername(user.getUsername())) {
return ResponseData.fail("Username already exists");
}
accountService.addUser(user);
return ResponseData.success();
}
@PutMapping("/edit")
public ResponseData editUser(@RequestBody UserRecord user) {
accountService.updateUser(user);
return ResponseData.success();
}
@DeleteMapping("/remove")
public ResponseData removeUsers(@RequestBody List<Long> ids) {
List<UserRecord> all = accountService.fetchAll();
if (all.size() <= 1) {
return ResponseData.fail("Atleast one admin must remain");
}
accountService.deleteUsers(ids);
return ResponseData.success();
}
}