/**
* TNTConcept Easy Enterprise Management by Autentia Real Bussiness Solution S.L.
* Copyright (C) 2007 Autentia Real Bussiness Solution S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.autentia.tnt.manager.billing;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.autentia.tnt.businessobject.AccountEntry;
import com.autentia.tnt.businessobject.Activity;
import com.autentia.tnt.businessobject.Bill;
import com.autentia.tnt.businessobject.BillBreakDown;
import com.autentia.tnt.businessobject.BillPayment;
import com.autentia.tnt.businessobject.BillState;
import com.autentia.tnt.businessobject.BillType;
import com.autentia.tnt.businessobject.CreditTitle;
import com.autentia.tnt.businessobject.Offer;
import com.autentia.tnt.businessobject.OfferCost;
import com.autentia.tnt.businessobject.OfferRole;
import com.autentia.tnt.businessobject.Organization;
import com.autentia.tnt.businessobject.Project;
import com.autentia.tnt.businessobject.ProjectCost;
import com.autentia.tnt.businessobject.ProjectRole;
import com.autentia.tnt.businessobject.User;
import com.autentia.tnt.dao.SortCriteria;
import com.autentia.tnt.dao.hibernate.ActivityDAO;
import com.autentia.tnt.dao.hibernate.BillDAO;
import com.autentia.tnt.dao.hibernate.ProjectCostDAO;
import com.autentia.tnt.dao.hibernate.ProjectDAO;
import com.autentia.tnt.dao.hibernate.ProjectRoleDAO;
import com.autentia.tnt.dao.search.ActivitySearch;
import com.autentia.tnt.dao.search.BillSearch;
import com.autentia.tnt.dao.search.ProjectCostSearch;
import com.autentia.tnt.dao.search.ProjectRoleSearch;
import com.autentia.tnt.dao.search.ProjectSearch;
import com.autentia.tnt.util.IvaApplicator;
import com.autentia.tnt.util.SpringUtils;
public class BillManager {
public Bill convertFromOfferToBill (final Offer offer) {
final Bill bill = new Bill();
// simple values
bill.setContact(offer.getContact());
bill.setName(offer.getDescription());
bill.setState(BillState.EMITTED);
bill.setBillType(BillType.ISSUED);
// concepts
final Set<BillBreakDown> billBreakDowns = new LinkedHashSet<BillBreakDown>();
billBreakDowns.addAll(convertFromOfferCostsToBillBreakDowns(bill, offer.getCosts()));
billBreakDowns.addAll(convertFromOfferRolesToBillBreakDowns(bill, offer.getRoles()));
bill.setBreakDown(billBreakDowns);
return bill;
}
private Set<BillBreakDown> convertFromOfferCostsToBillBreakDowns (final Bill bill, final Set<OfferCost> offerCosts) {
final Set<BillBreakDown> billBreakDowns = new LinkedHashSet<BillBreakDown>();
if (offerCosts != null)
{
for (OfferCost cost: offerCosts) {
if (cost.isBillable()) {
BillBreakDown billBreakDown = new BillBreakDown();
billBreakDown.setConcept(cost.getName());
billBreakDown.setUnits(cost.getUnits());
billBreakDown.setAmount(cost.getCost());
billBreakDown.setIva(cost.getIva());
billBreakDown.setBill(bill);
billBreakDowns.add(billBreakDown);
}
}
}
return billBreakDowns;
}
private Set<BillBreakDown> convertFromOfferRolesToBillBreakDowns (final Bill bill, final Set<OfferRole> offerRoles) {
final Set<BillBreakDown> billBreakDowns = new LinkedHashSet<BillBreakDown>();
if (offerRoles != null) {
for (OfferRole role: offerRoles) {
BillBreakDown billBreakDown = new BillBreakDown();
billBreakDown.setConcept(role.getName());
billBreakDown.setUnits(new BigDecimal(role.getExpectedHours()));
billBreakDown.setAmount(role.getCostPerHour());
billBreakDown.setIva(role.getIva());
billBreakDown.setBill(bill);
billBreakDowns.add(billBreakDown);
}
}
return billBreakDowns;
}
public void insertBillInCreditTitle (final Bill bill, final CreditTitle creditTitle, boolean createBillPayment) {
// la factura cambia de estado a 'incluida en pagaré' [bugzilla:2620]
bill.setState(BillState.IN_CREDITTITLE);
// Al asociar un pagaré a una factura no debería ser obligatorio que aparezca un nuevo vencimiento en la factura [bugzilla:3016]
if (createBillPayment) {
// se crea un pago de dicha factura en la fecha y cantidades indicadas en el pagaré [bugzilla:2641]
final BillPayment payment = new BillPayment();
payment.setBill(bill);
payment.setAmount(creditTitle.getAmount().abs());
payment.setExpirationDate(creditTitle.getExpirationDate());
bill.getBillPayment().add(payment);
}
this.updateEntity(bill);
}
public List<BillBreakDown> getAllBitacoreBreakDowns(Date start, Date end, Project project) {
final List<BillBreakDown> desgloses = new ArrayList<BillBreakDown>();
ActivityDAO activityDAO = ActivityDAO.getDefault();
ActivitySearch actSearch = new ActivitySearch();
actSearch.setBillable(new Boolean(true));
actSearch.setStartStartDate(start);
actSearch.setEndStartDate(end);
List<Activity> actividadesTotal = new ArrayList<Activity>();
Hashtable user_roles = new Hashtable();
ProjectRoleDAO projectRoleDAO = ProjectRoleDAO.getDefault();
ProjectRoleSearch prjRolSearch = new ProjectRoleSearch();
prjRolSearch.setProject(project);
List<ProjectRole> roles = projectRoleDAO.search(prjRolSearch, new SortCriteria("id", false));
for (ProjectRole proyRole : roles) {
actSearch.setRole(proyRole);
List<Activity> actividades = activityDAO.search(actSearch,
new SortCriteria("startDate", false));
actividadesTotal.addAll(actividades);
}
for (Activity act : actividadesTotal) {
String key = act.getRole().getId().toString()
+ act.getUser().getId().toString();
if (!user_roles.containsKey(key)) {
Hashtable value = new Hashtable();
value.put("ROLE", act.getRole());
value.put("USER", act.getUser());
user_roles.put(key, value);
}
}
Enumeration en = user_roles.keys();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
Hashtable pair = (Hashtable) user_roles.get(key);
actSearch.setBillable(new Boolean(true));
actSearch.setStartStartDate(start);
actSearch.setEndStartDate(end);
ProjectRole pR = (ProjectRole) pair.get("ROLE");
User u = (User) pair.get("USER");
actSearch.setRole(pR);
actSearch.setUser(u);
List<Activity> actividadesUsuarioRol = activityDAO.search(
actSearch, new SortCriteria("startDate", false));
BillBreakDown brd = new BillBreakDown();
brd.setConcept("Imputaciones (usuario - rol): " + u.getName()
+ " - " + pR.getName());
brd.setAmount(pR.getCostPerHour());
IvaApplicator.applyIvaToTaxableObject(start, brd);
BigDecimal unitsTotal = new BigDecimal(0);
for (Activity act : actividadesUsuarioRol) {
BigDecimal unitsActual = new BigDecimal(act.getDuration());
unitsActual = unitsActual.divide(new BigDecimal(60), 2,
RoundingMode.HALF_UP);
unitsTotal = unitsTotal.add(unitsActual);
}
brd.setUnits(unitsTotal);
brd.setSelected(true);
desgloses.add(brd);
}
ProjectCostDAO prjCostDAO = ProjectCostDAO.getDefault();
ProjectCostSearch prjCostSearch = new ProjectCostSearch();
prjCostSearch.setProject(project);
List<ProjectCost> costes = prjCostDAO.search(prjCostSearch, new SortCriteria("id", false));
for (ProjectCost proyCost : costes) {
BillBreakDown brd = new BillBreakDown();
brd.setConcept("Coste: " + proyCost.getName());
brd.setUnits(new BigDecimal(1));
brd.setAmount(proyCost.getCost());
IvaApplicator.applyIvaToTaxableObject(start, brd);
brd.setSelected(true);
desgloses.add(brd);
}
return desgloses;
}
/**
* Get a list of bills between start and end dates
* @param search
* @param sort
* @param start
* @param end
* @return
*/
public List<Bill> getAllEntities(BillSearch search, SortCriteria sort, Date start, Date end){
List<Bill> res = billDAO.search( search, sort );
List<Bill> list = new ArrayList<Bill>();
Calendar calendar = Calendar.getInstance();
// Recorremos la lista de Bills
for ( Bill item : res ) {
if (item.getExpiration() != null) {
// Metemos en el calendar la fecha del item
calendar.setTime( item.getExpiration() );
// Si la fecha está dentro del rango de fechas seleccionado se añade a la lista con la fecha calculada del próximo pago
if ( (calendar.getTimeInMillis() >= start.getTime()) && (calendar.getTimeInMillis() <= end.getTime()) ) {
// Añadimos a la lista
list.add( item);
}
}
}
return list;
}
public void calculateBillIsPaid (final Bill bill) {
if (bill.getState() != BillState.PAID)
{
BigDecimal accountEntryTotal = new BigDecimal(0);
for (AccountEntry accountEntry: bill.getEntries()) {
accountEntryTotal = accountEntryTotal.add(accountEntry.getAmount());
}
if (accountEntryTotal.abs().compareTo(bill.getTotal()) >= 0) {
bill.setState(BillState.PAID);
updateEntity(bill);
}
}
}
/**
* Busca todos los proyectos de una organización
*
* @param client es la organización por la que vamos a consultar
* @return la lista de proyectos
*/
public List<Project> getProjectsByOrganization(Organization client) {
final ProjectSearch projectSearch = new ProjectSearch();
projectSearch.setClient(client);
return ProjectDAO.getDefault().search(projectSearch, new SortCriteria("name"));
}
/* Bill - generated by stajanov (do not edit/delete) */
/** Logger */
private static final Log log = LogFactory.getLog(BillManager.class);
/** Bill DAO **/
private BillDAO billDAO;
/**
* Get default BillManager as defined in Spring's configuration file.
* @return the default singleton BillManager
*/
public static BillManager getDefault()
{
return (BillManager)SpringUtils.getSpringBean("managerBill");
}
/**
* Empty constructor needed by CGLIB (Spring AOP)
*/
protected BillManager()
{
}
/**
* Default constructor
* @deprecated do not construct managers alone: use Spring's declared beans
*/
public BillManager( BillDAO billDAO )
{
this.billDAO = billDAO;
}
/**
* List bills.
* @param search search filter to apply
* @param sort sorting criteria
* @return the list of all bills sorted by requested criterion
*/
public List<Bill> getAllEntities(BillSearch search, SortCriteria sort){
return billDAO.search( search, sort );
}
/**
* Get bill by primary key.
* @return bill selected by id.
*/
public Bill getEntityById(int id){
return billDAO.getById(id);
}
/**
* Insert bill.
*/
public void insertEntity(Bill bill) {
billDAO.insert(bill);
}
/**
* Update bill.
*/
public void updateEntity(Bill bill) {
billDAO.update(bill);
}
/**
* Delete bill.
*/
public void deleteEntity(Bill bill) {
billDAO.delete(bill);
}
/* Bill - generated by stajanov (do not edit/delete) */
public List<Bill> getAllMinusCreditTitle(BillSearch search, SortCriteria criteria){
return billDAO.search( search, criteria );
}
}