AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Функционал
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.11.2022, 14:01   #1  
MorpheusX is offline
MorpheusX
Участник
 
191 / 58 (2) ++++
Регистрация: 04.02.2022
ER Bank Statement MT940
Привет!
Речь пойдет об импорте банковской выписки из файла в формате MT940.

Содержимое файла разбивается на список строк начинающихся набором символов :20:.

Нажмите на изображение для увеличения
Название: MT940_Import_01.JPG
Просмотров: 54
Размер:	101.4 Кб
ID:	13495

Затем строки, содержащие набор символов :25:, присваиваются артефакту Statement.

Нажмите на изображение для увеличения
Название: MT940_Import_02.JPG
Просмотров: 46
Размер:	97.9 Кб
ID:	13496

Затем при помощи метода identifyBankAccount класса BankStatementBankAccountIdentify определяется банковский счет и юридическое лицо / компания.

Нажмите на изображение для увеличения
Название: MT940_Import_03.JPG
Просмотров: 54
Размер:	169.7 Кб
ID:	13497

Файл содержит транзакции разных банковских счетов но все транзакции из файла присваиваются во время импорта первому найденному банковскому счету. Почему?

Последний раз редактировалось MorpheusX; 11.11.2022 в 14:04.
Старый 14.11.2022, 16:50   #2  
MorpheusX is offline
MorpheusX
Участник
 
191 / 58 (2) ++++
Регистрация: 04.02.2022
Цитата:
Сообщение от MorpheusX Посмотреть сообщение
Файл содержит транзакции разных банковских счетов но все транзакции из файла присваиваются во время импорта первому найденному банковскому счету. Почему?
Проанализировав более тщательно Model mapping, пришел к выводу, что вероятно связь BankStatemenDocumentEntity: Record list = model в окне Data Model приводит к созданию одной строки для заголовка импортируемой выписки. Попробую изменить эти связь на BankStatemenDocumentEntity: Record list = model.Statement: Record list.

Нажмите на изображение для увеличения
Название: MT940_Import_04.JPG
Просмотров: 42
Размер:	172.5 Кб
ID:	13498
Старый 15.11.2022, 12:31   #3  
MorpheusX is offline
MorpheusX
Участник
 
191 / 58 (2) ++++
Регистрация: 04.02.2022
При отсутствии отладчика для импортируемых документов единственный способ отладки ER сущностей - построение гипотез и их проверка. На заре развития технологий такой подход был оправдан но не сейчас. Поэтому я принял решение "обойти" проблему и реализовать логику разбиения импортируемого файла и последующего импорта в расширении класса BankStatementImportBatch.
Старый 15.11.2022, 12:58   #4  
axm2017 is offline
axm2017
Участник
 
1,891 / 295 (13) ++++++
Регистрация: 15.05.2017
Цитата:
Сообщение от MorpheusX Посмотреть сообщение
При отсутствии отладчика для импортируемых документов единственный способ отладки ER сущностей - построение гипотез и их проверка.
Что мешает поставить точку остановки на ошибке в студии?


Цитата:
Сообщение от MorpheusX Посмотреть сообщение
На заре развития технологий такой подход был оправдан но не сейчас. .
А какой иной подход может быть?
Старый 15.11.2022, 14:25   #5  
MorpheusX is offline
MorpheusX
Участник
 
191 / 58 (2) ++++
Регистрация: 04.02.2022
Цитата:
Сообщение от axm2017 Посмотреть сообщение
Что мешает поставить точку остановки на ошибке в студии?
В ER доступен дебаггер, который pozvolyaet posmotret результат только для outbound-трансформации данных. В случае иморта данных увидеть inbound-трансформацию невозможно.

Цитата:
Сообщение от axm2017 Посмотреть сообщение
А какой иной подход может быть?
На заре развития, когда был только компилятор, отладочную информацию выводили из программы в файл. Трудоемкость отладки при таком подходе высокая.
Старый 15.11.2022, 14:36   #6  
axm2017 is offline
axm2017
Участник
 
1,891 / 295 (13) ++++++
Регистрация: 15.05.2017
Цитата:
Сообщение от MorpheusX Посмотреть сообщение
В ER доступен дебаггер, который pozvolyaet posmotret результат только для outbound-трансформации данных. В случае иморта данных увидеть inbound-трансформацию невозможно.
.
Причем здесь дебагер ER?
ER лишь модуль и часть ошибок вполне себе ловится на уровне точке останова поставленной в VS к примеру.

Цитата:
Сообщение от MorpheusX Посмотреть сообщение
На заре развития, когда был только компилятор, отладочную информацию выводили из программы в файл. Трудоемкость отладки при таком подходе высокая.
ER имеет скриптовый язык поэтому зачем/причем компилятор?
Фактически имеем редактор скриптов.
Старый 15.11.2022, 14:42   #7  
MorpheusX is offline
MorpheusX
Участник
 
191 / 58 (2) ++++
Регистрация: 04.02.2022
Цитата:
Сообщение от axm2017 Посмотреть сообщение
Причем здесь дебагер ER?
ER лишь модуль и часть ошибок вполне себе ловится на уровне точке останова поставленной в VS к примеру.
Задача стоит не ошибки ловить, а увидеть результат трансформации импортируемых данных.

Цитата:
Сообщение от axm2017 Посмотреть сообщение
ER имеет скриптовый язык поэтому зачем/причем компилятор?
Фактически имеем редактор скриптов.
Разве это важно при отладке код скомпилирован заранее или компилируется "на лету"? Как увидеть промежуточный результат работы скрипта?
Старый 16.11.2022, 13:40   #8  
MorpheusX is offline
MorpheusX
Участник
 
191 / 58 (2) ++++
Регистрация: 04.02.2022
Запилил вот такое расширение. Файл банковской выписки разбивается на отдельные файлы, по количеству секций начинающихся на :20:, и запаковывается в новый ZIP файл. При этом необходимо не забыть указать расширение файлов для импорта в поле BankStatementFormat.FileNameType, в моем случае это txt. Затем подменяем референсы с исходного файла на новый файл в ZIP формате и продолжаем выполнение стандартной логики импорта.

PHP код:
[ExtensionOf(classStr(BankStatementImportBatch))]
final class 
BankStatementImportBatch_Extension
{
    protected List 
importBankStatements()
    {
        
BankStatementFormat bankStatementFormat BankStatementFormat::find(bankStatementFormatRecId);
        
ERModelMappingTable erModelMappingTable ERModelMappingTable::find(bankStatementFormat.ERModelMappingTable);
        
        if (   
bankStatementFormat.UseGERConfiguration
            
&& strFind(erModelMappingTable.Name'MT940'0strLen(erModelMappingTable.Name)))
        {
            List 
splitUploadFileList this.splitUploadFileMT940(uploadFileId);
            
            
FileUploadTemporaryStorageResult fileUploadRet this.addFilesToZipArchive(splitUploadFileList);

            if (   
fileUploadRet != null
                
&& fileUploadRet.getUploadStatus())
            {
                
uploadFileId   fileUploadRet.getFileId();
                
uploadFileName fileUploadRet.getFileName();
                
uploadFileURL  fileUploadRet.getDownloadUrl();
            }
        }
        
        return 
next importBankStatements();
    }

    public List 
splitUploadFileMT940(str _fileId)
    {
        List 
ret = new List(Types::Container);

        
using (System.IO.Stream fileInputStream File::UseFileFromURL(DMFStagingWriter::getDownloadURLFromFileId(_fileId)))
        {
            
System.IO.StreamReader fileStreamReader = new System.IO.StreamReader(fileInputStreamSystem.Text.Encoding::GetEncoding(1252));
            
str                    fileInputContent fileStreamReader.ReadToEnd();
            
            
int fileInputContentLength strLen(fileInputContent);
            
str sectionHeader          '\:20\:';
            
int sectionStartIdx        0;
            
int sectionEndIdx          0;
            
int fileNum                0;

            
sectionStartIdx strFind(fileInputContentsectionHeadersectionStartIdxfileInputContentLength);

            while (
sectionEndIdx fileInputContentLength)
            {
                
sectionEndIdx strScan(fileInputContentsectionHeadersectionStartIdx strLen(sectionHeader), fileInputContentLength);
                
                if (!
sectionEndIdx)
                {
                    
sectionEndIdx fileInputContentLength;
                }

                
str sectionContent subStr(fileInputContentsectionStartIdxsectionEndIdx sectionStartIdx);
                
                
using (System.IO.Stream fileOutputStream = new System.IO.MemoryStream())
                {
                    
using (System.IO.StreamWriter fileOutputStreamWriter = new System.IO.StreamWriter(fileOutputStream))
                    {
                        
fileOutputStreamWriter.Write(sectionContent);
                        
fileOutputStreamWriter.Flush();
                
                        
fileNum++;

                        
FileUploadTemporaryStorageResult fileUploadRet File::SendFileToTempStore_GetResult(fileOutputStreamstrFmt('File_%1.txt'fileNum));

                        if (   
fileUploadRet != null
                            
&& fileUploadRet.getUploadStatus())
                        {
                            
ret.addEnd([fileUploadRet.getFileId(), fileUploadRet.getFileName()]);
                        }
                    }
                }
                
                
sectionStartIdx sectionEndIdx;
            }
        }

        return 
ret;
    }

    public 
FileUploadTemporaryStorageResult addFilesToZipArchive(List _fileList)
    {
        
FileUploadTemporaryStorageResult ret;

        
using (System.IO.MemoryStream zipStream = new System.IO.MemoryStream())
        {
            
using (System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(zipStreamSystem.IO.Compression.ZipArchiveMode::Createtrue))
            {
                
ListEnumerator fileListEnum _fileList.getEnumerator();

                while (
fileListEnum.moveNext())
                {
                    
str fileId;
                    
str fileName;

                    [
fileIdfileName] = fileListEnum.current();

                    
using (System.IO.MemoryStream file File::UseFileFromURL(DMFStagingWriter::getDownloadURLFromFileId(fileId)))
                    {
                        
System.IO.Compression.ZipArchiveEntry fileEntry zipArchive.CreateEntry(fileName);
                        
                        
using (System.IO.Stream fileEntryStream fileEntry.Open())
                        {
                            
file.CopyTo(fileEntryStream);
                        }
                    }
                }
            }

            
ret File::SendFileToTempStore_GetResult(zipStream'ArchiveFile.zip');
        }

        return 
ret;
    }



Последний раз редактировалось MorpheusX; 16.11.2022 в 14:46.
За это сообщение автора поблагодарили: EVGL (10).
Теги
d365, d365f&o, d365fo, dynamics ax, electronic reporting, er, ger, mt940

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
ER Bank statement MT940 MorpheusX DAX: Программирование 19 21.04.2022 12:40
emeadaxsupport: Import bank statement format MT940 Blog bot DAX Blogs 2 05.03.2018 19:56
stoneridgesoftware: Linking Your Bank Account to Dynamics 365 for Financials Blog bot DAX Blogs 0 05.07.2017 23:14
emeadaxsupport: Microsoft Dynamics AX – Setting up Bank statement import using format MT940 Blog bot DAX Blogs 0 19.04.2016 20:12
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 04:22.