Сложный процесс подключения с использованием модуля Inet системы BGBilling. Конфигурация типа процесса с мастером.

# константы
STATUS_IN_WORK=11
STATUS_WIZARD=35
STATUS_DONE=12
#
CONTRACT_PATTERN=52
CONTRACT_STATUS_ACTIVE=0
CONTRACT_STATUS_IN_CONNECT=5
BILLING_ID=mainBill
PARAM_VN_ADDR=52
PARAM_SMS=55
PARAM_MAC=58
PARAM_MAT=13
MODULE_INET=20
MODULE_NPAY=2
SERVICE_NPAY=3
POOLS_WHITE={141}
POOLS_GREY={121,134,138,141}
CONTRACT_PARAMS=1,2,118,109,115,121,124,127,130,133,136
SERVICE_INET_TYPE=10
TARIFF_GROUP_1=20
TARIFF_GROUP_3=22
SUBSCR_IDS=5
#
# обработка событий
# создание и привязка договора при переходе в статус "В работе"
onProcessEvent.{@inc:cnt}.events=statusChanged:{@STATUS_IN_WORK}
onProcessEvent.{@cnt}.doExpression=<<END
  curdate = new("java.util.Date");
  contractDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.ContractDAO", ctxUser, "{@BILLING_ID}");
  docDao = new("ru.bgcrm.plugin.document.dao.DocumentDAO", conSet.getConnection());
  linkDao = new("ru.bgcrm.dao.process.ProcessLinkDAO", conSet.getConnection());
  contractLink = u.getFirst(linkDao.getObjectLinksWithType(process.getId(), "contract%"));
  if (contractLink == null) {
    contract = contractDao.createContract({@CONTRACT_PATTERN}, tu.format(curdate, "ymd"), null, null);
    link = new("ru.bgcrm.model.CommonObjectLink", "process", process.getId(),
                     "contract:" + contract.getBillingId(), contract.getId(), contract.getTitle());
    linkDao.addLink(link);
  } else {
    contract = new("ru.bgcrm.plugin.bgbilling.proto.model.Contract", "{@BILLING_ID}", contractLink.getLinkedObjectId());
  }
  // генерация карточки и добавление её в документы
  card = contractDao.getContractCard2Pdf(contract.getId(), "card_inet_gig_04102017.xsl");
  docDao.add("process", process.getId(), card, "registration_card.pdf");
END
onProcessEvent.{@cnt}.commands=open
#
# уведомить о изменение процесса исполнителей внутренним сообщением
onProcessEvent.{@inc:cnt}.events=descriptionAdded;messageAdded;executorsChanged
onProcessEvent.{@cnt}.commands=newsPopupNotifyExecutors:Изменился процесс_
#onProcessEvent.{@cnt}.eventsExclude
#
# МАСТЕР ПОДКЛЮЧЕНИЯ
cnt=0
# проверки перед переходом в статус "Мастер"
createWizard.step.{@inc:cnt}.title=Проверка процесса
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.JexlStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() != {@STATUS_WIZARD}
createWizard.step.{@cnt}.doExpression=<<END
   linkDao = new("ru.bgcrm.dao.process.ProcessLinkDAO", conSet.getConnection());
   npayDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.NPayDAO", ctxUser, "{@BILLING_ID}", {@MODULE_NPAY});
   contractDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.ContractDAO", ctxUser, "{@BILLING_ID}");

   if ({@STATUS_IN_WORK} != process.getStatusId())
      return {"filled": false, "message": "Некорректный статус для запуска мастера."};

   contractLink = u.getFirst(linkDao.getObjectLinksWithType(process.getId(), "contract%"));
   if (contractLink == null)
       return {"filled": false, "message": "Не найден привязанный к процессу договор."};

   contractInfo = contractDao.getContractInfo(contractLink.getLinkedObjectId());
   if (contractInfo == null)
      return {"filled": false, "message": "Не найден договор в биллинге."};

   if (!contractInfo.getTariffList().isEmpty())
      return {"filled": false, "message": "Договор содержит тариф."};

   if (!contractInfo.getStatus().equals("В подключении"))
      return {"filled": false, "message": "Некорректный статус договора."};

   /*if (!npayDao.getServiceList(contractLink.getLinkedObjectId()).isEmpty())
      return {"filled": false, "message": "На договоре есть абонплаты."};  */

   // TODO: Проверка договора, тарифа и т.п.
   message = "Договор нормально проверен";
   return {"filled": true, "message": message};
END
#
createWizard.step.{@inc:cnt}.title=Переключение статуса и запуск мастера
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.SetStatusStep
createWizard.step.{@cnt}.checkExpression={@STATUS_IN_WORK} == process.getStatusId()
#
# отработка мастера
createWizard.step.{@inc:cnt}.title=СМС рассылки, MAC/ONU, Внешний адрес
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.FillParamsStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
createWizard.step.{@cnt}.parameterIds={@PARAM_SMS},{@PARAM_MAC},{@PARAM_VN_ADDR}
createWizard.step.{@cnt}.checkParamIds={@PARAM_VN_ADDR}
#
createWizard.step.{@inc:cnt}.title=СМС рассылки
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.JexlStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
createWizard.step.{@cnt}.doExpression=<<END
   // TODO: Можно переместить в шаг создания сервиса и избежать дублирования кода.
   linkDao = new("ru.bgcrm.dao.process.ProcessLinkDAO", conSet.getConnection());
   paramDao = new("ru.bgcrm.dao.ParamValueDAO", conSet.getConnection());
   contractLink = u.getFirst(linkDao.getObjectLinksWithType(process.getId(), "contract%"));
   if (contractLink == null)
       return {"filled": false, "message": "Не найден привязанный к процессу договор."};
   contractId = contractLink.getLinkedObjectId();
   //
   message = "Подписка на рассылки";
   // смс рассылки
   smsPhones = paramDao.getParamPhone(process.getId(), {@PARAM_SMS}).getItemList();
   if (!smsPhones.isEmpty()) {
       dispatchDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.DispatchDAO", ctxUser, "{@BILLING_ID}");
       if (dispatchDao.getContactList(contractId).isEmpty()) {
            contact = new("ru.bgcrm.plugin.bgbilling.proto.model.dispatch.Contact");
            contact.setContractId(contractId);
            contact.setContactTypeId(2);
            contact.setValue(smsPhones.get(0).getPhone());
            dispatchDao.updateContact(contact);
            dispatchDao.addSubscriptions({contractId}, { {@SUBSCR_IDS} });
       }
   }
   return {"filled": true, "message": message};
END
#
createWizard.step.{@inc:cnt}.title=Проверка и создание сервиса
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.JexlStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
createWizard.step.{@cnt}.doExpression=<<END
   ip = "100.64.70.131"; // ip = form.getHttpRequestRemoteAddr();
   curdate = new("java.util.Date");
   searchResult = new("ru.bgcrm.model.SearchResult", 1) ;
   statusDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.ContractStatusDAO", ctxUser, "{@BILLING_ID}");
   tariffDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.ContractTariffDAO", ctxUser, "{@BILLING_ID}");
   inetDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.InetDAO", ctxUser, "{@BILLING_ID}", {@MODULE_INET});
   resDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.ResourceDAO", ctxUser, "{@BILLING_ID}", {@MODULE_INET});
   npayDao = new("ru.bgcrm.plugin.bgbilling.proto.dao.NPayDAO", ctxUser, "{@BILLING_ID}", {@MODULE_NPAY});
   linkDao = new("ru.bgcrm.dao.process.ProcessLinkDAO", conSet.getConnection());
   paramDao = new("ru.bgcrm.dao.ParamValueDAO", conSet.getConnection());
   contractLink = u.getFirst(linkDao.getObjectLinksWithType(process.getId(), "contract%"));
   if (contractLink == null)
       return {"filled": false, "message": "Не найден привязанный к процессу договор."};
   contractId = contractLink.getLinkedObjectId();
   serviceList = inetDao.getServiceList(contractId);
   // создание сервиса
   if (serviceList.isEmpty()) {
       message += "Создание сервиса: " + ip;
       inetDao.getSessionAliveList(searchResult, null, null, null, null, ip, null, null, null);
       session = u.getFirst(searchResult.getList());
       if (session == null)
           return {"filled": false, "message": "Не найдена сессия с адресом: " + ip};
       device = inetDao.getDevice(session.getDeviceId());
       if (device == null)
           return {"filled": false, "message": "Не найдено устройство."};
       message += "<br>DeviceId: " + device.getId();
       // IP адрес
       pools = 1 =~ paramDao.getParamList(process.getId(), {@PARAM_VN_ADDR}) ? {@POOLS_WHITE} : {@POOLS_GREY};
       addr = u.getFirst(resDao.getFreeIpResourceRangeList(pools, 1, 1));
       if (addr == null)
           return {"filled": false, "message": "Ошибка выделения IP адреса"};
       message += "<br>IP: " + addr.getFrom();
       // VLAN
       port = session.getCircuitId();
       ident = device.getInvIdentifier();
       message += "<br>Port: " + port + "; Ident: " + ident;
       cvlan = u.parseInt(ident.substring(0, 3));
       block = u.parseInt(ident.substring(3));
       perdev = 28;
       if (550 <= cvlan && cvlan <= 574) perdev = 290;
       else if (575 <= cvlan && cvlan <= 599) perdev = 600;
       vlan = block * perdev + port + 500 - 1;
       if (vlan <= 0)
           return {"filled": false, "message": "Ошибка вычисления VLAN для identifier: " + ident + "; port: " +  port};
       message += "<br>VLAN: " + vlan;
       // создание сервиса
       service = new("ru.bgcrm.plugin.bgbilling.proto.model.inet.InetService");
       service.setContractId(contractId);
       service.setStatus(0);
       service.setTypeId({@SERVICE_INET_TYPE});
       service.setDeviceId(device.getId());
       service.setVlan(vlan);
       service.setIpResId(addr.getResId());
       service.setAddrFrom(addr.getFrom());
       service.setAddrTo(addr.getTo());
       service.setLogin("");
       service.setIfaceId(u.parseInt(port));
       service.setDateFrom(curdate);
       inetDao.updateService(service, null, true, true, 0L);
       // группа тарифов
       if (tariffDao.contractTariffGroupList(contractId).isEmpty()) {
          // TODO: зависимость от типа устройства
          tariffDao.updateContractTariffGroup(0, contractId, {@TARIFF_GROUP_1}, curdate, null, "Мастер");
       }
   }
   else
       message = "Сервис существует";

   // абонплата
   /*npayId = 0;
   npayServ = u.getFirst(npayDao.getServiceList(contractLink.getLinkedObjectId()))
   if (npayServ != null) npayId = npayServ.getId();
   npayDao.updateService(npayId, contractLink.getLinkedObjectId(), {@SERVICE_NPAY}, curdate, null, 0, 1, "Мастер");*/

   // открытие статуса
   statusDao.updateStatus(contractLink.getLinkedObjectId(), {@CONTRACT_STATUS_ACTIVE}, curdate, null, "Мастер");

   // TODO: Проверка договора, тарифа и т.п.
   return {"filled": true, "message": message};
END
#
createWizard.step.{@inc:cnt}.title=Тарифный план
createWizard.step.{@cnt}.class=ru.bgcrm.plugin.bgbilling.model.process.wizard.SetContractTariffStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
#
createWizard.step.{@inc:cnt}.title=Параметры договора
createWizard.step.{@cnt}.class=ru.bgcrm.plugin.bgbilling.model.process.wizard.FillParamsStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
createWizard.step.{@cnt}.parameterIds={@CONTRACT_PARAMS}
createWizard.step.{@cnt}.checkParamIds=
#
createWizard.step.{@inc:cnt}.title=Использованные материалы
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.FillParamsStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
createWizard.step.{@cnt}.parameterIds={@PARAM_MAT}
createWizard.step.{@cnt}.checkParamIds={@PARAM_MAT}
#
createWizard.step.{@inc:cnt}.title=Исполнитель
createWizard.step.{@cnt}.class=ru.bgcrm.model.process.wizard.SetExecutorsStep
createWizard.step.{@cnt}.checkExpression=process.getStatusId() == {@STATUS_WIZARD}
#
#
##### скопировано из существующих типов #####
#
document:processShowDocuments=1
document:processCreateDocumentsAllowedTemplates+=,1
#
hideDescriptionChange=1
show.tab.messages=1
show.tab.links.process=1
show.tab.links=1
#
# проверка заполненных параметров
#requireFillParamIdsBeforeStatusSet.11=5,6,7,27,10
requireFillParamIdsBeforeStatusSet.12=11,10
requireFillParamIdsBeforeStatusSet.17=27
requireFillParamIdsBeforeStatusSet.15=25
#
# строка в буфере
processReference.1.objectTypes=processCard
processReference.1.stringExpression="<span class='title'>П/ФЛ/МКД # " + process.getId() +  " " +  "</span><span>" + u.escapeXml( process.getDescription() )  + "</span>"
#
# cокрытие параметра 36 во всех статусах кроме 11 и 21
hideParamIdsInStatus.1=36
hideParamIdsInStatus.29=36
hideParamIdsInStatus.20=36
hideParamIdsInStatus.15=36
hideParamIdsInStatus.3=36
hideParamIdsInStatus.26=36
hideParamIdsInStatus.16=36
hideParamIdsInStatus.12=36
hideParamIdsInStatus.17=36
hideParamIdsInStatus.2=36
#