Часто при разработке структуры таблиц нам не хватает поля, которое формируется автоматически. Например, возрастает при добавлении новой записи. Обычно производители СУБД предусматривают простенький механизм – счетчик (counter), который представляет собой числовое поле, автоматически увеличивающее значении при добавлении новой записи. В MBS Axapta к реализации данного механизма подошли довольно серьезно – простенький счетчик заменили номерные серии. Теперь - это уже текстовое поле, с возможностью изменения шаблонов автоматического формирования следующего значения и поддерживаний свойства непрерывности серий. Однако возросшие возможности повлекли за собой и трудности при использовании и настройке и данного механизма. Как правильно использовать номерные серии, и посвящена данная статья.
Нанеишвили Георгий (George Nordic), george_nordic@hotmail.com
Герань и нумераторы
Не надо бояться номерных серий в своих разработках – напротив, их надо активно использовать. Это очень удобный и легкий механизм, заменяющий в Axapta то, что в других системах обычно подразумевают под типом «counter», т.е. счетчик. Надо заметить, что в Axapta он:
- реализован достаточно гибко,
- позволяет делать множество настроек,
- комбинировать в себе числовой код с символьным префиксом/суффиксом,
- и, в частности, даже предварительно выделять группу номеров для увеличения производительности.
Серии документов представляют собой интервалы порядковых номеров документов, и при оформлении каждого нового документа (например, чека или накладной) его номер генерируется на основании шаблона из соответствующей номерной серии и последнего присвоенного значения.
Определение серий документов – это одна из первых задач, с которой придется столкнуться при настройке новой базы. Конечно, поначалу, бывает непонятно, почему при такой, казалось бы, невинной операции, как ввод нового клиента (или поставщика) возникает ошибка:
Но экстренное изучение документации и настроек системы обычно быстро раскрывают тайну и зачастую приводят к правильному решению - настройке номерной серии в «CRM» - «Настройки» - «Параметры» - «Номерные серии» - «Отношения» и «Код отношений». Вот так обычно и начинается наше знакомство с данным функционалом.
Серии документов
Серии задаются в форме: Серии документов. Вы можете найти эту форму в «Основное» - «Настройки» - «Серии документов».
Перечень полей в таблице номерных серий:
| Поле | Описание |
Код серии документов |
Здесь задается код серии документов. О правилах формирования кода– немного ниже. |
Название |
Название серии документов |
Минимум |
С этого номера начнется автоматическое увеличение номера серии. По умолчанию предлагается 1. |
Максимум |
Максимальный номер серии документов. Очень важно распланировать различные серии документов так, чтобы номера документов не перекрывались, по крайней мере, в течение нескольких лет.
|
Следующий |
Следующий номер, который будет использоваться. Поле заполняется системой автоматически, но вы можете изменить его значение |
Формат |
Укажите формат номера. Например, вы можете использовать буквы в качестве префикса |
Используется |
Данное поле отмечено, если номерная серия уже используется |
Вручную |
Запретить автоматическое нумерацию. Пользователь должен вводить номер документа вручную |
Непрерывная |
Признак непрерывной серии. При данной настройке система следит за тем, что бы серия документов использовалась без разрывов в нумерации. |
Уменьшение номера |
Допустить изменения номера пользователем в сторону уменьшения |
Увеличения номера |
Допустить изменения номера пользователем в сторону увеличения. Для обеспечения полного доступа пользователя к изменению автоматически сгенерированных номеров установите два последних флага. |
Вы можете посмотреть, где используется данная серия документов, по кнопке «Ссылки».
В Microsoft Axapta существуют общие серии для различных документов. Например, можно задать единую нумерацию для счетов-фактур и кредитовых авизо, однако чаще применяется раздельная нумерация.
Настройка номерных серий
Для первоначальной настройки всех номерных серий Вы можете использовать мастер создания номерных серий («Основное» - «Настройки» - «Серии документов» - «Мастер»), он автоматически создаст все необходимые номерные серии, но назовет их, на мой взгляд, неудачно. Он формирует код по принципу [4символа модуля, для которого происходит настройка]_[порядковый номер серии]. Таким образом, для номерной серии Сводного Плана получается код «свод_107». Не очень информативно, не так ли? То же он делает и с форматом ввода – просто дописывает к числовому шаблону «_[порядковый номер серии]». Что может сказать шаблон ########_107?
Так что я предпочитаю настраивать все серии вручную. На самом деле, это не столь сложная работа, как кажется. Есть несколько методологий по настройке шаблонов: например, ставить суффикс, обозначающий принадлежность шаблона к той или иной серии, или префикс. Или и то, и другое сразу. Я сторонник школы, ратующий за префиксы.
Примечание: См. также обсуждение суффиксов и префиксов в номерных сериях на axforum.info
Так как серии генерируются автоматически, то отпадает необходимость вводить префикс вручную, зато при поиске документа достаточно будет ввести лишь несколько последних цифр: *1234 – откроет все документы данной серии, оканчивающиеся на 1234. При использовании суффикса на пришлось бы писать «*1234_107» или «*1234_*». А при вводе заключительной «*» в некоторых поисковых формах (lookup'ax) сразу открывается список и автоматически подставляется первое значение. Так что не удивляйтесь, если поиск будет идти по значению «*1234_*00000001_107».
При разработке префикса я рекомендую использовать следующее правило его формирования: использовать 4х символьный префикс. Первые 2 символа - обозначение модуля. Например, «ГК» – если настройка этой серии производиться из модуля «Главная Книга», «РК» (Расчеты с клиентами), «РП» (Расчеты с поставщиками), «ОС» (Основные Средства), «ОН» (Основное - Настройки). Следующие 2 символа - Код серии КП (код поставщика), РП (разовый поставщик) и т.д. По крайней мере, при использовании данного метода все понятно и наглядно.
Пример: когда разносится Накладная на услуги, используется 2 номерные серии: одна попадет в товарную накладную, а вторая в Главную книгу. Как бы вы назвали, например, Накладную на услуги, номер которой выводится в товарной накладной и Накладную на услуги, номер которой формируется при разноске в главную книгу? Так как первая серия настраивается из модуля «Расчеты с Клиентами», то её имеет смысл назвать РКНУ (И шаблон, соответственно РКНУ#######). Ту же накладную, которая настраивается из модуля «Главная Книга», имеет смысл назвать ГКНУ (шаблон - ГКНУ#######). И главное – давайте подробное описание в поле «Название». Имя «Главная Книга – Накладная на Услуги» очень, я думаю, подойдет нашему коду «ГКНУ».
Что бы завести новую серию документов, надо задать код серии, наименование, а так же минимальное / максимальное значение номерной серии и формат. Код и Название мы сформировали. Минимальное / Максимальное значение – здесь, я полагаю, сложностей не должно быть. Осталось сформировать формат шаблона, по которому будут формироваться номера документов. Формат задается с помощью символов, которые можно использовать не только в качестве префикса или суффикса, но даже и в середине шаблона, а так же спецсимволов, вместо которых будут подставляться числа или символы.
Спецсимвол «#» указывает место в строке формата, где нужно расположить цифры номера. Так например, если для нумерации счетов-фактур используется формат «РКСФ#####», то счет-фактура с номером 1978 в качестве номера получит строку «сф-01978». Специальные символы можно произвольно чередовать с обычными символами. Так, например, вполне допустим формат «###_РКСФ_##». Тогда та же самая счет-фактура в качестве номера получит строку «019_РКСФ_78». Спецсимвол «&» (только для Axapta 3.0) Он работает аналогично #, только для кодирования используются не цифры, а латинские буквы. Т.е. вместо цифры 0 используется символ A , вместо цифры 1 – B, вместо 2 - С и т.д. Также как и # специальный символ & можно использовать вперемешку с другими символами. Сами символы # и & также можно использовать вперемешку. Так, если указать формат «&&_РКСФ_78», счет-фактура с номером 1978 после форматирования получит в качестве номера строку «AR_сф_78».
Подробнее об использовании спецсимволов я рекомендую почитать на ресурсе, посвященном Axapta http://axapta.mazzy.ru/lib/numbersequenceformat/
Создание новой номерной серии
Теперь о том, как создать собственную номерную серию.
Первое, у Вас должно быть четкое представление, зачем нужна номерная серия и как Вы собираетесь её использовать. Детально расписанное техническое задание не обязательно (хотя, конечно, и очень желательно), но общий план действий должен быть уже сформирован. Дело в том, что номерные серии настраиваются из разных модулей. Для пользователя это выглядит следующим образом: он заходит в модуль, например, «Расчеты с клиентами», выбирает «Настройки», потом «Параметры», и на вкладке «Номерные серии» видит ссылки на номерные серии и привязанные к ним серии документов. Иногда путь может и отличаться, например «Основное» - «Настройки» - «Данные о компании». И за каждую такую настройку отвечает свой класс – наследник от NumberSeqReference. Так что, если Вы собираетесь добавлять настройку основной серии в «Расчетах с клиентами» - то Вам надо будет править класс «NumberSeqReference_Customer», а если в «Основном» - то «NumberSeqReference_General». Если же Вы собираетесь писать в своем модуле… Что ж… Все возможно. Вам только придется подправить enum « NumberSeqModule », добавить в него новый элемент. Только, пожалуйста, не надо давать ему номер 88 (Речь идет об Axapta 3.0 SP 3 HF 2, в данной версии у последнего элемента номер 87), а то любой очередной сервис-пак / хотфикс, в котором будет реализовано нечто подобное, то Ваш элемент элементарно, простите за каламбур, накроет ваш элемент своим с тем же номером, но к нему будут подвязаны уже совсем другие задачи. Так что обязательно оставляйте диапазон пустых значений, если Вы дополняете системное перечисление. Дайте ему номер 188, например.
Итак, Ваш класс должен
- быть унаследован от numberSeqReference
- у него должен быть реализован метод NumberSeqModule, который просто возвращает тип групп номерных серий, где используется данная номерная серии. К примеру, класс, отвечающий за настройку номерных серии в поставщиках, возвращает NumberSeqModule::Cust, а в основном - NumberSeqModule:: General.
- у него должен быть реализован метод loadModule . Об этом – чуть дальше.
Но если вы просто добавляете новую номерную серию к существующим, то нет надобности писать свой класс – достаточно немного подправить уже имеющийся. Внимание! У Вас уже должна быть разработана таблица с полем, в которое и будет записываться очередное значение номерной серии. Для этого обязательно создайте свой строковый «Extended Data Type», с длинной не менее 30 символов, хотя рекомендуется просто наследовать его от стандартного типа для номерных серий – типа «Num». Для примера сделаем небольшой пример – разработаем маленькую таблицу, например, с кодами групп менеджеров. Заведем новый тип SalesManagersGroupId и унаследуем его от Num , потом сделаем таблицу с группами менеджеров, которое будет содержать наш новый тип – номер группы и поле – описание группы.
Давайте для примера возьмем уже упоминавшийся NumberSeqReference_General. Обратите внимание на метод loadModule – именно его нам и придется править. Вот пример уже имеющегося кода:
// EGLA, Officials --> numRef.DataTypeId = typeid2extendedtypeid(typeid(OffSessionId_RU)); numRef.ReferenceHelp = literalStr("@DIS7575"); numRef.ReferenceLabel = literalStr("@DIS7574"); numRef.WizardContinuous = false; numRef.WizardManual = NoYes::No; numRef.WizardAllowChangeDown = NoYes::No; numRef.WizardAllowChangeUp = NoYes::No; numRef.SortField = 3; this.create(numRef); // EGLA, Officials <--
Теперь пишем и наш код:
// M 000_ GNRD _ SalesManagersGroupsNumSeq ---> // Укажем, какой тип мы хотим использовать.
// Разумеется, здесь должен быть наш тип – тот,что мы использовали в таблице. numRef.DataTypeId = typeid2extendedtypeid(typeid(SalesManagersGroupId)); // Это будет в подсказке numRef.ReferenceHelp = literalStr("Уникальный идентификатор групп менеджеров"); // А это само имя – его мы видим в графе «Ссылка» при настройке номерных серий. numRef.ReferenceLabel = literalStr("Идентификатор группы менеджеров"); // Настройка мастера. // Если мы решим запустить стандартны мастер, то он // по-умолчанию сформирует нашу серию как «Непрерывную» numRef.WizardContinuous = false; // Допускать изменения пользователем «Вручную» numRef.WizardManual = NoYes::No; // … только на понижении серии numRef.WizardAllowChangeDown = NoYes::No; // … только на повышение номера. numRef.WizardAllowChangeUp = NoYes::No; // Максимальный номер. // Здесь мы предполагаем, что у нас не будет больше 9999 групп менеджеров. numRef.WizardHighest = 9999; numRef.SortField = 3; // Создаем this.create( numRef); //M000_GNRD_SalesManagersGroupsNumSeq <---
К слову сказать, у NumberSequenceReference есть еще пара свойств, типа
numRef.WizardLowest = 1; // Минимальный номер, с которого и начнется отсчет
но они не так часто используются и их уже легко выучить самостоятельно.
Как грамотно дописать форму с нашей таблицей в виде источника данных, что бы она могла использовать нашу номерную серию? Очень просто!
- В classDeclaration указываем новую переменную – нашу номерную серию
NumberSeqFormHandler SalesManagersNumberSeqFormHandler;
- создаем новый метод, ответственный за состояние нашей номерной серии (вернее, возвращающий экземпляр класса, если он инициализирован или инициализирующий его - иначе)
public NumberSeqFormHandler SalesManagersNumberSeqFormHandler( FormRun _element, FormDataSource _Form_ds) { ; if (! SalesManagersNumberSeqFormHandler) { // если не инициализирован, то запускаем конструктор // для этого типа данных нашего источника данных // в данной таблице, именно для поля, куда будет писатся эта серия SalesManagersNumberSeqFormHandler = numberSeqFormHandler::newForm( NumberSequenceReference::find( TypeId2extendedTypeId(typeid(SalesManagersGroupId)) ).NumberSequence, _element, _Form_ds, fieldNum(SalesManagersGroups, GroupId) ); } return SalesManagersNumberSeqFormHandler; }
Потом мы должны не забывать вызывать определенные методы нашего класса по изменению данных в нашем источнике. Эти изменения отрабатываются методами create, validateWrite, write и linkActive (создание нового номера), и delete по удалении записи. Часть этих методов должна быть вызвана до super, часть – после. Вот их реализация, применительно к нашему примеру:
//Create public void create(boolean _append = false) { ; element.SalesManagersNumberSeqFormHandler( element, SalesManagersGroups_ds).formMethodDataSourceCreatePre(); // Обратите внимание, что до SP3 данная строчка не нужна! super(_append); element.SalesManagersNumberSeqFormHandler( element, SalesManagersGroups_ds).formMethodDataSourceCreate(); }//ValidateWrite public boolean validateWrite() { boolean ret; ; ret = super(); ret = ret && element.SalesManagersNumberSeqFormHandler( element, SalesManagersGroups_ds).formMethodDataSourceValidateWrite(); return ret; }//Write public void write() { ; ttsbegin; super(); element.SalesManagersNumberSeqFormHandler( element, SalesManagersGroups_ds).formMethodDataSourceWrite(); ttscommit; }//LinkActive public void linkActive() { ; element.SalesManagersNumberSeqFormHandler( element, SalesManagersGroups_ds).formMethodDataSourceLinkActive(); super(); }//Delete public void delete() { ; ttsbegin; element.SalesManagersNumberSeqFormHandler( element, SalesManagersGroups_ds).formMethodDataSourceDelete(); super(); ttscommit; }
В принципе, присвоить новый номер переменной можно и в коде.
NumberSeq SalesManagersNumberSeq; SalesManagersGroups SalesManagersGroups; ; ttsbegin; SalesManagersGroups.clear(); SalesManagersGroups.initValue(); SalesManagersNumberSeq = NumberSeq::newGetNum(NumberSequenceReference::find( TypeId2extendedTypeId(typeid(SalesManagersGroupId))) ); SalesManagersGroups.GroupId = SalesManagersNumberSeq.num(); SalesManagersGroups.GroupName = "Test Name"; SalesManagersGroups.insert(); ttscommit;
Отменить создание нового номера можно методом SalesManagersNumberSeq.abort(). Вот, в принципе, и все.
Осталась сделать самую малость – настроить нашу номерную серию!
Итак, заходим в «Основное» - «Настройки» - «Данные о компании», закладка «Номерные серии». Вот она – наша серии с гордым названием «Идентификатор группы менеджеров».
Щелкаем правой клавишей и переходим к основной таблице. Вот здесь как раз и заводятся все серии документов, которые в последствии можно привязать к номерной серии той или иной группы документов. Создаем свой шаблон нашей номерной серии, называем его, подвязываем к нашей серии документов и – все! Наш нумератор готов к использованию!
Автор выражает благодарность Sonny Wibawa Adi (SonnyWibawaAdi@yahoo.com) за документ How To Add A New Number Sequence Reference in Axapta.
Нанеишвили Георгий (George Nordic), george_nordic@hotmail.com







