Advertisement
Guest User

Untitled

a guest
Mar 26th, 2019
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 36.03 KB | None | 0 0
  1. package com.vilkivps.service;
  2.  
  3. import com.fasterxml.jackson.core.type.TypeReference;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import com.vilkivps.exception.CommonException;
  6. import com.vilkivps.exception.NotEnoughMoneyException;
  7. import com.vilkivps.exception.VMNotFoundException;
  8. import com.vilkivps.model.ConfigurationPrice;
  9. import com.vilkivps.model.db.ClientVM;
  10. import com.vilkivps.model.db.Promo;
  11. import com.vilkivps.model.db.User;
  12. import com.vilkivps.model.db.UserBalanceHistory;
  13. import com.vilkivps.model.enums.ClientVMStatus;
  14. import com.vilkivps.repository.BalanceRepository;
  15. import com.vilkivps.repository.VirtualMachineRepository;
  16. import com.vilkivps.service.db.UserService;
  17. import com.vilkivps.utils.DateUtils;
  18. import com.vilkivps.utils.NumberUtils;
  19. import freemarker.template.TemplateException;
  20. import org.apache.http.HttpResponse;
  21. import org.apache.http.NameValuePair;
  22. import org.apache.http.client.HttpClient;
  23. import org.apache.http.client.entity.UrlEncodedFormEntity;
  24. import org.apache.http.client.methods.HttpGet;
  25. import org.apache.http.client.methods.HttpPost;
  26. import org.apache.http.impl.client.HttpClientBuilder;
  27. import org.apache.http.message.BasicNameValuePair;
  28. import org.apache.log4j.Logger;
  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.stereotype.Service;
  31.  
  32. import javax.mail.MessagingException;
  33. import java.io.IOException;
  34. import java.math.BigDecimal;
  35. import java.math.RoundingMode;
  36. import java.util.*;
  37. import java.util.concurrent.TimeUnit;
  38. import java.util.stream.Collectors;
  39.  
  40. @Service
  41. public class ClientService {
  42.  
  43.     private static final Integer REBOOT_LIMIT = 5;
  44.     private static final Logger LOGGER = Logger.getLogger(ClientService.class);
  45.     private static final String BASE_URL = "http://92.53.91.144";
  46.     private static final String API_KEY = "blabla";
  47.     private static final String EMAIL_NOTIFICATION = "mail@vilki-vps.ru";
  48.     private static final Integer REBOOT_PRICE = 30;
  49.  
  50.     @Autowired
  51.     private VirtualMachineRepository vmRepository;
  52.  
  53.     @Autowired
  54.     private BalanceRepository balanceRepository;
  55.  
  56.     @Autowired
  57.     private UserService userService;
  58.  
  59.     @Autowired
  60.     private MailService mailService;
  61.  
  62.     @Autowired
  63.     private PromoService promoService;
  64.  
  65.     /**
  66.      * Создает виртуалку
  67.      *
  68.      * @param userId
  69.      * @param endDate
  70.      * @return
  71.      * @throws IOException
  72.      */
  73.     protected ClientVM createVirtualMachine(String userId, Date endDate, Integer powerType, String geo, int postponeAllowed) throws IOException {
  74.         LOGGER.info("Создание виртуалки для пользователя ID=" + userId);
  75.         ClientVM vm = new ClientVM(userId, endDate);
  76.         vm.setPostponeAllowed(postponeAllowed);
  77.         vm.setLastDateReset(new Date());
  78.         vm.setCreatingDateStart(new Date());
  79.         vmRepository.insert(vm);
  80.  
  81.         User user = userService.findById(userId);
  82.         String url = BASE_URL + "/api/vms/new/";
  83.         HttpClient client = HttpClientBuilder.create().build();
  84.         HttpPost post = new HttpPost(url);
  85.         post.addHeader("api-key", API_KEY);
  86.         List<NameValuePair> urlParameters = new ArrayList<>();
  87.         urlParameters.add(new BasicNameValuePair("id", vm.getId()));
  88.         urlParameters.add(new BasicNameValuePair("size", String.valueOf(powerType)));
  89.         urlParameters.add(new BasicNameValuePair("country", geo));
  90.         if (user.getFastCreating() != null) {
  91.             urlParameters.add(new BasicNameValuePair("fastCreating", String.valueOf(user.getFastCreating())));
  92.         }
  93.         post.setEntity(new UrlEncodedFormEntity(urlParameters));
  94.         HttpResponse response = client.execute(post);
  95.  
  96.         int statusCode = response.getStatusLine().getStatusCode();
  97.         if (statusCode != 202) {
  98.             vmRepository.delete(vm);
  99.             throw new IOException("Что-то пошло не так... Статус ответа: " + statusCode);
  100.         }
  101.         return vm;
  102.     }
  103.  
  104.  
  105.     /**
  106.      * Восстанавливает виртуалку
  107.      *
  108.      * @return
  109.      * @throws IOException
  110.      */
  111.     private ClientVM resumeVirtualMachine(ClientVM clientVM) throws IOException {
  112.         LOGGER.info("Восстановление виртуалки для пользователя ID=" + clientVM.getUserId());
  113.  
  114.         User user = userService.findById(clientVM.getUserId());
  115.         String url = BASE_URL + "/api/vms/new/";
  116.         HttpClient client = HttpClientBuilder.create().build();
  117.         HttpPost post = new HttpPost(url);
  118.         post.addHeader("api-key", API_KEY);
  119.         List<NameValuePair> urlParameters = new ArrayList<>();
  120.         urlParameters.add(new BasicNameValuePair("id", clientVM.getId()));
  121.         urlParameters.add(new BasicNameValuePair("size", String.valueOf(clientVM.getPureSize())));
  122.         urlParameters.add(new BasicNameValuePair("country", clientVM.getCountry()));
  123.         if (user.getFastCreating() != null) {
  124.             urlParameters.add(new BasicNameValuePair("fastCreating", String.valueOf(user.getFastCreating())));
  125.         }
  126.         post.setEntity(new UrlEncodedFormEntity(urlParameters));
  127.         HttpResponse response = client.execute(post);
  128.  
  129.         int statusCode = response.getStatusLine().getStatusCode();
  130.         if (statusCode != 202) {
  131. //            vmRepository.delete(clientVM);
  132.             throw new IOException("Что-то пошло не так... Статус ответа: " + statusCode);
  133.         }
  134.         return clientVM;
  135.     }
  136.  
  137.     /**
  138.      * Удаляет виртуалку на сервере, статус удаляемой виртуалки - DELETED
  139.      *
  140.      * @param vmId
  141.      * @throws IOException
  142.      */
  143.     public void closeVirtualMachine(String vmId) throws IOException {
  144.         LOGGER.info("Закрытие виртуалки " + vmId);
  145.         String url = BASE_URL + "/api/vms/delete/";
  146.  
  147.         HttpClient client = HttpClientBuilder.create().build();
  148.         HttpPost post = new HttpPost(url);
  149.         post.addHeader("api-key", API_KEY);
  150.         List<NameValuePair> urlParameters = new ArrayList<>();
  151.         urlParameters.add(new BasicNameValuePair("id", vmId));
  152.         post.setEntity(new UrlEncodedFormEntity(urlParameters));
  153.         HttpResponse response = client.execute(post);
  154.  
  155.         int statusCode = response.getStatusLine().getStatusCode();
  156.         if (statusCode != 202)
  157.             throw new IOException("Что-то пошло не так... Статус ответа: " + statusCode);
  158.         ClientVM vm = vmRepository.findOne(vmId);
  159.         vm.setStatus(ClientVMStatus.DELETED);
  160.         vm.setPassword("");
  161.         vm.setLogin("");
  162.         vm.setIp("");
  163.         vmRepository.save(vm);
  164.     }
  165.  
  166.     public void deleteForPostponeVirtualMachine(String vmId) throws IOException {
  167.         LOGGER.info("Закрытие виртуалки " + vmId);
  168.         String url = BASE_URL + "/api/vms/delete/";
  169.  
  170.         HttpClient client = HttpClientBuilder.create().build();
  171.         HttpPost post = new HttpPost(url);
  172.         post.addHeader("api-key", API_KEY);
  173.         List<NameValuePair> urlParameters = new ArrayList<>();
  174.         urlParameters.add(new BasicNameValuePair("id", vmId));
  175.         post.setEntity(new UrlEncodedFormEntity(urlParameters));
  176.         HttpResponse response = client.execute(post);
  177.  
  178.         int statusCode = response.getStatusLine().getStatusCode();
  179.         if (statusCode != 202)
  180.             throw new IOException("Что-то пошло не так... Статус ответа: " + statusCode);
  181.     }
  182.  
  183.  
  184.     /**
  185.      * Обновляет статус виртуалки. Закрывает виртуалку, срок действия которой истек.
  186.      * Обновляет счетчик виртуалок
  187.      *
  188.      * @param vm
  189.      */
  190.     public void updateVM(ClientVM vm) throws IOException, VMNotFoundException {
  191.         Date now = new Date();
  192.         if (vm.getStatus() == ClientVMStatus.CREATING || vm.getStatus() == ClientVMStatus.RECREATING) {
  193.             try {
  194.                 ClientVMStatus oldStatus = vm.getStatus();
  195.                 Map<String, String> infoMap = requestVMInfo(vm.getId());
  196.                 vm.setIp(infoMap.get("ip"));
  197.                 vm.setLogin(infoMap.get("username"));
  198.                 vm.setPassword(infoMap.get("password"));
  199.                 vm.setStatus(ClientVMStatus.valueOf(infoMap.get("status")));
  200.                 vm.setCountry(infoMap.get("country"));
  201.                 vm.setSize(infoMap.get("size"));
  202.                 vmRepository.save(vm);
  203.                 //По готовности отправляем на почту сообщение
  204.                 if (vm.getStatus().equals(ClientVMStatus.READY)) {
  205.                     User user = userService.findById(vm.getUserId());
  206.                     if (oldStatus.equals(ClientVMStatus.RECREATING)) {
  207.                         try {
  208.                             mailService.onVmReadyAfterRecreating(user);
  209.                         } catch (MessagingException | TemplateException e) {
  210.                             e.printStackTrace();
  211.                         }
  212.                     }
  213.                     if (oldStatus.equals(ClientVMStatus.CREATING)) {
  214.                         try {
  215.                             mailService.onVmReady(user);
  216.                         } catch (MessagingException | TemplateException e) {
  217.                             e.printStackTrace();
  218.                         }
  219.                     }
  220.                     vm.setCreatingDateStart(null);
  221.                 }
  222.                 if (vm.getStatus().equals(ClientVMStatus.CREATING) || vm.getStatus().equals(ClientVMStatus.RECREATING)) {
  223.                     if (vm.getCreatingDateStart() != null) {
  224.                         long minutes = DateUtils.minutesDistance(vm.getCreatingDateStart(), now);
  225.                         if (minutes > 61 && !vm.isLongCreationWarnNotify()) {
  226.                             try {
  227.                                 mailService.onVmLongCreation(vm, EMAIL_NOTIFICATION);
  228.                                 vm.setLongCreationWarnNotify(true);
  229.                                 vmRepository.save(vm);
  230.                             } catch (Exception e) {
  231.  
  232.                             }
  233.                         }
  234.                     }
  235.                 }
  236.             } catch (VMNotFoundException e) {
  237. //                closeVirtualMachine(vm.getId());
  238. //                vm.setStatus(ClientVMStatus.DELETED);
  239. //                vmRepository.save(vm);
  240.             }
  241.         } else if (vm.getStatus() == ClientVMStatus.READY) {
  242.             try {
  243.                 Map<String, String> infoMap = requestVMInfo(vm.getId());
  244.                 vm.setIp(infoMap.get("ip"));
  245.                 vm.setLogin(infoMap.get("username"));
  246.                 vm.setPassword(infoMap.get("password"));
  247.                 vm.setStatus(ClientVMStatus.valueOf(infoMap.get("status")));
  248.                 vm.setCountry(infoMap.get("country"));
  249.                 vm.setSize(infoMap.get("size"));
  250.                 vmRepository.save(vm);
  251.             } catch (VMNotFoundException e) {
  252.             }
  253.             if (vm.getLastDateReset() == null) {
  254.                 vm.setLastDateReset(now);
  255.                 vmRepository.save(vm);
  256.             }
  257.  
  258.             if (vm.getEndDate().before(now)) {
  259.                 closeVirtualMachine(vm.getId());
  260.                 vm.setStatus(ClientVMStatus.DELETED);
  261.                 vmRepository.save(vm);
  262.             } else {
  263.                 long hours = DateUtils.hoursDistance(vm.getLastDateReset(), now);
  264.                 if (hours >= 24) {
  265.                     vm.setLastDateReset(now);
  266.                     vm.getRebootDates().clear();
  267.                     vmRepository.save(vm);
  268.                 }
  269.             }
  270.             long hours = DateUtils.hoursDistance(now, vm.getEndDate());
  271.             if (hours <= 4 && !vm.isOneHourLateNotify()) {
  272.                 User user = userService.findById(vm.getUserId());
  273.                 try {
  274.                     mailService.onVmOneHourLast(vm, user);
  275.                     vm.setOneHourLateNotify(true);
  276.                     vmRepository.save(vm);
  277.                 } catch (Exception e) {
  278.                     e.printStackTrace();
  279.                 }
  280.             }
  281.         }
  282.         if (vm.getStatus() == ClientVMStatus.POSTPONED) {
  283.             if (vm.getPostponeEndDate().before(now)) {
  284.                 resumeVirtualMachine(vm);
  285.                 vm.setStatus(ClientVMStatus.CREATING);
  286.                 vm.setPostponeStartDate(null);
  287.                 vm.setPostponeInitEndDate(null);
  288.                 vm.setPostponeEndDate(null);
  289.                 vmRepository.save(vm);
  290.                 User user = userService.findById(vm.getUserId());
  291.                 try {
  292.                     mailService.onVmReady(user);
  293.                 } catch (MessagingException | TemplateException e) {
  294.                     e.printStackTrace();
  295.                 }
  296.             }
  297.         }
  298.     }
  299.  
  300.     /**
  301.      * Запрашивает данные о виртуалке. IP, login, password, ID, status - ключи мапы.
  302.      *
  303.      * @param vmId
  304.      * @return
  305.      * @throws IOException
  306.      */
  307.     private Map<String, String> requestVMInfo(String vmId) throws IOException, VMNotFoundException {
  308.         String url = BASE_URL + "/api/vms/id/" + vmId;
  309.  
  310.         HttpClient client = HttpClientBuilder.create().build();
  311.         HttpGet get = new HttpGet(url);
  312.         get.addHeader("api-key", API_KEY);
  313.         HttpResponse response = client.execute(get);
  314.  
  315.         int statusCode = response.getStatusLine().getStatusCode();
  316.         if (statusCode == 404) {
  317.             throw new VMNotFoundException();
  318.         }
  319.         if (statusCode != 200) {
  320.             throw new IOException("Что-то пошло не так... Статус ответа: " + statusCode);
  321.         }
  322.         ObjectMapper mapper = new ObjectMapper();
  323.         Map<String, String> map = mapper.readValue(response.getEntity().getContent(), new TypeReference<Map<String, String>>() {
  324.         });
  325.         return map;
  326.     }
  327.  
  328.     /**
  329.      * Очищает виртуалку
  330.      *
  331.      * @param vmId
  332.      * @throws IllegalStateException
  333.      */
  334.     public void rebootVM(String vmId, String userId) throws Exception {
  335.         ClientVM vm = vmRepository.getById(vmId);
  336.         BigDecimal price = new BigDecimal(REBOOT_PRICE);
  337.         if (!vm.getRecreationAllowed()) {
  338.             BigDecimal userBalance = getClientBalance(userId);
  339.             if (price.compareTo(userBalance) > 0) {
  340.                 throw new NotEnoughMoneyException();
  341.             }
  342.             // Списание средств
  343.             UserBalanceHistory transaction = new UserBalanceHistory(userId, new BigDecimal(REBOOT_PRICE).negate(), "Дополнительное пересоздание виртуальной машины");
  344.             transaction.setVmId(vmId);
  345.             balanceRepository.save(transaction);
  346.         }
  347.         // статистика пересозданий
  348.         UserBalanceHistory transaction = new UserBalanceHistory(userId, new BigDecimal(0), "Переоздание виртуальной машины");
  349.         transaction.setVmId(vmId);
  350.         balanceRepository.save(transaction);
  351.  
  352.         recreateVirtualMachine(vm.getId());
  353.         vm.setStatus(ClientVMStatus.RECREATING);
  354.         vm.getRebootDates().add(new Date());
  355.         vm.setCreatingDateStart(new Date());
  356.         vmRepository.save(vm);
  357.  
  358.     }
  359.  
  360.     /**
  361.      * Отправляет запрос на пересоздание виртуалки
  362.      *
  363.      * @param vmId
  364.      * @throws IOException
  365.      */
  366.     private void recreateVirtualMachine(String vmId) throws IOException {
  367.         LOGGER.info("Пересоздание виртуалки " + vmId);
  368.         String url = BASE_URL + "/api/vms/recreate/";
  369.  
  370.         HttpClient client = HttpClientBuilder.create().build();
  371.         HttpPost post = new HttpPost(url);
  372.         post.addHeader("api-key", API_KEY);
  373.         List<NameValuePair> urlParameters = new ArrayList<>();
  374.         urlParameters.add(new BasicNameValuePair("id", vmId));
  375.         post.setEntity(new UrlEncodedFormEntity(urlParameters));
  376.         HttpResponse response = client.execute(post);
  377.  
  378.         int statusCode = response.getStatusLine().getStatusCode();
  379.         if (statusCode != 202)
  380.             throw new IOException("Что-то пошло не так... Статус ответа: " + statusCode);
  381.     }
  382.  
  383.  
  384.     /**
  385.      * Продление виртуалки
  386.      *
  387.      * @throws RuntimeException
  388.      */
  389.     public void continueVirtualMachine(User user, Integer timeType, Integer timeCount, Integer country, Integer powerType, String ip) throws RuntimeException {
  390.  
  391.         // Проверка баланса
  392.         BigDecimal vmCost = estimateVmCost(timeType, timeCount, powerType, country);
  393.         BigDecimal postpone = estimatePostpone(timeType, country);
  394.         BigDecimal userBalance = getClientBalance(user.getId());
  395.         if (vmCost.compareTo(userBalance) > 0)
  396.             throw new NotEnoughMoneyException();
  397.  
  398.         int days = 0;
  399.         switch (timeType) {
  400.             case 0:
  401.                 days = 1;
  402.                 break;
  403.             case 1:
  404.                 days = 7;
  405.                 break;
  406.             case 2:
  407.                 days = 31;
  408.                 break;
  409.         }
  410.         days = days * timeCount;
  411.         ClientVM clientVM = vmRepository.getByIp(ip);
  412.  
  413.         //Продление виртуалки
  414.         Date endDate = DateUtils.addDays(clientVM.getEndDate(), days);
  415.         clientVM.setEndDate(endDate);
  416.         clientVM.setPostponeAllowed(clientVM.getPostponeAllowed() + postpone.intValue());
  417.         vmRepository.save(clientVM);
  418.  
  419.         // Списание средств
  420.         UserBalanceHistory transaction = new UserBalanceHistory(user.getId(), vmCost.negate(),
  421.                 String.format("Продление виртуалки %s на %s дней", powerType.toString(), days));
  422.         transaction.setVmId(clientVM.getId());
  423.         balanceRepository.save(transaction);
  424.     }
  425.  
  426.  
  427.     public void buyVirtualMachine(User user, Integer timeType, Integer powerType, Integer country, Integer timeCount, String promo) throws RuntimeException {
  428.         LOGGER.debug(String.format("userId=%s", user.getId()));
  429.  
  430.         BigDecimal vmCost = estimateVmCost(timeType, 1, powerType, country);
  431.  
  432.         vmCost = getDiscountForUser(user, promo, vmCost).setScale(0, RoundingMode.CEILING);
  433.  
  434.         vmCost = getPartnerDiscountForUser(user, vmCost);
  435.  
  436.         vmCost = getPartnerDiscountForUser(user, vmCost);
  437.  
  438.         String countryType = mapToCountry(country);
  439.         // Проверка баланса
  440.         BigDecimal userBalance = getClientBalance(user.getId());
  441.         BigDecimal postponeAllowed = estimatePostpone(timeType, country);
  442.         if (vmCost.compareTo(userBalance) > 0)
  443.             throw new NotEnoughMoneyException();
  444.         if (timeCount < 0) {
  445.             throw new CommonException();
  446.         }
  447.         int days = 0;
  448.         switch (timeType) {
  449.             case 0:
  450.                 days = 1;
  451.                 break;
  452.             case 1:
  453.                 days = 7;
  454.                 break;
  455.             case 2:
  456.                 days = 31;
  457.                 break;
  458.         }
  459.         days = days * timeCount;
  460.  
  461.         // Создание виртуалок
  462.         Date now = new Date();
  463.         now = DateUtils.addHours(now, 1);
  464.         Date endDate = DateUtils.addDays(now, days);
  465.         ClientVM vm = null;
  466.         powerType = mapToPower(powerType);
  467.         try {
  468.             vm = createVirtualMachine(user.getId(), endDate, powerType, countryType, postponeAllowed.intValue());
  469.         } catch (IOException ex) {
  470.             if (vm != null) {
  471.                 vmRepository.delete(vm);
  472.             }
  473.             LOGGER.error(ex.getMessage());
  474.             throw new CommonException();
  475.         }
  476.         // Списание средств
  477.         UserBalanceHistory transaction = new UserBalanceHistory(user.getId(), vmCost.negate(),
  478.                 String.format("Покупка виртуалки на %s дней", days));
  479.         transaction.setVmId(vm.getId());
  480.         balanceRepository.save(transaction);
  481.     }
  482.  
  483.     private Integer mapToPower(Integer power) {
  484.         switch (power) {
  485.             case 0:
  486.                 return 1;
  487.             case 1:
  488.                 return 2;
  489.             case 2:
  490.                 return 3;
  491.         }
  492.         return 1;
  493.     }
  494.  
  495.     private String mapToCountry(Integer country) {
  496.         switch (country) {
  497.             case 0:
  498.                 return "NETHERLANDS";
  499.             case 1:
  500.                 return "SINGAPORE";
  501.             case 2:
  502.                 return "GERMANY";
  503.             case 3:
  504.                 return "UNITED_KINGDOM";
  505.             case 4:
  506.                 return "BELARUS";
  507.         }
  508.         return "NETHERLANDS";
  509.     }
  510.  
  511.     /**
  512.      * Подсчитывает стоимость виртуалок, исходя из роли пользователя, периода, на который
  513.      * оформляются виртуалки, и кол-ва виртуалок.
  514.      *
  515.      * @return
  516.      */
  517.     public BigDecimal estimateVmCost(Integer timeType, Integer timeCount, Integer powerType, Integer country) {
  518.         ConfigurationPrice configurationPrice = mapToPrices(country);
  519.         BigDecimal amount = new BigDecimal(249);
  520.         switch (timeType) {
  521.             case 0: //День
  522.                 amount = BigDecimal.valueOf(timeCount).multiply(dayAmount(powerType, configurationPrice));
  523.                 break;
  524.             case 1: //Неделя
  525.                 amount = BigDecimal.valueOf(timeCount).multiply(weekAmount(powerType, configurationPrice));
  526.                 break;
  527.             case 2: //Месяц
  528.                 amount = BigDecimal.valueOf(timeCount).multiply(monthAmount(powerType, configurationPrice));
  529.                 break;
  530.         }
  531.         return amount;
  532.     }
  533.  
  534.     /**
  535.      * Подсчитываем цену для пользователя с учетом скидки
  536.      *
  537.      * @param user
  538.      * @param name
  539.      * @return
  540.      */
  541.     public BigDecimal getDiscountForUser(User user, String name, BigDecimal total) {
  542.         Promo promo = promoService.findByName(name);
  543.         BigDecimal newTotal = total;
  544.         if (promo != null && promo.getActive()) {
  545.             boolean promoAllow = false;
  546.             //Проверяем пользователей приватного промокода
  547.             if (promo.getCampaignType().equals(Promo.CampaignType.PRIVATE)) {
  548.                 for (String userId : promo.getUsers()) {
  549.                     if (userId.equals(user.getId())) {
  550.                         promoAllow = true;
  551.                         break;
  552.                     }
  553.                 }
  554.             }
  555.             if (promo.getCampaignType().equals(Promo.CampaignType.PUBLIC)) {
  556.                 promoAllow = true;
  557.             }
  558.             if (promoAllow) {
  559.                 switch (promo.getWorthType()) {
  560.                     case CONSTANT:
  561.                         newTotal = newTotal.subtract(new BigDecimal(promo.getAmount()));
  562.                         break;
  563.                     case DISCOUNT:
  564.                         newTotal = newTotal.subtract(new BigDecimal(NumberUtils.calculatePercent(newTotal.intValue(), promo.getAmount())));
  565.                         break;
  566.                 }
  567.             } else {
  568.                 return newTotal;
  569.             }
  570.  
  571.         } else {
  572.             return newTotal;
  573.         }
  574.         return newTotal;
  575.     }
  576.  
  577.     /**
  578.      * Подсчитываем цену для пользователя с учетом скидки от партнера
  579.      *
  580.      * @param user
  581.      * @return
  582.      */
  583.     public BigDecimal getPartnerDiscountForUser(User user, BigDecimal total) {
  584.         BigDecimal newTotal = total;
  585.  
  586.         if (user.getInvitedPromo() != null && user.getPromoAdminId() != null) {
  587.             User promoAdmin = userService.findById(user.getPromoAdminId());
  588.             if (promoAdmin.getPromoDiscount() != null) {
  589.                 Double cashBack = NumberUtils.calculatePercent(total.intValue(),
  590.                         promoAdmin.getPromoDiscount());
  591.                 return newTotal.subtract(new BigDecimal(cashBack)).setScale(0, RoundingMode.CEILING);
  592.             } else {
  593.                 return newTotal;
  594.             }
  595.         } else {
  596.             return newTotal;
  597.         }
  598.     }
  599.  
  600.     /**
  601.      * Подсчитывает количество дней приостановки виртуальной машины
  602.      */
  603.     public BigDecimal estimatePostpone(Integer timeType, Integer country) {
  604.  
  605.         BigDecimal postpone = new BigDecimal(0);
  606.         BigDecimal additionalCountry = BigDecimal.valueOf(0);
  607.         if (country.equals(2) || country.equals(3)) {
  608.             additionalCountry = BigDecimal.valueOf(1);
  609.         }
  610.         switch (timeType) {
  611.             case 0:
  612.                 postpone = new BigDecimal(0).add(additionalCountry);
  613.                 break;
  614.             case 1:
  615.                 postpone = BigDecimal.valueOf(2).add(additionalCountry);
  616.                 break;
  617.             case 2:
  618.                 postpone = BigDecimal.valueOf(5).add(additionalCountry);
  619.                 break;
  620.         }
  621.         return postpone;
  622.     }
  623.  
  624.     private ConfigurationPrice mapToPrices(Integer country) {
  625.         ConfigurationPrice azure = new ConfigurationPrice(199, 990, 2990, 349, 1990, 6490, 499, 2990, 9990);
  626. //        ConfigurationPrice vultr = new ConfigurationPrice(249, 1290, 3990, 390, 2490, 7990, 690, 4990, 13990);
  627.         ConfigurationPrice vultr = new ConfigurationPrice(199, 990, 2990, 349, 1990, 6490, 499, 2990, 9990);
  628.  
  629.         switch (country) {
  630.             case 0:
  631.                 return azure;
  632.             case 1:
  633.                 return azure;
  634.             case 2:
  635.                 return vultr;
  636.             case 3:
  637.                 return vultr;
  638.         }
  639.         return null;
  640.     }
  641.  
  642.     private BigDecimal dayAmount(Integer powerType, ConfigurationPrice configurationPrice) {
  643.         switch (powerType) {
  644.             case 0:
  645.                 return new BigDecimal(configurationPrice.getDayEasy());
  646.             case 1:
  647.                 return new BigDecimal(configurationPrice.getDayOptimal());
  648.             case 2:
  649.                 return new BigDecimal(configurationPrice.getDaySpeedup());
  650.         }
  651.         return new BigDecimal(configurationPrice.getDayOptimal());
  652.     }
  653.  
  654.     private BigDecimal weekAmount(Integer powerType, ConfigurationPrice configurationPrice) {
  655.         switch (powerType) {
  656.             case 0:
  657.                 return new BigDecimal(configurationPrice.getWeekEasy());
  658.             case 1:
  659.                 return new BigDecimal(configurationPrice.getWeekOptimal());
  660.             case 2:
  661.                 return new BigDecimal(configurationPrice.getWeekSpeedup());
  662.         }
  663.         return new BigDecimal(configurationPrice.getWeekOptimal());
  664.     }
  665.  
  666.     private BigDecimal monthAmount(Integer powerType, ConfigurationPrice configurationPrice) {
  667.         switch (powerType) {
  668.             case 0:
  669.                 return new BigDecimal(configurationPrice.getMonthEasy());
  670.             case 1:
  671.                 return new BigDecimal(configurationPrice.getMonthOptimal());
  672.             case 2:
  673.                 return new BigDecimal(configurationPrice.getMonthSpeedup());
  674.         }
  675.         return new BigDecimal(configurationPrice.getMonthOptimal());
  676.     }
  677.  
  678.     private void deleteAndPostpone(String vmId, ClientVM vm, Integer addDateCount, Integer postponeNegateCount, User user) throws IOException {
  679.         Date now = new Date();
  680.         deleteForPostponeVirtualMachine(vmId);
  681.         vm.setPostponeInitEndDate(vm.getEndDate());
  682.         vm.setPostponeStartDate(now);
  683.         Date endDate = DateUtils.addDays(vm.getEndDate(), addDateCount);
  684.         Date postponeEndDate = DateUtils.addDays(now, addDateCount);
  685.         vm.setPostponeEndDate(postponeEndDate);
  686.         vm.setEndDate(endDate);
  687.         vm.setPostponeAllowed(vm.getPostponeAllowed() - postponeNegateCount);
  688.         vm.setStatus(ClientVMStatus.POSTPONED);
  689.         vm.setIp("");
  690.         vmRepository.save(vm);
  691.     }
  692.  
  693.     public String postponeVM(String vmId, Integer count, User user) throws IOException {
  694.         ClientVM vm = vmRepository.findOne(vmId);
  695.         if (vm.getPostponeAllowed() >= count) {
  696.             deleteAndPostpone(vmId, vm, count, count, user);
  697.             UserBalanceHistory transaction = new UserBalanceHistory(user.getId(), new BigDecimal(0),
  698.                     String.format("Остановка виртуалки на %s дней", String.valueOf(count)));
  699.             transaction.setVmId(vmId);
  700.             balanceRepository.save(transaction);
  701.             return String.format("Виртуальная машинано удалена. Новая создастся через %s дней.", String.valueOf(count));
  702.         } else {
  703.             BigDecimal total = new BigDecimal(count * 70);
  704.             BigDecimal userBalance = getClientBalance(user.getId());
  705.             if (total.compareTo(userBalance) == 1) {
  706.                 return "Не достаточно денег не балансе.";
  707.             } else {
  708.                 deleteAndPostpone(vmId, vm, count, 0, user);
  709.                 UserBalanceHistory transaction = new UserBalanceHistory(user.getId(), total.negate(),
  710.                         String.format("Остановка виртуалки на %s дней", String.valueOf(count)));
  711.                 transaction.setVmId(vmId);
  712.                 balanceRepository.save(transaction);
  713.                 return String.format("Виртуальная машинано удалена. Новая создастся через %s дней.", String.valueOf(count));
  714.             }
  715.         }
  716.     }
  717.  
  718.     public String endPostpone(String vmId, User user) throws IOException {
  719.         ClientVM vm = vmRepository.findOne(vmId);
  720.         if (vm != null) {
  721.             Date now = new Date();
  722.             if (vm.getPostponeInitEndDate() != null) {
  723.                 long usedInMillies = Math.abs(now.getTime() - vm.getPostponeStartDate().getTime());
  724.                 Long usedInHours = TimeUnit.HOURS.convert(usedInMillies, TimeUnit.MILLISECONDS);
  725.                 Date newEndDate = DateUtils.addHours(vm.getPostponeInitEndDate(), usedInHours.intValue());
  726.                 vm.setEndDate(newEndDate);
  727.             } else {
  728.                 Date postponeEnd = vm.getPostponeEndDate();
  729.                 long diffInMillies = Math.abs(now.getTime() - postponeEnd.getTime());
  730.                 long diffNowAndPostpone = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
  731.                 long diffInMilliesStartAndEnd = Math.abs(vm.getStartDate().getTime() - vm.getEndDate().getTime());
  732.                 long diffStartAndVmEnd = TimeUnit.DAYS.convert(diffInMilliesStartAndEnd, TimeUnit.MILLISECONDS);
  733.                 long newEnd = diffStartAndVmEnd - diffNowAndPostpone;
  734.                 Date newEndDate = DateUtils.addDays(vm.getStartDate(), new Long(newEnd).intValue());
  735.                 vm.setEndDate(newEndDate);
  736.             }
  737.             resumeVirtualMachine(vm);
  738.             vm.setStatus(ClientVMStatus.CREATING);
  739.             vm.setPostponeEndDate(null);
  740.             vm.setPostponeStartDate(null);
  741.             vm.setPostponeInitEndDate(null);
  742.  
  743.             vm.setCreatingDateStart(new Date());
  744.             vmRepository.save(vm);
  745.             try {
  746.                 mailService.onVmReady(user);
  747.             } catch (MessagingException | TemplateException e) {
  748.                 e.printStackTrace();
  749.             }
  750.         } else {
  751.             return "Виртуальная машина не найдена.";
  752.         }
  753.         return "";
  754.     }
  755.  
  756.     /**
  757.      * Возвращает баланс клиента по его ИД
  758.      *
  759.      * @param clientId
  760.      * @return
  761.      */
  762.     public BigDecimal getClientBalance(String clientId) {
  763.         List<UserBalanceHistory> balanceHistories = balanceRepository.getClientBalanceHistory(clientId);
  764.         return balanceHistories.stream()
  765.                 .map(UserBalanceHistory::getAmount)
  766.                 .reduce(BigDecimal.ZERO, BigDecimal::add);
  767.     }
  768.  
  769.     /**
  770.      * Возвращает балансы всех клиентов в мапе, где ключ - ИД клиента,
  771.      * значение - баланс клиента
  772.      *
  773.      * @return
  774.      */
  775.     public Map<String, BigDecimal> listUserBalances() {
  776.         List<UserBalanceHistory> balanceHistories = balanceRepository.findAll();
  777.         Map<String, List<BigDecimal>> balanceByUser = balanceHistories.stream()
  778.                 .collect(Collectors.groupingBy(UserBalanceHistory::getUserId,
  779.                         Collectors.mapping(UserBalanceHistory::getAmount, Collectors.toList())));
  780.         Map<String, BigDecimal> balances = new HashMap<>();
  781.         for (Map.Entry<String, List<BigDecimal>> entry : balanceByUser.entrySet()) {
  782.             balances.put(entry.getKey(), entry.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
  783.         }
  784.         return balances;
  785.     }
  786.  
  787.     /**
  788.      * Возвращает балансы всех клиентов в мапе, где ключ - ИД клиента,
  789.      * значение - баланс клиента
  790.      *
  791.      * @return
  792.      */
  793.     public Map<String, BigDecimal> listUserSummaryBalances() {
  794.         List<UserBalanceHistory> balanceHistories = balanceRepository.findAll();
  795.         Map<String, List<BigDecimal>> balanceByUser = balanceHistories.stream().filter(balance -> balance.getAmount().doubleValue() > 0)
  796.                 .collect(Collectors.groupingBy(UserBalanceHistory::getUserId,
  797.                         Collectors.mapping(UserBalanceHistory::getAmount, Collectors.toList())));
  798.         Map<String, BigDecimal> balances = new HashMap<>();
  799.         for (Map.Entry<String, List<BigDecimal>> entry : balanceByUser.entrySet()) {
  800.             balances.put(entry.getKey(), entry.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
  801.         }
  802.         return balances;
  803.     }
  804.  
  805.  
  806.     /**
  807.      * Возвращает список транзакций клиента по его ИД
  808.      *
  809.      * @param clientId
  810.      * @return
  811.      */
  812.     public List<UserBalanceHistory> getClientBalanceHistory(String clientId) {
  813.         return balanceRepository.getClientBalanceHistory(clientId);
  814.     }
  815.  
  816.     public void save(UserBalanceHistory balanceHistory) {
  817.         balanceRepository.save(balanceHistory);
  818.     }
  819.  
  820.     /**
  821.      * Возвращает сумму транзакций со знаком плюс
  822.      *
  823.      * @param clientId
  824.      * @return
  825.      */
  826.     public Double getClientIncomesSum(String clientId) {
  827.         Double result = 0.0;
  828.         for (UserBalanceHistory userBalanceHistory : balanceRepository.getClientBalanceHistory(clientId)) {
  829.             if (userBalanceHistory.getAmount().doubleValue() > 0) {
  830.                 result += userBalanceHistory.getAmount().doubleValue();
  831.             }
  832.         }
  833.         return result;
  834.     }
  835.  
  836.     /**
  837.      * Возвращает сумму транзакций со знаком минус
  838.      *
  839.      * @param clientId
  840.      * @return
  841.      */
  842.     public Double getClientOutcomesSum(String clientId) {
  843.         Double result = 0.0;
  844.         for (UserBalanceHistory userBalanceHistory : balanceRepository.getClientBalanceHistory(clientId)) {
  845.             if (userBalanceHistory.getAmount().doubleValue() < 0) {
  846.                 result += userBalanceHistory.getAmount().doubleValue();
  847.             }
  848.         }
  849.         return result;
  850.     }
  851.  
  852.     /**
  853.      * Возвращает список виртуалок клиента по его ИД
  854.      *
  855.      * @param clientId
  856.      * @return
  857.      */
  858.     public List<ClientVM> listVirtualMachinesForClient(String clientId) {
  859.         List<ClientVM> vms = vmRepository.listByUserId(clientId);
  860.         vms = vms.stream().filter(vm -> !vm.getStatus().equals(ClientVMStatus.DELETED))
  861.                 .sorted((o1, o2) -> o2.getStartDate().compareTo(o1.getStartDate()))
  862.                 .collect(Collectors.toList());
  863.         return vms;
  864.     }
  865.  
  866.     public List<ClientVM> listActiveVms() {
  867.         return vmRepository.findActive();
  868.     }
  869. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement