/* * The contents of this file are subject to the OpenMRS Public License * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and * limitations under the License. * * Copyright (C) OpenHMIS. All Rights Reserved. */ package org.openmrs.module.openhmis.cashier.api.impl; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Criteria; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.openmrs.Patient; import org.openmrs.annotation.Authorized; import org.openmrs.api.context.Context; import org.openmrs.module.openhmis.cashier.api.IBillService; import org.openmrs.module.openhmis.cashier.api.IReceiptNumberGenerator; import org.openmrs.module.openhmis.cashier.api.ReceiptNumberGeneratorFactory; import org.openmrs.module.openhmis.cashier.api.model.Bill; import org.openmrs.module.openhmis.cashier.api.search.BillSearch; import org.openmrs.module.openhmis.cashier.api.util.PrivilegeConstants; import org.openmrs.module.openhmis.commons.api.PagingInfo; import org.openmrs.module.openhmis.commons.api.entity.impl.BaseEntityDataServiceImpl; import org.openmrs.module.openhmis.commons.api.entity.security.IEntityAuthorizationPrivileges; import org.openmrs.module.openhmis.commons.api.f.Action1; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.security.AccessControlException; import java.util.List; /** * Data service implementation class for {@link Bill}s. */ @Transactional public class BillServiceImpl extends BaseEntityDataServiceImpl<Bill> implements IEntityAuthorizationPrivileges , IBillService { private static final int MAX_LENGTH_RECEIPT_NUMBER = 255; private static final Log LOG = LogFactory.getLog(BillServiceImpl.class); @Override protected IEntityAuthorizationPrivileges getPrivileges() { return this; } @Override protected void validate(Bill bill) {} /** * Saves the bill to the database, creating a new bill or updating an existing one. * @param bill The bill to be saved. * @return The saved bill. * @should Generate a new receipt number if one has not been defined. * @should Not generate a receipt number if one has already been defined. * @should Throw APIException if receipt number cannot be generated. */ @Override @Authorized({ PrivilegeConstants.MANAGE_BILLS }) @Transactional public Bill save(Bill bill) { if (bill == null) { throw new NullPointerException("The bill must be defined."); } /* Check for refund. * A refund is given when the total of the bill's line items is negative. */ if (bill.getTotal().compareTo(BigDecimal.ZERO) < 0 && !Context.hasPrivilege(PrivilegeConstants.REFUND_MONEY)) { throw new AccessControlException("Access denied to give a refund."); } IReceiptNumberGenerator generator = ReceiptNumberGeneratorFactory.getGenerator(); if (generator == null) { LOG.warn("No receipt number generator has been defined. Bills will not be given a receipt number until one is" + " defined."); } else { if (StringUtils.isEmpty(bill.getReceiptNumber())) { bill.setReceiptNumber(generator.generateNumber(bill)); } } return super.save(bill); } @Override @Authorized({ PrivilegeConstants.VIEW_BILLS }) @Transactional(readOnly = true) public Bill getBillByReceiptNumber(String receiptNumber) { if (StringUtils.isEmpty(receiptNumber)) { throw new IllegalArgumentException("The receipt number must be defined."); } if (receiptNumber.length() > MAX_LENGTH_RECEIPT_NUMBER) { throw new IllegalArgumentException("The receipt number must be less than 256 characters."); } Criteria criteria = getRepository().createCriteria(getEntityClass()); criteria.add(Restrictions.eq("receiptNumber", receiptNumber)); Bill bill = getRepository().selectSingle(getEntityClass(), criteria); removeNullLineItems(bill); return bill; } @Override public List<Bill> getBillsByPatient(Patient patient, PagingInfo paging) { if (patient == null) { throw new NullPointerException("The patient must be defined."); } return getBillsByPatientId(patient.getId(), paging); } @Override public List<Bill> getBillsByPatientId(int patientId, PagingInfo paging) { if (patientId < 0) { throw new IllegalArgumentException("The patient id must be a valid identifier."); } Criteria criteria = getRepository().createCriteria(getEntityClass()); criteria.add(Restrictions.eq("patient.id", patientId)); criteria.addOrder(Order.desc("id")); List<Bill> results = getRepository().select(getEntityClass(), createPagingCriteria(paging, criteria)); removeNullLineItems(results); return results; } @Override public List<Bill> getBills(final BillSearch billSearch) { return getBills(billSearch, null); } @Override public List<Bill> getBills(final BillSearch billSearch, PagingInfo pagingInfo) { if (billSearch == null) { throw new NullPointerException("The bill search must be defined."); } else if (billSearch.getTemplate() == null) { throw new NullPointerException("The bill search template must be defined."); } return executeCriteria(Bill.class, pagingInfo, new Action1<Criteria>() { @Override public void apply(Criteria criteria) { billSearch.updateCriteria(criteria); } }); } /* These methods are overridden to ensure that any null line items (created as part of a bug in 1.7.0) are removed from the results before being returned to the caller. */ @Override public List<Bill> getAll(boolean includeVoided, PagingInfo pagingInfo) { List<Bill> results = super.getAll(includeVoided, pagingInfo); removeNullLineItems(results); return results; } @Override public Bill getById(int entityId) { Bill bill = super.getById(entityId); removeNullLineItems(bill); return bill; } @Override public Bill getByUuid(String uuid) { Bill bill = super.getByUuid(uuid); removeNullLineItems(bill); return bill; } @Override public List<Bill> getAll() { List<Bill> results = super.getAll(); removeNullLineItems(results); return results; } private void removeNullLineItems(List<Bill> bills) { if (bills == null || bills.size() == 0) { return; } for (Bill bill : bills) { removeNullLineItems(bill); } } private void removeNullLineItems(Bill bill) { if (bill == null) { return; } // Search for any null line items (due to a bug in 1.7.0) and remove them from the line items int index = bill.getLineItems().indexOf(null); while (index >= 0) { bill.getLineItems().remove(index); index = bill.getLineItems().indexOf(null); } } @Override public String getVoidPrivilege() { return PrivilegeConstants.MANAGE_BILLS; } @Override public String getSavePrivilege() { return PrivilegeConstants.MANAGE_BILLS; } @Override public String getPurgePrivilege() { return PrivilegeConstants.PURGE_BILLS; } @Override public String getGetPrivilege() { return PrivilegeConstants.VIEW_BILLS; } }