Java tutorial
/******************************************************************************* * HELIUM V, Open Source ERP software for sustained success * at small and medium-sized enterprises. * Copyright (C) 2004 - 2014 HELIUM V IT-Solutions GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of theLicense, or * (at your option) any later version. * * According to sec. 7 of the GNU Affero General Public License, version 3, * the terms of the AGPL are supplemented with the following terms: * * "HELIUM V" and "HELIUM 5" are registered trademarks of * HELIUM V IT-Solutions GmbH. The licensing of the program under the * AGPL does not imply a trademark license. Therefore any rights, title and * interest in our trademarks remain entirely with us. If you want to propagate * modified versions of the Program under the name "HELIUM V" or "HELIUM 5", * you may only do so if you have a written permission by HELIUM V IT-Solutions * GmbH (to acquire a permission please contact HELIUM V IT-Solutions * at trademark@heliumv.com). * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact: developers@heliumv.com ******************************************************************************/ package com.heliumv.api.worktime; import java.rmi.RemoteException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import javax.naming.NamingException; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.heliumv.api.BaseApi; import com.heliumv.api.item.ItemEntry; import com.heliumv.factory.IAuftragCall; import com.heliumv.factory.IAuftragpositionCall; import com.heliumv.factory.IFertigungCall; import com.heliumv.factory.IGlobalInfo; import com.heliumv.factory.IJudgeCall; import com.heliumv.factory.IMandantCall; import com.heliumv.factory.IParameterCall; import com.heliumv.factory.IPersonalCall; import com.heliumv.factory.IProjektCall; import com.heliumv.factory.IZeiterfassungCall; import com.heliumv.factory.query.ArtikelArbeitszeitQuery; import com.heliumv.factory.query.ZeitdatenQuery; import com.heliumv.tools.FilterKriteriumCollector; import com.heliumv.tools.StringHelper; import com.lp.server.auftrag.service.AuftragDto; import com.lp.server.auftrag.service.AuftragpositionDto; import com.lp.server.fertigung.service.FertigungFac; import com.lp.server.fertigung.service.LosDto; import com.lp.server.personal.service.PersonalDto; import com.lp.server.personal.service.TaetigkeitDto; import com.lp.server.personal.service.ZeitdatenDto; import com.lp.server.personal.service.ZeiterfassungFac; import com.lp.server.projekt.service.ProjektDto; import com.lp.server.system.service.LocaleFac; import com.lp.server.util.fastlanereader.service.query.FilterBlock; import com.lp.server.util.fastlanereader.service.query.QueryParameters; import com.lp.server.util.fastlanereader.service.query.QueryResult; import com.lp.util.EJBExceptionLP; /** * Funktionalität rund um die Zeit(daten)erfassung</br> * * Generell gilt, dass nur am HELIUM V angemeldete REST-API Benutzer diese Funktionen durchführen können. * Weiters werden die Rechte des Benutzers berücksichtigt. Er kann - wenn er darf - im Namen einer * anderen Person/Mitarbeiter die Buchungen durchführen. * * <p>Der Benutzer der API ist dafür verantwortlich, dass chronologisch richtige * Zeitbuchungen entstehen, da der HELIUM V Server zum gegebenen Zeitpunkt (noch) * nicht in Zukunft schauen kann.</p> * * <p>Weiterführende Dokumentation kann im * <a href="http://www.heliumv.com/documentation?token=Zeiterfassung">HELIUM V Benutzerhandbuch</a> nachgelesen werden. * * @author Gerold */ @Service("hvWorktime") @Path("/api/v1/worktime/") public class WorktimeApi extends BaseApi implements IWorktimeApi { @Autowired private IAuftragCall auftragCall; @Autowired private IAuftragpositionCall auftragpositionCall; @Autowired private IJudgeCall judgeCall; @Autowired private IFertigungCall fertigungCall; @Autowired private IMandantCall mandantCall; @Autowired private IProjektCall projektCall; @Autowired private IZeiterfassungCall zeiterfassungCall; @Autowired private IPersonalCall personalCall; @Autowired private ArtikelArbeitszeitQuery workItemQuery; @Autowired private IGlobalInfo globalInfo; @Autowired private ZeitdatenQuery zeitdatenQuery; @Autowired private IParameterCall parameterCall; @GET @Path("/{year}/{month}/{day}") @Produces({ FORMAT_JSON, FORMAT_XML }) @Override public List<ZeitdatenEntry> getWorktimeEntries(@QueryParam("userId") String userId, @PathParam("year") Integer year, @PathParam("month") Integer month, @PathParam("day") Integer day, @QueryParam("forStaffId") Integer forStaffId, @QueryParam("forStaffCnr") String forStaffCnr, @QueryParam("limit") Integer limit) { List<ZeitdatenEntry> entries = new ArrayList<ZeitdatenEntry>(); if (connectClient(userId) == null) return entries; Integer personalId = globalInfo.getTheClientDto().getIDPersonal(); try { ValidPersonalId validator = new ValidPersonalId(personalId, forStaffId, forStaffCnr); if (!validator.validate()) return entries; personalId = validator.getStaffIdToUse(); FilterKriteriumCollector collector = new FilterKriteriumCollector(); collector.add(zeitdatenQuery.getFilterForPersonalId(personalId)); collector.addAll(zeitdatenQuery.getFilterForDate(year, month, day)); FilterBlock filterCrits = new FilterBlock(collector.asArray(), "AND"); QueryParameters params = zeitdatenQuery.getDefaultQueryParameters(filterCrits); params.setLimit(limit); // params.setKeyOfSelectedRow(startIndex) ; QueryResult result = zeitdatenQuery.setQuery(params); entries = zeitdatenQuery.getResultList(result); } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnavailable(e); } return entries; } @DELETE @Path("/{worktimeId}") @Override public void removeWorktime(@QueryParam("userId") String userId, @PathParam("worktimeId") Integer worktimeId, @QueryParam("forStaffId") Integer forStaffId, @QueryParam("forStaffCnr") String forStaffCnr) { if (connectClient(userId) == null) return; Integer personalId = globalInfo.getTheClientDto().getIDPersonal(); try { ValidPersonalId validator = new ValidPersonalId(personalId, forStaffId, forStaffCnr); if (!validator.validate()) return; personalId = validator.getStaffIdToUse(); ZeitdatenDto zDto = zeiterfassungCall.zeitdatenFindByPrimaryKey(worktimeId); if (zDto == null) { respondBadRequest("worktimeId", worktimeId.toString()); return; } if (personalId.equals(zDto.getPersonalIId())) { zeiterfassungCall.removeZeitdaten(zDto); } else { respondUnauthorized(); } } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnavailable(e); } catch (EJBExceptionLP e) { respondBadRequest(e); } } @POST @Path("/coming/") @Consumes({ "application/json", "application/xml" }) public void bookComing(TimeRecordingEntry entry) { bookTimeEntryImpl(entry, ZeiterfassungFac.TAETIGKEIT_KOMMT); } // @POST // @Path("/coming/{userid}/{year}/{month}/{day}/{hour}/{minute}/{second}") // public Response bookComing( // @PathParam("userId") String userId, // @PathParam("year") Integer year, // @PathParam("month") Integer month, // @PathParam("day") Integer day, // @PathParam("hour") Integer hour, // @PathParam("minute") Integer minute, // @PathParam("second") Integer second) { // return bookComing(convertFrom(userId, year, month, day, hour, minute, second)) ; // } @POST @Path("/going/") @Consumes({ "application/json", "application/xml" }) public void bookGoing(TimeRecordingEntry entry) { bookTimeEntryImpl(entry, ZeiterfassungFac.TAETIGKEIT_GEHT); } @POST @Path("/pausing/") @Consumes({ "application/json", "application/xml" }) public void bookPausing(TimeRecordingEntry entry) { bookTimeEntryImpl(entry, ZeiterfassungFac.TAETIGKEIT_UNTER); } @POST @Path("/stopping/") @Consumes({ "application/json", "application/xml" }) public void bookStopping(TimeRecordingEntry entry) { bookTimeEntryImpl(entry, ZeiterfassungFac.TAETIGKEIT_ENDE); } @POST @Path("/order/") @Consumes({ "application/json", "application/xml" }) public void bookOrder(OrderRecordingEntry entry) { if (connectClient(entry.getUserId()) == null) return; try { if (!isValidBeleg(LocaleFac.BELEGART_AUFTRAG)) { respondUnauthorized(); return; } ValidPersonalId validator = new ValidPersonalId(globalInfo.getTheClientDto().getIDPersonal(), entry.getForStaffId(), entry.getForStaffCnr()); if (!validator.validate()) return; entry.setForStaffId(validator.getStaffIdToUse()); if (!isValidOrderId(entry.getOrderId())) { respondBadRequest("orderId", entry.getOrderId().toString()); return; } if (!isValidOrderPositionId(entry.getOrderId(), entry.getOrderPositionId())) { respondBadRequest("orderPositionId", entry.getOrderPositionId().toString()); return; } ZeitdatenDto zDto = createDefaultZeitdatenDto(entry); zDto.setIBelegartid(entry.getOrderId()); zDto.setIBelegartpositionid(entry.getOrderPositionId()); zeiterfassungCall.createAuftragZeitdaten(zDto, true, true, true); } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnavailable(e); } catch (EJBExceptionLP e) { respondBadRequest(e); } } @POST @Path("/production/") @Consumes({ "application/json", "application/xml" }) public void bookProduction(ProductionRecordingEntry entry) { if (connectClient(entry.getUserId()) == null) return; try { if (!isValidBeleg(LocaleFac.BELEGART_LOS)) { respondUnauthorized(); return; } ValidPersonalId validator = new ValidPersonalId(globalInfo.getTheClientDto().getIDPersonal(), entry.getForStaffId(), entry.getForStaffCnr()); if (!validator.validate()) return; entry.setForStaffId(validator.getStaffIdToUse()); if (!isValidProductionId(entry.getProductionId())) { respondBadRequest("productionId", entry.getProductionId().toString()); return; } ZeitdatenDto zDto = createDefaultZeitdatenDto(entry); zDto.setCBelegartnr(LocaleFac.BELEGART_LOS); zDto.setIBelegartid(entry.getProductionId()); zeiterfassungCall.createZeitdaten(zDto, true, true, true); } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnauthorized(); } catch (EJBExceptionLP e) { respondBadRequest(e); } } @POST @Path("/project/") @Consumes({ "application/json", "application/xml" }) public void bookProject(ProjectRecordingEntry entry) { if (connectClient(entry.getUserId()) == null) return; try { if (!isValidBeleg(LocaleFac.BELEGART_PROJEKT)) { respondUnauthorized(); return; } ValidPersonalId validator = new ValidPersonalId(globalInfo.getTheClientDto().getIDPersonal(), entry.getForStaffId(), entry.getForStaffCnr()); if (!validator.validate()) return; entry.setForStaffId(validator.getStaffIdToUse()); if (!isValidProjectId(entry.getProjectId())) { respondBadRequest("projectId", entry.getProjectId().toString()); return; } ZeitdatenDto zDto = createDefaultZeitdatenDto(entry); zDto.setArtikelIId(null); zDto.setCBelegartnr(LocaleFac.BELEGART_PROJEKT); zDto.setIBelegartid(entry.getProjectId()); zDto.setArtikelIId(entry.getWorkItemId()); zeiterfassungCall.createZeitdaten(zDto, true, true, true); } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnavailable(e); } catch (EJBExceptionLP e) { respondBadRequest(e); } } private ZeitdatenDto createDefaultZeitdatenDto(DocumentRecordingEntry entry) { ZeitdatenDto zDto = new ZeitdatenDto(); zDto.setPersonalIId(entry.getForStaffId()); zDto.setArtikelIId(entry.getWorkItemId()); zDto.setCBemerkungZuBelegart(entry.getRemark()); zDto.setXKommentar(entry.getExtendedRemark()); Timestamp t = getTimestamp(entry); zDto.setTZeit(t); zDto.setTAendern(t); zDto.setCWowurdegebucht(StringHelper.trim(entry.getWhere())); return zDto; } private boolean isValidProjectId(Integer projectId) throws NamingException, RemoteException { ProjektDto projektDto = projektCall.projektFindByPrimaryKeyOhneExc(projectId); if (projektDto == null) return false; return projektDto.getMandantCNr().equals(globalInfo.getMandant()); } private boolean isValidProductionId(Integer productionId) throws RemoteException, NamingException { LosDto losDto = fertigungCall.losFindByPrimaryKeyOhneExc(productionId); if (losDto == null) return false; if (!losDto.getMandantCNr().equals(globalInfo.getMandant())) return false; if (FertigungFac.STATUS_GESTOPPT.equals(losDto.getStatusCNr())) return false; if (FertigungFac.STATUS_ANGELEGT.equals(losDto.getStatusCNr()) && !parameterCall.isZeitdatenAufAngelegteLoseBuchbar()) return false; if (FertigungFac.STATUS_ERLEDIGT.equals(losDto.getStatusCNr()) && !parameterCall.isZeitdatenAufErledigteBuchbar()) return false; return true; } protected class ValidPersonalId { private Integer staffId; private String staffCnr; private Integer myPersonalId; private Integer staffIdToUse; public ValidPersonalId(Integer myPersonalId) { this.myPersonalId = myPersonalId; } public ValidPersonalId(Integer myPersonalId, Integer forStaffId, String forStaffCnr) { this.myPersonalId = myPersonalId; this.staffId = forStaffId; this.staffCnr = forStaffCnr; this.staffIdToUse = null; } public Integer getStaffIdToUse() { return staffIdToUse; } public boolean validate(Integer forStaffId, String forStaffCnr) throws RemoteException, NamingException { this.staffId = forStaffId; this.staffCnr = forStaffCnr; this.staffIdToUse = null; return validate(); } public boolean validate() throws RemoteException, NamingException { if (staffId != null) { PersonalDto forPers = personalCall.byPrimaryKeySmall(staffId); return validatePersonalDto("staffId", staffId.toString(), forPers); } if (staffCnr != null) { PersonalDto forPers = personalCall.byCPersonalnrMandantCNrOhneExc(staffCnr); return validatePersonalDto("staffCnr", staffCnr, forPers); } staffIdToUse = myPersonalId; return true; } private boolean validatePersonalDto(String fieldName, String value, PersonalDto forPers) throws NamingException { if (forPers != null) { if (judgeCall.hasPersSichtbarkeitAlle()) { staffIdToUse = forPers.getIId(); return true; } if (judgeCall.hasPersSichtbarkeitAbteilung()) { PersonalDto mePers = personalCall.byPrimaryKeySmall(myPersonalId); if (mePers.getKostenstelleIIdAbteilung() != null) { if (mePers.getKostenstelleIIdAbteilung().equals(forPers.getKostenstelleIIdAbteilung())) { staffIdToUse = forPers.getIId(); return true; } } } } respondBadRequest(fieldName, value); return false; } } private boolean isValidOrderId(Integer orderId) throws NamingException { AuftragDto auftragDto = auftragCall.auftragFindByPrimaryKeyOhneExc(orderId); if (auftragDto == null) return false; return auftragDto.getMandantCNr().equals(globalInfo.getMandant()); } private boolean isValidOrderPositionId(Integer orderId, Integer positionId) throws NamingException { AuftragpositionDto auftragPositionDto = auftragpositionCall .auftragpositionFindByPrimaryKeyOhneExc(positionId); if (auftragPositionDto == null) return false; return orderId.equals(auftragPositionDto.getBelegIId()); } @GET @Path("/activities/") @Produces({ FORMAT_JSON, FORMAT_XML }) @Override public List<ItemEntry> getActivities(@QueryParam("userid") String userId, @QueryParam("limit") Integer limit, @QueryParam("startIndex") Integer startIndex, @QueryParam("filter_cnr") String filterCnr) { List<ItemEntry> activities = new ArrayList<ItemEntry>(); try { if (null == connectClient(userId)) return activities; FilterKriteriumCollector collector = new FilterKriteriumCollector(); collector.add(workItemQuery.getFilterArtikelNummer(filterCnr)); FilterBlock filterCrits = new FilterBlock(collector.asArray(), "AND"); QueryParameters params = workItemQuery.getDefaultQueryParameters(filterCrits); params.setLimit(limit); params.setKeyOfSelectedRow(startIndex); QueryResult result = workItemQuery.setQuery(params); activities = workItemQuery.getResultList(result); } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnavailable(e); } return activities; } @GET @Path("/specialactivities/") @Produces({ FORMAT_JSON, FORMAT_XML }) public List<SpecialActivity> getSpecialActivities(@QueryParam("userid") String userId) { List<SpecialActivity> activities = new ArrayList<SpecialActivity>(); try { if (connectClient(userId) == null) return activities; boolean hasRechtNurBuchen = judgeCall.hasPersZeiteingabeNurBuchen(); if (hasRechtNurBuchen) { activities = zeiterfassungCall .getAllSprSondertaetigkeitenNurBDEBuchbar(globalInfo.getTheClientDto().getLocUiAsString()); } else { activities = zeiterfassungCall .getAllSprSondertaetigkeiten(globalInfo.getTheClientDto().getLocUiAsString()); } } catch (RemoteException e) { respondUnavailable(e); } catch (NamingException e) { respondUnavailable(e); } return activities; } @GET @Path("/documenttypes/") @Produces({ FORMAT_JSON, FORMAT_XML }) public List<DocumentType> getDocumentTypes(@QueryParam(Param.USERID) String userId) { List<DocumentType> documentTypes = new ArrayList<DocumentType>(); try { if (connectClient(userId) == null) return documentTypes; documentTypes = zeiterfassungCall.getBebuchbareBelegarten(globalInfo.getTheClientDto()); } catch (NamingException e) { respondUnavailable(e); } return documentTypes; } private void bookTimeEntryImpl(TimeRecordingEntry entry, String bookingType) { try { if (connectClient(entry.getUserId()) == null) return; ValidPersonalId validator = new ValidPersonalId(globalInfo.getTheClientDto().getIDPersonal(), entry.getForStaffId(), entry.getForStaffCnr()); if (!validator.validate()) return; entry.setForStaffId(validator.getStaffIdToUse()); Integer taetigkeitIId = getTaetigkeitIId(bookingType); if (null == taetigkeitIId) { respondBadRequest(bookingType, "undefined"); return; } Timestamp timestamp = getTimestamp(entry); bucheZeitPersonalID(validator.getStaffIdToUse(), timestamp, taetigkeitIId, entry.getWhere()); } catch (NamingException e) { respondUnavailable(e); } catch (RemoteException e) { respondUnavailable(e); } } // private TimeRecordingEntry convertFrom(String userId, int year, int month, int day, int hour, int minute, int second) { // TimeRecordingEntry entry = new TimeRecordingEntry() ; // entry.setUserId(userId) ; // entry.setYear(year) ; // entry.setMonth(month) ; // entry.setDay(day) ; // entry.setHour(hour) ; // entry.setMinute(minute) ; // entry.setSecond(second) ; // return entry ; // } private Timestamp getTimestamp(TimeRecordingEntry entry) { Calendar c = Calendar.getInstance(); c.set(entry.getYear(), entry.getMonth() - 1, entry.getDay(), entry.getHour(), entry.getMinute(), entry.getSecond()); return new Timestamp(c.getTimeInMillis()); } private void bucheZeitPersonalID(Integer personalIId, Timestamp timestamp, Integer taetigkeitIId, String station) { ZeitdatenDto zd = new ZeitdatenDto(); zd.setPersonalIId(personalIId); zd.setTZeit(timestamp); zd.setTaetigkeitIId(taetigkeitIId); zd.setCWowurdegebucht(StringHelper.trim(station)); zd.setTAendern(timestamp); try { zeiterfassungCall.createZeitdaten(zd, true, true, false); } catch (EJBExceptionLP e) { respondBadRequest(e); } catch (RemoteException e) { respondUnavailable(e); } catch (NamingException e) { respondUnavailable(e); } } private Integer getTaetigkeitIId(String cNr) throws NamingException { TaetigkeitDto taetigkeitDto = zeiterfassungCall.taetigkeitFindByCNr(cNr.trim()); return taetigkeitDto == null ? null : taetigkeitDto.getIId(); } private boolean isValidBeleg(String belegart) throws NamingException { List<DocumentType> allowedTypes = zeiterfassungCall.getBebuchbareBelegarten(); for (DocumentType documentType : allowedTypes) { if (belegart.equals(documentType.getId())) return true; } return false; } }