Top.Mail.Ru
26 февраля в 17:00 МСК
онлайн-митап
Как мы перенесли игру «Герои меча и магии 3» на 1С

Cоздание SSRS-отчета в Microsoft Dynamics 365 Finance and Operations

SSRS-отчеты (SQL Server Reporting Services) в Microsoft Dynamics 365 Finance and Operations (D365 F&O) используются для создания сложных отчетов с высокой гибкостью. Тип источника данных Report Data Provider (RDP) предоставляет возможность обрабатывать данные в X++ до их передачи в отчет.
Эта инструкция подробно описывает процесс создания такого отчета.

Создаём Query (необязательный шаг)

Query определяет параметры, которые пользователь может изменить при выполнении отчета.

Query

Создание класса контракта (Data Contract) (необязательный шаг)

Контракт определяет параметры, которые пользователь будет задавать при выполнении отчета.

  1. Создайте новый класс, например, InventCountingContract:
    1. Щелкните правой кнопкой мыши по проекту → Add > New Item > Class.
    2. Включите атрибуты [DataContractAttribute] для класса и [DataMemberAttribute] для его полей:
    3. Поля с атрибутом [DataMemberAttribute] будут отображаться на форме параметров отчета.
  2. Добавьте столько полей, сколько требуется для параметров вашего отчета.
[DataContractAttribute]
public class InventCountingContract
{
    boolean                 fillCounted;
	
    str                     sysVersion;
    DirPartyName            userName;
    LogisticsAddressing     companyAddress;

    [
        DataMemberAttribute(identifierStr(FillCounted)),
        SysOperationLabelAttribute(literalstr("Counted")),
        SysOperationHelpTextAttribute(literalstr("Counted "))
    ]
    public boolean parmFillCounted(boolean _fillCounted = fillCounted)
    {
        fillCounted = _fillCounted;
        return fillCounted;
    }

    [
        DataMemberAttribute(identifierStr(SysVersion))
    ]
    public Description255 parmSysVersion(str _sysVersion = sysVersion)
    {
        sysVersion = _sysVersion;
        return sysVersion;
    }

    [
        DataMemberAttribute(identifierStr(UserName))
    ]
    public DirPartyName parmUserName(DirPartyName _userName = userName)
    {
        userName = _userName;
        return userName;
    }

    [
        DataMemberAttribute(identifierStr(CompanyAddress))
    ]
    public LogisticsAddressing parmCompanyAddress(LogisticsAddressing _companyAddress = companyAddress)
    {
        companyAddress = _companyAddress;
        return companyAddress;
    }
}

Создание временной таблицы

Временная таблица используется для хранения промежуточных данных, которые передаются в SSRS.

  1. Создайте новую таблицу (Add > New Item > Table):
    • Назовите её, например, InventCountingTmp.
    • В свойствах таблицы установите TableType = TempDB.
    • Добавьте необходимые поля.
    • Настройте свойства полей:
Таблица

Для каждого поля задайте понятные названия, чтобы их было удобно использовать в отчетах.

Создание класса для обработки данных (Data Provider)

Класс Data Provider (DP) отвечает за выборку и подготовку данных для отчета.
В вашем проекте создайте новый класс:
• Щелкните правой кнопкой мыши по проекту → Add > New Item > Class.
• Назовите класс, например, InventCountingDP.
Унаследуйте класс от SrsReportDataProviderBase и добавьте атрибут [SRSReportParameterAttribute] и SRSReportQueryAttribute, из шагов 1 и 2, они не обязательны, но в данном примере они есть:

[
    SRSReportParameterAttribute(classstr(InventCountingContract)),
    SRSReportQueryAttribute(queryStr(InventCounting))
]
public class InventCountingDP extends SrsReportDataProviderPreProcessTempDB
{
    InventCountingTmp         inventCountingTmp;
    
    [
        SRSReportDataSetAttribute(tableStr(InventCountingTmp))
    ]
    public InventCountingTmp getInventCountingTmp()
    {
        select inventCountingTmp;
        return inventCountingTmp;
    }

    public void processReport()
    {
        InventJournalTrans                          inventJournalTrans;
        InventJournalTable                          inventJournalTable;
        InventDim                                   inventDim;
        QueryRun                                    queryRun;
        RecordInsertList                            recInsInventCountingTmp;
        InventCountingContract            			contract = this.parmDataContract();

        recInsInventCountingTmp = new RecordInsertList(tableNum(InventCountingTmp),
                                                          false, false, false, false, false,
                                                          inventCountingTmp);
        
        queryRun = new QueryRun(this.parmQuery());

        while (queryRun.next())
        {
            inventJournalTable = queryRun.get(tableNum(InventJournalTable)) as InventJournalTable;
            inventJournalTrans = queryRun.get(tableNum(InventJournalTrans)) as InventJournalTrans;
            inventDim = queryRun.get(tableNum(InventDim)) as InventDim;
                        
            inventCountingTmp.InventJournalCountId                      = inventJournalTable.InventJournalCountId_;
            inventCountingTmp.CntTypeId                                 = inventJournalTable.CntTypeId_;
            inventCountingTmp.Description                               = inventJournalTable.Description;
            inventCountingTmp.InventLocationId                          = inventJournalTable.InventLocationId;
            inventCountingTmp.JournalDate                               = inventJournalTable.JournalDate_;
            inventCountingTmp.ItemId                                    = inventJournalTrans.ItemId;
            inventCountingTmp.ItemName                                  = inventJournalTrans.itemName();
            inventCountingTmp.InventBatchId                             = inventDim.inventBatchId;
            inventCountingTmp.UnitId                                    = inventJournalTrans.unitId();
            inventCountingTmp.AverageCostPriceUnit                      = InventSum::find(InventJournalTrans.ItemId, InventJournalTrans.InventDimId).averageCostPrice();
            inventCountingTmp.Counted                                   = contract.parmFillCounted() ? inventJournalTrans.Counted : 0;
            inventCountingTmp.Qty                                       = inventJournalTrans.Qty;
            inventCountingTmp.Total                                     = inventCountingTmp.AverageCostPriceUnit * inventCountingTmp.Qty;

            recInsInventCountingTmp.add(inventCountingTmp);
        }

        recInsInventCountingTmp.insertDatabase();
    }

}

• Метод processReport() используется для обработки данных, которые будут помещены во временную таблицу, созданную в шаге 3.
• Метод getInventCountingTmp() с атрибутом SRSReportDataSetAttribute. Атрибут SRSReportDataSetAttribute в D365 F&O используется для связывания метода класса с набором данных (DataSet) в SSRS отчете. Этот атрибут указывает SSRS, что метод возвращает данные, которые могут быть использованы в качестве источника данных для отчета.

Регистрация отчета в AOT

  1. В Visual Studio добавьте объект Report:
    • Щелкните правой кнопкой мыши на проекте → Add > New Item > Report.
    • Назовите отчет, например, InventCounting.
    • Создайте DataSet, укажите класс InventCountingDP, который мы создали в шаге 4.
    • Если вы создавали Query в шаге 1, то укажите параметр Dynamics Filters = True на DataSet, этот параметр отвечает за возможность изменения запроса через диалог.
Свойства отчета

• Создайте дизайн и настройте его.
• Настройте свойства отчета.

Отчет

Создание класса Controller (необязательный)

  1. В Visual Studio создайте новый класс (правой кнопкой мыши на проекте → Add > New Item > Class) и назовите его, например, InventCountingController.
  2. Унаследуйте его от SrsReportRunController:
public class InventCountingController extends SrsReportRunController
{
    protected void prePromptModifyContract()
    {
        this.parmDialogCaption("Physical inventory sheet");
    }

    protected void preRunModifyContract()
    {
        InventCountingContract			contract = this.parmReportContract().parmRdpContract() as InventCountingContract;


        contract.parmSysVersion(SysReportRun::sysVersion());
        contract.parmUserName(SysReportRun::userName());
    }

    public static void main(Args _args)
    {
        InventCountingController controller = new InventCountingController();
        controller.parmArgs(_args);
        controller.parmReportName(ssrsReportStr(InventCounting, Report));
        controller.startOperation();
    }
}

В этом классе:
• Метод prePromptModifyContract позволяет изменить значения контракта (параметров) отчета до того, как пользователю будет показана форма ввода параметров. Этот метод вызывается до отображения окна с параметрами, предоставляя разработчику возможность задать значения по умолчанию или модифицировать их в зависимости от контекста выполнения.

• Метод preRunModifyContract используется для модификации параметров отчета перед запуском обработки данных и непосредственно перед выполнением отчета. Это позволяет внести изменения в контракт (набор параметров), уже заполненный пользователем или установленный системой, чтобы адаптировать данные перед передачей в Data Provider.

• Метод parmReportName связывает отчет с конкретным отчетом (InventCounting) и дизайном (Report).
• InventCounting — это отчет, указанная в AOT.
• Report — название дизайна отчета (RDL).
• Метод startOperation() запускает процесс выполнения отчета.

Создайте объект меню (Output Menu Item):

• В Application Explorer найдите User Interface > Menu Items > Output.
• Щелкните правой кнопкой мыши → Add Menu Item.
• В настройках меню, если вы не пропустили шаг 6, то тип объекта установите в Class и укажите имя класса контроллера (InventCountingController) в поле Object, если вы решили не создавать класс Controller, то тип объекта установите в SSRSReport, укажите имя отчета InventCounting в поле Object и выберите ваш дизайн (Report) в поле Report Design.
• Добавляем пункт меня в нужное вам место.

Развертывание и тестирование

  1. Разверните отчет:
    • В Visual Studio выполните Build проекта.
    • Нажмите Deploy для загрузки отчета в D365 Finance and Operations.
  2. Проверьте отчет в D365 Finance and Operations:
    • Откройте пользовательский интерфейс, где вызывается отчет.
    • Убедитесь, что параметры отображаются корректно, и данные заполняются из временной таблицы.
Диалог отчета
Отчет

Заключение

Эта инструкция охватывает все основные этапы создания RDP-отчета в Dynamics 365 Finance and Operations. Благодаря подходу RDP можно реализовать сложную логику обработки данных и гибко настроить их отображение.

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar