@Transactional
  @Override
  public CommandProcessingResult createHoliday(final JsonCommand command) {

    try {
      this.context.authenticatedUser();
      this.fromApiJsonDeserializer.validateForCreate(command.json());

      validateInputDates(command);

      final Set<Office> offices = getSelectedOffices(command);

      final Holiday holiday = Holiday.createNew(offices, command);

      this.holidayRepository.save(holiday);

      return new CommandProcessingResultBuilder()
          .withCommandId(command.commandId())
          .withEntityId(holiday.getId())
          .build();
    } catch (final DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult submitApplication(final JsonCommand command) {
    try {
      this.savingsAccountDataValidator.validateForSubmit(command.json());
      final AppUser submittedBy = this.context.authenticatedUser();

      final SavingsAccount account = this.savingAccountAssembler.assembleFrom(command, submittedBy);
      this.savingAccountRepository.save(account);

      if (account.isAccountNumberRequiresAutoGeneration()) {
        final AccountNumberGenerator accountNoGenerator =
            this.accountIdentifierGeneratorFactory.determineSavingsAccountNoGenerator(
                account.getId());
        account.updateAccountNo(accountNoGenerator.generate());

        this.savingAccountRepository.save(account);
      }

      final Long savingsId = account.getId();
      return new CommandProcessingResultBuilder() //
          .withCommandId(command.commandId()) //
          .withEntityId(savingsId) //
          .withOfficeId(account.officeId()) //
          .withClientId(account.clientId()) //
          .withGroupId(account.groupId()) //
          .withSavingsId(savingsId) //
          .build();
    } catch (final DataAccessException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult createOffice(final JsonCommand command) {

    try {
      final AppUser currentUser = context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForCreate(command.json());

      Long parentId = null;
      if (command.parameterExists("parentId")) {
        parentId = command.longValueOfParameterNamed("parentId");
      }

      final Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, parentId);
      final Office office = Office.fromJson(parent, command);

      // pre save to generate id for use in office hierarchy
      this.officeRepository.save(office);

      office.generateHierarchy();

      this.officeRepository.save(office);

      return new CommandProcessingResultBuilder() //
          .withCommandId(command.commandId()) //
          .withEntityId(office.getId()) //
          .withOfficeId(office.getId()) //
          .build();
    } catch (DataIntegrityViolationException dve) {
      handleOfficeDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult followUpProspect(
      final JsonCommand command, final Long prospectId) {
    try {
      context.authenticatedUser();
      this.clientProspectCommandFromApiJsonDeserializer.validateForUpdate(command.json());

      final ProspectDetail prospectDetail = ProspectDetail.fromJson(command, prospectId);
      prospectDetailJpaRepository.save(prospectDetail);

      return new CommandProcessingResultBuilder()
          .withCommandId(command.commandId())
          .withEntityId(prospectDetail.getProspectId())
          .build();

    } catch (DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    } catch (ParseException e) {
      throw new PlatformDataIntegrityException(
          "invalid.date.and.time.format",
          "invalid.date.and.time.format",
          "invalid.date.and.time.format");
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult updateCharge(final Long chargeId, final JsonCommand command) {

    try {
      this.context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForUpdate(command.json());

      final Charge chargeForUpdate = this.chargeRepository.findOne(chargeId);
      if (chargeForUpdate == null) {
        throw new ChargeNotFoundException(chargeId);
      }

      final Map<String, Object> changes = chargeForUpdate.update(command);

      if (!changes.isEmpty()) {
        this.chargeRepository.save(chargeForUpdate);
      }

      return new CommandProcessingResultBuilder()
          .withCommandId(command.commandId())
          .withEntityId(chargeId)
          .with(changes)
          .build();
    } catch (DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  @Caching(
      evict = {
        @CacheEvict(
            value = "offices",
            key =
                "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat(#root.target.context.authenticatedUser().getOffice().getHierarchy()+'of')"),
        @CacheEvict(
            value = "officesForDropdown",
            key =
                "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat(#root.target.context.authenticatedUser().getOffice().getHierarchy()+'ofd')"),
        @CacheEvict(
            value = "officesById",
            key =
                "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat(#officeId)")
      })
  public CommandProcessingResult updateOffice(final Long officeId, final JsonCommand command) {

    try {
      final AppUser currentUser = context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForUpdate(command.json());

      Long parentId = null;
      if (command.parameterExists("parentId")) {
        parentId = command.longValueOfParameterNamed("parentId");
      }

      final Office office = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, officeId);

      final Map<String, Object> changes = office.update(command);

      if (changes.containsKey("parentId")) {
        final Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, parentId);
        office.update(parent);
      }

      if (!changes.isEmpty()) {
        this.officeRepository.saveAndFlush(office);
      }

      return new CommandProcessingResultBuilder() //
          .withCommandId(command.commandId()) //
          .withEntityId(office.getId()) //
          .withOfficeId(office.getId()) //
          .with(changes) //
          .build();
    } catch (DataIntegrityViolationException dve) {
      handleOfficeDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  @CacheEvict(value = "usersByUsername", allEntries = true)
  public CommandProcessingResult createUser(final JsonCommand command) {

    try {
      this.context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForCreate(command.json());

      final String officeIdParamName = "officeId";
      final Long officeId = command.longValueOfParameterNamed(officeIdParamName);

      final Office userOffice = this.officeRepository.findOne(officeId);
      if (userOffice == null) {
        throw new OfficeNotFoundException(officeId);
      }

      final String[] roles = command.arrayValueOfParameterNamed("roles");
      final Set<Role> allRoles = assembleSetOfRoles(roles);

      final AppUser appUser = AppUser.fromJson(userOffice, allRoles, command);
      final Boolean sendPasswordToEmail =
          command.booleanObjectValueOfParameterNamed("sendPasswordToEmail");
      this.userDomainService.create(appUser, sendPasswordToEmail);

      return new CommandProcessingResultBuilder() //
          .withCommandId(command.commandId()) //
          .withEntityId(appUser.getId()) //
          .withOfficeId(userOffice.getId()) //
          .build();
    } catch (final DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    } catch (final PlatformEmailSendException e) {
      final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();

      final String email = command.stringValueOfParameterNamed("email");
      final ApiParameterError error =
          ApiParameterError.parameterError(
              "error.msg.user.email.invalid", "The parameter email is invalid.", "email", email);
      dataValidationErrors.add(error);

      throw new PlatformApiDataValidationException(
          "validation.msg.validation.errors.exist",
          "Validation errors exist.",
          dataValidationErrors);
    }
  }
  @Transactional
  @Override
  @CacheEvict(value = "usersByUsername", allEntries = true)
  public CommandProcessingResult updateUser(final Long userId, final JsonCommand command) {

    try {
      this.context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForUpdate(command.json());

      final AppUser userToUpdate = this.appUserRepository.findOne(userId);
      if (userToUpdate == null) {
        throw new UserNotFoundException(userId);
      }

      final Map<String, Object> changes =
          userToUpdate.update(command, this.platformPasswordEncoder);

      if (changes.containsKey("officeId")) {
        final Long officeId = (Long) changes.get("officeId");
        final Office office = this.officeRepository.findOne(officeId);
        if (office == null) {
          throw new OfficeNotFoundException(officeId);
        }

        userToUpdate.changeOffice(office);
      }

      if (changes.containsKey("roles")) {
        final String[] roleIds = (String[]) changes.get("roles");
        final Set<Role> allRoles = assembleSetOfRoles(roleIds);

        userToUpdate.updateRoles(allRoles);
      }

      if (!changes.isEmpty()) {
        this.appUserRepository.saveAndFlush(userToUpdate);
      }

      return new CommandProcessingResultBuilder() //
          .withEntityId(userId) //
          .withOfficeId(userToUpdate.getOffice().getId()) //
          .with(changes) //
          .build();
    } catch (final DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
 @Transactional
 @Override
 public CommandProcessingResult deleteEventPricing(JsonCommand command) {
   try {
     EventPricing eventPricing = this.eventPricingRepository.findOne(command.entityId());
     eventPricing.setClientType(null);
     eventPricing.setOptType(null);
     eventPricing.setFormatType(null);
     eventPricing.setIsDeleted('y');
     this.eventPricingRepository.save(eventPricing);
     return new CommandProcessingResultBuilder().withEntityId(eventPricing.getId()).build();
   } catch (DataIntegrityViolationException dev) {
     return CommandProcessingResult.empty();
   }
 }
 public CommandProcessingResult updateEventPricing(JsonCommand command) {
   try {
     this.apiJsonDeserializer.validateForCreate(command.json());
     EventPricing eventPrice = this.eventPricingRepository.findOne(command.entityId());
     EventMaster eventMaster = eventPrice.getEventId();
     EventPricing newEventPricing = EventPricing.fromJson(command, eventMaster);
     eventPrice = (EventPricing) UpdateCompareUtil.compare(eventPrice, newEventPricing);
     this.eventPricingRepository.save(eventPrice);
     return new CommandProcessingResultBuilder()
         .withEntityId(eventPrice.getId())
         .withCommandId(command.commandId())
         .build();
   } catch (DataIntegrityViolationException dev) {
     return CommandProcessingResult.empty();
   }
 }
  @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.officeRepository.findOne(officeId);
      if (office == null) {
        throw new OfficeNotFoundException(officeId);
      }

      // TODO: Get Tenant specific date
      // ensure closure date is not in the future
      final Date todaysDate = DateUtils.getDateOfTenant();
      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 createCharge(final JsonCommand command) {
    try {
      this.context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForCreate(command.json());

      final Charge charge = Charge.fromJson(command);
      this.chargeRepository.save(charge);

      return new CommandProcessingResultBuilder()
          .withCommandId(command.commandId())
          .withEntityId(charge.getId())
          .build();
    } catch (DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  @CacheEvict(value = "hooks", allEntries = true)
  public CommandProcessingResult createHook(final JsonCommand command) {

    try {
      this.context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForCreate(command.json());

      final HookTemplate template =
          retrieveHookTemplateBy(command.stringValueOfParameterNamed(nameParamName));
      final String configJson = command.jsonFragment(configParamName);
      final Set<HookConfiguration> config =
          assembleConfig(command.mapValueOfParameterNamed(configJson), template);
      final JsonArray events = command.arrayOfParameterNamed(eventsParamName);
      final Set<HookResource> allEvents = assembleSetOfEvents(events);
      Template ugdTemplate = null;
      if (command.hasParameter(templateIdParamName)) {
        final Long ugdTemplateId = command.longValueOfParameterNamed(templateIdParamName);
        ugdTemplate = this.ugdTemplateRepository.findOne(ugdTemplateId);
        if (ugdTemplate == null) {
          throw new TemplateNotFoundException(ugdTemplateId);
        }
      }
      final Hook hook = Hook.fromJson(command, template, config, allEvents, ugdTemplate);

      validateHookRules(template, config, allEvents);

      this.hookRepository.save(hook);

      return new CommandProcessingResultBuilder()
          .withCommandId(command.commandId())
          .withEntityId(hook.getId())
          .build();
    } catch (final DataIntegrityViolationException dve) {
      handleHookDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult createSavingAccount(final JsonCommand command) {
    try {
      this.context.authenticatedUser();
      this.savingsAccountDataValidator.validateForCreate(command.json());

      final List<Long> existingTransactionIds = new ArrayList<Long>();
      final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
      final SavingsAccount account =
          this.savingAccountAssembler.assembleFrom(
              command, existingTransactionIds, existingReversedTransactionIds);
      this.savingAccountRepository.save(account);

      if (account.isAccountNumberRequiresAutoGeneration()) {
        final AccountNumberGenerator accountNoGenerator =
            this.accountIdentifierGeneratorFactory.determineLoanAccountNoGenerator(account.getId());
        account.updateAccountNo(accountNoGenerator.generate());

        this.savingAccountRepository.save(account);
      }

      postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);

      final Long savingsId = account.getId();
      return new CommandProcessingResultBuilder() //
          .withCommandId(command.commandId()) //
          .withEntityId(savingsId) //
          .withOfficeId(account.officeId()) //
          .withClientId(account.clientId()) //
          .withGroupId(account.groupId()) //
          .withSavingsId(savingsId) //
          .build();
    } catch (DataAccessException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult updateOffice(final Long officeId, final JsonCommand command) {

    try {
      final AppUser currentUser = context.authenticatedUser();

      this.fromApiJsonDeserializer.validateForUpdate(command.json());

      Long parentId = null;
      if (command.parameterExists("parentId")) {
        parentId = command.longValueOfParameterNamed("parentId");
      }

      final Office office = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, officeId);

      final Map<String, Object> changes = office.update(command);

      if (changes.containsKey("parentId")) {
        final Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, parentId);
        office.update(parent);
      }

      if (!changes.isEmpty()) {
        this.officeRepository.saveAndFlush(office);
      }

      return new CommandProcessingResultBuilder() //
          .withCommandId(command.commandId()) //
          .withEntityId(office.getId()) //
          .withOfficeId(office.getId()) //
          .with(changes) //
          .build();
    } catch (DataIntegrityViolationException dve) {
      handleOfficeDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Transactional
  @Override
  public CommandProcessingResult updateHoliday(final JsonCommand command) {

    try {
      this.context.authenticatedUser();
      this.fromApiJsonDeserializer.validateForUpdate(command.json());

      final Holiday holiday =
          this.holidayRepository.findOneWithNotFoundDetection(command.entityId());
      Map<String, Object> changes = holiday.update(command);

      validateInputDates(
          holiday.getFromDateLocalDate(),
          holiday.getToDateLocalDate(),
          holiday.getRepaymentsRescheduledToLocalDate());

      if (changes.containsKey(officesParamName)) {
        final Set<Office> offices = getSelectedOffices(command);
        final boolean updated = holiday.update(offices);
        if (!updated) {
          changes.remove(officesParamName);
        }
      }

      this.holidayRepository.saveAndFlush(holiday);

      return new CommandProcessingResultBuilder()
          .withEntityId(holiday.getId())
          .with(changes)
          .build();
    } catch (final DataIntegrityViolationException dve) {
      handleDataIntegrityIssues(command, dve);
      return CommandProcessingResult.empty();
    }
  }
  @Override
  public CommandProcessingResult updateBillMaster(
      final List<BillDetail> billDetails,
      final BillMaster billMaster,
      final BigDecimal clientBalance) {

    try {
      BigDecimal chargeAmount = BigDecimal.ZERO;
      BigDecimal adjustmentAmount = BigDecimal.ZERO;
      BigDecimal paymentAmount = BigDecimal.ZERO;
      BigDecimal dueAmount = BigDecimal.ZERO;
      BigDecimal taxAmount = BigDecimal.ZERO;
      BigDecimal oneTimeSaleAmount = BigDecimal.ZERO;
      BigDecimal serviceTransferAmount = BigDecimal.ZERO;
      BigDecimal depositRefundAmount = BigDecimal.ZERO;

      for (final BillDetail billDetail : billDetails) {
        if ("SERVICE_CHARGES".equalsIgnoreCase(billDetail.getTransactionType())) {
          if (billDetail.getAmount() != null)
            chargeAmount = chargeAmount.add(billDetail.getAmount());

        } else if ("TAXES".equalsIgnoreCase(billDetail.getTransactionType())) {
          if (billDetail.getAmount() != null) taxAmount = taxAmount.add(billDetail.getAmount());

        } else if ("ADJUSTMENT".equalsIgnoreCase(billDetail.getTransactionType())) {
          if (billDetail.getAmount() != null)
            adjustmentAmount = adjustmentAmount.add(billDetail.getAmount());

        } else if (billDetail.getTransactionType().contains("PAYMENT")) {
          if (billDetail.getAmount() != null)
            paymentAmount = paymentAmount.add(billDetail.getAmount());

        } else if ("ONETIME_CHARGES".equalsIgnoreCase(billDetail.getTransactionType())) {
          if (billDetail.getAmount() != null)
            oneTimeSaleAmount = oneTimeSaleAmount.add(billDetail.getAmount());

        } else if ("SERVICE_TRANSFER".equalsIgnoreCase(billDetail.getTransactionType())) {
          if (billDetail.getAmount() != null)
            serviceTransferAmount = serviceTransferAmount.add(billDetail.getAmount());

        } else if ("DEPOSIT&REFUND".equalsIgnoreCase(billDetail.getTransactionType())) {
          if (billDetail.getAmount() != null)
            depositRefundAmount = depositRefundAmount.add(billDetail.getAmount());
        }
      }
      dueAmount =
          chargeAmount
              .add(taxAmount)
              .add(oneTimeSaleAmount)
              .add(clientBalance)
              .add(depositRefundAmount)
              .add(serviceTransferAmount)
              .subtract(paymentAmount)
              .subtract(adjustmentAmount);
      billMaster.setChargeAmount(chargeAmount.add(oneTimeSaleAmount).add(serviceTransferAmount));
      billMaster.setAdjustmentAmount(adjustmentAmount);
      billMaster.setTaxAmount(taxAmount);
      billMaster.setPaidAmount(paymentAmount);
      billMaster.setDueAmount(dueAmount);
      billMaster.setPreviousBalance(clientBalance);
      billMaster.setDepositRefundAmount(depositRefundAmount);
      this.billMasterRepository.save(billMaster);
      return new CommandProcessingResult(billMaster.getId(), billMaster.getClientId());
    } catch (DataIntegrityViolationException dve) {
      LOGGER.error("unable to retrieve data" + dve.getLocalizedMessage());
      return CommandProcessingResult.empty();
    }
  }