diff --git a/Implemented operations b/Implemented operations index 7e7070b..d6da228 100644 --- a/Implemented operations +++ b/Implemented operations @@ -6,3 +6,5 @@ - Просмотр оплаченных и неоплаченных счетов - Интернационализация - что-то еще? + +- add 404 page \ No newline at end of file diff --git a/application.log b/application.log new file mode 100644 index 0000000..344e49c --- /dev/null +++ b/application.log @@ -0,0 +1,12 @@ +[2018-02-02 10:47:05] ERROR There is an error: java.lang.NullPointerException Default message: null +[2018-02-02 10:55:32] ERROR [THYMELEAF][http-nio-80-exec-6] Exception processing template "service/service_user_list": An error happened during template parsing (template: "class path resource [templates/service/service_user_list.html]" - line 122, col 37) +[2018-02-02 10:55:32] ERROR Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/service/service_user_list.html]" - line 122, col 37)] with root cause +[2018-02-02 10:55:32] ERROR [THYMELEAF][http-nio-80-exec-6] Exception processing template "error": Error resolving template "error", template might not exist or might not be accessible by any of the configured Template Resolvers +[2018-02-02 10:55:32] ERROR Servlet.service() for servlet [dispatcherServlet] threw exception +[2018-02-02 10:55:32] ERROR Exception Processing ErrorPage[errorCode=0, location=/error] +[2018-02-02 10:59:24] ERROR An internal error occurred while trying to authenticate the user. +[2018-02-02 12:21:57] ERROR An internal error occurred while trying to authenticate the user. +[2018-02-02 12:37:13] ERROR There is an error: java.lang.NullPointerException Default message: null +[2018-02-02 12:37:30] ERROR [THYMELEAF][http-nio-80-exec-2] Exception processing template "error": Error resolving template "error", template might not exist or might not be accessible by any of the configured Template Resolvers +[2018-02-02 12:37:30] ERROR Servlet.service() for servlet [dispatcherServlet] threw exception +[2018-02-02 12:37:30] ERROR Exception Processing ErrorPage[errorCode=0, location=/error] diff --git a/pom.xml b/pom.xml index 5b494fb..ca3ef59 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ org.thymeleaf.extras thymeleaf-extras-springsecurity4 - 2.1.2.RELEASE + 3.0.2.RELEASE org.springframework.boot diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/GlobalControllerExceptionHandler.java b/src/main/java/com/epam/lab/mobilepaymentsystem/GlobalControllerExceptionHandler.java index d6258f4..dd44956 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/GlobalControllerExceptionHandler.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/GlobalControllerExceptionHandler.java @@ -1,22 +1,20 @@ package com.epam.lab.mobilepaymentsystem; +import com.epam.lab.mobilepaymentsystem.controller.ServiceUnitController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.servlet.ModelAndView; -import javax.servlet.http.HttpServletRequest; -import java.util.Arrays; - @ControllerAdvice class GlobalControllerExceptionHandler { private static final String DEFAULT_ERROR_VIEW = "errorhandler"; - // TODO: make a pretty page with error stuff and no stack trace + private Logger logger = LoggerFactory.getLogger(ServiceUnitController.class); - @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(Exception.class) public ModelAndView defaultErrorHandler(Exception e) throws Exception { ModelAndView mav = new ModelAndView(); @@ -29,10 +27,10 @@ private void introduceErrors(Exception e, ModelAndView mav) throws Exception { throw e; } - String s = Arrays.deepToString(e.getStackTrace()); mav.addObject("exception", e.toString()); - mav.addObject("stackTrace", s); mav.addObject("message", e.getMessage()); mav.setViewName(DEFAULT_ERROR_VIEW); + e.printStackTrace(); + logger.error("There is an error: " + e.toString() + " Default message: " + e.getMessage(), e); } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/MobilePaymentSystemApplication.java b/src/main/java/com/epam/lab/mobilepaymentsystem/MobilePaymentSystemApplication.java index 82ae028..f675d91 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/MobilePaymentSystemApplication.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/MobilePaymentSystemApplication.java @@ -2,17 +2,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.LocaleResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; -import org.springframework.web.servlet.i18n.SessionLocaleResolver; - -import java.util.Locale; @SpringBootApplication public class MobilePaymentSystemApplication extends WebMvcConfigurerAdapter{ diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/config/MvcConfig.java b/src/main/java/com/epam/lab/mobilepaymentsystem/config/MvcConfig.java index 207ab49..6ab78b8 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/config/MvcConfig.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/config/MvcConfig.java @@ -18,7 +18,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter { @Bean public LocaleResolver localeResolver() { SessionLocaleResolver slr = new SessionLocaleResolver(); - slr.setDefaultLocale(Locale.US); + slr.setDefaultLocale(new Locale("ru")); return slr; } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/config/WebSecurityConfig.java b/src/main/java/com/epam/lab/mobilepaymentsystem/config/WebSecurityConfig.java index a255323..34c952e 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/config/WebSecurityConfig.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/config/WebSecurityConfig.java @@ -27,18 +27,13 @@ protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers( - "/h2/**", - "/registration", - "/profile", - "/bills/**", - "/services/**", - "/users/**", - "/h2/**", - "/test/**", + "/registration", "/h2**", "/resources/**", "/static/**", "/css/**", "/js/**", "/images/**", "/data/**", "/dist/**", "/js/**", "/vendor/**").permitAll() -// .antMatchers( -// "/users").access("hasRole('ROLE_ADMIN')") + .antMatchers( + "/users**", "/bills**").access("hasRole('ADMIN')") + .antMatchers("/profile**", + "/services**").access("hasAnyRole('USER', 'SUBSCRIBER', 'ADMIN')") .anyRequest().authenticated() .and() .formLogin() diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/BillController.java b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/BillController.java index 92308ec..a164473 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/BillController.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/BillController.java @@ -2,27 +2,135 @@ import com.epam.lab.mobilepaymentsystem.model.Bill; import com.epam.lab.mobilepaymentsystem.service.BillService; +import com.epam.lab.mobilepaymentsystem.service.ServiceUnitService; +import com.epam.lab.mobilepaymentsystem.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.List; @Controller public class BillController { private final BillService billService; + private final ServiceUnitService serviceUnitService; + private final UserService userService; @Autowired - public BillController(BillService billService) { + public BillController(BillService billService, ServiceUnitService serviceUnitService, UserService userService) { this.billService = billService; + this.serviceUnitService = serviceUnitService; + this.userService = userService; } @GetMapping("/bills") public String getBills(Model model) { - Iterable oldBills = billService.listAllPaidBillsOfUser(); - Iterable unpaidBills = billService.listAllUnpaidBillsOfUser(); + List oldBills = billService.getAllPaidBillsOfAllUsersOrderedById(); // todo: check + List unpaidBills = billService.getAllUnpaidBillsOfAllUsersOrderedById(); model.addAttribute("paidBills", oldBills); model.addAttribute("unpaidBills", unpaidBills); return "bill/bill_list"; } + + @GetMapping("/users/{uid}/bills") + public String getBillListByUser(@PathVariable final long uid, Model model) { + List userBills = billService.getAllUnpaidBillsOfUserByUserId(uid); + model.addAttribute("currentUserId", userService.getCurrentUserId()); + model.addAttribute("empty", userBills.isEmpty()); + model.addAttribute("userBills", userBills); + return "bill/bill_user_list"; + } + + @GetMapping("/users/{uid}/services") + public String getServiceListByUser(@PathVariable final long uid, Model model) { + List userBills = billService.getAllNonExpiredActivePaidServiceOfUserByUserId(uid); + List userInactiveBills = billService.getAllExpiredActiveServicesOfUserByUserId(uid); + model.addAttribute("currentUserId", userService.getCurrentUserId()); + model.addAttribute("empty", userBills.isEmpty()); + model.addAttribute("userBills", userBills); + model.addAttribute("oldUserServices", userInactiveBills); + model.addAttribute("empty2", userInactiveBills.isEmpty()); + return "service/service_user_list"; + } + + @GetMapping("/profile/bills") + public String getBillListByCurrentUser(Model model) { + final long id = userService.getCurrentUserId(); + List userBills = billService.getAllUnpaidBillsOfUserByUserId(id); + model.addAttribute("currentUserId", userService.getCurrentUserId()); + model.addAttribute("empty", userBills.isEmpty()); + model.addAttribute("userBills", userBills); + return "bill/bill_user_list"; + } + + @GetMapping("/profile/services") + public String getServiceListByCurrentUser(Model model) { + final long id = userService.getCurrentUserId(); + List userBills = billService.getAllNonExpiredActivePaidServiceOfUserByUserId(id); + List userInactiveBills = billService.getAllExpiredActiveServicesOfUserByUserId(id); + model.addAttribute("currentUserId", userService.getCurrentUserId()); + model.addAttribute("empty", userBills.isEmpty()); + model.addAttribute("userBills", userBills); + model.addAttribute("oldUserServices", userInactiveBills); + model.addAttribute("empty2", userInactiveBills.isEmpty()); + return "service/service_user_list"; + } + + @GetMapping("/profile/bills/{bid}") + public String getBillUnit(@PathVariable("bid") final long bid, + Model model) { + Bill currentBill = billService.getById(bid); + model.addAttribute("bill", currentBill); + model.addAttribute("service", currentBill.getServiceUnit()); + model.addAttribute("userId", userService.getCurrentUserId()); + model.addAttribute("unsubscribeAviable", billService.isNewBill(currentBill)); + return "bill/bill_item"; + } + + @GetMapping("/users/{uid}/bills/{bid}") + public String getBillUnit(@PathVariable("uid") final long uid, + @PathVariable("bid") final long bid, + Model model) { + Bill currentBill = billService.getById(bid); + model.addAttribute("bill", currentBill); + model.addAttribute("service", currentBill.getServiceUnit()); + model.addAttribute("userId", uid); + model.addAttribute("currentUserId", userService.getCurrentUserId()); + model.addAttribute("unsubscribeAviable", billService.isNewBill(currentBill)); + return "bill/bill_item"; + } + + @PostMapping("/profile/bills/{bid}/unsub") + public String unsubscribeFromUnpaidBill(@PathVariable("bid") final long bid) { + long uid = userService.getCurrentUserId(); + serviceUnitService.unsubscribeUserFromServiceByBillAndUserId(billService.getById(bid), uid); + return "redirect:/profile/bills"; + } + + @PostMapping("/users/{uid}/bills/{bid}/unsub") + public String unsubscribeFromUnpaidBill(@PathVariable("uid") final long uid, + @PathVariable("bid") final long bid) { + serviceUnitService.unsubscribeUserFromServiceByBillAndUserId(billService.getById(bid), uid); + return "redirect:/users/" + uid + "/bills"; + } + + @PostMapping("/profile/bills/{bid}/pay") + public String payUnpaidBill(@PathVariable("bid") final long bid) { + long uid = userService.getCurrentUserId(); + billService.withdrawCashToPayForOneBill(billService.getById(bid), + userService.getUserById(uid)); + return "redirect:/profile/bills"; + } + + @PostMapping("/users/{uid}/bills/{bid}/pay") + public String payUnpaidBill(@PathVariable("uid") final long uid, + @PathVariable("bid") final long bid) { + billService.withdrawCashToPayForOneBill(billService.getById(bid), + userService.getUserById(uid)); + return "redirect:/users/" + uid + "/bills"; + } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/HomeController.java b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/HomeController.java index 6eb9997..15f7094 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/HomeController.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/HomeController.java @@ -1,5 +1,6 @@ package com.epam.lab.mobilepaymentsystem.controller; +import com.epam.lab.mobilepaymentsystem.model.Role; import com.epam.lab.mobilepaymentsystem.service.BillService; import com.epam.lab.mobilepaymentsystem.service.ServiceUnitService; import com.epam.lab.mobilepaymentsystem.service.UserService; @@ -7,6 +8,7 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; @Controller public class HomeController { @@ -26,11 +28,21 @@ public HomeController(UserService userService, @GetMapping("/") public String showHomePage(Model model) { - model.addAttribute("numberOfUsers", userService.numberOfUsers()); - model.addAttribute("numberOfServices", serviceUnitService.numberOfServices()); - model.addAttribute("numberOfBills", billService.numberOfUnpaidBills()); - model.addAttribute("numberOfUnpaidBills", billService.numberOfUnpaidBills()); + model.addAttribute("numberOfSubs", userService.numberOfUsersByRole( + Role.ROLE_SUBSCRIBER.getDisplayName())); + model.addAttribute("numberOfUsers", userService.numberOfUsersByRole( + Role.ROLE_USER.getDisplayName())); + model.addAttribute("numberOfServices", serviceUnitService.numberOfAllService()); + model.addAttribute("numberOfBills", billService.numberOfAllBills()); + model.addAttribute("numberOfUnpaidBills", billService.numberOfAllUnpaidBills()); model.addAttribute("userId", userService.getCurrentUserId()); + model.addAttribute("userRole", userService.getCurrentUser().getRole()); return "index"; } + + @PostMapping("/") + public String checkBills() { + serviceUnitService.globalCheckBill(); + return "redirect:/"; + } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/ServiceUnitController.java b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/ServiceUnitController.java index 3125880..668ff45 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/ServiceUnitController.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/ServiceUnitController.java @@ -40,9 +40,10 @@ public String serviceAdding(@Valid @ModelAttribute("service") ServiceUnit servic @GetMapping("/services") public String listAllServices(Model model, @ModelAttribute("selectedService") ServiceUnit serviceUnit) { - List inactiveServices = serviceUnitService.getAllServicesWithoutSubscribe(); + List inactiveServices = serviceUnitService.getAllServicesWithoutSubscribeOfUserByUserId(userService.getCurrentUserId()); model.addAttribute("inactiveServices", inactiveServices); model.addAttribute("services", serviceUnitService.getAllServices()); + model.addAttribute("userRole", userService.getCurrentUser().getRole()); return "service/service_list"; } @@ -54,22 +55,7 @@ public String serviceUnitPage(@PathVariable Long id, Model model) { @PostMapping("/services") public String subscribeToService(@ModelAttribute("selectedService") ServiceUnit serviceUnit) { - serviceUnitService.subscribeUserToService(serviceUnit.getId()); + serviceUnitService.subscribeUserToServiceByUserAndServiceId(userService.getCurrentUserId(), serviceUnit.getId()); return "redirect:/services"; } - - // TODO: unsubscribe process doesn't return actual data after pressing a button - @GetMapping("service/my") - public String listActiveServices(@ModelAttribute("selectedService") ServiceUnit serviceUnit, Model model) { - List activeServices = userService.getActiveServicesByUserId(); - model.addAttribute("activeServices", activeServices); - return "service/my"; - } - - @PostMapping("users/{id}/services") - public String unsubscribeFromService(@PathVariable Long id, - @ModelAttribute("selectedService") ServiceUnit serviceUnit) { - serviceUnitService.unsubscribeUserFromService(serviceUnit.getId()); - return "redirect:/users/" + id + "/services"; - } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/TestController.java b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/TestController.java deleted file mode 100644 index 96b0bae..0000000 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/TestController.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.epam.lab.mobilepaymentsystem.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@RequestMapping("/test") -public class TestController { - - @GetMapping - public String showHomePage() { - return "test/index"; - } - - @GetMapping("/login") - public String showLoginPage() { - return "test/login"; - } - - @GetMapping("/registration") - public String showRegistrationPage() { - return "test/registration"; - } - - @GetMapping("/users") - public String showUserList() { - return "test/user_list"; - } - - @GetMapping("/users/{id}") - public String showUserPage(@PathVariable Long id, Model model) { - model.addAttribute("id", id); - return "test/user_item"; - } - - ////////////// - - @GetMapping("/services") - public String showServiceList() { - return "test/service_list"; - } - - @GetMapping("/services/{slug}") - public String showServiceItem(@PathVariable String slug, Model model) { - model.addAttribute("slug", slug); - return "test/service_item"; - } - - @GetMapping("/bills") - public String showBillList() { - return "test/bill_list"; - } - - @GetMapping("/bills/{id}") - public String showBillItem(@PathVariable Long id, Model model) { - model.addAttribute("id", id); - return "test/bill_item"; - } -} diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/UserController.java b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/UserController.java index 851a07b..d0d7193 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/controller/UserController.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/controller/UserController.java @@ -1,7 +1,9 @@ package com.epam.lab.mobilepaymentsystem.controller; import com.epam.lab.mobilepaymentsystem.model.User; +import com.epam.lab.mobilepaymentsystem.service.BillService; import com.epam.lab.mobilepaymentsystem.service.SecurityService; +import com.epam.lab.mobilepaymentsystem.service.ServiceUnitService; import com.epam.lab.mobilepaymentsystem.service.UserService; import com.epam.lab.mobilepaymentsystem.wrapper.IntegerWrapper; import org.springframework.beans.factory.annotation.Autowired; @@ -11,25 +13,29 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; -import java.security.Principal; @Controller public class UserController { private final UserService userService; private final SecurityService securityService; + private final BillService billService; + private final ServiceUnitService serviceUnitService; @Autowired public UserController(UserService userService, - SecurityService securityService) { + SecurityService securityService, + BillService billService, + ServiceUnitService serviceUnitService) { this.userService = userService; this.securityService = securityService; + this.billService = billService; + this.serviceUnitService = serviceUnitService; } @GetMapping("/registration") public String registration(Model model) { model.addAttribute("userForm", new User()); - return "user/registration"; } @@ -55,40 +61,65 @@ public String login(Model model, String error, String logout) { @GetMapping("/users") public String getUsers(Model model) { model.addAttribute("users", userService.getAllUsers()); + model.addAttribute("userService", userService); return "user/user_list"; } @GetMapping("/profile") - public String showMyProfile(Principal principal) { - Long id = userService.getByUsername(principal.getName()).getId(); - return "redirect:/users/" + id; + public String showMyProfile(Model model) { + long id = userService.getCurrentUserId(); + model.addAttribute("user", userService.getCurrentUser()); + model.addAttribute("myProfile", true); + addModelAttributes(model, id); + return "user/user_item"; + } + + @PostMapping("/profile") + public String showButtonTopUpBalance(@Valid @ModelAttribute("howMuchToIncrease") IntegerWrapper howMuch, + BindingResult bindingResult, Model model) { + if (bindingResult.hasErrors()) { + long id = userService.getCurrentUserId(); + addModelAttributes(model, id); + model.addAttribute("user", userService.getCurrentUser()); + model.addAttribute("error", true); + return "user/user_item"; + } + userService.topUpBalance(userService.getCurrentUserId(), howMuch.getTranche()); + return "redirect:/profile"; } @GetMapping("/users/{id}") public String showUserProfile(@PathVariable final Long id, Model model) { model.addAttribute("user", userService.getUserById(id)); - model.addAttribute("howMuchToIncrease", new IntegerWrapper()); + model.addAttribute("myProfile", false); + addModelAttributes(model, id); return "user/user_item"; } - @PostMapping("/users/{id}/refill") - public String showButtonTopUpBalance(@PathVariable final Long id, - @ModelAttribute("howMuchToIncrease") IntegerWrapper howMuch) { - // todo минимальная сумма для пополнения 50 - userService.topUpBalance(id, howMuch.getTranche()); - // todo add binding with success message - return "redirect:/users/" + id; + @PostMapping("/users/{id}/delete") + public String deleteUser(@PathVariable final long id) { + userService.deleteUserById(id); + return "redirect:/users"; } - @GetMapping("/profile/services") - public String showMyServices(Principal principal) { - Long id = userService.getByUsername(principal.getName()).getId(); - return "redirect:/users/" + id + "/services"; + @PostMapping("/users/{id}/block") + public String blockUser(@PathVariable final long id) { + userService.blockUserById(id, false); + return "redirect:/users"; } - @DeleteMapping("users/{id}/delete") - public String deleteUser(@PathVariable final Long id) { - userService.deleteUserById(id); + @PostMapping("/users/{id}/unblock") + public String unblockUser(@PathVariable final long id) { + userService.blockUserById(id, true); return "redirect:/users"; } + + private void addModelAttributes(Model model, long userId) { + model.addAttribute("currentUserId", userId); + model.addAttribute("numberOfServices", + serviceUnitService.numberOfAllPaidActiveUserServicesByUserId(userId)); + model.addAttribute("numberOfBills", + billService.numberOfUnpaidBillsOfUserByUserId(userId)); + model.addAttribute("howMuchToIncrease", new IntegerWrapper()); + } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/dao/BillsRepository.java b/src/main/java/com/epam/lab/mobilepaymentsystem/dao/BillsRepository.java index 8b541f9..e8582d9 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/dao/BillsRepository.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/dao/BillsRepository.java @@ -3,11 +3,24 @@ import com.epam.lab.mobilepaymentsystem.model.Bill; import org.springframework.data.repository.CrudRepository; +import java.sql.Date; +import java.util.List; + public interface BillsRepository extends CrudRepository { void deleteByUser_IdAndServiceUnit_IdAndPaidFor(long userId, long serviceId, boolean isPaid); - Bill findBillByUser_IdAndServiceUnit_id(long userId, long serviceId); + Bill findBillByUser_IdAndServiceUnit_idAndEndDateBefore(long user_id, long serviceUnit_id, Date endDate); + + List findAllByUser_IdAndPaidFor(long userId, boolean isPaid); + + List findAllByPaidForOrderByUser_Id(Boolean paidFor); + + List findAllByUser_IdAndPaidForAndStartDateLessThanEqualAndEndDateGreaterThanEqualOrderByActualCostDesc(long user_id, Boolean paidFor, Date startDate, Date endDate); + + List findAllByUser_IdAndPaidForAndEndDateBefore(long user_id, Boolean paidFor, Date endDate); + + long countAllByPaidFor(Boolean paidFor); - Iterable findAllByUser_IdAndPaidFor(long userId, boolean isPaid); + long countAllByPaidForAndUser_Id(Boolean paidFor, long user_id); } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/dao/ServiceUnitsRepository.java b/src/main/java/com/epam/lab/mobilepaymentsystem/dao/ServiceUnitsRepository.java index bafa2d3..05fcbe6 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/dao/ServiceUnitsRepository.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/dao/ServiceUnitsRepository.java @@ -4,8 +4,12 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface ServiceUnitsRepository extends CrudRepository { ServiceUnit findByName(String name); + + List findAll(); } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/dao/UserRepository.java b/src/main/java/com/epam/lab/mobilepaymentsystem/dao/UserRepository.java index 540a617..f4ece7d 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/dao/UserRepository.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/dao/UserRepository.java @@ -9,7 +9,9 @@ public interface UserRepository extends CrudRepository { User findByUsername(String username); - void removeById(long id); - User findUserById(long id); + + Iterable findAllByRoleNot(String role); + + long countAllByRole(String role); } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/model/Bill.java b/src/main/java/com/epam/lab/mobilepaymentsystem/model/Bill.java index 6724304..9ade0fb 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/model/Bill.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/model/Bill.java @@ -8,10 +8,10 @@ @Table(name = "bills") public class Bill extends AbstractEntity { - @ManyToOne (cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @ManyToOne (cascade = CascadeType.DETACH, fetch = FetchType.LAZY) private User user; - @ManyToOne (cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @ManyToOne (cascade = CascadeType.DETACH, fetch = FetchType.LAZY) private ServiceUnit serviceUnit; @Column(name = "is_paid") @@ -77,7 +77,6 @@ public void setEndDate(Date endDate) { this.endDate = endDate; } - // TODO: fix when we will change Set to List @Override public int hashCode() { return Objects.hash(user.getId(), serviceUnit.getId(), paidFor, actualCost, startDate, endDate); diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/model/ServiceUnit.java b/src/main/java/com/epam/lab/mobilepaymentsystem/model/ServiceUnit.java index ffb308a..dc01faa 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/model/ServiceUnit.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/model/ServiceUnit.java @@ -58,7 +58,6 @@ public void setDuration(Integer duration) { this.duration = duration; } - // todo: fix when we will change Set to List @Override public int hashCode() { return Objects.hash(name, cost, duration); diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/service/BillService.java b/src/main/java/com/epam/lab/mobilepaymentsystem/service/BillService.java index ae0312d..789318d 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/service/BillService.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/service/BillService.java @@ -6,9 +6,11 @@ import com.epam.lab.mobilepaymentsystem.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.sql.Date; import java.util.Calendar; +import java.util.List; @Service public class BillService { @@ -29,54 +31,126 @@ public void save(Bill bill) { billsRepository.save(bill); } - public void createAndSaveBill(User user, ServiceUnit serviceUnit) { + public Bill createAndSaveBill(User user, ServiceUnit serviceUnit) { Bill bill = new Bill(); bill.setUser(user); bill.setServiceUnit(serviceUnit); bill.setPaidFor(false); bill.setActualCost(serviceUnit.getCost()); + setDateForBill(bill); + billsRepository.save(bill); + return bill; + } + + private void setDateForBill(Bill bill) { Calendar calendar = Calendar.getInstance(); bill.setStartDate(new Date(calendar.getTimeInMillis())); - int duration = serviceUnit.getDuration(); + int duration = bill.getServiceUnit().getDuration(); if (duration <= 0) { calendar.set(2038, Calendar.JANUARY, 13); // https://en.wikipedia.org/wiki/Year_2038_problem :) bill.setEndDate(new Date(calendar.getTimeInMillis())); } else { - calendar.add(Calendar.DATE, serviceUnit.getDuration()); + calendar.add(Calendar.DATE, bill.getServiceUnit().getDuration()); bill.setEndDate(new Date(calendar.getTimeInMillis())); } + } - billsRepository.save(bill); + public Bill getById(long billId) { + return billsRepository.findOne(billId); } - public void deleteUnpaidBill(long userId, long serviceId) { + @Transactional + public void deleteUnpaidBillByUserIdAndServiceId(long userId, long serviceId) { billsRepository.deleteByUser_IdAndServiceUnit_IdAndPaidFor(userId, serviceId, UNPAID); } - public Iterable listAllPaidBillsOfUser() { - return billsRepository.findAllByUser_IdAndPaidFor(userService.getCurrentUserId(), PAID); + private List getAllNonExpiredPaidBillsOfUserByUserId(long userId) { + return billsRepository. + findAllByUser_IdAndPaidForAndStartDateLessThanEqualAndEndDateGreaterThanEqualOrderByActualCostDesc(userId, PAID, getCurrentDate(), getCurrentDate()); } - public Iterable listAllUnpaidBillsOfUser() { - return billsRepository.findAllByUser_IdAndPaidFor(userService.getCurrentUserId(), UNPAID); + public List getAllUnpaidBillsOfUserByUserId(long userId) { + return billsRepository.findAllByUser_IdAndPaidFor(userId, UNPAID); } - public long numberOfPaidBills() { - return billsRepository.count(); + public List getAllUnpaidBillsOfAllUsersOrderedById() { + return billsRepository.findAllByPaidForOrderByUser_Id(UNPAID); + } + + public List getAllPaidBillsOfAllUsersOrderedById() { + return billsRepository. + findAllByPaidForOrderByUser_Id(PAID); } - public long numberOfUnpaidBills() { + public long numberOfAllBills() { return billsRepository.count(); } - public int countTotalSum(Iterable bills) { - int total = 0; + public long numberOfAllUnpaidBills() { + return billsRepository.countAllByPaidFor(UNPAID); + } + + public long numberOfUnpaidBillsOfUserByUserId(long userId) { + return billsRepository.countAllByPaidForAndUser_Id(UNPAID, userId); + } + + /** + * Withdraw cash to pay for all services of User with ID userId + * Find expired active services and try to renew subscription + * @param userId id of User + */ + public void withdrawCashToPayForServicesByUserId(long userId) { + List serviceUnits = userService.getActiveServicesByUserId(userId); + User user = userService.getUserById(userId); + + for (ServiceUnit service : serviceUnits) { + Bill bill = getExpiredPaidBillByUserIdAndServiceId(userId, service.getId()); + if (bill != null) { + withdrawCashToPayForOneBill(bill, user); + } + } + + userService.updateUser(user); + } + + public void withdrawCashToPayForOneBill(Bill bill, User user) { + if (bill.getActualCost() <= user.getBankAccount()) { + int bankAccount = user.getBankAccount() - bill.getActualCost(); + user.setBankAccount(bankAccount); + bill.setPaidFor(true); + setDateForBill(bill); + save(bill); + } + } + + private Date getCurrentDate() { + return new Date(System.currentTimeMillis()); + } + + private Bill getExpiredPaidBillByUserIdAndServiceId(long userId, long serviceId) { + return billsRepository.findBillByUser_IdAndServiceUnit_idAndEndDateBefore(userId, serviceId, getCurrentDate()); + } - for (Bill bill: bills) { - total += bill.getActualCost(); + public boolean isNewBill(Bill bill) { + if (bill.getUser().getServiceUnits().contains(bill.getServiceUnit())) { + return bill.getEndDate().compareTo(getCurrentDate()) >= 0; } - return total; + return false; + } + + public List getAllNonExpiredActivePaidServiceOfUserByUserId(long userId) { + List allServices = getAllNonExpiredPaidBillsOfUserByUserId(userId); + + allServices.removeIf(bill -> !bill.getUser().getServiceUnits().contains(bill.getServiceUnit())); + return allServices; + } + + public List getAllExpiredActiveServicesOfUserByUserId(long userId) { + List bills = billsRepository.findAllByUser_IdAndPaidForAndEndDateBefore(userId, PAID, getCurrentDate()); + + bills.removeIf(bill -> !bill.getUser().getServiceUnits().contains(bill.getServiceUnit())); + return bills; } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/service/ServiceUnitService.java b/src/main/java/com/epam/lab/mobilepaymentsystem/service/ServiceUnitService.java index 9efea73..5f16ee7 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/service/ServiceUnitService.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/service/ServiceUnitService.java @@ -1,10 +1,12 @@ package com.epam.lab.mobilepaymentsystem.service; import com.epam.lab.mobilepaymentsystem.dao.ServiceUnitsRepository; +import com.epam.lab.mobilepaymentsystem.model.Bill; import com.epam.lab.mobilepaymentsystem.model.ServiceUnit; import com.epam.lab.mobilepaymentsystem.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; @@ -33,9 +35,9 @@ public Iterable getAllServices() { return serviceUnitsRepository.findAll(); } - public List getAllServicesWithoutSubscribe() { - List services = (List) serviceUnitsRepository.findAll(); - User user = userService.getCurrentUser(); + public List getAllServicesWithoutSubscribeOfUserByUserId(long userId) { + List services = serviceUnitsRepository.findAll(); + User user = userService.getUserById(userId); Set userServices = user.getServiceUnits(); services.removeAll(userServices); return services; @@ -49,37 +51,54 @@ public ServiceUnit getServiceById(Long id) { return serviceUnitsRepository.findOne(id); } - public long numberOfServices() { + public long numberOfAllService() { return serviceUnitsRepository.count(); } - public void subscribeUserToService(long serviceId) { - // if we chose actual existing service + public long numberOfAllPaidActiveUserServicesByUserId(long userId) { + return billService.getAllNonExpiredActivePaidServiceOfUserByUserId(userId).size() + + billService.getAllExpiredActiveServicesOfUserByUserId(userId).size(); + } + + /** + * Subscribe User with ID userId to Service with ID serviceID + * Withdraw cash at the moment of subscribing + * Create paid bill if payment is successful + * Create unpaid bill if payment is unsuccessful + * Already existing Service cannot be subscribed to User + * @param userId ID of User + * @param serviceId ID of Service + */ + public void subscribeUserToServiceByUserAndServiceId(long userId, long serviceId) { if (serviceId != -1) { - User user = userService.getCurrentUser(); + User user = userService.getUserById(userId); ServiceUnit service = getServiceById(serviceId); - // we create bill only if the service is new if (user.addService(service)) { - billService.createAndSaveBill(user, service); + Bill bill = billService.createAndSaveBill(user, service); + billService.withdrawCashToPayForOneBill(bill, user); userService.updateUser(user); } } } - public void unsubscribeUserFromService(long serviceId) { - User user = userService.getCurrentUser(); - ServiceUnit service = getServiceById(serviceId); + /** + * Unsubscribe User from Service + * Delete unpaid Bill of this Service from User in process + * Service cannot be unsubscribed if User doesn't have it + * @param bill Bill that contains information about User subscribed to Service + * @param userId ID of User + */ + public void unsubscribeUserFromServiceByBillAndUserId(Bill bill, long userId) { + User user = userService.getUserById(userId); + ServiceUnit service = getServiceById(bill.getServiceUnit().getId()); - // if service exists and it is unpaid - remove also unpaid bill if (user.removeService(service)) { userService.updateUser(user); - billService.deleteUnpaidBill(user.getId(), serviceId); + billService.deleteUnpaidBillByUserIdAndServiceId(userId, service.getId()); } } - - // TODO: error about problems with cost doesn't appear public String validateNewServiceAndAdd(ServiceUnit serviceUnit, BindingResult bindingResult, Model model) { if(getByServiceName(serviceUnit.getName()) != null) { bindingResult.reject("name"); @@ -87,11 +106,28 @@ public String validateNewServiceAndAdd(ServiceUnit serviceUnit, BindingResult bi } if(bindingResult.hasErrors()) { - // TODO: info about other errors! return "service/service_add"; } save(serviceUnit); return "redirect:/services"; } + + public void globalCheckBill() { + Iterable users = userService.getAllUsers(); + for (User user : users) { + localCheckBill(user.getId()); + } + } + + @Transactional + public void localCheckBill(long userId) { + List outOfDateUnpaidBills = billService.getAllUnpaidBillsOfUserByUserId(userId); + + for (Bill bill : outOfDateUnpaidBills) { + unsubscribeUserFromServiceByBillAndUserId(bill, userId); + } + + billService.withdrawCashToPayForServicesByUserId(userId); + } } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/service/UserService.java b/src/main/java/com/epam/lab/mobilepaymentsystem/service/UserService.java index 7595462..1c701fd 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/service/UserService.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/service/UserService.java @@ -34,12 +34,22 @@ private void addUser(User user) { userRepository.save(user); } - public void deleteUserById(Long id) { + public void deleteUserById(long id) { User user = userRepository.findUserById(id); user.setRole(Role.ROLE_DELETED.getDisplayName()); userRepository.save(user); } + public void blockUserById(long id, boolean isAlreadyBlocked) { + User user = userRepository.findUserById(id); + String role = Role.ROLE_LOCKED.getDisplayName(); + if (isAlreadyBlocked) { + role = Role.ROLE_SUBSCRIBER.getDisplayName(); + } + user.setRole(role); + userRepository.save(user); + } + public void topUpBalance(Long id, Integer tranche) { User user = getUserById(id); if (user.getRole().equals(Role.ROLE_USER.getDisplayName())) { @@ -47,7 +57,7 @@ public void topUpBalance(Long id, Integer tranche) { } user.setBankAccount(user.getBankAccount() + tranche); - user = updateUser(user); + updateUser(user); } public User getByUsername(String username) { @@ -59,11 +69,16 @@ public User getUserById(Long id) { } public Iterable getAllUsers() { - return userRepository.findAll(); + return userRepository.findAllByRoleNot( + Role.ROLE_DELETED.getDisplayName()); } - public long numberOfUsers() { - return userRepository.count(); + public long numberOfUsersByRole(String role) { + return userRepository.countAllByRole(role); + } + + public void updateUser(User user) { + userRepository.save(user); } public Long getCurrentUserId() { @@ -81,34 +96,38 @@ public User getCurrentUser() { return userRepository.findByUsername(userSecurity.getUsername()); } - public User updateUser(User user) { - return userRepository.save(user); - } - - public List getActiveServicesByUserId() { - User user = getCurrentUser(); + public List getActiveServicesByUserId(long userId) { + User user = getUserById(userId); return new ArrayList<>(user.getServiceUnits()); } - // TODO: not sure about working with model in backend - // On the other hand validation logic being in frontend is bad - // And maybe it is better to autowire SecurityService in UserService instead of passing it as param public String validateNewUserAndRegister(User user, BindingResult bindingResult, Model model, SecurityService securityService) { - if(getByUsername(user.getUsername()) != null) { + if((getByUsername(user.getUsername()) != null) && (!user.getPassword().equals(user.getConfirmPassword()))) { bindingResult.reject("username"); + bindingResult.reject("password"); model.addAttribute("userWithSameUserName", "There is already a user registered with the username provided"); + model.addAttribute("passwordsNotSame", "Passwords don't match"); return "user/registration"; } - if(!user.getPassword().equals(user.getConfirmPassword())) { + if(getByUsername(user.getUsername()) != null) { + bindingResult.reject("username"); + model.addAttribute( + "userWithSameUserName", + "There is already a user registered with the username provided"); + return "user/registration"; + } + + if (!user.getPassword().equals(user.getConfirmPassword())) { bindingResult.reject("password"); - model.addAttribute("passwordsNotSame", "Passwords don't match"); + model.addAttribute( + "passwordsNotSame", + "Passwords don't match"); return "user/registration"; } - if(bindingResult.hasErrors()) { - // TODO: info about other errors + if (bindingResult.hasErrors()) { return "user/registration"; } diff --git a/src/main/java/com/epam/lab/mobilepaymentsystem/wrapper/IntegerWrapper.java b/src/main/java/com/epam/lab/mobilepaymentsystem/wrapper/IntegerWrapper.java index 834a080..59bf5c1 100644 --- a/src/main/java/com/epam/lab/mobilepaymentsystem/wrapper/IntegerWrapper.java +++ b/src/main/java/com/epam/lab/mobilepaymentsystem/wrapper/IntegerWrapper.java @@ -1,8 +1,13 @@ package com.epam.lab.mobilepaymentsystem.wrapper; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + public class IntegerWrapper { - private int tranche = 0; + @Min(50) + @Max(1000) + private int tranche; public int getTranche() { return tranche; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 85f567b..b7066de 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,7 +1,7 @@ server.port=80 server.error.whitelabel.enabled=false -spring.thymeleaf.cache=false +spring.thymeleaf.cache=true spring.thymeleaf.enabled=true spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html @@ -21,3 +21,10 @@ spring.datasource.driver-class-name=org.h2.Driver # Spring Security / Queries for AuthenticationManagerBuilder spring.queries.users-query=select password, username from USERS where username=? spring.queries.roles-query=select u.username, r.role from user u inner join user_role ur on(u.user_id=ur.user_id) inner join role r on(ur.role_id=r.role_id) where u.email=? + +# Logging +logging.level.root= ERROR +logging.file=application.log +logging.pattern.file=[%d{yyyy-MM-dd HH:mm:ss}] %level %msg %nopex %n +logging.pattern.console=[%d{yyyy-MM-dd HH:mm:ss}] %ex{5} %n +logging.level.org.springframework.web=ERROR diff --git a/src/main/resources/data-h2.sql b/src/main/resources/data-h2.sql index 2808e76..a69162d 100644 --- a/src/main/resources/data-h2.sql +++ b/src/main/resources/data-h2.sql @@ -1,25 +1,31 @@ --- pass: admin +-- ADMIN -- login: admin, pass: admin +-- SUBSCRIBER -- login: subscriber, pass: 123456 +-- USER -- login: userr, pass: qwerty +-- LOCKED -- login: locked, pass: qwerty +-- DELETED -- login: deleted, pass: qwerty INSERT INTO USERS (username, fullname, bankaccount, password, role) -VALUES ('admin', 'Admin Adminski', 99999, '$2a$10$hW7TdoUPWhEdprtj0XjCJ.iDopWV2UUaHWp2l7FoK3mRbLTX7W81q', 'ROLE_ADMIN'); - --- pass: 123456 -INSERT INTO USERS (username, fullname, bankaccount, password, role) -VALUES ('vlavik', 'Vladimir Kostin', 435, '$2a$10$Q7vEKw6rzmpNulORJMheF./2QAjAq15fGzCoSoZgSj02jHaOITxRi', 'ROLE_SUBSCRIBER'); - --- pass: qwerty -INSERT INTO USERS (username, fullname, bankaccount, password, role) -VALUES ('boy', 'Anton Pavlov', 582, '$2a$10$fPK7rqD0QjOBVGp9YdxnfOxBBX2ZSdiNp3wCp1nlLIxQf6EAaOlsK', 'ROLE_USER'); - --- pass: qwerty -INSERT INTO USERS (username, fullname, bankaccount, password, role) -VALUES ('dram', 'Bertolt Breckht', 943, '444', 'ROLE_SUBSCRIBER'); +VALUES + ('admin', 'Vladimir Kostin', 99999, '$2a$10$hW7TdoUPWhEdprtj0XjCJ.iDopWV2UUaHWp2l7FoK3mRbLTX7W81q', 'ROLE_ADMIN'), + ('mikey', 'Marsel Allaiarov', 435, '$2a$10$fPK7rqD0QjOBVGp9YdxnfOxBBX2ZSdiNp3wCp1nlLIxQf6EAaOlsK', 'ROLE_SUBSCRIBER'), + ('stranger', 'Bill Gates', 107, '$2a$10$fPK7rqD0QjOBVGp9YdxnfOxBBX2ZSdiNp3wCp1nlLIxQf6EAaOlsK', 'ROLE_LOCKED'), + ('exceptional', 'Gryu Felonius', 0, '$2a$10$fPK7rqD0QjOBVGp9YdxnfOxBBX2ZSdiNp3wCp1nlLIxQf6EAaOlsK', 'ROLE_LOCKED'); -- -INSERT INTO SERVICES (cost, name, description) -VALUES (40, 'Интеллектуальный диктофон', - 'Не думайте, забудете Вы информацию или нет — просто наберите Вашего помощника! Мы запишем текст под диктовку и перешлём Вам на почту.'); +INSERT INTO SERVICES (cost, duration, name, description) +VALUES + (40, 2, 'Интеллектуальный диктофон', + 'Не думайте, забудете Вы информацию или нет — просто наберите Вашего помощника! ' || + 'Мы запишем текст под диктовку и перешлём Вам на почту.'), + (130, 5, 'Ведение телефонных переговоров по Вашему поручению', + 'Позвоним • дозвонимся в самые недоступные организации ' || + '• договоримся и добьёмся того, что Вам необходимо.'), + (200, 30, 'Красивый телефонный звонок', + 'Подарите звонящему минутку Шопена.'); -INSERT INTO SERVICES (cost, name, description) -VALUES (130, 'Ведение телефонных переговоров по Вашему поручению', - 'Позвоним • дозвонимся в самые недоступные организации • договоримся и добьёмся того, что Вам необходимо.'); +INSERT INTO USER_SERVICES (user_id, service_id) VALUES (2, 1), (2, 2), (2, 3); +INSERT INTO BILLS (actual_cost, is_paid, start_date, end_date, service_unit_id, user_id) +VALUES + (40, TRUE, '2017-02-01', '2017-02-03', 1, 2), + (100, TRUE, '2018-02-01', '2018-02-06', 2, 2), + (200, FALSE, '2018-01-31', '2018-03-01', 3, 2); \ No newline at end of file diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 14a8b23..0a0057c 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,7 +1,9 @@ app.title=Mobile Payment System -app.version=v1.0.beta +app.version=v1.1.demo app.project.title=Проект №7. Система Телефонная станция. app.project.description=Администратор осуществляет подключение Абонентов. Абонент может выбрать одну или несколько из предоставляемых Услуг. Абонент оплачивает счет за разговоры и услуги. Администратор может просмотреть список неоплаченных счетов и заблокировать абонента. +app.header.myprofile=Мой профиль +app.header.logout=Выйти app.add-item=Добавить новую app.create-user=Create User @@ -10,14 +12,32 @@ app.user-details=User Details lang.english=Английский lang.russian=Русский +role.user.greeting=Добро пожаловать! +role.user.text=Для того, чтобы иметь возможность выбирать и оплачивать услуги, Вы должны иметь статус Абонента, который присваивается сразу после первого пополнения Вашего лицевого счета. +role.user.refill=Перейти к пополнению счета + +services.new.brief=Краткая информация +services.new.points=
  • Ниже вы можете ознакомиться со списком предоставляемых услуг.
  • Для того, чтобы добавить нужную услугу, выберете ее название в поле ниже и нажмите кнопку "Добавить".
  • После этого будет сформирован соответствующий счет, который нужно будет оплатить в ближайшее время.
  • Все услуги имеют свою продолжительность, будьте внимательны.
  • +services.new.select-text=Выберите сервис, чтобы подписаться +services.new.subscribe=Подписаться +services.item.name=Название +services.item.description=Описание +services.item.cost=Стоимость +services.item.duration=Длительность +services.item.backtolist=Вернуться к списку услуг +services.old=Истекшие услуги + title.page.home=Обзор +title.page.home.locked=К сожалению, Ваш аккаунт заблокирован. Свяжитесь с администрацией для решения вопроса. +title.page.home.deleted=Ваш аккаунт удален. +title.page.check.button=Оплатить счета title.page.users=Пользователи title.page.user-item=Профиль пользователя title.page.services=Список услуг title.page.services.add=Добавление новой услуги +title.page.bills=Список счетов +title.page.bill-item=Счет -sidebar.myservices.title=Мои услуги -sidebar.myservices.none=Услуг пока нет... sidebar.link.homepage=Главная sidebar.link.users=Пользователи sidebar.link.services=Услуги @@ -26,38 +46,61 @@ sidebar.link.services.my=Мои услуги sidebar.link.bills=Счета sidebar.link.bills.all=Все счета sidebar.link.bills.unpaid=Неоплаченные счета +sidebar.copyrights.title=Все права защищены +sidebar.copyrights.date=EPAM-SPB © 2018 container.word.unpaid=Неоплаченные +container.word.subscribers=Абоненты +container.word.unconfirmed=Неподтвержденных +container.word.view-details=Подробнее -user.id=ID -user.username=Username -user.fullname=Fullname -user.password=Password -user.confirmPassword=Confirm password -user.bankBook=Bank book -user.role=Role -user.services=Services -user.profile=Profile +bills.table.paid.title=Оплаченные счета +bills.table.unpaid.title=Неоплаченные счета +bills.table.th.service=Услуга +bills.table.th.cost=Цена +bills.table.th.start-date=С +bills.table.th.end-date=До +bills.table.th.owner=Владелец +bills.item.order=Заказ +bills.item.payer=Плательщик: +bills.item.receiver=Получатель: +bills.item.method=Способ платежа: +bills.item.cash=Наличные +bills.item.start-date=С какого: +bills.item.end-date=По какое: +bills.item.summary=Информация об услуге +bills.item.status=Статус +bills.item.status.paid=ОПЛАЧЕНО +bills.item.status.unpaid=НЕ ОПЛАЧЕНО +bills.item.price=Цена, $ +bills.item.button.pay=Оплатить +bills.item.button.cancel=Отказаться -user.form.submit=Submit -user.form.reset=Reset -user.add-more-users=Add More Users +users.list.title=Список всех активных пользователей +users.list.table.fullname=Полное имя +users.list.table.username=Логин +users.list.table.bankbook=Лицевой счет +users.list.table.group=Группа +users.list.table.actions=Действия +users.item.refill=Пополнить error.user.id=ID должно содержать от 3 до 10 символов error.user.name=Имя пользователя должно содержать от 5 до 20 символов. +error.tranche=Вводимое значение должно находиться в диапазоне от 50 до 1000. service.form.header=Создание новой услуги service.form.add.name=Название услуги service.form.add.description=Краткое описание услуги service.form.add.cost=Стоимость услуги +service.form.add.duration=Введите длительность услуги service.form.button.submit=Добавить услугу -service_adding=Добавление услуг -service_list=Список услуг -service_name=Название услуги -service_cost=Стоимость услуги -service_description=Описание услуги +global.isEmpty=Этот список в настоящее время пуст. + name=Имя cost=Стоимость submit=Добавить lang.change=Изменить язык +users.list.table.button.delete=Удалить +users.list.table.button.block=Заблокировать +users.list.table.button.unblock=Разблокировать diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 0e51524..3e9245e 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -1,7 +1,9 @@ app.title=Mobile Payment System -app.version=v1.0.beta +app.version=v1.1.demo app.project.title=Project #7. Mobile Payment System. app.project.description=The administrator connects subscribers. The subscriber can choose one or several of the provided services. The subscriber pays the bill for calls and services. The administrator can view the list of unpaid invoices and block the subscriber. +app.header.myprofile=My profile +app.header.logout=Logout app.add-item=Add new app.create-user=Create User @@ -10,14 +12,32 @@ app.user-details=User Details lang.english=English lang.russian=Russian +role.user.greeting=Welcome! +role.user.text=In order to be able to choose and pay for services, you must have the status of Subscriber, which is assigned immediately after the first replenishment of your personal account. +role.user.refill=Go to account replenishment + +services.new.brief=Brief information +services.new.points=
  • Below you can see the list of services provided.
  • To add the desired service, select its name in the box below and click the "Subscribe" button.
  • A corresponding account has been generated and will need to be paid in the near future.
  • All services have their own duration, please be careful.
  • +services.new.select-text=Select new service to subscribe +services.new.subscribe=Subscribe +services.item.name=Name +services.item.description=Description +services.item.cost=Cost +services.item.duration=Duration +services.item.backtolist=Back to services +services.old=Expired services + title.page.home=Summary +title.page.home.locked=Unfortunately, your account has been suspended. Contact the administration to resolve the issue. +title.page.home.deleted=Your account has been deleted. +title.page.check.button=Check bills title.page.users=User list title.page.user-item=User profile title.page.services=Service list title.page.services.add=Add new service +title.page.bills=Bill list +title.page.bill-item=Invoice -sidebar.myservices.title=My services -sidebar.myservices.none=No services yet... sidebar.link.homepage=Homepage sidebar.link.users=Users sidebar.link.services=Services @@ -26,8 +46,43 @@ sidebar.link.services.my=My services sidebar.link.bills=Bills sidebar.link.bills.all=All bills sidebar.link.bills.unpaid=Unpaid bills +sidebar.copyrights.title=All rights reserved +sidebar.copyrights.date=EPAM-SPB (c) 2018 container.word.unpaid=Unpaid +container.word.subscribers=Subscribers +container.word.unconfirmed=Unconfirmed +container.word.view-details=View details + +bills.table.paid.title=Paid bills +bills.table.unpaid.title=Unpaid bills +bills.table.th.service=Service +bills.table.th.cost=Cost +bills.table.th.start-date=From +bills.table.th.end-date=To +bills.table.th.owner=Owner +bills.item.order=Order +bills.item.payer=Billed To: +bills.item.receiver=Payment receiver: +bills.item.method=Payment Method: +bills.item.cash=Cash +bills.item.start-date=Order Date From: +bills.item.end-date=Order Date To: +bills.item.summary=Order summary +bills.item.status=Status +bills.item.status.paid=PAID +bills.item.status.unpaid=UNPAID +bills.item.price=Price, $ +bills.item.button.pay=Pay now +bills.item.button.cancel=Cancel + +users.list.title=List of all active users +users.list.table.fullname=Fullname +users.list.table.username=Username +users.list.table.bankbook=Bank account +users.list.table.group=Group +users.list.table.actions=Actions +users.item.refill=Refill user.id=ID user.username=Username @@ -45,9 +100,17 @@ user.add-more-users=Add More Users error.user.id=Id must be between 3 to 10 characters. error.user.name=User name must be between 5 to 20 characters. +error.tranche=The input value should be in range from 50 to 1000. service.form.header=Create new service service.form.add.name=Service name service.form.add.description=Service description service.form.add.cost=Service cost -service.form.button.submit=Create service \ No newline at end of file +service.form.add.duration=Service duration +service.form.button.submit=Create service + +global.isEmpty=This list is currently empty. + +users.list.table.button.delete=Remove +users.list.table.button.block=Block +users.list.table.button.unblock=Unblock \ No newline at end of file diff --git a/src/main/resources/templates/bill/bill_item.html b/src/main/resources/templates/bill/bill_item.html index 717c018..e4f32a6 100644 --- a/src/main/resources/templates/bill/bill_item.html +++ b/src/main/resources/templates/bill/bill_item.html @@ -11,29 +11,9 @@ - Bill info + Bill - - - - - - - - - - - - - - - - - - +
    @@ -43,114 +23,9 @@
    @@ -174,39 +49,41 @@ -
    -
    +
    +
    -

    Invoice

    Order #

    +

    Invoice

    +

    Order #


    -
    - Billed To:
    - Vladimir Kostin
    - vlavik
    -
    + Billed To:
    +

    + + () +

    +
    -
    - Shipped To:
    - MPS -
    + Shipped To:
    + MPS
    -
    - Payment Method:
    - Cash -
    + Payment Method:
    + Cash
    -
    -
    - Order Date:
    - January 23, 2018

    -
    +
    +
    + Order Date From:
    +

    +
    +
    + Order Date To:
    +

    +
    @@ -214,92 +91,86 @@

    Invoice

    Order #

    -
    +
    -

    Order summary

    +

    Order summary

    - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +
    ServicePriceQuantityTotalsServiceStatusPrice, $
    WebTV$10.991$10.99
    Kaspersky Crystal$20.003$60.00
    Static IP-adress$600.001$600.00
    Subtotal$670.99
    Shipping$15
    Total$685.99
    StatusUNPAID + PAID + UNPAID +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    -
    + +
    + + + + +
    - - - - - - - - - - - +
    + diff --git a/src/main/resources/templates/bill/bill_list.html b/src/main/resources/templates/bill/bill_list.html index abc645e..5886b28 100644 --- a/src/main/resources/templates/bill/bill_list.html +++ b/src/main/resources/templates/bill/bill_list.html @@ -38,63 +38,35 @@

    Bill list.

    - - - - - - - - - -
    -
    +
    -
    - Paid bills -
    +
    - - - - - + + + + + - + - - - + + + @@ -107,31 +79,30 @@ -
    +
    -
    - Unpaid bills -
    +
    -
    NameCostStart dateEnd datePaidNameCostStart dateEnd dateOwner
    + + + +
    +
    - - - - - + + + - + - - - +
    NameCostStart dateEnd datePaidNameCostOwner
    + + + +
    diff --git a/src/main/resources/templates/bill/bill_user_list.html b/src/main/resources/templates/bill/bill_user_list.html new file mode 100644 index 0000000..5867b1f --- /dev/null +++ b/src/main/resources/templates/bill/bill_user_list.html @@ -0,0 +1,97 @@ + + + + + + + + + + + + Bill list + +
    + + + + + +
    + + + + +
    +
    +
    +

    Bill list.

    +
    + +
    + + + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    NameCostOwner
    + + + + + + + +
    +
    + +
    + +
    + +
    + +
    + +
    + + +
    + + +
    + + + + diff --git a/src/main/resources/templates/bill/old.html b/src/main/resources/templates/bill/old.html deleted file mode 100644 index 42abf98..0000000 --- a/src/main/resources/templates/bill/old.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Bills payment - - -
    -
    -

    Old bill operations

    - - - - - - - - - - - -
    NameCostPaid?
    -
    -

    Total cost: [[${total}]]

    -

    -
    - - \ No newline at end of file diff --git a/src/main/resources/templates/bill/payment.html b/src/main/resources/templates/bill/payment.html deleted file mode 100644 index 8781133..0000000 --- a/src/main/resources/templates/bill/payment.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Bills payment - - -
    -
    -

    Unpaid bill list

    - - - - - - - - - - - -
    NameCostPaid?
    -
    -

    Total cost: [[${total}]]

    -

    -
    - - \ No newline at end of file diff --git a/src/main/resources/templates/fragments/footer.html b/src/main/resources/templates/fragments/footer.html index fa32ad9..cb3ec07 100644 --- a/src/main/resources/templates/fragments/footer.html +++ b/src/main/resources/templates/fragments/footer.html @@ -8,21 +8,21 @@ - + - + - + - - - + + + - + - - - - -

    - -
    -

    -

    -

    -

    -

    -
    - - - - - - - - - - - - - - -
    ID
    - - - - - \ No newline at end of file diff --git a/src/main/resources/templates/user/registration.html b/src/main/resources/templates/user/registration.html index 3490296..5649d74 100644 --- a/src/main/resources/templates/user/registration.html +++ b/src/main/resources/templates/user/registration.html @@ -113,10 +113,10 @@

    Sign up now

    Fill in the form below to get instant access.


    -

    -

    +
    +
    -

    +
    @@ -124,9 +124,9 @@

    Sign up now

    -

    +
    -

    +
    diff --git a/src/main/resources/templates/user/user_item.html b/src/main/resources/templates/user/user_item.html index d499d37..005bc9c 100644 --- a/src/main/resources/templates/user/user_item.html +++ b/src/main/resources/templates/user/user_item.html @@ -11,7 +11,7 @@ - User list + User list
    @@ -48,26 +48,43 @@

    User profile.

    fullname

    login
    -
    Bank book: 0 $
    -
    Group: subscriber
    +
    Bank book: + 0 $
    +
    Group: + subscriber
    -
    + + +
    - + +
    - +
    -
    +
    @@ -78,14 +95,21 @@
    Group: subscriber
    -
    4
    -
    Services
    +
    +
    Services
    - + + + + @@ -100,14 +124,21 @@
    Group: subscriber
    -
    2
    -
    Unpaid bills
    +
    2
    +
    Unpaid bills
    - + + + + diff --git a/src/main/resources/templates/user/user_list.html b/src/main/resources/templates/user/user_list.html index 346cfe6..26cbfc9 100644 --- a/src/main/resources/templates/user/user_list.html +++ b/src/main/resources/templates/user/user_list.html @@ -37,38 +37,6 @@

    User list.

    - - - - - - - - - - -
    @@ -77,20 +45,18 @@ table.table-striped .btn {padding: 0 6px;}
    -
    - DataTables Advanced Tables -
    +
    - - - - - + + + + + @@ -101,32 +67,36 @@
    IDFullnameUsernameBank bookGroupActionsFullnameUsernameBank bookGroupActions
    Subscriber -
    - - - - - - - - - - +
    +
    + +
    + +
    + +
    + +
    + +
    -
    -

    DataTables Usage Information

    -

    DataTables is a very flexible, advanced tables plugin for jQuery. In SB Admin, we are using a specialized version of DataTables built for Bootstrap 3. We have also customized the table headings to use Font Awesome icons in place of images. For complete documentation on DataTables, visit their website at https://datatables.net/.

    - View DataTables Documentation -
    diff --git a/src/test/java/com/epam/lab/mobilepaymentsystem/ServiceTests.java b/src/test/java/com/epam/lab/mobilepaymentsystem/ServiceTests.java index bad69ab..70cc2f9 100644 --- a/src/test/java/com/epam/lab/mobilepaymentsystem/ServiceTests.java +++ b/src/test/java/com/epam/lab/mobilepaymentsystem/ServiceTests.java @@ -41,7 +41,7 @@ public void addService() { // todo: for some reason it fails @Test public void numberOfServices() { - assertEquals(count, serviceUnitService.numberOfServices()); + assertEquals(count, serviceUnitService.numberOfAllService()); } @Test