edu.byu.softwareDist.manager.impl.PurchaseManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for edu.byu.softwareDist.manager.impl.PurchaseManagerImpl.java

Source

package edu.byu.softwareDist.manager.impl;

import edu.byu.ccp.client.CcpClient;
import edu.byu.ccp.domain.TransactionRecord;
import edu.byu.ccp.domain.TransactionRecordList;
import edu.byu.ccp.objects.CreateCheckoutURL;
import edu.byu.ccp.provider.objects.CheckoutURL;
import edu.byu.ccp.provider.objects.Items;
import edu.byu.chartblock.AccountCodeValidation;
import edu.byu.chartblock.ValidateChartBlockResult;
import edu.byu.security.userdetails.IdentityDetails;
import edu.byu.softwareDist.ces.GroupRepo;
import edu.byu.softwareDist.dao.*;
import edu.byu.softwareDist.domain.*;
import edu.byu.softwareDist.helper.PersonInfo;
import edu.byu.softwareDist.manager.*;
import edu.byu.spring.ByuAppStage;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;

import static java.math.BigDecimal.ZERO;

@Service("purchaseManager")
public class PurchaseManagerImpl implements PurchaseManager {

    private static final Logger LOG = Logger.getLogger(PurchaseManagerImpl.class);

    @Autowired
    @Qualifier("purchaseDao")
    private PurchaseDao purchaseDao;

    @Autowired
    @Qualifier("productDao")
    private ProductDao productDao;

    @Autowired
    @Qualifier("purchaseLineItemDao")
    private PurchaseLineItemDao purchaseLineItemDao;

    @Autowired
    @Qualifier("maintenanceLineItemDao")
    private MaintenanceLineItemDAO maintenanceLineItemDAO;

    @Autowired
    @Qualifier("groupRepo")
    private GroupRepo groManager;

    @Autowired
    @Qualifier("licenseManager")
    private LicenseManager licenseManager;

    @Autowired
    @Qualifier("fileSetDao")
    private FileSetDao fileSetDao;

    @Autowired
    @Qualifier("lineItemDao")
    private LineItemDao lineItemDao;

    @Autowired
    @Qualifier("sendEmail")
    private SendEmail emailSender;

    @Autowired
    @Qualifier("pendingPurchaseDao")
    private PendingPurchaseDao pendingPurchaseDao;

    @Autowired
    @Qualifier("pendingLineItemDao")
    private PendingLineItemDao pendingLineItemDao;

    @Autowired
    @Qualifier("pendingPurchaseKeyDao")
    private PendingPurchaseKeyDao pendingPurchaseKeyDao;

    @Autowired
    private SoaManager soaMgr;

    @Autowired
    @Qualifier("purchaseKeyDao")
    private PurchaseKeyDao purchaseKeyDao;

    @Autowired
    @Qualifier("licenseDao")
    private LicenseDao licenseDao;

    @Autowired
    @Qualifier("client")
    private CcpClient ccpClient;

    @Autowired
    @Qualifier("appStage")
    private ByuAppStage appStage;

    @Autowired
    @Qualifier("Executor")
    protected ThreadPoolTaskExecutor executor;

    @Autowired
    @Qualifier("licenseCountChecker")
    protected LicenseCountChecker licenseCountChecker;

    @Autowired
    @Qualifier("accountCodeValidationClient")
    protected AccountCodeValidation accountcodeValidation;

    private final String BYU_ACCOUNT = "BYU_ACCOUNT";
    private final String CASHNET = "CASHNET";
    private final Integer systemUserId = 1;

    @PostConstruct
    public void afterPropertiesSet() {
        executor.submit(licenseCountChecker);
    }

    private List<AcquireLicenses> doAcquireLicenses(List<LineItem> lineItems) {
        List<AcquireLicenses> acquireLicenses = new LinkedList<AcquireLicenses>();
        for (final LineItem lineItem : lineItems) {
            List<License> licenses;
            if (lineItem instanceof PurchaseLineItem) {
                final PurchaseLineItem pli = (PurchaseLineItem) lineItem;
                licenses = licenseManager.assignLicenses(pli.getProduct(), pli.getQty());
            } else {
                licenses = Collections.emptyList();
            }
            acquireLicenses.add(new AcquireLicenses(licenses, lineItem));
        }
        return acquireLicenses;
    }

    private PersonInfo loadPersonInfo() {
        IdentityDetails identityDetails = IdentityDetails.getCurrentIdentityDetails();
        return new PersonInfo(identityDetails.getPersonId(), identityDetails.getNetId(), identityDetails.getByuId(),
                identityDetails.getEmailAddress(), identityDetails.getName());
    }

    private Boolean isAdmin() {
        return groManager.isMember(IdentityDetails.getCurrentIdentityDetails().getPersonId(), "SDFA");
    }

    @Override
    public AccountInformation checkAccountCode(final AccountCode accountCode) {
        return checkAccountCode(accountCode, isAdmin());
    }

    private AccountInformation checkAccountCode(final AccountCode accountCode, final Boolean isAdmin) {
        LOG.debug("validating account code: " + accountCode);
        Assert.notNull(accountCode);
        if (!accountCode.isValid()) {
            throw new InvalidAccountCodeException(accountCode);
        }

        if (accountCode.isTestAccountCode() && isAdmin && !appStage.isInProd()) {
            final AccountInformation accountInformation = new AccountInformation();
            accountInformation.setAccountCode(accountCode);
            accountInformation.setDepartmentId("TEST");
            accountInformation.setDepartmentName("CSR TEST");
            final AccountContact accountContact = new AccountContact();
            accountContact.setName("CSR TEST");
            accountContact.setNetId("CSR TEST");
            accountInformation.setManager(accountContact);
            accountInformation.setContact(accountContact);
            return accountInformation;
        } else {
            final ValidateChartBlockResult account = accountcodeValidation.getAccount(accountCode.getAccountCode());
            if (account.isSuccessful()) {
                final Map<String, String> map = account.getFields();
                final AccountInformation accountInformation = new AccountInformation();
                final AccountContact contact = new AccountContact();
                final AccountContact manager = new AccountContact();
                accountInformation.setAccountCode(accountCode);
                accountInformation.setDepartmentId(map.get("DEPARTMENT_ID"));
                accountInformation.setDepartmentName(map.get("DEPARTMENT_NAME"));
                contact.setName(map.get("CONTACT_NAME"));
                contact.setNetId(map.get("CONTACT_NETID"));
                contact.setEmailAddress(map.get("DEPARTMENT_CONTACT_EMAIL"));
                manager.setName(map.get("MANAGER_NAME"));
                manager.setNetId(map.get("MANAGER_NETID"));
                manager.setEmailAddress(map.get("MANAGER_EMAIL"));
                //Think we need to create another AccountContact to properly give back the data but is the web using it?
                accountInformation.setContact(contact);
                accountInformation.setManager(manager);
                return accountInformation;
            } else {
                throw new InvalidAccountCodeException(accountCode);
            }
        }
    }

    @Override
    public List<AccountCode> getUsedAccountCodes(final String personId) {
        return purchaseDao.findAllAccountCodes(personId);
    }

    @Override
    public boolean refund(final LineItem lineItem) {
        Boolean cashNet = false;
        Boolean costMoney = lineItem.getTotalCost().compareTo(ZERO) != 0;
        Assert.notNull(lineItem.getPurchase(), "lineItem [" + lineItem.getClass().getSimpleName() + "] with id ["
                + lineItem.getLineItemId() + "] does not have a purchase");
        Purchase purchase = purchaseDao.findById(lineItem.getPurchase().getPurchaseId());
        if (costMoney) {
            if (lineItem.getOrderId() != null) {
                LOG.info("purchase[" + purchase.getPurchaseId() + "] acct code: " + purchase.getAccountCode());
                Assert.notNull(purchase.getAccountCode(), "purchase [" + purchase.getPurchaseId()
                        + "] does not have an account code, but requires one");
                checkAccountCode(purchase.getAccountCode(), isAdmin());
            }
        }
        PurchaseLineItem pli = new PurchaseLineItem();
        if (lineItem instanceof PurchaseLineItem) {
            licenseManager.returnLicenses((PurchaseLineItem) lineItem);
            pli = (PurchaseLineItem) lineItem;
        }
        LineItem returnedLineItem = lineItem.returnItem();
        lineItemDao.update(lineItem);
        if (costMoney) {
            if (returnedLineItem.getCashNetId() == null) {
                final PersonInfo personInfo = loadPersonInfo();
                soaMgr.submitOITRefundOrder(returnedLineItem, personInfo, purchase);
                lineItemDao.save(returnedLineItem);
                return false;
            } else {
                cashNet = true;
                if (lineItem instanceof PurchaseLineItem) {
                    emailSender.sendEmail(pli);
                }
            }
        }
        lineItemDao.save(returnedLineItem);
        LOG.info("purchase[" + purchase.getPurchaseId() + "] acct code: " + purchase.getAccountCode());
        return cashNet;
    }

    @Override
    public void checkForPayingPurchase(final String personId) {
        final List<PendingPurchase> pendingPurchases = pendingPurchaseDao.findByOwnerId(personId);
        if (pendingPurchases.size() < 0) {
            return;
        }
        LOG.info(personId + " has Pending Purchases");
        for (final PendingPurchase pendingPurchase : pendingPurchases) {
            final List<PendingLineItem> pendingLineItems = pendingLineItemDao
                    .findByPendingPurchaseId(pendingPurchase.getPendingPurchaseId());
            for (final PendingLineItem pendingLineItem : pendingLineItems) {
                if (pendingLineItem.getPaymentType().equals(BYU_ACCOUNT)) {
                    continue;
                }
                if (pendingLineItem.getPaymentType().equals(CASHNET)) {
                    //Checks for credit card purchase
                    if (!checkForCreditCard(pendingLineItem))
                        continue;
                }
                pendingPurchaseToPurchase(pendingPurchase, pendingLineItem);
            }
        }
    }

    private void pendingPurchaseToPurchase(final PendingPurchase pendingPurchase,
            final PendingLineItem pendingLineItem) {
        Purchase purchase = new Purchase();
        final List<TransactionRecord> transactionRecords = ccpClient.getTransactionRecordSearch(systemUserId, null,
                null, null, pendingLineItem.getPendingPurchaseId().toString(), null, null, null)
                .getTransactionRecord();
        for (final TransactionRecord tr : transactionRecords) {
            if (pendingLineItem.getUnitCost().equals(tr.getAmount()) && tr.getSuccess()) {
                pendingPurchase.setCashNetId(tr.getTransactionRecordId().toString());
                break;
            }
        }
        if (pendingPurchase.getPurchaseId() == null) {
            PersonInfo personInfo = new PersonInfo();
            personInfo.setPersonId(pendingPurchase.getOwnerId());
            purchase = createPurchase(purchase, personInfo, null);
            LOG.debug("Created Purchase");
            pendingPurchase.setPurchaseId(purchase.getPurchaseId());
        } else {
            purchase = purchaseDao.findById(pendingPurchase.getPurchaseId());
            LOG.debug("Found purchase");
        }
        final Integer purchaseLineItem = updatePurchase(purchase, pendingLineItem);
        if (pendingLineItem.getPeriodId() == null || pendingLineItem.getPeriodId() == 0) {
            sendEmailIfNeeded(purchaseLineItemDao.findById(purchaseLineItem));
        }
        LOG.debug("Updating purchase");
        final Integer pendingLineItemId = pendingLineItem.getPendingLineItemId();
        pendingLineItemDao.delete(pendingLineItem);
        setPurchaseKeyFromPendingPurchaseKey(purchaseLineItem, pendingLineItemId);
        deletePendingPurchase(pendingPurchase);
    }

    private void setPurchaseKeyFromPendingPurchaseKey(Integer purchaseLineItem, Integer pendingLineItemId) {
        final List<PendingPurchaseKey> pendingPurchaseKeys = pendingPurchaseKeyDao
                .findByPurchaseLineItemId(pendingLineItemId);
        for (final PendingPurchaseKey pendingPurchaseKey : pendingPurchaseKeys) {
            PurchaseKey purchaseKey = new PurchaseKey();
            purchaseKey.setCount(pendingPurchaseKey.getQty());
            purchaseKey.setLicense(licenseDao.findById(pendingPurchaseKey.getLicense()));
            purchaseKey.setLicenseKey(pendingPurchaseKey.getLicenseKey());
            purchaseKey.setPurchaseLineItemId(purchaseLineItem);
            purchaseKeyDao.save(purchaseKey);
            pendingPurchaseKeyDao.delete(pendingPurchaseKey);
        }
    }

    private void deletePendingPurchase(final PendingPurchase pendingPurchase) {
        final List<PendingLineItem> pendingLineItemsList = pendingLineItemDao
                .findByPendingPurchaseId(pendingPurchase.getPendingPurchaseId());
        //This is to make sure we don't delete the pending purchase before all of the pending lines items are gone
        if (pendingLineItemsList.size() == 0) {
            pendingPurchaseDao.delete(pendingPurchase);
        }
    }

    private boolean checkForCreditCard(PendingLineItem pendingLineItem) {
        try {
            final TransactionRecordList transactionRecords = ccpClient.getTransactionRecordSearch(systemUserId,
                    null, null, null, pendingLineItem.getPendingPurchaseId().toString(), null, null, null);
            if (transactionRecords == null || transactionRecords.getTransactionRecord() == null) {
                return false;
            }
            for (final TransactionRecord tr : transactionRecords.getTransactionRecord()) {
                if (!tr.getSuccess()) {
                    continue;
                }
                if (tr.getUserTransactionId().equals(pendingLineItem.getPendingPurchaseId().toString())) {
                    return true;
                }
            }
            return false;
        } catch (IllegalStateException e) {
            return false;
        }
    }

    @Override
    public PurchaseHelper purchase(PurchaseHelper purchaseHelper) {
        Purchase purchase = new Purchase();
        boolean purchaseCreated = false;
        final PersonInfo personInfo = loadPersonInfo();
        if (purchaseHelper.getFreeItems().size() > 0) {
            LOG.debug("Purchasing free items size=" + purchaseHelper.getFreeItems().size());
            final List<AcquireLicenses> acquireLicensesList = doAcquireLicenses(purchaseHelper.getFreeItems());
            purchase = createPurchase(purchase, personInfo, null);
            purchaseCreated = true;
            purchaseHelper = updatePurchase(purchase, acquireLicensesList, personInfo);
            purchaseDao.update(purchaseHelper.getCheckOutResults().getPurchase());
        }
        if (purchaseHelper.getAccountCodeItems().size() > 0) {
            LOG.debug("Purchasing account code items, size=" + purchaseHelper.getAccountCodeItems().size());
            final List<AcquireLicenses> acquireLicensesList = doAcquireLicenses(
                    purchaseHelper.getAccountCodeItems());
            if (!purchaseCreated) {
                purchase = createPurchase(purchase, personInfo, purchaseHelper.getAccountCode());
                purchaseCreated = true;
            } else {
                purchase.setAccountCode(purchaseHelper.getAccountCode());
            }
            final List<AcquireLicenses> success = new LinkedList<AcquireLicenses>();
            for (final AcquireLicenses al : acquireLicensesList) {
                final LineItem lineItem = soaMgr.submitOITOrderRequest(al.getLineItem(),
                        purchaseHelper.getAccountCode(), personInfo);
                al.getLineItem().setOrderId(lineItem.getOrderId());
                success.add(al);
            }
            purchaseHelper = updatePurchase(purchase, success, personInfo);
            purchaseDao.update(purchaseHelper.getCheckOutResults().getPurchase());
        }
        if (purchaseHelper.getCreditCardItems().size() > 0) {
            LOG.debug("Purchasing credit card items, size=" + purchaseHelper.getCreditCardItems().size());
            final List<AcquireLicenses> acquireLicensesList = doAcquireLicenses(
                    purchaseHelper.getCreditCardItems());
            final PendingPurchase pendingPurchase = createPendingPurchase(purchase.getPurchaseId(),
                    personInfo.getPersonId());
            purchaseHelper.setPendingPurchase(pendingPurchase);
            BigDecimal totalAmount = BigDecimal.ZERO;
            final List<Items> itemTypes = new ArrayList<Items>();
            for (final AcquireLicenses al : acquireLicensesList) {
                final PendingLineItem pendingLineItem = createPendingLineItem(
                        purchaseHelper.getPendingPurchase().getPendingPurchaseId(), al.getLineItem(), CASHNET,
                        null);
                createPendingPurchaseKey(al.getLicenseList(), pendingLineItem.getPendingLineItemId(),
                        al.getLineItem().getQty());
                final BigDecimal quantity = new BigDecimal(al.getLineItem().getQty());
                final BigDecimal costLineItem = al.getLineItem().getTotalPrice().multiply(quantity);
                totalAmount = totalAmount.add(costLineItem);
                itemTypes.add(setItemType(totalAmount, al.getLineItem().getQty()));
            }
            final CheckoutURL checkoutURL = ccpClient.getCheckoutURL(
                    createCheckoutURL(personInfo, itemTypes, pendingPurchase.getPendingPurchaseId().toString()));
            purchaseHelper.setCreditCardUrl("redirect:" + checkoutURL.getCompleteURL());
        }
        purchaseHelper.setCheckOutResults(new CheckOutResults(purchase, null));
        try {
            final LicenseCountRunner runner = new LicenseCountRunner(purchaseHelper, licenseCountChecker);
            executor.submit(runner);
        } catch (final Throwable t) {
        }
        return purchaseHelper;
    }

    private CreateCheckoutURL createCheckoutURL(final PersonInfo personInfo, final List<Items> items,
            final String softwareDistTransactionNumber) {
        CreateCheckoutURL ccu = new CreateCheckoutURL();
        ccu.setByuId(personInfo.getByuId());
        ccu.setItemsList(items);
        ccu.setSellerTransactionId(softwareDistTransactionNumber);
        ccu.setSystemUserId(systemUserId);
        ccu.setProviderName("cashnet");
        return ccu;
    }

    private Items setItemType(final BigDecimal totalAmount, final int qty) {
        final Items itemType = new Items();
        itemType.setAmount(totalAmount);
        itemType.setQuantity(qty);
        itemType.setDescription("Software");
        return itemType;
    }

    private PendingPurchase createPendingPurchase(final Integer purchaseId, final String ownerId) {
        PendingPurchase pendingPurchase = new PendingPurchase();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR, 1);
        pendingPurchase.setExpireTime(calendar.getTime());
        pendingPurchase.setPurchaseId(purchaseId);
        pendingPurchase.setStatus("PENDING");
        pendingPurchase.setOwnerId(ownerId);
        return pendingPurchaseDao.save(pendingPurchase);
    }

    private PendingLineItem createPendingLineItem(final Integer pendingPurchaseId, LineItem lineItem,
            final String paymentType, final Integer orderId) {
        final PendingLineItem pendingLineItem = new PendingLineItem();
        pendingLineItem.setPendingPurchaseId(pendingPurchaseId);
        pendingLineItem.setNote(lineItem.getNote());
        pendingLineItem.setPaymentType(paymentType);
        pendingLineItem.setPeriodId(lineItem.getLineItemId());
        pendingLineItem.setProductId(lineItem.getLineItemId());
        pendingLineItem.setPurchasedFor(lineItem.getPurchasedFor());
        pendingLineItem.setQty(lineItem.getQty());
        pendingLineItem.setUnitCost(lineItem.getUnitCost());
        pendingLineItem.setUnitPrice(lineItem.getUnitPrice());
        pendingLineItem.setOrderId(orderId);
        if (lineItem instanceof PurchaseLineItem) {
            PurchaseLineItem pli = (PurchaseLineItem) lineItem;
            pendingLineItem.setProductId(pli.getProduct().getProductId());
        } else if (lineItem instanceof MaintenanceLineItem) {
            MaintenanceLineItem mli = (MaintenanceLineItem) lineItem;
            pendingLineItem.setPeriodId(mli.getPeriodId());
        } else {
            throw new IllegalStateException("Needs to be a maintenance or purchase line item");
        }
        return pendingLineItemDao.save(pendingLineItem);
    }

    private void createPendingPurchaseKey(final List<License> licenses, final Integer pendingLineItemId,
            final Integer qty) {
        for (final License license : licenses) {
            PendingPurchaseKey pendingPurchaseKey = new PendingPurchaseKey();
            pendingPurchaseKey.setLicense(license.getLicenseId());
            pendingPurchaseKey.setLicenseKey(license.getLicenseKey());
            pendingPurchaseKey.setQty(qty);
            pendingPurchaseKey.setPendingLineItemId(pendingLineItemId);
            LOG.info(license.getLicenseId() + ", " + license.getLicenseKey() + ", " + qty + ", "
                    + pendingLineItemId);
            pendingPurchaseKeyDao.save(pendingPurchaseKey);
        }
    }

    private Purchase createPurchase(final Purchase purchase, final PersonInfo personInfo,
            final AccountCode accountCode) {
        purchase.setLineItems(new HashSet<PurchaseLineItem>());
        purchase.setMainItems(new HashSet<MaintenanceLineItem>());
        purchase.setPurchaseDate(new Date());
        purchase.setPurchasedBy(personInfo.getPersonId());
        purchase.setAccountCode(accountCode);
        return purchaseDao.save(purchase);
    }

    private PurchaseHelper updatePurchase(final Purchase purchase, final List<AcquireLicenses> acquireLicensesList,
            final PersonInfo personInfo) {
        List<CheckOutResults.FailedReason> failedReason = new LinkedList<CheckOutResults.FailedReason>();
        PurchaseHelper purchaseHelper = new PurchaseHelper();
        for (final AcquireLicenses acquireLicenses : acquireLicensesList) {
            switch (acquireLicenses.getLineItem().getType()) {
            case PURCHASE_LINE_ITEM:
                savePurchaseLineItem(purchase, personInfo, failedReason, acquireLicenses);
                break;
            case MAINTENANCE_LINE_ITEM:
                saveMaintenanceLineItem(purchase, personInfo, failedReason, acquireLicenses);
                break;
            }
            LOG.debug(personInfo.getNetId() + " Generated Order " + acquireLicenses.getLineItem());
        }
        CheckOutResults checkOutResults = new CheckOutResults(purchase, failedReason);
        purchaseHelper.setCheckOutResults(checkOutResults);
        LOG.debug("purchase info: " + purchase.getLineItems().size() + " " + purchase.getMainItems() + " "
                + failedReason.size());
        boolean sendEmail = true;
        for (PurchaseLineItem pli : purchase.getLineItems()) {
            if (pli.getDisplayName().toLowerCase().endsWith("home use only")) {
                sendEmail = false;
            } else {
                sendEmail = true;
                break;
            }
        }
        if (sendEmail) {
            emailSender.sendEmail(purchase);
        }
        return purchaseHelper;
    }

    private void sendEmailIfNeeded(final PurchaseLineItem purchaseLineItem) {
        List<FileSet> fileSets = fileSetDao.findAllByProduct(purchaseLineItem.getProduct());
        for (final FileSet fileSet : fileSets) {
            if (fileSet.isEmailDefined()) {
                emailSender.sendEmail(purchaseLineItem, fileSet);
            }
        }
    }

    private Integer updatePurchase(final Purchase purchase, final PendingLineItem pendingLineItem) {
        final PersonInfo personInfo = loadPersonInfo();
        if (pendingLineItem.getPeriodId() == null || pendingLineItem.getPeriodId() == 0) {
            PurchaseLineItem purchaseLineItem = new PurchaseLineItem();
            purchaseLineItem.setCashNetId(pendingLineItem.getCashNetId());
            purchaseLineItem.setPurchase(purchase);
            purchaseLineItem.setProduct(productDao.findById(pendingLineItem.getProductId()));
            purchaseLineItem.setPurchasedFor(pendingLineItem.getPurchasedFor());
            purchaseLineItem.setNote(pendingLineItem.getNote());
            purchaseLineItem.setQty(pendingLineItem.getQty());
            purchaseLineItem.setUnitPrice(pendingLineItem.getUnitPrice());
            purchaseLineItem.setUnitCost(pendingLineItem.getUnitCost());
            purchaseLineItem.setOrderId(pendingLineItem.getOrderId());
            try {
                purchaseLineItem = purchaseLineItemDao.save(purchaseLineItem);
            } catch (Throwable t) {
                LOG.error(personInfo.getNetId() + " Unknown error", t);
                throw new IllegalStateException("Unknown error ");
            }
            sendEmailIfNeeded(purchaseLineItem);
            return purchaseLineItem.getPurchaseLineItemId();
        } else {
            MaintenanceLineItem maintenanceLineItem = new MaintenanceLineItem();
            maintenanceLineItem.setCashNetId(pendingLineItem.getCashNetId());
            maintenanceLineItem.setPurchase(purchase);
            maintenanceLineItem.setPeriodId(pendingLineItem.getPeriodId());
            maintenanceLineItem.setPurchasedFor(pendingLineItem.getPurchasedFor());
            maintenanceLineItem.setNote(pendingLineItem.getNote());
            maintenanceLineItem.setQty(pendingLineItem.getQty());
            maintenanceLineItem.setUnitPrice(pendingLineItem.getUnitPrice());
            maintenanceLineItem.setUnitCost(pendingLineItem.getUnitCost());
            maintenanceLineItem.setOrderId(pendingLineItem.getOrderId());
            try {
                maintenanceLineItem = maintenanceLineItemDAO.save(maintenanceLineItem);
            } catch (Throwable t) {
                LOG.error(personInfo.getNetId() + " Unknown error", t);
                throw new IllegalStateException("Unknown error ");
            }
            return maintenanceLineItem.getMaintenanceLineItemId();
        }
    }

    private void saveMaintenanceLineItem(final Purchase purchase, final PersonInfo personInfo,
            final List<CheckOutResults.FailedReason> failedReason, final AcquireLicenses acquireLicenses) {
        try {
            final MaintenanceLineItem mli = (MaintenanceLineItem) acquireLicenses.getLineItem();
            maintenanceLineItemDAO.save(mli);
            purchase.getMainItems().add(mli);
        } catch (Throwable t) {
            LOG.error(personInfo.getNetId() + " Unknown error", t);
            failedReason.add(new CheckOutResults.FailedReason(acquireLicenses.getLineItem(), "Unknown error"));
            if (!acquireLicenses.getLicenseList().isEmpty()) {
                licenseManager.returnLicenses(acquireLicenses.getLicenseList());
            }
        }
    }

    private void savePurchaseLineItem(final Purchase purchase, final PersonInfo personInfo,
            final List<CheckOutResults.FailedReason> failedReason, final AcquireLicenses acquireLicenses) {
        PurchaseLineItem pli = (PurchaseLineItem) acquireLicenses.getLineItem();
        pli.setPurchase(purchase);
        boolean failed = false;
        try {
            purchaseLineItemDao.save(pli);
        } catch (Throwable t) {
            LOG.error(personInfo.getNetId() + " Unknown error", t);
            failed = true;
            failedReason.add(new CheckOutResults.FailedReason(pli, "Unknown error"));
            if (!acquireLicenses.getLicenseList().isEmpty()) {
                licenseManager.returnLicenses(acquireLicenses.getLicenseList());
            }
        }
        try {
            if (!failed) {
                licenseManager.associateLicenses(pli, acquireLicenses.getLicenseList());
                sendEmailIfNeeded(pli);
                purchase.getLineItems().add(pli);
            }
        } catch (Throwable t) {
            LOG.error(personInfo.getNetId() + " Unknown error", t);
            purchaseLineItemDao.delete(pli);
            failedReason.add(new CheckOutResults.FailedReason(pli, "Unknown error"));
            if (!acquireLicenses.getLicenseList().isEmpty()) {
                licenseManager.returnLicenses(acquireLicenses.getLicenseList());
            }
        }
    }

}