com.ccserver.digital.service.LOSService.java Source code

Java tutorial

Introduction

Here is the source code for com.ccserver.digital.service.LOSService.java

Source

package com.ccserver.digital.service;

import java.io.IOException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import javax.xml.bind.JAXBElement;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ccserver.digital.common.Constants;
import com.ccserver.digital.common.Utils;
import com.ccserver.digital.common.ValidationErrorDTO;
import com.ccserver.digital.config.LOSConfiguration;
import com.ccserver.digital.domain.CreditCardApplication;
import com.ccserver.digital.domain.type.Status;
import com.ccserver.digital.domain.type.TypeOfEmployment;
import com.ccserver.digital.dto.AddressDTO;
import com.ccserver.digital.dto.ApplicationLOSDTO;
import com.ccserver.digital.dto.BaseCreditCardDTO;
import com.ccserver.digital.dto.BranchDTO;
import com.ccserver.digital.dto.CountryDTO;
import com.ccserver.digital.dto.CreditCardApplicationDTO;
import com.ccserver.digital.dto.CreditCardApplicationDocumentThumbNailDTO;
import com.ccserver.digital.dto.CreditCardDTO;
import com.ccserver.digital.dto.LosResponseDTO;
import com.ccserver.digital.dto.PhoneDTO;
import com.ccserver.digital.dto.SelectionListDTO;
import com.ccserver.digital.mapper.GeneralMapper;
import com.ccserver.digital.repository.CreditCardApplicationRepository;
import com.vpbank.common.envelope.commonheader._1.ClientType;
import com.vpbank.common.envelope.commonheader._1.CommonType;
import com.vpbank.common.envelope.commonheader._1.HeaderType;
import com.vpbank.common.envelope.commonheader._1.ResponseStatusErroInfoType;
import com.vpbank.common.envelope.commonheader._1.ResponseStatusType;
import com.vpbank.common.envelope.commonheader._1.TargetAppIDs;
import com.vpbank.common.envelope.commonheader._1.UserDetail;
import com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1.ConfigureDocumentHandlingOperationCreditCardRequestType;
import com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1.ConfigureDocumentHandlingOperationCreditCardResponseType;
import com.vpbank.entity.vn.ba34.bd85.salesproductagreement.initiatesalesproductagreementcreditcard._1.BodyRequestType;
import com.vpbank.entity.vn.ba34.bd85.salesproductagreement.initiatesalesproductagreementcreditcard._1.InitiateSalesProductAgreementCreditCardRequestType;
import com.vpbank.entity.vn.ba34.bd85.salesproductagreement.initiatesalesproductagreementcreditcard._1.InitiateSalesProductAgreementCreditCardResponseType;
import com.vpbank.entity.vn.ba34.bd85.salesproductagreement.initiatesalesproductagreementcreditcard._1.ObjectFactory;
import com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1.RetrieveSalesProductAgreementCreditCardRequestType;
import com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1.RetrieveSalesProductAgreementCreditCardResponseType;
import com.vpbank.entity.vn.common.account._1.CardInfoType;
import com.vpbank.entity.vn.common.document._1.ApplicationInfoType;
import com.vpbank.entity.vn.common.document._1.ApplicationStageType;
import com.vpbank.entity.vn.common.document._1.DocumentInfoType;
import com.vpbank.entity.vn.common.document._1.FileInfoType;
import com.vpbank.entity.vn.common.document._1.StatusInfoType;
import com.vpbank.entity.vn.common.party._1.AddressInfoType;
import com.vpbank.entity.vn.common.party._1.AmountType;
import com.vpbank.entity.vn.common.party._1.BranchInfoType;
import com.vpbank.entity.vn.common.party._1.ContactInfoType;
import com.vpbank.entity.vn.common.party._1.ContractInfoType;
import com.vpbank.entity.vn.common.party._1.CustomerInfoType;
import com.vpbank.entity.vn.common.party._1.DeliveryInfoType;
import com.vpbank.entity.vn.common.party._1.EmployeeInfoType;
import com.vpbank.entity.vn.common.party._1.FrequencyInfoType;
import com.vpbank.entity.vn.common.party._1.IDInfoType;
import com.vpbank.entity.vn.common.party._1.OrganizationInfoType;
import com.vpbank.entity.vn.common.party._1.PersonInfoType;
import com.vpbank.entity.vn.common.party._1.PhoneInfoType;
import com.vpbank.entity.vn.common.party._1.ReferencePersonInfoType;
import com.vpbank.entity.vn.common.product._1.ProductInfoType;
import com.vpbank.entity.vn.common.product._1.PromotionInfoType;

@Service
public class LOSService {

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

    private static final String LOS_DATA_SUBMIT_PACKAGE = "com.vpbank.entity.vn.ba34.bd85.salesproductagreement.initiatesalesproductagreementcreditcard._1";
    private static final String LOS_DATA_RETREIVE_PACKAGE = "com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1";
    private static final String LOS_DOCUMENT_PACKAGE = "com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1";

    @Autowired
    private LOSConfiguration losConfig;

    @Autowired
    private GeneralMapper mapper;

    @Autowired
    private CreditCardService creditCardService;

    @Autowired
    private CreditCardApplicationService applicationService;

    @Autowired
    private CreditCardApplicationRepository repository;

    @Autowired
    private CreditCardApplicationDocumentService docService;

    @Autowired
    private UtilService utilService;

    @Autowired
    private ZipFileService zipFileService;

    private Map<String, String> configLos;

    public LosResponseDTO submitCreditCardData(Long appId, String ipAddress) {
        AtomicReference<Object> refError = new AtomicReference<Object>("");
        CreditCardApplicationDTO creditCardDTO = applicationService.getApplication(appId);
        LosResponseDTO losResponseDTO = new LosResponseDTO();
        if (creditCardDTO != null) {
            if (creditCardDTO.getSubmittedAppTime() != null) {
                losResponseDTO.setValidationError(new ValidationErrorDTO(Constants.MODIFYING_SUBMITTED_APPLICATION,
                        "The application submitted already"));
                return losResponseDTO;
            }
            configLos = utilService.getConfigurations();
            InitiateSalesProductAgreementCreditCardResponseType result = submitDataToLos(creditCardDTO, refError);

            ApplicationLOSDTO applicationLOS = creditCardDTO.getApplicationLOS();
            if (result == null) {
                applicationLOS.setErrorMessage("Can not call webservie");
                return losResponseDTO;
            }
            String status = result.getResponseStatus().getStatus();
            losResponseDTO.setStatus(status);
            if (status.equals("0")) {
                if (result.getBodyResponse().getAppicationInfo() != null) {
                    String losAppId = result.getBodyResponse().getAppicationInfo().getApplicationId();
                    if (!StringUtils.isEmpty(losAppId)) {
                        applicationLOS.setLosApplicationId(losAppId);
                    }
                }
                applicationLOS.setErrorCode(StringUtils.EMPTY);
                applicationLOS.setErrorMessage(StringUtils.EMPTY);
            } else {
                applicationLOS.setErrorCode(result.getResponseStatus().getGlobalErrorCode());
                applicationLOS.setErrorMessage(getErrorDescription(result.getResponseStatus()));

                logger.error(Utils.getErrorFormatLog("LOSService", "submitCreditCardData", "",
                        "Cannot submit creditCardData", appId, applicationLOS.getErrorMessage()));
            }
            applicationService.updateLosInfo(creditCardDTO.getId(), applicationLOS, ipAddress);
            losResponseDTO.setResponseStatusType(result.getResponseStatus());
            return losResponseDTO;
        }
        losResponseDTO.setValidationError(
                new ValidationErrorDTO(Constants.CREDIT_CARD_OBJECT_REQUIRED, "The application is required"));
        return losResponseDTO;
    }

    private String getConfiguration(String key, String out) {
        Map<String, String> map = configLos;
        if (map == null || map.isEmpty()) {
            return out;
        } else
            return map.getOrDefault(key, out);
    }

    public LosResponseDTO retrieveApplicationStatus(CreditCardApplicationDTO dto) {
        LosResponseDTO losResponseDTO = new LosResponseDTO();
        if (dto != null) {
            configLos = utilService.getConfigurations();
            RetrieveSalesProductAgreementCreditCardResponseType result = retrieveStatus(dto);

            if (result == null) {
                losResponseDTO.setValidationError(
                        new ValidationErrorDTO(Constants.APPLICATION_UNEXPECT_ERROR, "Can not call webservice"));
                return losResponseDTO;
            }

            String status = result.getResponseStatus().getStatus();
            losResponseDTO.setStatus(status);
            logger.info(String.format("Retrieve AppId %s status with result %s", dto.getId(), status));
            if (status.equals("0")) {
                StatusInfoType statusInfoType = result.getBodyResponse().getApplicationInfo().getStatus();
                if (statusInfoType != null) {
                    String appStatus = statusInfoType.getStatus();
                    logger.info(String.format("Status for %s is %s", dto.getId(), appStatus));
                    if (!StringUtils.isEmpty(appStatus)) {
                        losResponseDTO.setAppStatus(appStatus);
                        applicationService.updateStatus(dto.getId(), appStatus);
                    }
                }
            }

            losResponseDTO.setResponseStatusType(result.getResponseStatus());
            return losResponseDTO;
        }
        losResponseDTO.setValidationError(
                new ValidationErrorDTO(Constants.CREDIT_CARD_OBJECT_REQUIRED, "The application is required"));
        return losResponseDTO;
    }

    public LosResponseDTO submitCreditCardDocument(Long creditCardId) {

        AtomicReference<Object> refError = new AtomicReference<Object>("");

        CreditCardApplication app = repository.findOne(creditCardId);

        LosResponseDTO losResponseDTO = new LosResponseDTO();

        if (app == null
                || !Arrays.asList(new Status[] { Status.SubmittedApp, Status.Processing, Status.No_wf_initiated })
                        .contains(app.getStatus())) {
            losResponseDTO.setValidationError(new ValidationErrorDTO(Constants.APPLICATION_FIELD_INVALID,
                    "The application status is invalid!"));
            return losResponseDTO;
        }

        if (app.getSubmittedDocTime() != null) {
            losResponseDTO.setValidationError(new ValidationErrorDTO(Constants.MODIFYING_SUBMITTED_DOCUMENT,
                    "The application's document submitted already"));
            return losResponseDTO;
        }

        List<CreditCardApplicationDocumentThumbNailDTO> entities = docService
                .getDocumentsThumbNailByApplicationId(creditCardId);

        if (CollectionUtils.isEmpty(entities)) {
            losResponseDTO.setValidationError(
                    new ValidationErrorDTO(Constants.OBJECT_REQUIRED, "The application's documents are required!"));
            return losResponseDTO;
        }

        configLos = utilService.getConfigurations();

        String messageId = java.util.UUID.randomUUID().toString();
        com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1.ObjectFactory objectFactory = new com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1.ObjectFactory();
        JAXBElement<ConfigureDocumentHandlingOperationCreditCardRequestType> jaxbRequest = objectFactory
                .createConfigureDocumentHandlingOperationCreditCardRequest(
                        getRequestOfDoc(app, entities, messageId, refError));

        if (refError.get().toString() != "") {
            losResponseDTO.setValidationError(
                    new ValidationErrorDTO(Constants.FILE_SIZE_LIMIT_ERROR, "File Size is exceeded!"));
            return losResponseDTO;
        }
        Object result = null;
        try {
            result = new ExternalGatewaySupport(LOS_DOCUMENT_PACKAGE).getWebServiceTemplate()
                    .marshalSendAndReceive(losConfig.getUrlDoc(), jaxbRequest, null);
        } catch (Exception ex) {
            logger.error(Utils.getErrorFormatLog("LOSService", "submitCreditCardDocument", "",
                    "Can not call webservice", losConfig.getUrlDoc(), ex));
        }
        if (result != null) {
            ConfigureDocumentHandlingOperationCreditCardResponseType resultResponse = ((JAXBElement<ConfigureDocumentHandlingOperationCreditCardResponseType>) result)
                    .getValue();
            String status = resultResponse.getResponseStatus().getStatus();
            losResponseDTO.setStatus(status);
            ApplicationLOSDTO losApplicationDTO = mapper.applicationLOSToDTO(app.getApplicationLOS());
            losApplicationDTO.setMessageDocId(messageId);
            if (status.equals("0")) {
                losApplicationDTO.setDocErrorCode(StringUtils.EMPTY);
                losApplicationDTO.setDocErrorMessage(StringUtils.EMPTY);
                CreditCardApplicationDTO dto = applicationService.updateLosDocStatus(app.getId(), Status.Processing,
                        losApplicationDTO);
                losResponseDTO.setAppDTO(dto);
            } else {
                losApplicationDTO.setDocErrorCode(resultResponse.getResponseStatus().getGlobalErrorCode());
                losApplicationDTO.setDocErrorMessage(getErrorDescription(resultResponse.getResponseStatus()));
                applicationService.updateLosDocStatus(app.getId(), null, losApplicationDTO);
            }
            losResponseDTO.setResponseStatusType(resultResponse.getResponseStatus());
            return losResponseDTO;
        }
        losResponseDTO.setValidationError(
                new ValidationErrorDTO(Constants.APPLICATION_DOC_UNEXPECT_ERROR, "Unexpect error!"));
        return losResponseDTO;
    }

    private ConfigureDocumentHandlingOperationCreditCardRequestType getRequestOfDoc(CreditCardApplication app,
            List<CreditCardApplicationDocumentThumbNailDTO> entities, String messageId,
            AtomicReference<Object> error) {
        ConfigureDocumentHandlingOperationCreditCardRequestType request = new ConfigureDocumentHandlingOperationCreditCardRequestType();

        request.setHeader(getHeaderOfRequest(messageId));
        com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1.BodyRequestType bodyRequestType = new com.vpbank.entity.vn.ba251.bd324.documentservice.configuredocumenthandlingoperationcreditcard._1.BodyRequestType();
        ApplicationInfoType applicationInfoType = new ApplicationInfoType();

        // ApplicationId
        applicationInfoType.setApplicationId(app.getApplicationLOS().getLosApplicationId());

        // Stage Name
        ApplicationStageType applicationStageType = new ApplicationStageType();
        applicationStageType.setName(getConfiguration("LOS_SUBMISSION", "SUBMISSION"));
        applicationInfoType.getStage().add(applicationStageType);

        bodyRequestType.setApplicationInfo(applicationInfoType);

        List<DocumentInfoType> documentInfoTypes = bodyRequestType.getDocumentInfo();

        Map<Long, Long> docByIds = new HashMap<Long, Long>();
        entities.forEach(x -> addSubTypeContent(docByIds, x.getSubTypeId()));

        int totalSize = 0;
        for (Map.Entry<Long, Long> entry : docByIds.entrySet()) {

            Map<String, byte[]> docBySubType = new HashMap<String, byte[]>();
            String documentTypeId = StringUtils.EMPTY;
            String documentTypeCode = StringUtils.EMPTY;
            int indexOfDoc = 1;
            for (CreditCardApplicationDocumentThumbNailDTO item : entities) {
                if (entry.getKey() == item.getSubTypeId()) {
                    byte[] itemDocument = item.getDocument();
                    if (itemDocument != null) {
                        docBySubType.put(String.valueOf(indexOfDoc + "_" + item.getFileName()), itemDocument);
                        indexOfDoc++;
                        documentTypeId = item.getDocumentTypeId();
                        documentTypeCode = item.getDocumentTypeCode();
                    }
                }
            }

            if (StringUtils.isEmpty(documentTypeId)) {
                continue;
            }

            DocumentInfoType documentInfoType = new DocumentInfoType();
            try {
                byte[] contentZip = zipFileService.zipIt(docBySubType);

                documentInfoType.setContent(contentZip);
                // DocumentType
                documentInfoType.setDocumentType(documentTypeId);

                FileInfoType fileInfoType = new FileInfoType();

                fileInfoType.setType(getConfiguration("LOS_DOCUMENT_TYPE", "copy"));

                // Size
                fileInfoType.setSize("" + contentZip.length);
                if (contentZip != null) {
                    totalSize = totalSize + contentZip.length;
                }

                // File Name
                fileInfoType.setName(documentTypeCode + ".zip");

                documentInfoType.setFileInfo(fileInfoType);

                documentInfoTypes.add(documentInfoType);
            } catch (IOException e) {
                logger.error(Utils.getErrorFormatLog("LOSService", "getRequestOfDoc", "", "Can not zip file",
                        e.toString()));

            }

        }
        //
        int limitSize = Integer.parseInt(getConfiguration("TOTAL_FILE_SIZE_LIMIT", "104857600"));
        if (totalSize > limitSize) {
            error.set("OVER LIMIT");
        }

        request.setBodyRequest(bodyRequestType);
        return request;
    }

    private String getErrorDescription(ResponseStatusType response) {
        StringBuilder resultAsString = new StringBuilder();
        resultAsString.append(response.getGlobalErrorDescription());

        List<ResponseStatusErroInfoType> listErrors = response.getErrorInfo();
        if (CollectionUtils.isEmpty(listErrors)) {
            return resultAsString.toString();
        }
        listErrors.forEach(x -> resultAsString.append(x.getErrorDesc()));
        return resultAsString.toString();
    }

    private void addSubTypeContent(Map<Long, Long> subTypes, Long id) {
        if (subTypes.get(id) == null) {
            subTypes.put(id, id);
        }
    }

    protected RetrieveSalesProductAgreementCreditCardResponseType retrieveStatus(CreditCardApplicationDTO dto) {

        com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1.ObjectFactory objectFactory = new com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1.ObjectFactory();

        JAXBElement<RetrieveSalesProductAgreementCreditCardRequestType> jaxbRequest = objectFactory
                .createRetrieveSalesProductAgreementCreditCardRequest(getInputForRetrieveStatus(dto));

        Object result = null;
        try {
            result = new ExternalGatewaySupport(LOS_DATA_RETREIVE_PACKAGE).getWebServiceTemplate()
                    .marshalSendAndReceive(losConfig.getUrlStatus(), jaxbRequest, null);
        } catch (Exception ex) {
            logger.error(Utils.getErrorFormatLog("LOSService", "retrieveStatus", "", "Can not open webservice",
                    losConfig.getUrlStatus(), ex));
        }
        if (result != null) {
            return ((JAXBElement<RetrieveSalesProductAgreementCreditCardResponseType>) result).getValue();
        }
        return null;
    }

    protected RetrieveSalesProductAgreementCreditCardRequestType getInputForRetrieveStatus(
            CreditCardApplicationDTO dto) {
        RetrieveSalesProductAgreementCreditCardRequestType request = new RetrieveSalesProductAgreementCreditCardRequestType();
        String messageId = java.util.UUID.randomUUID().toString();

        dto.getApplicationLOS().setMessageDocId(messageId);

        request.setHeader(getHeaderOfRequest(messageId));
        com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1.BodyRequestType bodyRequestType = new com.vpbank.entity.vn.ba34.bd85.salesproductagreement.retrievesalesproductagreementcreditcard._1.BodyRequestType();

        ApplicationInfoType applicationInfoType = new ApplicationInfoType();
        applicationInfoType.setApplicationId(dto.getApplicationLOS().getLosApplicationId());
        bodyRequestType.setApplicationInfo(applicationInfoType);
        request.setBodyRequest(bodyRequestType);
        return request;
    }

    protected InitiateSalesProductAgreementCreditCardResponseType submitDataToLos(CreditCardApplicationDTO dto,
            AtomicReference<Object> error) {

        ObjectFactory objectFactory = new ObjectFactory();

        InitiateSalesProductAgreementCreditCardRequestType request = new InitiateSalesProductAgreementCreditCardRequestType();

        String messageId = java.util.UUID.randomUUID().toString();

        ApplicationLOSDTO losDTO = new ApplicationLOSDTO();
        losDTO.setMessageId(messageId);
        dto.setApplicationLOS(losDTO);

        request.setHeader(getHeaderOfRequest(messageId));
        request.setBodyRequest(getBodyRequestType(dto, error));

        logger.info(Utils.getFormatLog("Request", "LOSService", "submitDataToLos", "", request.getBodyRequest()));
        JAXBElement<InitiateSalesProductAgreementCreditCardRequestType> jaxbRequest = objectFactory
                .createInitiateSalesProductAgreementCreditCardRequest(request);

        Object result = null;
        try {
            result = new ExternalGatewaySupport(LOS_DATA_SUBMIT_PACKAGE).getWebServiceTemplate()
                    .marshalSendAndReceive(losConfig.getUrl(), jaxbRequest, null);
        } catch (Exception ex) {
            logger.error(Utils.getErrorFormatLog("LOSService", "submitDataToLos", "", "Can not open webservice",
                    losConfig.getUrl(), ex));
        }
        if (result != null) {
            return ((JAXBElement<InitiateSalesProductAgreementCreditCardResponseType>) result).getValue();
        }
        return null;
    }

    protected BodyRequestType getBodyRequestType(CreditCardApplicationDTO dto, AtomicReference<Object> error) {
        BodyRequestType bodyRequestType = new BodyRequestType();
        bodyRequestType.setCustomerInfo(getCustomerInfoType(dto));
        bodyRequestType.setEmploymentInfo(getEmploymentInfo(dto));
        bodyRequestType.setCardInfo(getCardInfoType(dto));

        String saleCode = dto.getSaleAgentId();
        if (StringUtils.isEmpty(saleCode)) {
            saleCode = getConfiguration("LOS_DEFAULT_SALE_CODE", "S04819");
        }
        bodyRequestType.setSaleCode(saleCode);

        bodyRequestType.setDeliveryInfo(getDeliveryInfoType(dto));

        bodyRequestType.setSubProduct(getConfiguration("LOS_SUB_PRODUC", "08691fa54ec9498c9fa8402e37b2ff24"));// Digital
        // CC
        PromotionInfoType promotionInfoType = new PromotionInfoType();
        // BVANBINH will be replaced by Digital01
        promotionInfoType.setPromotionCode(getConfiguration("LOS_DEFAULT_PROMOTION_CODE", "BVANBINH"));
        bodyRequestType.setPromotionInfo(promotionInfoType);

        BranchInfoType branchInfo = new BranchInfoType();
        branchInfo.setBranchNo(getConfiguration("LOS_BRANCH", "7fd2984fc4eb45a4a2f6f92d9ccca55f"));// VN0010005
        bodyRequestType.setBranchInfo(branchInfo);

        bodyRequestType.getReferencePersonInfo().add(getReferencePersonInfoType(dto));
        bodyRequestType.setChannel(losConfig.getChannel());
        return bodyRequestType;
    }

    private ReferencePersonInfoType getReferencePersonInfoType(CreditCardApplicationDTO dto) {
        ReferencePersonInfoType referencePersonInfoType = new ReferencePersonInfoType();
        ContactInfoType contactInfoType = new ContactInfoType();
        PersonInfoType personInfoType = new PersonInfoType();
        personInfoType.setFullName(dto.getReferenceName());
        personInfoType.setFirstName(dto.getReferenceName());
        personInfoType.setLastName(dto.getReferenceName());
        PhoneInfoType phoneInfoType = new PhoneInfoType();
        phoneInfoType.setPhoneNo(getPhoneNumber(dto.getPhoneOfReference()));

        contactInfoType.getPhoneInfo().add(phoneInfoType);
        personInfoType.setContactInfo(contactInfoType);

        if (dto.getRelationshipReference() != null) {
            referencePersonInfoType.setRelationship(dto.getRelationshipReference().getCode());
        }

        referencePersonInfoType.setPersonInfo(personInfoType);
        return referencePersonInfoType;
    }

    private CustomerInfoType getCustomerInfoType(CreditCardApplicationDTO dto) {
        CustomerInfoType customerInfo = new CustomerInfoType();
        customerInfo.setFirstName(dto.getFirstName());
        customerInfo.setLastName(dto.getLastName());
        customerInfo.setMidName(dto.getMiddleName());

        customerInfo.setFullName(getFullName(dto));
        customerInfo.setCustomerType(getConfiguration("LOS_PCARD", "NORMAL"));

        IDInfoType idInfo = new IDInfoType();
        switch (dto.getTypeOfID()) {
        case Passport:
            idInfo.setIDType(getConfiguration("LOS_PV", "PV"));
            break;
        case NationalID:
            idInfo.setIDType(getConfiguration("LOS_IDTYPE_IC", "IC"));
            break;
        }
        idInfo.setIDNo(dto.getPassportNumber());
        idInfo.setIDIssueDate(dateToXMLGregorianCalendar(dto.getDateOfIssue()));

        if (dto.getPlaceOfIssue() != null) {
            idInfo.setIDIssueBy(dto.getPlaceOfIssue().getCode());
        }

        CountryDTO citizenship = dto.getCitizenship();
        if (citizenship != null) {
            customerInfo.setNationality(citizenship.getIsoCode());
            idInfo.setCountry(citizenship.getCode());
            if (!"+84".equalsIgnoreCase(citizenship.getCode())) {
                idInfo.setIDIssueBy(getConfiguration("LOS_ID_ISSUE_BY_FOREIGNER", "Cuc quan ly xuat nhap canh"));
            }
        }

        customerInfo.getIDInfo().add(idInfo);

        if (!StringUtils.isEmpty(dto.getLicenseNumber())) {
            IDInfoType licenseNumberInfo = new IDInfoType();
            licenseNumberInfo.setIDType(getConfiguration("LOS_IDTYPE_BSL", "BSL"));
            licenseNumberInfo.setIDNo(dto.getLicenseNumber());
            customerInfo.getIDInfo().add(licenseNumberInfo);
        }

        ContactInfoType contactInfo = new ContactInfoType();
        PhoneInfoType phoneInfoMobile = new PhoneInfoType();
        phoneInfoMobile.setPhoneNo(getPhoneNumber(dto.getMobile()));
        phoneInfoMobile.setPhoneType(getConfiguration("LOS_PHONETYPE", "mobiphone"));
        contactInfo.getPhoneInfo().add(phoneInfoMobile);

        // TODO check with UI design (aLy)
        PhoneInfoType workPhone = new PhoneInfoType();
        workPhone.setPhoneNo(getPhoneNumber(dto.getMobile()));
        workPhone.setPhoneType(getConfiguration("LOS_WORKPHONETYPE", "workphone"));
        contactInfo.getPhoneInfo().add(workPhone);

        AddressDTO currentAddressDto = dto.getCurrentAddress();
        if (dto.isCurrentIsPermanent()) {
            currentAddressDto = dto.getPermanentAddress();
        }
        String totalMonthsLiving = getDurationFormat(dto.getMonthsOfLiving(), dto.getYearsOfLiving());
        LocalDateTime startLivingTime = LocalDateTime.now().minusMonths(Integer.parseInt(totalMonthsLiving));
        AddressInfoType currentAddress = getAddressInfoType(currentAddressDto);
        currentAddress.setStartDate(dateToXMLGregorianCalendar(startLivingTime));
        currentAddress.setDuration(totalMonthsLiving);
        currentAddress.setIsPermanent(
                dto.isCurrentIsPermanent() ? getConfiguration("LOS_YES", "Y") : getConfiguration("LOS_NO", "N"));
        contactInfo.setAddressInfo(currentAddress);

        contactInfo.setMailAddress(dto.getEmail());
        AddressInfoType permanentAddress = getAddressInfoType(dto.getPermanentAddress());
        permanentAddress.setStartDate(dateToXMLGregorianCalendar(startLivingTime));
        permanentAddress.setDuration(totalMonthsLiving);
        permanentAddress.setIsPermanent(dto.isCurrentIsPermanent() ? "Y" : "N");
        contactInfo.setPermanentAddressInfo(permanentAddress);

        customerInfo.setContactInfo(contactInfo);

        switch (dto.getGender()) {
        case Male:
            customerInfo.setGender(getConfiguration("LOS_MALE", "M"));
            break;
        case Female:
            customerInfo.setGender(getConfiguration("LOS_FEMALE", "F"));
            break;
        }

        customerInfo.setBirthday(dateToXMLGregorianCalendar(dto.getDob()));

        SelectionListDTO education = dto.getEducation();
        if (education != null) {
            customerInfo.setEducation(education.getCode());
        }

        SelectionListDTO maritalStatus = dto.getMaritalStatus();
        if (maritalStatus != null) {
            customerInfo.setMaritalStatus(maritalStatus.getCode());
        }

        if (dto.getNumberOfChildren() != null) {
            customerInfo.setNumberOfChildren(dto.getNumberOfChildren().toString());
        }
        customerInfo.setSector(getConfiguration("LOS_SECTOR", "1001"));
        customerInfo.setSegments(getConfiguration("LOS_KHCN", "SEG1"));
        // pass FT because risk from los
        customerInfo.setEmploymentStatus(getConfiguration("LOS_FT", "FT"));
        // customerInfo.setEmploymentStatus(dto.getTypeOfEmployement().equals(TypeOfEmployement.Business)
        // ? "BO" : "FT");

        FrequencyInfoType incomeFrequency = new FrequencyInfoType();
        incomeFrequency.setType(getConfiguration("LOS_IC", "INC2"));
        incomeFrequency.setFrequency(getConfiguration("LOS_FREQUENCY", "M"));
        AmountType amountType = new AmountType();
        BigDecimal monthlyIncome = dto.getMonthlyIncome();
        if (monthlyIncome != null) {
            amountType.setAmount(monthlyIncome.toString());
        }
        amountType.setCurrency(getConfiguration("LOS_VND", "VND"));
        incomeFrequency.setAmount(amountType);
        incomeFrequency.setMonthlyAmount(amountType);
        incomeFrequency.setTotalMonthlyAmount(amountType);
        customerInfo.setIncomeFrequency(incomeFrequency);

        FrequencyInfoType expenseFrequency = new FrequencyInfoType();
        expenseFrequency.setType(getConfiguration("LOS_FREQUENCY_TYPE", "EXP1"));
        expenseFrequency.setFrequency(getConfiguration("LOS_FREQUENCY", "M"));
        AmountType exAmountType = new AmountType();
        exAmountType.setAmount(dto.getMonthlyExpenses() + "");
        exAmountType.setCurrency(getConfiguration("LOS_VND", "VND"));
        expenseFrequency.setAmount(exAmountType);
        expenseFrequency.setMonthlyAmount(exAmountType);
        expenseFrequency.setTotalMonthlyAmount(exAmountType);
        customerInfo.setExpenseFrequency(expenseFrequency);
        FrequencyInfoType netFrequency = new FrequencyInfoType();
        AmountType netAmountType = new AmountType();
        if (monthlyIncome != null) {
            netAmountType.setAmount(monthlyIncome.subtract(
                    dto.getMonthlyExpenses() != null ? dto.getMonthlyExpenses() : BigDecimal.valueOf(0L)) + "");
        }
        netFrequency.setAmount(netAmountType);
        netFrequency.setMonthlyAmount(netAmountType);
        netFrequency.setTotalMonthlyAmount(netAmountType);
        customerInfo.setNetFrequency(netFrequency);

        customerInfo.setGreenCard(String.valueOf(convertBooleanToString(dto.isHaveGreenCard())));
        customerInfo.setTinNumber(StringUtils.isEmpty(dto.getTinNumber()) ? "0" : dto.getTinNumber());
        customerInfo.setGLPNumber(dto.getGlpNumber());
        return customerInfo;
    }

    private String getDurationFormat(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return StringUtils.EMPTY;
        }
        return String.valueOf(ChronoUnit.MONTHS.between(localDateTime, LocalDateTime.now()));
    }

    private String getDurationFormat(Integer months, Integer years) {
        if (months == null) {
            months = 0;
        }
        if (years == null) {
            years = 0;
        }
        return String.valueOf(months + years * 12);
    }

    private String convertBooleanToString(boolean value) {
        return value ? "YES" : "NO";
    }

    private EmployeeInfoType getEmploymentInfo(CreditCardApplicationDTO dto) {
        EmployeeInfoType employeeInfoType = new EmployeeInfoType();
        employeeInfoType.setEmploymentType(dto.getTypeOfEmployement().toString());
        // los: occupation, ccapp: industry
        employeeInfoType.setOccupation(dto.getIndustry() != null ? dto.getIndustry().getCode() : "OCP8");
        // los: position,ccapp: occupation
        SelectionListDTO occupation = dto.getOccupation();
        if (occupation != null) {
            employeeInfoType.setPosition(occupation.getCode());
            employeeInfoType.setJobTitle(occupation.getCode());
        }

        ContractInfoType contractInfoType = new ContractInfoType();
        contractInfoType.setContractType(getConfiguration("LOS_CONTRACT_TYPE", "CON14"));
        employeeInfoType.setContractInfo(contractInfoType);

        if (dto.getTypeOfEmployement().equals(TypeOfEmployment.Business)) {
            employeeInfoType.setStartDate(dateToXMLGregorianCalendar(dto.getBusinessStartDate()));
            employeeInfoType.setDuration(getDurationFormat(dto.getBusinessStartDate()));
            employeeInfoType.setPosition(getConfiguration("LOS_POSITION_BO_DEFAULT", "POSH36"));
        } else {
            int year = dto.getYearsOfWorking() != null ? dto.getYearsOfWorking() : 0;
            int month = dto.getMonthsOfWorking() != null ? dto.getMonthsOfWorking() : 0;

            int totalMonth = year * 12 + month;
            employeeInfoType.setDuration(String.valueOf(totalMonth));

            employeeInfoType.setStartDate(dateToXMLGregorianCalendar(LocalDateTime.now().minusMonths(totalMonth)));
        }

        employeeInfoType.setOrganizationInfo(getOrganizationInfoType(dto));
        return employeeInfoType;
    }

    private OrganizationInfoType getOrganizationInfoType(CreditCardApplicationDTO dto) {
        OrganizationInfoType organizationInfoType = new OrganizationInfoType();
        organizationInfoType.setIndustry(getConfiguration("LOS_DEFAULT_INDUSTRY", "300703"));
        organizationInfoType.setOrganizationCategory(getConfiguration("LOS_ORGANIZATION_CATEGORY", "NC"));
        organizationInfoType.setOrganizationType(getConfiguration("LOS_ORGANIZATION_TYPE", "TC3"));
        // ContactInfoType
        // 1. ContactInfoType - phone InfoType
        ContactInfoType contactInfoType = new ContactInfoType();
        PhoneInfoType phoneInfoType = new PhoneInfoType();
        if (dto.getTypeOfEmployement() == TypeOfEmployment.Business) {
            phoneInfoType.setPhoneNo(getPhoneNumber(dto.getBusinessPhone()));
        }
        String ext = "0";
        if (dto.getTypeOfEmployement() == TypeOfEmployment.Employed) {
            PhoneDTO businessTelephone = dto.getBusinessTelephone();
            if (businessTelephone != null) {
                phoneInfoType.setPhoneNo(getPhoneNumber(businessTelephone));
                if (!StringUtils.isEmpty(businessTelephone.getExt())) {
                    ext = businessTelephone.getExt();
                }
            }
        }
        phoneInfoType.setPhoneType(getConfiguration("LOS_LANDLINE", "landline"));
        contactInfoType.getPhoneInfo().add(phoneInfoType);
        // 2. ContactInfoType -internal phone InfoType
        PhoneInfoType internalPhoneType = new PhoneInfoType();
        internalPhoneType.setPhoneNo(ext);
        internalPhoneType.setPhoneType(getConfiguration("LOS_INTERNAL_PHONE", "internalphone"));
        contactInfoType.getPhoneInfo().add(internalPhoneType);
        // 3. ContactInfoType - address InfoType
        AddressInfoType addressInfoType = new AddressInfoType();
        AddressDTO businessAddress = dto.getTypeOfEmployement() == TypeOfEmployment.Business
                ? dto.getBusinessAddress()
                : dto.getEmployerAddress();
        if (businessAddress != null) {
            addressInfoType.setCountry(getConfiguration("LOS_VN", "VN"));
            addressInfoType.getAddress()
                    .add(businessAddress.getAddressDetails() + " " + businessAddress.getStreet());
            if (businessAddress.getProvince() != null) {
                addressInfoType.setCity(businessAddress.getProvince().getCode());
            }
            if (businessAddress.getDistrict() != null) {
                addressInfoType.setDistrict(businessAddress.getDistrict().getCode());
            }
        }
        contactInfoType.setAddressInfo(addressInfoType);
        organizationInfoType.setContactInfo(contactInfoType);
        // Company Code & Company Name
        if (dto.getTypeOfEmployement().equals(TypeOfEmployment.Business)) {
            organizationInfoType.setOrganizationName(getConfiguration("LOS_COMPANY_CODE_DEFAULT", "OTHER"));
            organizationInfoType.setOrganizationLegalName(dto.getCompanyName());
        } else {
            if (dto.getNameOfEmployer() != null) {
                organizationInfoType.setOrganizationName(dto.getNameOfEmployer().getCode());
            }
            organizationInfoType.setOrganizationLegalName(dto.getOtherCompanyName());
        }

        return organizationInfoType;
    }

    private CardInfoType getCardInfoType(CreditCardApplicationDTO dto) {
        CardInfoType cardInfoType = new CardInfoType();

        cardInfoType.setCardClassification(getConfiguration("LOS_PRINCIPAL", "PRINCIPAL"));

        String middleName = StringUtils.EMPTY;
        if (!StringUtils.isEmpty(dto.getMiddleName())) {
            middleName = " " + dto.getMiddleName();
        }
        cardInfoType.setCardHolderName(dto.getLastName() + middleName + " " + dto.getFirstName());

        // type of customer
        cardInfoType.setCardType(getConfiguration("LOS_CARD_INFO_PCARD", "PCARD"));

        BaseCreditCardDTO selectedCardDto = dto.getSelectedCard();

        ProductInfoType productInfoType = new ProductInfoType();
        productInfoType.setProductGroup(getConfiguration("LOS_PRODUCT_GROUP", "ca14f3f04c354dbe931ee820600b6283"));

        com.vpbank.entity.vn.common.account._1.AmountType amountType = new com.vpbank.entity.vn.common.account._1.AmountType();
        amountType.setCurrency(getConfiguration("LOS_VND", "VND"));

        if (selectedCardDto != null) {
            CreditCardDTO card = creditCardService.getById(selectedCardDto.getId());
            cardInfoType.setType(card.getCode());
            cardInfoType.setCardTypeName(card.getName());
            cardInfoType.setInterestRate(card.getInterest() + "");
            amountType.setAmount(card.getCreditLimit());
            productInfoType.setProductCode(card.getCode());
        }

        if (dto.getSecurityQuestion() != null) {
            cardInfoType.setSecQuestion(dto.getSecurityQuestion().getCode());
        }
        cardInfoType.setAnsSecQues(dto.getSecurityAnswer());
        cardInfoType.setProductInfo(productInfoType);

        amountType.setAmount(dto.getCreditLimit() + "");
        amountType.setCurrency(getConfiguration("LOS_VND", "VND"));
        cardInfoType.setCardLimit(amountType);

        return cardInfoType;
    }

    private String getPhoneNumber(PhoneDTO phone) {
        return phone != null ? phone.getPhoneNumber() : StringUtils.EMPTY;
    }

    private String getFullName(CreditCardApplicationDTO dto) {
        String middleName = StringUtils.EMPTY;
        if (!StringUtils.isEmpty(dto.getMiddleName())) {
            middleName = " " + dto.getMiddleName();
        }
        //return dto.getFirstName() + middleName + " " + dto.getLastName();
        return dto.getLastName() + middleName + " " + dto.getFirstName();
    }

    private DeliveryInfoType getDeliveryInfoType(CreditCardApplicationDTO dto) {
        DeliveryInfoType deliveryInfoType = new DeliveryInfoType();
        String deliveryCode = StringUtils.EMPTY;
        if (dto.getDeliveryCard() != null) {
            deliveryCode = dto.getDeliveryCard().getCode();
            deliveryInfoType.setDeliveryMethod(deliveryCode);
        }

        BranchDTO branchAddress = dto.getBranchAddress();

        if (branchAddress != null) {
            BranchInfoType branchInfoType = new BranchInfoType();
            branchInfoType.setBranchName(branchAddress.getName());
            branchInfoType.setBranchNo(branchAddress.getCode());
            branchInfoType.setCode(branchAddress.getCode());
            if (branchAddress.getProvince() != null) {
                branchInfoType.setCityName(branchAddress.getProvince().getName());
            }
            deliveryInfoType.setDeliveryBranch(branchInfoType);
        } else {
            AddressInfoType addressInfoType = new AddressInfoType();
            if (deliveryCode.equalsIgnoreCase(getConfiguration("CCAPP_COADDR", "COADDR"))) {
                addressInfoType = getAddressInfoType(dto.getBusinessAddress());
            } else {
                addressInfoType = getAddressInfoType(dto.getMailingAddress());
            }

            deliveryInfoType.setDeliveryAddress(addressInfoType);
        }
        return deliveryInfoType;
    }

    private AddressInfoType getAddressInfoType(AddressDTO address) {
        AddressInfoType addressInfo = new AddressInfoType();
        addressInfo.setCountry(getConfiguration("LOS_VN", "VN"));
        if (address != null) {
            addressInfo.getAddress().add(address.getAddressDetails() + " " + address.getStreet());
            if (address.getProvince() != null) {
                addressInfo.setCity(address.getProvince().getCode());
            }
            // addressInfo.setStreet(address.getStreet());
            if (address.getDistrict() != null) {
                addressInfo.setDistrict(address.getDistrict().getCode());
            }
        }

        return addressInfo;
    }

    private XMLGregorianCalendar dateToXMLGregorianCalendar(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        return dateToXMLGregorianCalendar(date);
    }

    private XMLGregorianCalendar dateToXMLGregorianCalendar(Date date) {
        if (date == null) {
            return null;
        }
        try {
            GregorianCalendar gregory = new GregorianCalendar();
            gregory.setTime(date);
            return DatatypeFactory.newInstance()
                    .newXMLGregorianCalendarDate(gregory.get(Calendar.YEAR), gregory.get(Calendar.MONTH) + 1,
                            gregory.get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED)
                    .normalize();

        } catch (DatatypeConfigurationException e) {
            logger.error(Utils.getErrorFormatLog("LOSService", "dateToXMLGregorianCalendar", "",
                    "Can not convert from LocalDateTime to XMLGregorianCalenda", e.toString()));

        }
        return null;
    }

    protected HeaderType getHeaderOfRequest(String messageId) {
        HeaderType headerType = new HeaderType();
        headerType.setCommon(getCommonType(messageId));
        headerType.setClient(getClientType());
        return headerType;
    }

    private CommonType getCommonType(String messageId) {
        CommonType commonType = new CommonType();
        commonType.setServiceVersion(getConfiguration("LOS_SERVICE_VERSION", "1"));
        commonType.setMessageId(messageId);
        commonType.setTransactionId(java.util.UUID.randomUUID().toString());

        try {
            GregorianCalendar gregory = new GregorianCalendar();
            gregory.setTime(new Date());
            XMLGregorianCalendar dealCloseDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregory);
            commonType.setMessageTimestamp(dealCloseDate);
        } catch (DatatypeConfigurationException e) {
            logger.error(Utils.getErrorFormatLog("LOSService", "getCommonType", "", e.toString()));
        }

        return commonType;
    }

    private ClientType getClientType() {
        ClientType clientType = new ClientType();
        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(losConfig.getUserName());

        MessageDigest digester = null;
        try {
            digester = MessageDigest.getInstance("MD5");
            digester.update(losConfig.getPassword().getBytes());
        } catch (NoSuchAlgorithmException e) {
            logger.error(Utils.getErrorFormatLog("LOSService", "getClientType", "", e.toString()));
        }

        userDetail.setUserPassword(digester.digest());

        clientType.setUserDetail(userDetail);
        clientType.setSourceAppID(getConfiguration("LOS_SOURCE_ID", "CCApp"));

        TargetAppIDs targetAppIDs = new TargetAppIDs();
        targetAppIDs.getTargetAppID().add(getConfiguration("LOS_TARGET_ID", "ESB"));
        clientType.setTargetAppIDs(targetAppIDs);
        return clientType;
    }
}