com.nec.harvest.controller.SuihController.java Source code

Java tutorial

Introduction

Here is the source code for com.nec.harvest.controller.SuihController.java

Source

/*
 * Copyright(C) 2014
 * NEC Corporation All rights reserved.
 * 
 * No permission to use, copy, modify and distribute this software
 * and its documentation for any purpose is granted.
 * This software is provided under applicable license agreement only.
 */
package com.nec.harvest.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.functors.EqualPredicate;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import com.nec.core.exception.ObjectNotFoundException;
import com.nec.core.exception.TooManyObjectsException;
import com.nec.harvest.bean.mapping.BudgetPerformanceBean;
import com.nec.harvest.bean.mapping.SuisMonthBean;
import com.nec.harvest.bean.mapping.SuisTotalBean;
import com.nec.harvest.constant.Constants;
import com.nec.harvest.exception.ServiceException;
import com.nec.harvest.http.HttpServletContentType;
import com.nec.harvest.menu.group.ProfitAndLossManagementProGroup;
import com.nec.harvest.model.Division;
import com.nec.harvest.model.Organization;
import com.nec.harvest.model.Tighten;
import com.nec.harvest.model.VJiseki;
import com.nec.harvest.service.ActualViewService;
import com.nec.harvest.service.BudgetPerformanceService;
import com.nec.harvest.service.ConsumptionTaxRateService;
import com.nec.harvest.service.DivisionService;
import com.nec.harvest.service.InventoryService;
import com.nec.harvest.service.OrganizationService;
import com.nec.harvest.service.TightenService;
import com.nec.harvest.stereotype.SessionAttribute;
import com.nec.harvest.util.DateFormatUtil;
import com.nec.harvest.util.DateFormatUtil.DateFormat;
import com.nec.harvest.util.DateUtil;
import com.nec.harvest.util.RoundNumericUtil;

/**
 * A controller that listen every request after process logic for (Suih)
 * After response to page html
 * 
 * @author hungpd
 * 
 */
@Controller
@RequestMapping(value = Constants.SUIH_PATH)
public class SuihController extends ProfitAndLossManagementProGroup implements PageRenderer, TitleRenderer {

    private static final Logger logger = LoggerFactory.getLogger(SuihController.class);

    private static final String DEFAULT_KBN_ID = "KAISOU";

    private final OrganizationService organizationService;

    private final ActualViewService actualViewService;

    private final TightenService tightenService;

    private final InventoryService inventoryService;

    private final BudgetPerformanceService budgetPerformanceService;

    private final ConsumptionTaxRateService consumptionTaxRateService;

    private final DivisionService divisionService;

    @Inject
    public SuihController(ActualViewService actualViewService, TightenService tightenService,
            InventoryService inventoryService, BudgetPerformanceService budgetPerformanceService,
            ConsumptionTaxRateService consumptionTaxRateService, OrganizationService organizationService,
            DivisionService divisionService) {
        this.actualViewService = actualViewService;
        this.tightenService = tightenService;
        this.inventoryService = inventoryService;
        this.budgetPerformanceService = budgetPerformanceService;
        this.consumptionTaxRateService = consumptionTaxRateService;
        this.divisionService = divisionService;
        this.organizationService = organizationService;
    }

    /** {@inheritDoc} */
    @Override
    @RequestMapping(value = "", method = RequestMethod.GET)
    public String render(@SessionAttribute(Constants.SESS_ORGANIZATION_CODE) String orgCode,
            @SessionAttribute(Constants.SESS_BUSINESS_DAY) Date businessDay, @PathVariable String proGNo,
            final Model model) {
        if (logger.isDebugEnabled()) {
            logger.debug("Redering suih report...");
        }

        // get current quarter business
        int quarter = Integer.parseInt((DateUtil.getQuarter(businessDay)));
        if (quarter == 1) {
            quarter = 4;
        } else {
            quarter = quarter - 1;
        }

        // get current year business
        String currentYear = DateFormatUtil.format(businessDay, DateFormat.DATE_YEAR);
        Date year = null;
        try {
            year = DateFormatUtil.parse(currentYear, DateFormat.DATE_YEAR);
        } catch (NullPointerException | IllegalArgumentException | ParseException ex) {
            logger.warn(ex.getMessage());
        }

        // get three month of current quarter business
        final String CURRENT_MONTHLIES = "monthlies";
        String[] monthiesCurrentQuarter = DateUtil.getMonthliesOfQuarter(year, quarter);

        //
        model.addAttribute(CURRENT_MONTHLIES, monthiesCurrentQuarter);

        final String CURRENT_QUARTER = "currentQuarter";
        model.addAttribute(CURRENT_QUARTER, DateUtil.getCurrentQuarter(businessDay));

        // ?
        try {
            // get classification list
            List<Division> divisions = divisionService.findByKbnId(DEFAULT_KBN_ID);
            model.addAttribute("classifies", divisions);
        } catch (IllegalArgumentException | ObjectNotFoundException ex) {
            logger.warn(ex.getMessage());
        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR, true);
            model.addAttribute(ERROR_MESSAGE, getSystemError());
        }
        return getViewName();
    }

    /**
     * Render page with path variables mapping suih/{unitLevel}/{unitDept}
     * 
     * @param businessDay
     *            Actual business day
     * @param proGNo
     *            A path variable user's group code
     * @param unitLevel
     *            A path variable classify's code
     * @param unitDept
     *            A path variable department level2's code
     * @return A redirect URL
     */
    @RequestMapping(value = "/{unitLevel}/{unitDept}", method = RequestMethod.GET)
    public String render(@SessionAttribute(Constants.SESS_BUSINESS_DAY) Date businessDay,
            @PathVariable String proGNo, @PathVariable String unitLevel, @PathVariable String unitDept) {

        // 
        UriComponents uriComponents = UriComponentsBuilder
                .fromUriString(Constants.SUIH_PATH + "/{unitLevel}/{unitDept}/{deptCode}").build();
        URI uri = uriComponents.expand(proGNo, unitLevel, unitDept, unitDept).encode().toUri();
        logger.info("Redirect to suih screen with params in path [/suih/{unitLevel}/{unitDept}/{deptCode}]");
        return "redirect:" + uri.toString();
    }

    /**
     * Render page with path variables mapping suih/{unitLevel}/{unitDept}/{deptCode}
     * 
     * @param businessDay
     *            Actual business day
     * @param proGNo
     *            A path variable user's group code
     * @param unitLevel
     *            A path variable classify's code
     * @param unitDept
     *            A path variable department level2's code
     * @param deptCode
     *            A path variable department selected on page view
     * @param year
     *            A path variable year
     * @param quarter
     *            A path variable quarter
     * @return A redirect URL
     */
    @RequestMapping(value = "/{unitLevel}/{unitDept}/{deptCode}", method = RequestMethod.GET)
    public String render(@SessionAttribute(Constants.SESS_BUSINESS_DAY) Date businessDay,
            @PathVariable String proGNo, @PathVariable String unitLevel, @PathVariable String unitDept,
            @PathVariable String deptCode) {
        logger.info(
                "Loading profit quarter data by full path [/suih/{unitLevel}/{unitDept}/{deptCode}/{year}/{quarter}]");

        // get year and quarter by business day
        String yearQuater = StringUtils.EMPTY;
        try {
            yearQuater = DateUtil.getCurrentQuarter(businessDay);
        } catch (IllegalArgumentException ex) {
            logger.warn(ex.getMessage());
        }

        // build path for redirect
        UriComponents uriComponents = UriComponentsBuilder
                .fromUriString(Constants.SUIH_PATH + "/{unitLevel}/{unitDept}/{deptCode}/{currentQuarter}").build();
        URI uri = uriComponents.expand(proGNo, unitLevel, unitDept, deptCode, yearQuater).encode().toUri();
        logger.info(
                "Redirect to suih screen with params in path [/suih/{unitLevel}/{unitDept}/{deptCode}/{year}/{quarter}]");
        return "redirect:" + uri.toString();
    }

    /**
     * Render page with path variables mapping
     * /{unitLevel}/{unitDept}/{deptCode}/{year:\\d{4}}/{quarter:[1-4]}
     * 
     * @param userOrgCode
     *            Logged-in user's code
     * @param businessDay
     *            Actual business day
     * @param proGNo
     *            A path variable user's group code
     * @param unitLevel
     *            A path variable classify's code
     * @param unitDept
     *            A path variable department level2's code
     * @param deptCode
     *            A path variable department selected on page view
     * @param year
     *            A path variable year
     * @param quarter
     *            A path variable quarter
     * @param model
     *            Spring's model that can be used to render a view
     * @return A redirect URL
     */
    @RequestMapping(value = "/{unitLevel}/{unitDept}/{deptCode}/{year:\\d{4}}/{quarter:[1-4]}", method = RequestMethod.GET)
    public String render(@SessionAttribute(Constants.SESS_ORGANIZATION_CODE) String userOrgCode,
            @SessionAttribute(Constants.SESS_BUSINESS_DAY) Date businessDay, @PathVariable String proGNo,
            @PathVariable String unitLevel, @PathVariable String unitDept, @PathVariable String deptCode,
            @PathVariable String year, @PathVariable String quarter, final HttpServletRequest request,
            final Model model) {
        logger.info(
                "Loading profit and loss manager in a quarter data by full path [/suih/{unitLevel}/{unitDept}/{deptCode}/{year}/{quarter}]");

        Date currentYear = null;
        int currentQuarter = 0;

        // cast year, quarter
        try {
            currentYear = DateFormatUtil.parse(year, DateFormat.DATE_YEAR);
            currentQuarter = Integer.parseInt(quarter);
        } catch (NullPointerException | IllegalArgumentException | ParseException ex) {
            logger.warn(ex.getMessage());
        }

        try {
            /* Get classify list */
            List<Division> divisions;
            try {
                divisions = divisionService.findByKbnId(DEFAULT_KBN_ID);
            } catch (IllegalArgumentException | ObjectNotFoundException ex) {
                logger.warn(ex.getMessage());

                // Set divisions is empty
                divisions = Collections.emptyList();
            }

            // set list classifies first drop down list
            final String CLASSIFIES = "classifies";
            model.addAttribute(CLASSIFIES, divisions);

            // set value selected first drop down list
            final String UNIT_LEVEL = "unitLevel";
            model.addAttribute(UNIT_LEVEL, selectedClassify(divisions, unitLevel));

            List<Organization> departments = null;
            try {
                // Get the list of organizations level 2
                departments = organizationService.findByKaisoBango(unitLevel);
            } catch (IllegalArgumentException | ObjectNotFoundException ex) {
                logger.warn(ex.getMessage());
            }

            // set attribute list departments for drop down list level2
            final String DEPARTMENTS = "departments";
            model.addAttribute(DEPARTMENTS, departments);

            // set attribute name selected for drop down list level2
            final String UNIT_DEPT = "unitDeptName";
            model.addAttribute(UNIT_DEPT, selectedDepartment(departments, unitDept));

            final String UNIT_DEPT_CODE = "unitDeptCode";
            model.addAttribute(UNIT_DEPT_CODE, unitDept);

            // set attribute department code
            final String DEPT_CODE = "deptCode";
            boolean isTotalCalculation = unitDept.equals(deptCode);
            model.addAttribute(DEPT_CODE, isTotalCalculation ? unitDept : deptCode);

            // set attribute current quarter of business
            final String CURRENT_QUARTER = "currentQuarter";
            model.addAttribute(CURRENT_QUARTER, year.concat("/").concat(quarter));

            InputStreamReader in = null;
            try {
                UriComponents uriComponents = UriComponentsBuilder.fromUriString(
                        request.getContextPath() + Constants.PAGINATION_PATH + "/{unitDept}/{deptCode}/{pageindex}")
                        .build();
                URI uri = uriComponents.expand(proGNo, unitDept, deptCode, 0).encode().toUri();

                // initial HttpHost, HttpGet
                CloseableHttpClient httpClient = HttpClientBuilder.create().build();
                HttpHost httpHost = new HttpHost(request.getServerName(), request.getLocalPort(),
                        request.getScheme());
                HttpGet httpGet = new HttpGet(uri.toString());
                HttpResponse httpResp = httpClient.execute(httpHost, httpGet);
                if (httpResp.getStatusLine().getStatusCode() != 200) {
                    // Release the connection
                    httpClient.close();
                    httpClient = null;

                    // call rest paging error
                    throw new RuntimeException(
                            "Failed : HTTP error code : " + httpResp.getStatusLine().getStatusCode());
                }

                // read pagination 
                in = new InputStreamReader(httpResp.getEntity().getContent(),
                        HttpServletContentType.DEFAULT_ENCODING);
                BufferedReader rd = new BufferedReader(in);
                StringBuilder textView = new StringBuilder();

                String line = "";
                while ((line = rd.readLine()) != null) {
                    textView.append(line);
                }

                // set attribute pagination
                final String HTML_PAGINATION = "pagination";
                model.addAttribute(HTML_PAGINATION, textView);

                // Release the connection
                httpClient.close();
                httpClient = null;
            } catch (Exception ex) {
                logger.error(ex.getMessage(), ex);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException ex) {
                        logger.warn(ex.getMessage());
                    }
                }
            }
        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR, true);
            model.addAttribute(ERROR_MESSAGE, getSystemError());
        }

        // 
        return processingSuih(userOrgCode, businessDay, unitDept, deptCode, currentYear, currentQuarter, model);
    }

    /**
     * Render page with path variables mapping
     * 
     * @param userOrgCode
     *            Logged-in user's code
     * @param businessDay
     *            Actual business day
     * @param deptCode
     *            A path variable department selected on page view
     * @param year
     *            A path variable year
     * @param quarter
     *            A path variable quarter
     * @param model
     *            Spring's model that can be used to render a view
     * @return A redirect URL
     */
    @RequestMapping(value = "/load/{unitDept}/{deptCode}/{year:\\d{4}}/{quarter:[1-4]}", method = RequestMethod.GET)
    public String render(@SessionAttribute(Constants.SESS_ORGANIZATION_CODE) String userOrgCode,
            @SessionAttribute(Constants.SESS_BUSINESS_DAY) Date businessDay, @PathVariable String unitDept,
            @PathVariable String deptCode, @PathVariable @DateTimeFormat(pattern = "yyyy") Date year,
            @PathVariable int quarter, final Model model) {

        // 
        return processingSuih(userOrgCode, businessDay, unitDept, deptCode, year, quarter, model);
    }

    /**
     * 
     * 
     * @param userOrgCode
     * @param businessDay
     * @param unitDept
     * @param deptCode
     * @param year
     * @param quarter
     * @param model
     * @return
     */
    private String processingSuih(String userOrgCode, Date businessDay, String unitDept, String deptCode, Date year,
            int quarter, Model model) {
        // check department code empty
        final String CURRENT_MONTHLIES = "monthlies";

        // get three month in quarter business
        String[] monthiesCurrentQuarter = DateUtil.getMonthliesOfQuarter(year, quarter);
        model.addAttribute(CURRENT_MONTHLIES, monthiesCurrentQuarter);

        // get final tighten
        Date finalTighten = checkFinalMonthlyTighten(businessDay, model);
        if (finalTighten == null) {
            return getViewName();
        }

        List<String> listOrgCodes = null;
        try {
            listOrgCodes = organizationService.findOrgsByDepartmentCode(unitDept);
        } catch (IllegalArgumentException | ObjectNotFoundException ex) {
            logger.warn(ex.getMessage());

        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            model.addAttribute(ERROR, true);
            return getViewName();
        }
        // ???[?]?????
        if (!availableNext(quarter, year, model, finalTighten, listOrgCodes, businessDay)) { // enable, disable Next
            return getViewName();
        }

        // ??????????
        if (!availablePrevious(quarter, year, model, finalTighten, listOrgCodes)) { // enable, disable Previous
            return getViewName();
        }

        if (!unitDept.equals(deptCode)) {
            try {
                listOrgCodes = organizationService.findOrgsByDepartmentCode(deptCode);
            } catch (IllegalArgumentException | ObjectNotFoundException ex) {
                logger.warn(ex.getMessage());

            } catch (ServiceException ex) {
                logger.error(ex.getMessage(), ex);

                // ???????????
                model.addAttribute(ERROR_MESSAGE, getSystemError());
                model.addAttribute(ERROR, true);
                return getViewName();
            }
        }

        // get startMonth
        String currentYear = DateFormatUtil.format(year, "yyyy");
        String startMonth = currentYear.concat("04");

        // get endMonth 
        String nextYear = DateFormatUtil.format(DateUtils.addYears(year, 1), "yyyy");
        String endMonth = nextYear.concat("03");
        int countMonth = 12;

        try {
            Date endDate = DateFormatUtil.parse(endMonth, DateFormat.DATE_WITHOUT_DAY);
            if (endDate.after(businessDay)) {
                countMonth = countMonth - DateUtil.monthsBetween(businessDay, endDate);
                endMonth = DateFormatUtil.format(businessDay, DateFormat.DATE_WITHOUT_DAY);
            }
        } catch (NullPointerException | IllegalArgumentException | ParseException ex) {
            logger.warn(ex.getMessage());
        }

        // ???jiseki??
        Map<String, List<VJiseki>> mapSuis = null;
        List<VJiseki> listSuisYear = null;

        try {
            if (CollectionUtils.isNotEmpty(listOrgCodes)) {
                listSuisYear = actualViewService.findByPeriodMonthlyAndOrgCodes(startMonth, endMonth, listOrgCodes);
            }
        } catch (IllegalArgumentException | ObjectNotFoundException | NullPointerException ex) {
            logger.warn(ex.getMessage());

        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            model.addAttribute(ERROR, true);
            return getViewName();
        }

        // ????
        try {
            mapSuis = getMapOfSuihsByMonthly(listSuisYear,
                    DateFormatUtil.parse(startMonth, DateFormat.DATE_WITHOUT_DAY), countMonth);
        } catch (NullPointerException | IllegalArgumentException | ParseException ex) {
            logger.warn(ex.getMessage());
        }

        // find data budget performance
        Map<String, BudgetPerformanceBean> mapBudgetPerformance = null;
        try {
            mapBudgetPerformance = budgetPerformanceService.findByOrgCodesAndPeriodMonthAndKmkCodeJs(listOrgCodes,
                    startMonth, endMonth, Constants.DEFAULT_KMKCODEJ_K7111, Constants.DEFAULT_KMKCODEJ_K7521,
                    Constants.DEFAULT_KMKCODEJ_K8110, Constants.DEFAULT_KMKCODEJ_K8210,
                    Constants.DEFAULT_KMKCODEJ_K8310);
        } catch (IllegalArgumentException | ObjectNotFoundException ex) {
            logger.warn(ex.getMessage());

        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            model.addAttribute(ERROR, true);
            return getViewName();
        }

        // ???
        Map<String, Double> mapInventory = null;
        try {
            mapInventory = inventoryService.findByPeriodMonthAndOrgCodes(startMonth, endMonth, listOrgCodes);
        } catch (IllegalArgumentException | ObjectNotFoundException ex) {
            logger.warn(ex.getMessage());

        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            model.addAttribute(ERROR, true);
            return getViewName();
        }

        // ??
        calculateSuih(mapSuis, finalTighten, businessDay, mapBudgetPerformance, mapInventory, quarter, model);
        return getViewName();
    }

    /**
     * 
     * @param month
     * @param suisMonthly
     * @param model
     */
    private void setDataMonthly(int month, SuisMonthBean suisMonthly, Model model) {
        switch (month) {
        case 0:
            // ?????
            model.addAttribute("firstMonth", suisMonthly);
            break;
        case 1:
            // ??
            model.addAttribute("secondMonth", suisMonthly);
            break;
        case 2:
            // ???
            model.addAttribute("thirdMonth", suisMonthly);
            break;
        default:
            break;
        }
    }

    /**
     * 
     * @param currentQuater
     * @param currentYear
     * @param model
     * @param finalTighten
     * @param orgCodes
     * @param businessDay
     * @return
     */
    private boolean availableNext(int currentQuater, Date currentYear, Model model, Date finalTighten,
            List<String> orgCodes, Date businessDay) {
        final String URL_NEXT = "nextUrl";
        String nextQuarter = null;
        try {
            // if quarter equal 4 then set quarter equal 1
            int intNextQuater = currentQuater + 1;
            if (currentQuater == 5) {
                intNextQuater = 1;
            }

            // get three month of next quarter
            String[] monthiesNext = DateUtil.getMonthliesOfQuarter(currentYear, intNextQuater);
            Date firstDate = DateFormatUtil.parse(monthiesNext[0], DateFormat.DATE_WITHOUT_DAY);
            if (firstDate.after(businessDay)) {
                // next url set null <=> disabled button next 
                model.addAttribute(URL_NEXT, nextQuarter);
                return true;
            }
            // greater than tighten date
            if (firstDate.after(finalTighten)) {
                // count data in v_jiseki view if count greater > 0 then return true otherwise return false
                if (actualViewService.checkAvailableByOrgCodesAndMonthlies(orgCodes, monthiesNext)) {
                    nextQuarter = DateUtil.nextQuarter(firstDate);
                }
            } else {
                // count data in budget performance if count greater > 0 then return true otherwise return false
                boolean isNextAvailable = budgetPerformanceService.checkAvailableByOrgCodesAndMonthlyAndKmkCodeJs(
                        orgCodes, monthiesNext[0], Constants.DEFAULT_KMKCODEJ_K7111,
                        Constants.DEFAULT_KMKCODEJ_K7521, Constants.DEFAULT_KMKCODEJ_K8110,
                        Constants.DEFAULT_KMKCODEJ_K8210, Constants.DEFAULT_KMKCODEJ_K8310);
                if (isNextAvailable) {
                    nextQuarter = DateUtil.nextQuarter(firstDate);
                }
            }
            model.addAttribute(URL_NEXT, nextQuarter);
        } catch (IllegalArgumentException | NullPointerException | ParseException ex) {
            logger.warn(ex.getMessage());

            // next url set null <=> disabled button next
            model.addAttribute(URL_NEXT, nextQuarter);
        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            model.addAttribute(ERROR, true);
            return false;
        }
        return true;
    }

    /**
     * 
     * @param currentQuater
     * @param currentYear
     * @param model
     * @param finalTighten
     * @param orgCodes
     * @return
     */
    private boolean availablePrevious(int currentQuater, Date currentYear, Model model, Date finalTighten,
            List<String> orgCodes) {
        final String URL_PREVIOUS = "previousUrl";
        try {
            // if quarter equal 1 then set quarter equal 4
            int preQuater = currentQuater - 1;
            if (currentQuater == 0) {
                preQuater = 4;
            }

            // get three month of previous quarter
            String[] monthiesPrevious = DateUtil.getMonthliesOfQuarter(currentYear, preQuater);
            String previousQuarter = null;
            Date date = DateFormatUtil.parse(monthiesPrevious[2], DateFormat.DATE_WITHOUT_DAY);

            // greater than tighten date
            if (date.after(finalTighten)) {
                if (actualViewService.checkAvailableByOrgCodesAndMonthlies(orgCodes, monthiesPrevious)) {
                    previousQuarter = DateUtil.previousQuarter(date);
                }
            } else {
                boolean isPreviousAvailable = budgetPerformanceService
                        .checkAvailableByOrgCodesAndMonthlyAndKmkCodeJs(orgCodes, monthiesPrevious[2],
                                Constants.DEFAULT_KMKCODEJ_K7111, Constants.DEFAULT_KMKCODEJ_K7521,
                                Constants.DEFAULT_KMKCODEJ_K8110, Constants.DEFAULT_KMKCODEJ_K8210,
                                Constants.DEFAULT_KMKCODEJ_K8310);
                if (isPreviousAvailable) {
                    previousQuarter = DateUtil.nextQuarter(date);
                }
            }
            model.addAttribute(URL_PREVIOUS, previousQuarter);
        } catch (IllegalArgumentException | NullPointerException | ParseException | ObjectNotFoundException ex) {
            logger.warn(ex.getMessage());

            // 
            model.addAttribute(URL_PREVIOUS, null);
        } catch (ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            model.addAttribute(ERROR, true);
            return false;
        }
        return true;
    }

    /**
     * Calculator total data 12 month and fill 3 month of quarter
     * 
     * @param listSuisYear
     *            Data profit and loss
     * @param monthly
     *            month
     * @param businessDay
     *            a day business
     * @param mapBudgetPerformance
     *            Map at023
     * @param mapInventory
     *            Map at015
     * @param quarter
     *            a current quarter
     * @param model
     */
    private void calculateSuih(Map<String, List<VJiseki>> mapSuisYear, Date monthly, Date businessDay,
            Map<String, BudgetPerformanceBean> mapBudgetPerformance, Map<String, Double> mapInventory, int quarter,
            Model model) {
        logger.info("Begin calculator suih for 3 month and total of year");

        final String TOTAL_QUARTER = "totalQuarter";
        Integer no12 = null; // _??__??
        Integer no14 = null; // _?__??)
        Integer no16 = null; // ___??
        Integer no18 = null; // _??__??
        Integer no20 = null; // ___??
        Integer no22 = null; // _?__??
        Integer no25 = null; // ___??
        Double no26 = null; // ___
        Integer no29 = null; // __??
        Double no30 = null; // __
        Integer no33 = null; // __??
        Double no34 = null; // __
        Integer no37 = null; // __??
        Double no38 = null; // __
        int index = 0;
        SuisMonthBean suisMonthly = null;
        String valueBlank = "1";

        if (mapSuisYear != null && mapSuisYear.size() > 0) {
            for (Map.Entry<String, List<VJiseki>> entry : mapSuisYear.entrySet()) {
                String key = entry.getKey();
                List<VJiseki> listJiseki = entry.getValue();
                try {
                    String getsudo = key;
                    Date yearmonth = DateFormatUtil.parse(getsudo, DateFormat.DATE_WITHOUT_DAY);
                    double taxRate = 0d;
                    try {
                        taxRate = consumptionTaxRateService.findActualTaxRateByDate(yearmonth);
                    } catch (IllegalArgumentException | ObjectNotFoundException ex) {
                        logger.warn(ex.getMessage());

                    } catch (ServiceException ex) {
                        logger.error(ex.getMessage(), ex);

                        // ???????????
                        model.addAttribute(ERROR_MESSAGE, getSystemError());
                        model.addAttribute(ERROR, true);
                    }

                    Integer no11 = null; // _??_n1n3_?
                    Integer no15 = null; // __n1n3_????
                    Integer no13 = null; // _?_n1n3_?
                    Integer no17 = null; // _??_n1n3_??
                    Integer no19 = null; // __n1n3_??
                    Integer no21 = null; // _?_n1n3_??
                    Integer no23 = null; // __n1n3_??
                    Double no24 = null; // __n1n3_
                    Integer no27 = null; // _n1n3_??
                    Double no28 = null; // _n1n3_
                    Integer no31 = null; // _n1n3_??
                    Double no32 = null; // _n1n3_
                    Integer no35 = null; // _n1n3_??
                    Double no36 = null; // _n1n3_
                    Double no19Percent = null;

                    if (yearmonth.after(monthly)) {
                        int days = DateUtil.getNumberOfDays(yearmonth, businessDay);
                        if (CollectionUtils.isNotEmpty(listJiseki)) {
                            for (VJiseki jiseki : listJiseki) { // for list together month
                                int tmp = 0;
                                String strValueBlank = "";
                                int daysInMonth = DateUtil.getActualMaximumOfMonth(businessDay);
                                logger.info("Total days of month {} ", daysInMonth);

                                //                        // NO11 ???????? ? ????? ??1,000??????                  
                                //                        if (jiseki.getUriSkKG() != null) {
                                //                           double uriSkKG = jiseki.getUriSkKG().doubleValue();
                                //                           tmp = (int) Math.floor((uriSkKG - Math.floor(uriSkKG / (100 + taxRate) * taxRate)) / 1000);
                                //                           no11 = (no11 == null) ? 0 : no11.intValue();
                                //                           no11 = no11 + tmp;
                                //                        }

                                // Modified by SONDN 2014/12/22: Update SPEC 20141222
                                // NO11 ???????? ? ????? ??1,000??????                  
                                if (jiseki.getUriSkKG() != null || jiseki.getKtSkKG() != null
                                        || jiseki.getIdoSkKGU() != null || jiseki.getIdoSkKGH() != null) {
                                    Double uriSkKG = jiseki.getUriSkKG();
                                    Double ktSkKG = jiseki.getKtSkKG();
                                    Double idoSkKGU = jiseki.getIdoSkKGU();
                                    Double idoSkKGH = jiseki.getIdoSkKGH();
                                    double step1 = uriSkKG == null ? 0
                                            : uriSkKG - Math.floor((uriSkKG / (100 + taxRate)) * taxRate);
                                    double step2 = ktSkKG == null ? 0 : ktSkKG;
                                    int tmpDays = DateUtil.getNumberOfDays(yearmonth, businessDay);
                                    if (tmpDays > 0) {
                                        step2 = (step2 / daysInMonth) * tmpDays;
                                    }
                                    double step3 = idoSkKGU == null ? 0 : idoSkKGU;
                                    double step4 = idoSkKGH == null ? 0 : idoSkKGH;
                                    tmp = (int) Math.floor((step1 + step2 + step3 - step4) / 1000);
                                    no11 = (no11 == null) ? 0 : no11.intValue();
                                    no11 = no11 + tmp;
                                }

                                // (1) ? ????
                                double temp1 = 0d;
                                if (jiseki.getUriKrKG() != null) {
                                    double uriKrKG = jiseki.getUriKrKG().doubleValue();
                                    temp1 = Math.floor(uriKrKG - Math.floor(uriKrKG / (100 + taxRate) * taxRate));
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1
                                }

                                // (2) ? ???
                                double temp2 = 0d;
                                if (jiseki.getKtKrKG() != null) {
                                    temp2 = jiseki.getKtKrKG().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11
                                }

                                if (days > 0) {
                                    temp1 = (temp1 / daysInMonth) * days;
                                    temp2 = (temp2 / daysInMonth) * days;
                                } else if (days == 0) {
                                    strValueBlank = "11";
                                }

                                // NO13  ????????(1) + (2)
                                if (!strValueBlank.equals("11")) {
                                    no13 = (no13 == null) ? 0 : no13.intValue();
                                    tmp = (int) Math.floor((temp1 + temp2) / 1000);
                                    no13 = no13 + tmp;
                                }

                                // ????????
                                strValueBlank = "";
                                double ktsrkg = 0d;

                                // (1) ? ?
                                if (jiseki.getKtSrKG() != null) {
                                    ktsrkg = jiseki.getKtSrKG().doubleValue();
                                    if (days >= 0) {
                                        ktsrkg = (ktsrkg / daysInMonth) * days;
                                    }
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1
                                }
                                // (2) ? ??
                                double kgcSrKG = 0d;
                                if (jiseki.getKgcSrKG() != null) {
                                    kgcSrKG = jiseki.getKgcSrKG().doubleValue();
                                    kgcSrKG = Math.floor(kgcSrKG - Math.floor(kgcSrKG / (100 + taxRate) * taxRate));
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11
                                }

                                // (3) ? ??????
                                double idoSrkGU = 0d;
                                if (jiseki.getIdoSrKGU() != null) {
                                    idoSrkGU = jiseki.getIdoSrKGU().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 111
                                }

                                // (4) ? ??
                                double idoSrkGH = 0d;
                                if (jiseki.getIdoSrKGH() != null) {
                                    idoSrkGH = jiseki.getIdoSrKGH().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1111
                                }

                                // (5) ? ?
                                double knSrKG = 0d;
                                if (jiseki.getKnSrKG() != null) {
                                    knSrKG = jiseki.getKnSrKG().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11111
                                }

                                // (1) + (2) + (3) + (4) - (5)
                                if (!strValueBlank.equals("11111")) {
                                    tmp = (int) Math
                                            .floor((knSrKG + ktsrkg + kgcSrKG + idoSrkGU - idoSrkGH) / 1000);
                                    no19 = (no19 == null) ? 0 : no19.intValue();
                                    no19 = no19 + tmp;
                                }

                                // NO27 ????????
                                strValueBlank = "";

                                // (1) ? ??
                                double ktJkKG = 0d;
                                if (jiseki.getKtJkKG() != null) {
                                    ktJkKG = jiseki.getKtJkKG().doubleValue();
                                    if (days >= 0) {
                                        ktJkKG = (ktJkKG / daysInMonth) * days;
                                    }
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1
                                }

                                // (2) ? ?            
                                double jkJkKG = 0d;
                                if (jiseki.getJkJkKG() != null) {
                                    jkJkKG = jiseki.getJkJkKG().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11
                                }

                                // (3) ? ??????         
                                double kgcJkKG = 0d;
                                if (jiseki.getKgcJkKG() != null) {
                                    kgcJkKG = jiseki.getKgcJkKG().doubleValue();
                                    kgcJkKG = Math.floor(kgcJkKG - Math.floor(kgcJkKG / (100 + taxRate) * taxRate));
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 111
                                }

                                // (4) ? ??
                                double idoJkKGU = 0d;
                                if (jiseki.getIdoJkKGU() != null) {
                                    idoJkKGU = jiseki.getIdoJkKGU().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1111
                                }

                                // (5) ? ?
                                double idoJkKGH = 0d;
                                if (jiseki.getIdoJkKGH() != null) {
                                    idoJkKGH = jiseki.getIdoJkKGH().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11111
                                }

                                // (6) ? ??
                                double helpJkKGU = 0d;
                                if (jiseki.getHelpJkKGU() != null) {
                                    helpJkKGU = jiseki.getHelpJkKGU().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 111111
                                }

                                // (7) ? ?
                                double helpJkKGH = 0d;
                                if (jiseki.getHelpJkKGH() != null) {
                                    helpJkKGH = jiseki.getHelpJkKGH().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1111111
                                }

                                // (1) + (2) + (3) + (4) - (5) + (6) - (7)
                                if (!strValueBlank.equals("1111111")) {
                                    tmp = (int) Math.floor((ktJkKG + jkJkKG + kgcJkKG + idoJkKGU - idoJkKGH
                                            + helpJkKGU - helpJkKGH) / 1000);
                                    no27 = (no27 == null) ? 0 : no27.intValue();
                                    no27 = no27 + tmp;
                                }

                                // NO31  ????????

                                // (1) ? ??
                                strValueBlank = "";
                                double ktKhKG = 0d;
                                if (jiseki.getKtKhKG() != null) {
                                    ktKhKG = jiseki.getKtKhKG().doubleValue();
                                    if (days >= 0) {
                                        ktKhKG = ktKhKG / daysInMonth * days;
                                    }
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1
                                }

                                // (2) ? ?
                                double knKhKG = 0d;
                                if (jiseki.getKnKhKG() != null) {
                                    knKhKG = jiseki.getKnKhKG().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11
                                }

                                // (3) ? ??????
                                double kgcKhKG = 0d;
                                if (jiseki.getKgcKhKG() != null) {
                                    kgcKhKG = jiseki.getKgcKhKG().doubleValue();
                                    kgcKhKG = Math.floor(kgcKhKG - Math.floor(kgcKhKG / (100 + taxRate) * taxRate));
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 111
                                }

                                // (4) ? ??
                                double idoKhKGU = 0d;
                                if (jiseki.getIdoKhKGU() != null) {
                                    idoKhKGU = jiseki.getIdoKhKGU().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 1111
                                }

                                // (5) ? ?
                                double idoKhKGH = 0d;
                                if (jiseki.getIdoKhKGH() != null) {
                                    idoKhKGH = jiseki.getIdoKhKGH().doubleValue();
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 11111
                                }

                                // (6) ? ??
                                double uriKhKG = 0d;
                                if (jiseki.getUriKhKG() != null) {
                                    uriKhKG = jiseki.getUriKhKG().doubleValue();
                                    uriKhKG = Math.floor(uriKhKG - Math.floor(uriKhKG / (100 + taxRate) * taxRate));
                                    if (days >= 0) {
                                        uriKhKG = uriKhKG / daysInMonth * days;
                                    }
                                } else {
                                    strValueBlank = strValueBlank.concat(valueBlank);// 111111
                                }

                                // (1) + (2) + (3) + (4) - (5) + (6)
                                if (!strValueBlank.equals("111111")) {
                                    tmp = (int) Math.floor(
                                            (ktKhKG + knKhKG + kgcKhKG + idoKhKGU - idoKhKGH + uriKhKG) / 1000);

                                    no31 = (no31 == null) ? 0 : no31.intValue();
                                    no31 = no31 + tmp;
                                }
                            } // end for together monthly

                            // NO12 ??????_??_??? ??1,000??????
                            if (no11 != null) {
                                no12 = (no12 == null) ? 0 : no12.intValue();
                                no12 += no11;
                            }

                            // NO14 ??????_?_???   ??1,000??????
                            if (no13 != null) {
                                no14 = (no14 == null) ? 0 : no14.intValue();
                                no14 += no13;
                            }

                            // NO15 ????????   _??__???  _?__??? ??1,000??????2
                            if (no11 != null || no13 != null) {
                                int temp11 = (no11 == null) ? 0 : no11.intValue();
                                int temp13 = (no13 == null) ? 0 : no13.intValue();
                                no15 = (no15 == null) ? 0 : no15.intValue();
                                no15 = temp11 + temp13;
                            }

                            // NO19/NO11
                            if (no19 != null && (no11 != null && no11.intValue() > 0)) {
                                no19Percent = RoundNumericUtil.roundSonekiSuii(no19, no11);
                            }
                        }

                        // NO21 ?????????   ????????  ??1,000??????
                        Double amount = (mapInventory != null) ? mapInventory.get(getsudo) : null;
                        if (amount != null && amount.doubleValue() != -1) {
                            no21 = (int) amount.doubleValue() / 1000;
                        }

                        // NO17 ?????????????????? ??1,000??????
                        if (no21 != null) {
                            int previousGetSudo = Integer.parseInt(DateFormatUtil
                                    .format(DateUtil.monthsToSubtract(yearmonth, 1), DateFormat.DATE_WITHOUT_DAY));
                            Double temp = (mapInventory != null)
                                    ? (Double) mapInventory.get(String.valueOf(previousGetSudo))
                                    : null;
                            if (temp != null && temp.doubleValue() != -1) {
                                // Change SPEC 01/09/2014
                                if (days != -1 && no21 == 0) {
                                    no17 = null;
                                    no21 = null;
                                } else {
                                    no17 = (int) (temp.doubleValue() / 1000);
                                }
                                // End change SPEC 01/09/2014
                            }
                        }

                        // Modified by SONDN 2014/12/23: Update SPEC 20141222
                        // NO17 ?????0?????????????
                        if (yearmonth.getYear() == businessDay.getYear()
                                && yearmonth.getMonth() == businessDay.getMonth() && (no21 == null || no21 == 0)) {
                            no17 = null;
                        }

                        // (NO23) _??_n_??__n_??-_?_n_??
                        if (no17 != null || no19 != null || no21 != null) {
                            int temp17 = (no17 == null) ? 0 : no17.intValue();
                            int temp19 = (no19 == null) ? 0 : no19.intValue();
                            int temp21 = (no21 == null) ? 0 : no21.intValue();
                            no23 = temp17 + temp19 - temp21;
                        }

                        // NO35 ???????? ___???___???__???__??
                        if (no15 != null || no23 != null || no27 != null || no31 != null) {
                            int temp15 = (no15 == null) ? 0 : no15.intValue();
                            int temp23 = (no23 == null) ? 0 : no23.intValue();
                            int temp27 = (no27 == null) ? 0 : no27.intValue();
                            int temp31 = (no31 == null) ? 0 : no31.intValue();
                            no35 = temp15 - temp23 - temp27 - temp31;
                        }
                    } else {
                        if (mapBudgetPerformance != null) {
                            // (N015) ??????????? ? =???
                            BudgetPerformanceBean kingaku = (BudgetPerformanceBean) mapBudgetPerformance
                                    .get(getsudo + Constants.DEFAULT_KMKCODEJ_K7111);
                            if (kingaku != null && kingaku.getJisekiKingaku() != null) {
                                no15 = (int) Math.floor(kingaku.getJisekiKingaku().doubleValue() / 1000);
                            }

                            // (NO19) ??????????? ? =???
                            kingaku = (BudgetPerformanceBean) mapBudgetPerformance
                                    .get(getsudo + Constants.DEFAULT_KMKCODEJ_K7521);
                            if (kingaku != null && kingaku.getJisekiKingaku() != null) {
                                no19 = (int) Math.floor(kingaku.getJisekiKingaku().doubleValue() / 1000);
                            }

                            // (NO27) ???????????? =???
                            kingaku = (BudgetPerformanceBean) mapBudgetPerformance
                                    .get(getsudo + Constants.DEFAULT_KMKCODEJ_K8110);
                            if (kingaku != null && kingaku.getJisekiKingaku() != null) {
                                no27 = (int) Math.floor(kingaku.getJisekiKingaku().doubleValue() / 1000);
                            }

                            // (NO31) ??????????? ? =???
                            kingaku = (BudgetPerformanceBean) mapBudgetPerformance
                                    .get(getsudo + Constants.DEFAULT_KMKCODEJ_K8210);
                            if (kingaku != null && kingaku.getJisekiKingaku() != null) {
                                no31 = (int) Math.floor(kingaku.getJisekiKingaku().doubleValue() / 1000);
                            }

                            // NO 35  ???????????? =???
                            kingaku = (BudgetPerformanceBean) mapBudgetPerformance
                                    .get(getsudo + Constants.DEFAULT_KMKCODEJ_K8310);
                            if (kingaku != null && kingaku.getJisekiKingaku() != null) {
                                no35 = (int) Math.floor(kingaku.getJisekiKingaku().doubleValue() / 1000);
                            }
                        }

                        // (NO23) _??_n_??__n_??-_?_n_??
                        if (no17 != null || no19 != null || no21 != null) {
                            int temp17 = (no17 == null) ? 0 : no17.intValue();
                            int temp19 = (no19 == null) ? 0 : no19.intValue();
                            int temp21 = (no21 == null) ? 0 : no21.intValue();
                            no23 = temp17 + temp19 - temp21;
                        }
                    }

                    if (no15 != null && no15.intValue() > 0) {
                        //(NO24) __n_???__n_??   ???
                        if (no23 != null) {
                            no24 = RoundNumericUtil.roundSonekiSuii(no23, no15);
                        }

                        // (NO28) _n_???__n_??   ???
                        if (no27 != null) {
                            no28 = RoundNumericUtil.roundSonekiSuii(no27, no15);
                        }

                        // (NO32) _n_???__n_?? ???
                        if (no31 != null) {
                            no32 = RoundNumericUtil.roundSonekiSuii(no31, no15);
                        }

                        // (NO36) _n_???__n_?? ???
                        if (no35 != null) {
                            no36 = RoundNumericUtil.roundSonekiSuii(no35, no15);
                        }
                    }

                    int currentQuarter = Integer.parseInt(DateUtil.getQuarter(yearmonth)) - 1;
                    if (currentQuarter == 0) {
                        currentQuarter = 4;
                    }

                    // ??
                    if (quarter == currentQuarter) {
                        suisMonthly = new SuisMonthBean(no11, no13, no15, no17, no19, no21, no23, no24, no27, no28,
                                no31, no32, no35, no36, no19Percent);
                        setDataMonthly(index, suisMonthly, model);

                        logger.info("??");
                        index++;
                    }

                    // ?? (NO16, NO18, NO20, NO22, NO24, NO29, NO33)
                    if (no15 != null) {
                        no16 = (no16 == null) ? 0 : no16.intValue();
                        no16 += no15;
                    }
                    if (no17 != null) {
                        no18 = (no18 == null) ? 0 : no18.intValue();
                        no18 += no17;
                    }
                    if (no19 != null) {
                        no20 = (no20 == null) ? 0 : no20.intValue();
                        no20 += no19;
                    }
                    if (no21 != null) {
                        no22 = (no22 == null) ? 0 : no22.intValue();
                        no22 += no21;
                    }
                    if (no27 != null) {
                        no29 = (no29 == null) ? 0 : no29.intValue();
                        no29 += no27;
                    }
                    if (no31 != null) {
                        no33 = (no33 == null) ? 0 : no33.intValue();
                        no33 += no31;
                    }
                    if (no35 != null) {
                        no37 = (no37 == null) ? 0 : no37.intValue();
                        no37 += no35;
                    }
                } catch (NullPointerException | IllegalArgumentException | ParseException ex) {
                    logger.warn(ex.getMessage());
                }

                // (NO21) _??_n_??__n_??-_?_n_??
                if (no18 != null || no20 != null || no22 != null) {
                    int temp18 = (no18 == null) ? 0 : no18.intValue();
                    int temp20 = (no20 == null) ? 0 : no20.intValue();
                    int temp22 = (no22 == null) ? 0 : no22.intValue();
                    no25 = temp18 + temp20 - temp22;
                }

                if (no16 != null && no16.intValue() > 0) {

                    // (NO22) ___???___?? ???
                    if (no25 != null) {
                        no26 = RoundNumericUtil.roundSonekiSuii(no25, no16);
                    }

                    // (NO26) __???___?? ???
                    if (no29 != null) {
                        no30 = RoundNumericUtil.roundSonekiSuii(no29, no16);
                    }

                    // (NO30) __???___?? ???
                    if (no33 != null) {
                        no34 = RoundNumericUtil.roundSonekiSuii(no33, no16);
                    }

                    // (NO34) __???___?? ???
                    if (no37 != null) {
                        no38 = RoundNumericUtil.roundSonekiSuii(no37, no16);
                    }
                }
            }
        }
        // ?? 
        SuisTotalBean suisTotal = new SuisTotalBean(no12, no14, no16, no18, no20, no22, no25, no26, no29, no30,
                no33, no34, no37, no38);
        model.addAttribute(TOTAL_QUARTER, suisTotal);

        // Log calculator finished
        logger.info("End calculator suih for 3 month and total of year");
    }

    /**
     * 
     * @param startMonth
     * @param countMonth
     * @return
     */
    private Map<String, List<VJiseki>> getMapOfSudo(Date startMonth, int countMonth) {
        Calendar bCalendar = Calendar.getInstance();
        Map<String, List<VJiseki>> mapSuih = new TreeMap<String, List<VJiseki>>();
        for (int i = 0; i < countMonth; i++) {
            bCalendar.setTime(startMonth);
            bCalendar.add(Calendar.MONTH, i);
            int month = bCalendar.get(Calendar.MONTH) + 1;
            mapSuih.put(
                    String.valueOf(bCalendar.get(Calendar.YEAR)) + String.valueOf(month < 10 ? "0" + month : month),
                    null);
        }
        return mapSuih;
    }

    /**
     * 
     * @param listSuis
     * @param startMonth
     * @param countMonth
     * @return
     */
    private Map<String, List<VJiseki>> getMapOfSuihsByMonthly(List<VJiseki> listSuis, Date startMonth,
            int countMonth) {
        Map<String, List<VJiseki>> mapSuis = getMapOfSudo(startMonth, countMonth);
        if (CollectionUtils.isNotEmpty(listSuis)) {
            for (Map.Entry<String, List<VJiseki>> entry : mapSuis.entrySet()) {
                String key = entry.getKey();
                EqualPredicate nameEqlPredicate = new EqualPredicate(key);
                BeanPredicate beanPredicate = new BeanPredicate("pk.getSudo", nameEqlPredicate);

                List<VJiseki> suiiMonthly = new ArrayList<VJiseki>();
                suiiMonthly.addAll(listSuis);

                // Filter
                CollectionUtils.filter(suiiMonthly, beanPredicate);
                if (CollectionUtils.isNotEmpty(suiiMonthly)) {
                    mapSuis.put(key, suiiMonthly);
                }
            }
        }
        return mapSuis;
    }

    /**
     * Check the final monthly of tighten
     * 
     * @param businessDay
     * @param model
     * @return
     */
    private Date checkFinalMonthlyTighten(Date businessDay, Model model) {
        Date tightenDate = null;
        try {
            Tighten tighten = tightenService.findByClassifyAndMonth("1");

            // get date tighten
            tightenDate = DateFormatUtil.parse(tighten.getGetSudo(), DateFormat.DATE_WITHOUT_DAY);
        } catch (IllegalArgumentException | NullPointerException | ParseException | ObjectNotFoundException ex) {
            logger.warn(ex.getMessage());

            tightenDate = DateUtil.monthsToSubtract(businessDay, 3);
        } catch (TooManyObjectsException | ServiceException ex) {
            logger.error(ex.getMessage(), ex);

            // ???????????
            model.addAttribute(ERROR, true);
            model.addAttribute(ERROR_MESSAGE, getSystemError());
            return tightenDate;
        }
        return tightenDate;
    }

    /**
     * Get full display of classify to show on page
     * 
     * @param classifies
     *            List of classify
     * @param classify
     *            Classify code to get name
     * @return Name of classify in strings
     */
    private String selectedClassify(List<Division> classifies, String classify) {
        if (CollectionUtils.isNotEmpty(classifies) && StringUtils.isNotEmpty(classify)) {
            boolean result = false;
            for (int i = 0; i < classifies.size(); i++) {
                result = result || classifies.get(i).getKbnCode().equals(classify);
                Division division = classifies.get(i);
                if (division.getKbnCode().equals(classify)) {
                    return (classify + ": " + division.getKbnName());
                }
            }
        }
        return null;
    }

    /**
     * Get full display of department to show on page
     * 
     * @param departments
     *            List of department
     * @param deptCode
     *            Department code to get name
     * @return Department name in string
     */
    private String selectedDepartment(List<Organization> departments, String deptCode) {
        if (CollectionUtils.isNotEmpty(departments) && StringUtils.isNotEmpty(deptCode)) {
            for (int i = 0; i < departments.size(); i++) {
                Organization department = departments.get(i);
                if (department.getStrCode().equalsIgnoreCase(deptCode)) {
                    return deptCode + ": " + department.getStrNameR();
                }
            }
        }
        return null;
    }

    @Override
    public String getViewName() {
        return "suih/suih";
    }

    @Override
    public String getTitleName() {
        return "??";
    }

}