Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.gst.accounting.closure.service; import java.util.Date; import java.util.Map; import com.gst.accounting.closure.api.GLClosureJsonInputParams; import com.gst.accounting.closure.command.GLClosureCommand; import com.gst.accounting.closure.domain.GLClosure; import com.gst.accounting.closure.domain.GLClosureRepository; import com.gst.accounting.closure.exception.GLClosureDuplicateException; import com.gst.accounting.closure.exception.GLClosureInvalidDeleteException; import com.gst.accounting.closure.exception.GLClosureInvalidException; import com.gst.accounting.closure.exception.GLClosureInvalidException.GL_CLOSURE_INVALID_REASON; import com.gst.accounting.closure.exception.GLClosureNotFoundException; import com.gst.accounting.closure.serialization.GLClosureCommandFromApiJsonDeserializer; import com.gst.infrastructure.core.api.JsonCommand; import com.gst.infrastructure.core.data.CommandProcessingResult; import com.gst.infrastructure.core.data.CommandProcessingResultBuilder; import com.gst.infrastructure.core.exception.PlatformDataIntegrityException; import com.gst.organisation.office.domain.Office; import com.gst.organisation.office.domain.OfficeRepositoryWrapper; import org.joda.time.LocalDate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class GLClosureWritePlatformServiceJpaRepositoryImpl implements GLClosureWritePlatformService { private final static Logger logger = LoggerFactory .getLogger(GLClosureWritePlatformServiceJpaRepositoryImpl.class); private final GLClosureRepository glClosureRepository; private final OfficeRepositoryWrapper officeRepositoryWrapper; private final GLClosureCommandFromApiJsonDeserializer fromApiJsonDeserializer; @Autowired public GLClosureWritePlatformServiceJpaRepositoryImpl(final GLClosureRepository glClosureRepository, final OfficeRepositoryWrapper officeRepositoryWrapper, final GLClosureCommandFromApiJsonDeserializer fromApiJsonDeserializer) { this.glClosureRepository = glClosureRepository; this.officeRepositoryWrapper = officeRepositoryWrapper; this.fromApiJsonDeserializer = fromApiJsonDeserializer; } @Transactional @Override public CommandProcessingResult createGLClosure(final JsonCommand command) { try { final GLClosureCommand closureCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); closureCommand.validateForCreate(); // check office is valid final Long officeId = command.longValueOfParameterNamed(GLClosureJsonInputParams.OFFICE_ID.getValue()); final Office office = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId); // TODO: Get Tenant specific date // ensure closure date is not in the future final Date todaysDate = new Date(); final Date closureDate = command .DateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue()); if (closureDate.after(todaysDate)) { throw new GLClosureInvalidException(GL_CLOSURE_INVALID_REASON.FUTURE_DATE, closureDate); } // shouldn't be before an existing accounting closure final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(officeId); if (latestGLClosure != null) { if (latestGLClosure.getClosingDate().after(closureDate)) { throw new GLClosureInvalidException(GL_CLOSURE_INVALID_REASON.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate()); } } final GLClosure glClosure = GLClosure.fromJson(office, command); this.glClosureRepository.saveAndFlush(glClosure); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(officeId) .withEntityId(glClosure.getId()).build(); } catch (final DataIntegrityViolationException dve) { handleGLClosureIntegrityIssues(command, dve); return CommandProcessingResult.empty(); } } @Transactional @Override public CommandProcessingResult updateGLClosure(final Long glClosureId, final JsonCommand command) { final GLClosureCommand closureCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); closureCommand.validateForUpdate(); // is the glClosure valid final GLClosure glClosure = this.glClosureRepository.findOne(glClosureId); if (glClosure == null) { throw new GLClosureNotFoundException(glClosureId); } final Map<String, Object> changesOnly = glClosure.update(command); if (!changesOnly.isEmpty()) { this.glClosureRepository.saveAndFlush(glClosure); } return new CommandProcessingResultBuilder().withCommandId(command.commandId()) .withOfficeId(glClosure.getOffice().getId()).withEntityId(glClosure.getId()).with(changesOnly) .build(); } @Transactional @Override public CommandProcessingResult deleteGLClosure(final Long glClosureId) { final GLClosure glClosure = this.glClosureRepository.findOne(glClosureId); if (glClosure == null) { throw new GLClosureNotFoundException(glClosureId); } /** * check if any closures are present for this branch at a later date * than this closure date **/ final Date closureDate = glClosure.getClosingDate(); final GLClosure latestGLClosure = this.glClosureRepository .getLatestGLClosureByBranch(glClosure.getOffice().getId()); if (latestGLClosure.getClosingDate().after(closureDate)) { throw new GLClosureInvalidDeleteException(latestGLClosure.getOffice().getId(), latestGLClosure.getOffice().getName(), latestGLClosure.getClosingDate()); } this.glClosureRepository.delete(glClosure); return new CommandProcessingResultBuilder().withOfficeId(glClosure.getOffice().getId()) .withEntityId(glClosure.getId()).build(); } /** * @param command * @param dve */ private void handleGLClosureIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { final Throwable realCause = dve.getMostSpecificCause(); if (realCause.getMessage().contains("office_id_closing_date")) { throw new GLClosureDuplicateException( command.longValueOfParameterNamed(GLClosureJsonInputParams.OFFICE_ID.getValue()), new LocalDate( command.DateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue()))); } logger.error(dve.getMessage(), dve); throw new PlatformDataIntegrityException("error.msg.glClosure.unknown.data.integrity.issue", "Unknown data integrity issue with resource GL Closure: " + realCause.getMessage()); } }