Package ru.bitel.bgbilling.modules.license.server.bean

# Class LicenseManager

java.lang.Object
ru.bitel.bgbilling.kernel.base.server.logger.BGLogger
ru.bitel.common.dao.AbstarctDaoConstant
ru.bitel.bgbilling.modules.license.server.bean.LicenseManager

public class LicenseManager extends ru.bitel.common.dao.AbstarctDaoConstant
Класс-менеджер для обработки экшэнов лицензии

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected Connection`
  `con`
  `protected int`
  `moduleId`

  ### Fields inherited from class ru.bitel.common.dao.AbstarctDaoConstant

  `ERROR, fields, SQL_ALL, SQL_AND, SQL_CALC_FOUND_ROWS, SQL_DELETE, SQL_DISTINCT, SQL_EQ, SQL_EQCS, SQL_FROM, SQL_GROUP, SQL_IN, SQL_INSERT, SQL_JOIN, SQL_LEFT_JOIN, SQL_LIMIT, SQL_NOT_IN, SQL_ON, SQL_ON_DUPLICATE_KEY_UPDATE, SQL_ORDER, SQL_SELECT, SQL_SET, SQL_UPDATE, SQL_VALUES, SQL_WHERE`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `LicenseManager(Connection con, int moduleId)`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `checkCopyItemStatus(int copyItemId)`
  Проверяет, является ли статус для заказа данного компонента "выполнен" (если куплен) или "подтвержден" (если тестовый)
  `boolean`
  `checkHaveNonSignAdditionalAgreement(int copyId)`
  Проверка, есть ли не подписанный допик.
  `protected void`
  `closeConnection(Connection con)`
  `int`
  `createLicense(License lic)`
  `void`
  `createTestCopiesForOrder(Order order, int term, int count)`
  `void`
  `deleteAdditionalAgreement(int idAdditionalAgreement)`
  Удалит доп. соглашение из базе
  `void`
  `deleteComponent(int id)`
  `void`
  `deleteComponents(int productId)`
  `void`
  `deleteOrder(int orderId)`
  `void`
  `deleteProduct(int productId)`
  `List<ContractData>`
  `doContractData(int productId, int componentId)`
  select distinct c.id, title, c.comment from lic_order_154 as a left join lic_copy_154 as b on a.copy_id=b.id and product_id=20 left join contract as c on c.id=contract_id where component_id=28
  `AdditionalAgreement`
  `getAdditionalAgreement(int id)`
  Вернет допик по его ид
  `Component`
  `getComponent(int id)`
  `Component`
  `getComponent(String name)`
  `List<Component>`
  `getComponentList()`
  Получает список всех компонентов.
  `List<Component>`
  `getComponentList(int copyId, boolean showHidden, Boolean availableOnWeb)`
  Получает список всех компонентов для заданной копии продукта.
  `List<Component>`
  `getComponentsForProduct(int productId)`
  `List<Contract>`
  `getContractByTitlePart(String titlePart)`
  Возвращает договоры, номера которых начинаются с заданной подстроки.
  `String`
  `getContractComment(int contractId)`
  `Copy`
  `getCopy(int copyId)`
  `Map<Integer,int[]>`
  `getCopyCountForComponentByProductMap(int productId)`
  находим в скольких копиях продукта встречается компонент select component_id, count(copy_id) from lic_order_16 where type=0 and status=2 and copy_id in (select id from lic_copy_16 where product_id=3) group by component_id unlimited select component_id, count(copy_id) from lic_order_16 where type=1 and status=2 and count=0 and copy_id in (select id from lic_copy_16 where product_id=3) group by component_id SELECT component_id, SUM(count) FROM lic_order_16 WHERE type=1 AND status=2 AND count=0 AND copy_id IN ( SELECT id FROM lic_copy_16 WHERE product_id=3 ) AND concat(copy_id,' ',component_id) NOT IN ( SELECT concat(copy_id,' ',component_id) FROM lic_order_16 WHERE count=0 AND type=1 AND status=2 ) GROUP BY component_id
  `int[]`
  `getCopyItemIds(int copyId)`
  `List<ConfirmedOrder>`
  `getCopyItems(int copyId, int filter)`
  Получает список экземпляров компонентов для указанной копии продукта.
  `List<ConfirmedOrder>`
  `getCopyItemsFromPackage(int packageId)`
  `List<Copy>`
  `getCopyList(int contractId)`
  Получает список копий продукта для заданного договора.
  `License`
  `getCurrentLicense(int copyId)`
  Получает текущую лицензию для заданной копии.
  `BigDecimal`
  `getDiscount(int contractId, int copyId)`
  Вернет скидку(ну или ту сумму которую они уже оплатили и которую необходимо учитовать).
  `int`
  `getLastNumber(int contractId)`
  Вернет максимальный номер допика для соответсвующего контракта.
  `License`
  `getLicenseById(int licenseId)`
  Получает текущую лицензию для заданной копии.
  `List<ConfirmedOrder>`
  `getLicenseItems(int licenseId, boolean testDateForNow)`
  `List<License>`
  `getLicenses(int copyId)`
  Получает список лицензий для заданной копии продукта
  `String`
  `getLicenseText(int licenseId)`
  `List<AdditionalAgreement>`
  `getListAdditionalAgreement(int contractId, int copyId)`
  `Order`
  `getOrder(int orderId)`
  `int`
  `getOrderIdFromConfirmedId(int condirmedOrderId)`
  возращает код заказа для потвержденного заказа
  `List<Order>`
  `getOrders(int copyId)`
  `List<Order>`
  `getOrders(int copyId, String filterPermanentStatus, String filterTestStatus, int filterComponentItemId)`
  Если все 3 фильтра незначимые (filterPermanentStatus=null ,filterTestStatus=null ,filterComponentItemId=-1 ), то выведит все заказы.
  `List<Order>`
  `getOrders(int copyId, List<OrderType> filterTypes, List<Integer> statusIds, int filterComponentItemId)`
  `int`
  `getOrdersCountOnComponent(int componentId)`
  `int`
  `getOrdersCountOnProduct(int productId)`
  `int`
  `getOrderStatus(int id)`
  `int`
  `getOrderType(int id)`
  `String`
  `getOrganizationTitle(int contractId, int fullOrganizationNameParamId)`
  Получает наименование организации.
  `String`
  `getOriginalLicenseText(int licenseId)`
  `Product`
  `getProduct(int productId)`
  `List<Product>`
  `getProducts()`
  `List<Product>`
  `getProductsWithComponent(int componentId)`
  `List<SpecificationTitle>`
  `getSpecificationOfAdditionalAgreement(int id)`
  Вернет список всех компонентов соответсвующего допика.
  `ConfirmedOrder`
  `groupCopyItems(int productItemId, int copyId, int[] orderStatuses)`
  Получает информацию заказанных компонентах ( id компонента, название компонента, количество) по заданному id компонента, группируя все заказы на данный компонент
  `protected int`
  `lastInsertId(PreparedStatement ps)`
  `void`
  `linkComponentToProduct(int productId, int componentId)`
  `void`
  `resetCopyDiscount(int contractId, int productCopyId)`
  `void`
  `setAdditionalAgreement(int contractId, AdditionalAgreement additionalAgreement)`
  Сохранит доп. соглашение в базе
  `void`
  `setCharge(int id, int chargeId)`
  Установит ид расхода у допика.
  `void`
  `setDiscount(BigDecimal discount, int contractId, int copyId)`
  Установим скидку для конткретного договора и продукта.
  `void`
  `setInvoice(int id, int invoiceId)`
  `void`
  `setStatusSigned(int id)`
  Установит статус "Подписано"
  `void`
  `unlinkComponentFromProduct(int productId, int componentId)`
  `void`
  `updateAdditionalAgreement(int contractId, AdditionalAgreement additionalAgreement)`
  `void`
  `updateComponent(Component component)`
  `void`
  `updateCopy(Copy copy)`
  `void`
  `updateCopyItem(ConfirmedOrder copyItem)`
  Создает записи о компонентах, входящих в состав заданной копии продукта.
  `void`
  `updateCopyItemOrder(Order order)`
  Создает или обновляет заказ
  `void`
  `updateCopyItemOrder(Order order, boolean updateConfirmed)`
  Создает или обновляет заказ
  `void`
  `updateCopyItemOrder(Order order, Date copyItemToDate)`
  `void`
  `updateLicenseData(License lic)`
  `void`
  `updateProduct(Product product)`
  Создает или обновляет запись о продукте.
  `void`
  `updateTestComponentDateTo(int orderId, Date dateTo)`
  Обновляет дату окончания действия лицензии на тестовый компонент.

  ### Methods inherited from class ru.bitel.common.dao.AbstarctDaoConstant

  `getSQLOrder, psSetDate, psSetInt, psSetString, sqlLimit`

  ### Methods inherited from class ru.bitel.bgbilling.kernel.base.server.logger.BGLogger

  `error, error, error, getLogger, logError, logError`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### con

    protected Connection con

  - ### moduleId

    protected int moduleId

- ## Constructor Details

  - ### LicenseManager

    public LicenseManager(Connection con, int moduleId)

- ## Method Details

  - ### updateProduct

    public void updateProduct(Product product) throws ru.bitel.bgbilling.common.BGException
    Создает или обновляет запись о продукте.
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### deleteProduct

    public void deleteProduct(int productId)

  - ### getProduct

    public Product getProduct(int productId)

  - ### getOrdersCountOnProduct

    public int getOrdersCountOnProduct(int productId)

  - ### getProductsWithComponent

    public List<Product> getProductsWithComponent(int componentId) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### updateComponent

    public void updateComponent(Component component) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### deleteComponent

    public void deleteComponent(int id)

  - ### deleteComponents

    public void deleteComponents(int productId)

  - ### getComponent

    public Component getComponent(int id)

  - ### getComponent

    public Component getComponent(String name)

  - ### getComponentList

    public List<Component> getComponentList()
    Получает список всех компонентов.

  - ### getComponentList

    public List<Component> getComponentList(int copyId, boolean showHidden, Boolean availableOnWeb)
    Получает список всех компонентов для заданной копии продукта.
    Parameters:
      `copyId` - - код копии
      `showHidden` - - если true, то в список будут включены компоненты, отмеченные как 'скрытые'
    Returns:

  - ### getOrdersCountOnComponent

    public int getOrdersCountOnComponent(int componentId)

  - ### getComponentsForProduct

    public List<Component> getComponentsForProduct(int productId)

  - ### linkComponentToProduct

    public void linkComponentToProduct(int productId, int componentId)

  - ### unlinkComponentFromProduct

    public void unlinkComponentFromProduct(int productId, int componentId)

  - ### updateCopy

    public void updateCopy(Copy copy)

  - ### getCopy

    public Copy getCopy(int copyId) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### updateCopyItem

    public void updateCopyItem(ConfirmedOrder copyItem)
    Создает записи о компонентах, входящих в состав заданной копии продукта.

  - ### updateCopyItemOrder

    public void updateCopyItemOrder(Order order) throws ru.bitel.bgbilling.common.BGException, ru.bitel.bgbilling.common.BGMessageException
    Создает или обновляет заказ
    Throws:
      `ru.bitel.bgbilling.common.BGMessageException` - - если кол-во общих заказов привысит unlim
      `ru.bitel.bgbilling.common.BGException`

  - ### updateCopyItemOrder

    public void updateCopyItemOrder(Order order, boolean updateConfirmed) throws ru.bitel.bgbilling.common.BGException, ru.bitel.bgbilling.common.BGMessageException
    Создает или обновляет заказ
    Throws:
      `ru.bitel.bgbilling.common.BGMessageException` - - если кол-во общих заказов привысит unlim
      `ru.bitel.bgbilling.common.BGException`

  - ### updateCopyItemOrder

    public void updateCopyItemOrder(Order order, Date copyItemToDate) throws ru.bitel.bgbilling.common.BGException, ru.bitel.bgbilling.common.BGMessageException
    Throws:
      `ru.bitel.bgbilling.common.BGException`
      `ru.bitel.bgbilling.common.BGMessageException`

  - ### getOrderStatus

    public int getOrderStatus(int id)

  - ### getOrderType

    public int getOrderType(int id)

  - ### getOrders

    public List<Order> getOrders(int copyId, List<OrderType> filterTypes, List<Integer> statusIds, int filterComponentItemId)

  - ### getOrders

    public List<Order> getOrders(int copyId, String filterPermanentStatus, String filterTestStatus, int filterComponentItemId)
    Если все 3 фильтра незначимые (filterPermanentStatus=null ,filterTestStatus=null ,filterComponentItemId=-1 ), то выведит все заказы.
    Parameters:
      `copyId` -
      `filterPermanentStatus` - - фильтр для "постоянных" заказов в виде 0,1,2 или 2,1 или 0 , где в скобках соответсвующий id (0-новый , 1-отказано, 2 -выполнен). Если передать null или пустую строку, фильтр не будет выводить "постоянные" заказы.
      `filterTestStatus` - - фильтр для "тестовых" заказов в виде 0,1,3 или 3,1 или 0 , где в скобках соответсвующий id (0-новый , 1-отказано, 3 -подтвержден). Если передать null или пустую строку, фильтр не будет выводить "тестовые" заказы.
      `filterComponentItemId` - - id компонента, фильтр по компоненту ну там id email или id ipn или id npay ну и т.д. или -1 если фильтр по нему не нужен.
    Returns:
      - отфильтрованный лист заказов

  - ### getOrders

    public List<Order> getOrders(int copyId)

  - ### getOrder

    public Order getOrder(int orderId)

  - ### createTestCopiesForOrder

    public void createTestCopiesForOrder(Order order, int term, int count) throws ru.bitel.bgbilling.common.BGException, ru.bitel.bgbilling.common.BGMessageException
    Throws:
      `ru.bitel.bgbilling.common.BGException`
      `ru.bitel.bgbilling.common.BGMessageException`

  - ### deleteOrder

    public void deleteOrder(int orderId)

  - ### checkCopyItemStatus

    public boolean checkCopyItemStatus(int copyItemId)
    Проверяет, является ли статус для заказа данного компонента "выполнен" (если куплен) или "подтвержден" (если тестовый)
    Parameters:
      `copyItemId` -
    Returns:

  - ### checkHaveNonSignAdditionalAgreement

    public boolean checkHaveNonSignAdditionalAgreement(int copyId) throws ru.bitel.bgbilling.common.BGException
    Проверка, есть ли не подписанный допик.
    Parameters:
      `copyId` - - ид копии продукта.
    Returns:
      - true, если есть не подписанный.
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### createLicense

    public int createLicense(License lic)

  - ### updateLicenseData

    public void updateLicenseData(License lic)

  - ### groupCopyItems

    public ConfirmedOrder groupCopyItems(int productItemId, int copyId, int[] orderStatuses)
    Получает информацию заказанных компонентах ( id компонента, название компонента, количество) по заданному id компонента, группируя все заказы на данный компонент
    Parameters:
      `productItemId` -
    Returns:
    Throws:
      `SQLException`

  - ### getLicenses

    public List<License> getLicenses(int copyId)
    Получает список лицензий для заданной копии продукта
    Parameters:
      `copyId` - - id копии продукта
    Returns:
      - список пакетов

  - ### getCurrentLicense

    public License getCurrentLicense(int copyId)
    Получает текущую лицензию для заданной копии. Текущей лицензией является последняя сгенерированная пользователем лицензия, то есть при наличии нескольких лицензий выбирается та, у которой дата создания самая поздняя.
    Parameters:
      `copyId` - - id копии продукта.
    Returns:
      - текущая лицензия

  - ### getLicenseById

    public License getLicenseById(int licenseId)
    Получает текущую лицензию для заданной копии. Текущей лицензией является последняя сгенерированная пользователем лицензия, то есть при наличии нескольких лицензий выбирается та, у которой дата создания самая поздняя.
    Parameters:
      `copyId` - - id копии продукта.
    Returns:
      - текущая лицензия

  - ### getLicenseItems

    public List<ConfirmedOrder> getLicenseItems(int licenseId, boolean testDateForNow)
    Parameters:
      `licenseId` -
      `testDate` - - если true, то не будут выведены тестовые дата завершения которых меньше текущей даты.
    Returns:

  - ### getCopyList

    public List<Copy> getCopyList(int contractId)
    Получает список копий продукта для заданного договора.
    Parameters:
      `contractId` - - id договора
    Returns:
      - список копий

  - ### getCopyItems

    public List<ConfirmedOrder> getCopyItems(int copyId, int filter) throws ru.bitel.bgbilling.common.BGException
    Получает список экземпляров компонентов для указанной копии продукта.
    Parameters:
      `copyId` - - id копии продукта
      `filter` - - если 0, то в список попадают только компоненты с наибольшим количеством если 1 - только купленные компоненты если 2 - все компоненты
    Returns:
      - список экземпляров модулей
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getCopyItemIds

    public int[] getCopyItemIds(int copyId) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getProducts

    public List<Product> getProducts() throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getContractByTitlePart

    public List<Contract> getContractByTitlePart(String titlePart) throws ru.bitel.bgbilling.common.BGException
    Возвращает договоры, номера которых начинаются с заданной подстроки. Позволяет искать договор по номеру без указания года.
    Parameters:
      `title` - номер договора
    Returns:
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### updateTestComponentDateTo

    public void updateTestComponentDateTo(int orderId, Date dateTo)
    Обновляет дату окончания действия лицензии на тестовый компонент. Обновляются только те компоненты, для которых новая дата позже текущей даты окончания лицензии.
    Parameters:
      `orderId` - - код заказа, для которого продливается тестовая лицензия.
      `dateTo` - - новая дата окончания действия лицензии.

  - ### getCopyItemsFromPackage

    public List<ConfirmedOrder> getCopyItemsFromPackage(int packageId)

  - ### getOrganizationTitle

    public String getOrganizationTitle(int contractId, int fullOrganizationNameParamId)
    Получает наименование организации.
    Parameters:
      `contractId` - - id договора
      `fullOrganizationNameParamId` - - id параметра, содержащего полное наименование организации
    Returns:
      наименование организации

  - ### getContractComment

    public String getContractComment(int contractId)

  - ### getLicenseText

    public String getLicenseText(int licenseId)

  - ### getOriginalLicenseText

    public String getOriginalLicenseText(int licenseId)

  - ### lastInsertId

    protected int lastInsertId(PreparedStatement ps) throws SQLException
    Throws:
      `SQLException`

  - ### closeConnection

    protected void closeConnection(Connection con)

  - ### getListAdditionalAgreement

    public List<AdditionalAgreement> getListAdditionalAgreement(int contractId, int copyId) throws ru.bitel.bgbilling.common.BGException
    Parameters:
      `cid` - - id договора
    Returns:
      Список всех доп.соглошений для соответсвующего договора.
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getAdditionalAgreement

    public AdditionalAgreement getAdditionalAgreement(int id) throws ru.bitel.bgbilling.common.BGException
    Вернет допик по его ид
    Parameters:
      `id` -
    Returns:
      допик
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### setAdditionalAgreement

    public void setAdditionalAgreement(int contractId, AdditionalAgreement additionalAgreement) throws ru.bitel.bgbilling.common.BGException
    Сохранит доп. соглашение в базе
    Parameters:
      `additionalAgreement` - - доп. соглашение которое было создано
      `contractId` - - номер договора к которому приписываем д.с.
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### updateAdditionalAgreement

    public void updateAdditionalAgreement(int contractId, AdditionalAgreement additionalAgreement) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### deleteAdditionalAgreement

    public void deleteAdditionalAgreement(int idAdditionalAgreement) throws ru.bitel.bgbilling.common.BGException
    Удалит доп. соглашение из базе
    Parameters:
      `idAdditionalAgreement` - - ид. удаляемого допика
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### resetCopyDiscount

    public void resetCopyDiscount(int contractId, int productCopyId) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getSpecificationOfAdditionalAgreement

    public List<SpecificationTitle> getSpecificationOfAdditionalAgreement(int id) throws ru.bitel.bgbilling.common.BGException
    Вернет список всех компонентов соответсвующего допика.
    Parameters:
      `id` - ид допика, у которого будет взят SpecificationTitle
    Returns:
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getLastNumber

    public int getLastNumber(int contractId) throws ru.bitel.bgbilling.common.BGException
    Вернет максимальный номер допика для соответсвующего контракта. Если номера еще нет то вернет -1
    Parameters:
      `contractId` -
    Returns:
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getDiscount

    public BigDecimal getDiscount(int contractId, int copyId) throws ru.bitel.bgbilling.common.BGException
    Вернет скидку(ну или ту сумму которую они уже оплатили и которую необходимо учитовать). Она необхадима для вывода суммы при создание первого доп.согл. и для информирования в дальнейшем.
    Parameters:
      `contractId` -
      `copyId` -
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### setDiscount

    public void setDiscount(BigDecimal discount, int contractId, int copyId) throws ru.bitel.bgbilling.common.BGException
    Установим скидку для конткретного договора и продукта.
    Parameters:
      `discount` - - скидка
      `contractId` - - номер договоро
      `copyId` - - код копии продукта
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### setStatusSigned

    public void setStatusSigned(int id) throws ru.bitel.bgbilling.common.BGException
    Установит статус "Подписано"
    Parameters:
      `id` - - ид доп. соглошения
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### setCharge

    public void setCharge(int id, int chargeId) throws ru.bitel.bgbilling.common.BGException
    Установит ид расхода у допика.
    Parameters:
      `id` - - ид допика.
      `chargeId` - - ид расхода.
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### setInvoice

    public void setInvoice(int id, int invoiceId) throws ru.bitel.bgbilling.common.BGException
    Throws:
      `ru.bitel.bgbilling.common.BGException`

  - ### getOrderIdFromConfirmedId

    public int getOrderIdFromConfirmedId(int condirmedOrderId)
    возращает код заказа для потвержденного заказа

  - ### getCopyCountForComponentByProductMap

    public Map<Integer,int[]> getCopyCountForComponentByProductMap(int productId)
    находим в скольких копиях продукта встречается компонент select component_id, count(copy_id) from lic_order_16 where type=0 and status=2 and copy_id in (select id from lic_copy_16 where product_id=3) group by component_id unlimited select component_id, count(copy_id) from lic_order_16 where type=1 and status=2 and count=0 and copy_id in (select id from lic_copy_16 where product_id=3) group by component_id SELECT component_id, SUM(count) FROM lic_order_16 WHERE type=1 AND status=2 AND count=0 AND copy_id IN ( SELECT id FROM lic_copy_16 WHERE product_id=3 ) AND concat(copy_id,' ',component_id) NOT IN ( SELECT concat(copy_id,' ',component_id) FROM lic_order_16 WHERE count=0 AND type=1 AND status=2 ) GROUP BY component_id

  - ### doContractData

    public List<ContractData> doContractData(int productId, int componentId)
    select distinct c.id, title, c.comment from lic_order_154 as a left join lic_copy_154 as b on a.copy_id=b.id and product_id=20 left join contract as c on c.id=contract_id where component_id=28
    Parameters:
      `productId` -
      `componentId` -
    Returns: