docs: protected ContractBean createContractInternal(String organizationId, String clientId,
              String version, NewContractBean bean) throws StorageException, Exception {
          ContractBean contract;
          ClientVersionBean cvb;
          cvb = storage.getClientVersion(organizationId, clientId, version);
          if (cvb == null) {
              throw ExceptionFactory.clientVersionNotFoundException(clientId, version);
          }
          if (cvb.getStatus() == ClientStatus.Retired) {
              throw ExceptionFactory.invalidClientStatusException();
          }
          ApiVersionBean avb = storage.getApiVersion(bean.getApiOrgId(), bean.getApiId(), bean.getApiVersion());
          if (avb == null) {
              throw ExceptionFactory.apiNotFoundException(bean.getApiId());
          }
          if (avb.getStatus() != ApiStatus.Published) {
              throw ExceptionFactory.invalidApiStatusException();
          }
          Set<ApiPlanBean> plans = avb.getPlans();
          String planVersion = null;
          if (plans != null) {
              for (ApiPlanBean apiPlanBean : plans) {
                  if (apiPlanBean.getPlanId().equals(bean.getPlanId())) {
                      planVersion = apiPlanBean.getVersion();
                  }
              }
          }
          if (planVersion == null) {
              throw ExceptionFactory.planNotFoundException(bean.getPlanId());
          }
          PlanVersionBean pvb = storage.getPlanVersion(bean.getApiOrgId(), bean.getPlanId(), planVersion);
          if (pvb == null) {
              throw ExceptionFactory.planNotFoundException(bean.getPlanId());
          }
          if (pvb.getStatus() != PlanStatus.Locked) {
              throw ExceptionFactory.invalidPlanStatusException();
          }
  
          contract = new ContractBean();
          contract.setClient(cvb);
          contract.setApi(avb);
          contract.setPlan(pvb);
          contract.setCreatedBy(securityContext.getCurrentUser());
          contract.setCreatedOn(new Date());
  
          // Move the client to the "Ready" state if necessary.
          if (cvb.getStatus() == ClientStatus.Created && clientValidator.isReady(cvb, true)) {
              cvb.setStatus(ClientStatus.Ready);
          }
  
          storage.createContract(contract);
          storage.createAuditEntry(AuditUtils.contractCreatedFromClient(contract, securityContext));
          storage.createAuditEntry(AuditUtils.contractCreatedToApi(contract, securityContext));
  
          // Update the version with new meta-data (e.g. modified-by)
          cvb.setModifiedBy(securityContext.getCurrentUser());
          cvb.setModifiedOn(new Date());
          storage.updateClientVersion(cvb);
  
          return contract;
      }