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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 23.05.2007, 23:40   #1  
Blog bot is offline
Blog bot
Участник
 
25,584 / 848 (80) +++++++
Регистрация: 28.10.2006
Denis Fedotenko: Новые поля в складских проводках
Источник: http://blogs.technet.com/denisfed/ar...3/1029577.aspx
==============




Общие вопросы


При внедрении DAX часто возникает примерно следующая задача: Клиент говорит что-нибудь типа "Мне нужно добавить в заказы (складские журналы, закупки, производственные заказы и т.п.) новое поле - направление продаж (код продавца, номер автомобиля для отгрузки, идентификатор кредитной линии клиента и тп). Кроме того - мне нужно уметь строить отчеты (обычные или OLAP) по складским списаниям (приходам) в разрезе этого нового поля".
Первое что приходит в голову - это просто добавить новое поле в строки заказов и потом переделать некоторые складские отчеты таким образом, чтобы они строились по соединению (join) таблицы складских проводок с исходным документом. Проблема в том, что в реальности постоянно возникают ситуации, при которых клиент, задним числом вспоминает что неплохо бы это поле добавить не только в заказы (например), но и в складские журналы списания или переноса. В этой ситуации внедренцу приходится либо плодить кучу отчетов - по одному для каждого вида складских документов, либо строить какой-то хитромудрый отчет, который собирает данные из множества таблиц. Очевидно, что оба подхода имеют свои минусы и почти не имеют плюсов.
Второй, более продвинутый вариант - это добавление нового поля либо в таблицу складских проводок (inventTrans) либо в таблицу складской аналитики (inventDim). Надо понимать, что с точки зрения нагрузки на систему, вариант добавления в таблицу inventDim новых полей значительно более затратный. Это связано с тем, что с ростом числа записей в таблице inventDim, растет и таблица inventSum (запасы в наличии). Поскольку модуль логистики ПОСТОЯННО использует таблицу inventSum для получения текущего складского остатка, критически важно для производительности, чтобы эта таблица не разросталась. Поэтому, добавлять новые поля в складскую аналитику имеет смысл только при выполнении следующих условий:
1. Имеет смысл сальдирование по этой аналитике. Грубо говоря - количественный или денежный остаток в разрезе этой аналитики имеет экономический смысл.
2. Предполагается, что система должна проверять неотрицательность остатка в разрезе этой складской аналитики.
Поэтому - реально добавлять новые поля в складскую аналитику приходится достаточно нечасто. Например - ни код продавца, ни номер автомобиля явно не проходят по обоим условиям. Мне приходилось добавлять, например, складскую аналитику "Материально ответственное лицо" или "Вид продукции" (своя, комисионная, давальческая) и некоторые другие. Причем добавлять ее приходилось в первую очередь даже не для отчетности, а для контроля - чтобы нечаянно не списать с аналитики "МОЛ" или "Вид продукции" больше номенклатуры, чем на нее изначально было оприходовано.
Для всех остальных случаев - правильнее добавлять новое поле в inventTrans. Причем я для себя выработал следующий приблизительный критерий, позволяющий принимать решение - добавлять новое поле в inventTrans или попытаться обойтись хитрым запросом (с джойном inventTrans и исходного документа): Добавлять новое поле в inventTrans следует если выполняется одно из следующих условий:
1. Новый аттрибут есть более чем в одном типе складского документа
2. Новый аттрибут будет заполняться для более чем 25% складских проводок данного вида (то есть - либо приходов, либо расходов)
3. Новый аттрибут будет использоваться для вычисления дополнительных количеств в таблице остатков в наличии (Об этом подходе я напишу в другой раз. Основная идея состоит в том, чтобы в остатках в наличии иметь не только поле, допустим, "Зарезервировано", но еще и дополнительное поле "Зарезервировано в журналах перемещения".)
Наивный подход к реализации заполнения нового поля в складских проводках состоит в том, чтобы переопределить методы insert() или update() таблиц inventTrans и, допустим, SalesLine таким образом, чтобы при обеспечить синхронизацию этого нового поля между двумя таблицами. Надо сказать, что во первых этот метод приводит к серьезному возрастанию нагрузки не систему во время обновления, во вторых - очень сильно не вяжется с идеологией логистического модуля DAX.
Цель данной заметки состоит как раз в том, чтобы дать приблизительное описание той инфраструктуры которая обеспечивает интерфейс между исходными логистическими документами (заказами, закупками, складскими журналами, производственными заказами и т.п.) и стандартными механизмами логистических операций DAX, а затем дать простой пример того как можно обеспечить копирование аттрибутов из исходных документов в складские проводки. Немного о программной инфраструктуре логистики


На мой взгляд - инфраструктура логистического модуля, это очень наглядный пример мощи объектно ориентированного подхода. При проектировании классов этого модуля разработчиками было принято очень простое решение:
1. Классы отвечающие за выполнение типовых логистических операций - резервирования, комплектации, регистрации, физической и финансовой разноски ничего не знают о том, на основании какого исходного документа выполняются эти операции.
2. Вся логика, связанная со специфическими операциями по конкретному складскому документу инкапуслирована в иерархию классов (inventMov_*). При этом каждому виду складского документа соответствует ОДИН конкретный класс в этой иерархии.
3. При выполнении логистических операций классы InventUpd* либо запрашивают у классов InventMov* нужную им информацию (например код номенклатуры или заказанную дату), либо вызывают методы классов inventMov, чтобы те выполнили некторые операции, специфичные для данного складского документа.
Рассмотрим несколько конкретных примеров:
В иерархии классов inventMovement имеется метод mustBeAutoReserved. Этот метод вызывается классов inventUpd_expected, отвечающим за создание и обновление складских проводок в статусе "Заказано"/"В заказе" для того чтобы определить - не следует ли автоматически резервировать данную проводку списания. В классе inventMovement этот метод возвращает значение false. В классе inventMov_sales (отвечающим за модуль заказов) - возвращает значение в зависимости от режима авторезервирования в шапке заказа, а в классе InventMov_QuarantineOrder (отвечающем за карантинный заказ) этот метод всегда возвращает значение true, чтобы по карантинному заказу у нас товар автоматически резервировался на карантинном складе.
Метод inventMovement.updateLedgerFinancial() используется для создания проводок в ГК по приходным операциям. В большинстве случаев, эта операция выполняется методом самого базового класса, который вытаскивает из дочернего класса (относящегося к данному виду приходного документа) данные о счете и коррсчете проводки (через методы accountBalanceSheet() и accountOperations()), финансовой аналитике (через метод Dimension()) и разноске в ГК (методы postingBalanceSheet() и postingOperations()). Для закупок, этот метод был переопределен в классе inventMov_purch(), поскольку по закупкам разноска по коррсчету делается совсем другим классом (vendVoucher), который также создает запись в проводках по поставщику (vendTrans). Поэтому - в методе inventMov_purch.updateLedgerFinancial() создется только вторая половина проводки - приход на инвентарный счет (10.x или 41.x).
Метод inventMov.addRemainFinancialUnit() обновляет недопоставленное количество в исходном складском документе. В базовом классе inventMovement этот метод определен так, чтобы он ничего не делал если для данного типа складского документа обновление недопоставленного количества не требуется и чтобы он выдавал сообщение об ошибке если таковое обновление требуется. В классах inventMov_purch,inventMov_sales, inventMov_prodLine этот метод переопределен таким образом, чтобы он обновлял соответствующие количества в строке закупки, заказа и производственной спецификации.
Ну и так далее...
При создании экземпляра класса inventMovement используется constructor controlled inheritance: Для создания экземпляра класса используется метод inventMovement::construct(common table). При этом, логика внутри метода contruct (точнее даже метода constructNoThrow, который вызывается из construct), на основании информации о типе таблицы со строкой исходного складского документа, создает нужный экземпляр конкретного наследника класса inventMovement. При этом, переданный экземпляр строки исходного складского документа храниться в переменной buffer, доступной из класса inventMovement и его наследников. Кроме того - существует еще один метод создания экземпляра класса inventMovement. В таблице inventTrans существует метод inventMovement, который находит нужную строку таблицы с исходным документом, а затем через inventMovement::construct() создает и возвращает соответствующий экземпляр объекта класса inventMovement. Конкретный пример.


Заказчик – крупная торговая организация. Им для работы требуется четко контролировать складские резервы в двух дополнительных разрезах:
1. Менеджер по продажам (сейл), к которому относится резерв
2. Срок жизни резерва. Резервы, которые кто-то создал и потом в течении N-дней не продал – должны автоматически удаляться системой.
Если транслировать эту задачу в более приземленные термины, то нужно:
1. Добавить в таблицу складских проводок (inventTrans) поле "Сейл" и копировать туда поле "Ответственный продавец" из шапки заказа (возможно – и из некого дополнительного поля, которое мы добавим в шапку складского журнала – для резервов по складским журналам).
2. Добавить в таблицу складских проводок поле "Дата автоматического снятия резерва". При резервировании – в это поле должна заносится текущая дата + 5 дней. Желательно сделать механизм расчета автоматической даты снятия расширяемым, поскольку велика вероятность того, что в дальнейшем метод расчета срока жизни резерва будет зависеть от типа исходного документа, номенклатуры, клиента под которого ставиться резерв и тп.
3. Разработать процедуру удаления просроченных резервов. Здесь я эту тему рассматривать не буду - оставлю для самостоятельного изучения :)
Для начала попытаемся решить задачу с ответственным продавцом. Для этого:
· В классе inventMovement создадим метод salesResponsible(), возвращающий значение типа emplId. В базовом классе этот метод будет возвращать пустую строку.
· В классе inventMov_sales (связанном со строкой заказа) переопределяем этот метод таким образом, чтобы он возвращал значение salesResponsible из шапки соответствующего заказа.
· Добавляем поле salesResponsible в таблицу inventTrans
· Изменяем метод inventMovement.initInventTransFromBuffer() таким образом, чтобы он инициализировал новое поле значением, полученным из метода inventMovement.salesResponsible().
Первичное тестирование данная доработка пройдет. Если при создании заказа заполнить в шапке поле "Ответственный продавец", то при создании строк оно попадет в складские проводки. Но вот если попробовать изменить это поле у уже созданного заказа, то в складских проводках так и останется старое значение. Почему это происходит ? Давайте попробуем изменить в шапке заказа поле "Дата заказа" и протрассировать метод inventUpd_estimated.updateNow(), который где-то в своих недрах должен изменить значение поля dateExpected таблицы складских проводок. При трассировке довольно быстро натыкаешься на код метода updateFieldsChange(), который вызывает метод инициализации полей складской проводки (inventMovement.initInventTransFromBuffer()) в том случае, если метод inventMovement.mustUpdateInventTransFields() вернул true. Если заглянуть в этот метод, то можно обнаружить следующий код:
return (this.transDate() != _movement_orig.transDate() ||
this.shippingDateRequested()!= _movement_orig.shippingDateRequested()||
this.transSchedTime() != _movement_orig.transSchedTime() ||
this.transItemBOMId() != _movement_orig.transItemBOMId() ||
this.transItemRouteId() != _movement_orig.transItemRouteId() ||
this.transIdReturn() != _movement_orig.transIdReturn() ||
this.projCategoryId() != _movement_orig.projCategoryId() ||
this.custVendAc() != _movement_orig.custVendAc() ||
this.assetId() != _movement_orig.assetId() ||
this.inventRefTransId() != _movement_orig.inventRefTransId()) ||
this.probabilityId() != _movement_orig.probabilityId().
Попросту говоря – система создает на основании старой (не измененной) копии строки исходного документа (доставаемой через buffer.Orig()) экземпляр класса InventMovement() и сравнивает значение некоторых методов, значения которых в дальнейшем попадают в складские проводки. Значит – для того чтобы добиться правильного поведения системы нам нужно:
1. Добавить в этот метод сравнение значений, возвращаемых методом salesResponsible()
2. Для того чтобы логика сравнения отработала нам придется добавить в СТРОКИ заказа копию поля salesResponsible. (Ведь метод пляшет от сравнения СТРОКИ ЗАКАЗА до и после обновления, а не от значения шапки заказа.). Нам придется переопределить метод обновления шапки заказа (salesTableType.update()) таким образом, чтобы при изменении ответственного продавца в шапке заказа, новое значение поля копировалось бы и в строки заказа. При этом – обновление строки заказа у нас будет вызывать обращение к inventUpd_estimated.updateNow(), порождая таким образом обновление информации и в складских проводках.
Теперь попробуем разобраться с датой автоматического снятия резерва.
· Для начала добавим в таблицу складских проводок новое поле dateExpired
· Поскольку хочется сделать механизм расчета даты автоматического снятия максимально гибким, создадим метод inventMovement.dateExpired(). Этот метод получает в качестве параметра дату создания резерва, а возвращает рассчитанную на ее основе дату снятия резерва (на первых порах – просто дату+5 дней).
· Подправим метод inventUpd_Reservation.updateReserveMore() (этот метод собственно и резервирует складские проводки), таким образом, чтобы в поле inventTrans,dateExpired записывалось значение, полученное из нового метода inventMovement.dateExpired().
· В методе inventUpdReservation.updateReserveLess() (он снимает резервы) вставляем очистку поля dateExpired – чтобы дата снятия резерва не была заполнена для проводок в статусе "Заказанно"
· Наконец – для того чтобы дата снятия резерва не стояла у уже отгруженных проводок – вставляем очистку даты резервирования в методе inventMovement.initInventTransPhysical(), который вызывается для заполнения полей inventTrans при физической разноске складских проводок. (Кстати – inventMovement.initInventTransFinancial выполняет аналогичную ситуацию при финансовой разноске). Поле salesResponsible я бы не стал зачищать в этом методе, поскольку достаточно удобно, когда это поле заполнено в проводках с любым статусом – а не только в проводках резервирования.
Если после выполнения этих модификаций поэкспериментировать с резервированием, выясняется что в целом все работает, однако есть один тонкий момент: Как известно, DAX умеет схлопывать записи в inventTrans в рамках одного номера лота, если КЛЮЧЕВЫЕ поля этих записей совпадают. В том случае, если галка "Автоматическое добавление" в параметрах модуля управления запасами установлена – это происходит автоматически – при любом обновлении inventTrans. Если галка не установлена, аналогичного эффекта можно добиться через пункт меню "Суммирование" в форме складских проводок. Так вот – если мы нарезервировали по одному и тому же лоту в разное время, с разными датами автоматического снятия резерва, система при схлопывании проводок может схлопнуть проводки с разными датами снятия резерва, подставив в результирующую проводку первую попавшуюся из нескольких дат. Для того чтобы предотвратить подобный эффект, нужно изменить метод inventTrans.setSumAmount(), так чтобы он дополнительно проверял совпадение даты резервирования и ответственного продавца в двух проводках.
NB. Кстати – если у вас на проекте есть проблемы с ростом inventTrans, посмотрите – включена ли галка "Автоматическое добавление". Если не включена – попробуйте оценить выигрыш от ее включения. Напишите джобик, который пробежится по существующим складским проводкам и проверит их на совпадение полей, проверяемых в методе inventTrans.setSumAmount. На моей практике – установка этой галки однажды позволила уменьшить число записей в inventTrans по заказам почти в два раза. Хотя с другой стороны – включение этой галки заведомо замедляет обновление inventTrans.

Подводя общий итог рассмотренному примеру, можно дать следующую рекомендацию:
  1. Если аттрибут копируется в складскую проводку из исходного документа, то необходимо дополнить метод inventMovement.initInventTrans* инициализацией нового поля из вновь созданного метода класса InventMovement.
  2. Если аттрибут тем или иным образом рассчитывается в процессе выполнения логистической операции, следует поместить инициализацию этого аттрибута в методы соответствующего класса inventUpd_*.
P.S. Рассмотренный пример (по крайней мере - с датой автоматического снятия резеров) хорошо работает только при отсутствии резервирования в заказанных. По логике вещей - автоматическое снятие резерва должно работать только для товара, уже находящегося на складе. Для товара в пути эта логика в принципе не работает, поскольку время обработки закупки поставщиком и транспортировки закупленного товара до его прибытия на склад достаточно непредсказуемо и, обычно, значительно больше типичного времени жизни резерва на складе. Поэтому, в случае использования резервирования в заказанных, надо во первых заблокировать удаление просроченных резервов в заказанных, а во вторых - подправить метод inventUpdate.updateDimReserveChange(), таким образом, чтобы при приходе товара, у складской проводки резервирования повторно инициализировалась дата автоматического снятия резерва. (Попросту говоря - этот метод при вызывается при физическом приходе товара, ищет по двум разным алгоритмам подходящую проводку в статусе "Зарезервировано в заказанных" и переводит ее в статус "Физически зарезервировано").


Источник: http://blogs.technet.com/denisfed/ar...3/1029577.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
За это сообщение автора поблагодарили: mazzy (20), glibs (4), Neosy (1), blokva (3), e@gle (-1), player (1).
Старый 23.05.2007, 23:59   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Мегареспект!

Дополнительная информация:
= о копировании из шапки в строки http://axapta.mazzy.ru/lib/salestable2line/
= о резервировании http://axapta.mazzy.ru/lib/reserve_from_code/

Несколько слов о задаче снятия с резерва: если в необработанном заказе изменить Тип заказа с "Заказ" на "Журнал", то резервы снимутся автоматически по всем строкам. Затем нужно сменить Авторезервирование и вернуть в тип заказа обратно в Заказ. При этом система пытается удалить старые складские операции и пересоздать их заново.
__________________
полезное на axForum, github, vk, coub.
Старый 24.05.2007, 00:13   #3  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Blog bot Посмотреть сообщение
Первое что приходит в голову - это просто добавить новое поле в строки заказов и потом переделать некоторые складские отчеты таким образом, чтобы они строились по соединению (join) таблицы складских проводок с исходным документом. Проблема в том, что в реальности постоянно возникают ситуации, при которых клиент, задним числом вспоминает что неплохо бы это поле добавить не только в заказы (например), но и в складские журналы списания или переноса.
И не только это.
Заказы - это по сути специализированные Журналы.
Журналы - это по сути черновики.
При разноске информация из черновиков переносится в беловики (в проводки и документы)
А черновики могут быть удалены!!!! (это штатное поведение Аксапты)

Join с первичным документам приводит к массе неприятных побочных эффектов.
Первый - черновики становится нельзя удалять (в результате растет база).
Второй - нарушается логика, которая гласит: в черновиках то, что мы собираемся сделать, а в проводках то, что уже сделали
Третий - значение поля в первичном документе становится нельзя измененять впоследствии (особенно для заказов/закупок). Если делается join, то в этом случае УЖЕ проведенный документ может ИЗМЕНИТЬ свое значение. Следовательно, нельзя изменять заджойненое поле при частичных отгрузки/закупках. Например, в заказе 100 шт. Ответственный Иванов. Клиенту отгружено 60 штук. Иванов заболел/умер/уволился, вместо него Петров. Но если мы поставим Петрова в шапку, то и уже отгруженные 60 штук пойдут на Петрова. Но с другой стороны, оставшиеся 40 надо отдать Петрову. Проблема.
Четвертый - о котором говорит Denis Fedotenko - первичные документы разные и в коде обрабатывать их надо по-разному.

К сожалению, эту ошибку "Join с первичными документами" сделали при локализации. При некоторых условиях заказы/закупки/журналы удалять нельзя (книги продаж/покупок, налоговый учет, ОС).

Цитата:
Сообщение от Blog bot Посмотреть сообщение
Если транслировать эту задачу в более приземленные термины, то нужно:
1. Добавить в таблицу складских проводок (inventTrans) поле "Сейл" и копировать туда поле "Ответственный продавец" из шапки заказа
Ох. Ни в коем случае не напрямую из шапки заказа!
Поля обязательно надо протаскивать через SalesParmTable, PurchParmTable!
Иначе концов не собрать при разборе полетов!

А слово "копировать" очень правильное.
__________________
полезное на axForum, github, vk, coub.
Старый 24.05.2007, 01:06   #4  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от mazzy Посмотреть сообщение
Иванов заболел/умер/уволился
однако, секвенция...

P/S. хм... интересно также, однако, что события происходят именно в такой последовательности...
Старый 24.05.2007, 01:16   #5  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Blog bot Посмотреть сообщение
Подводя общий итог рассмотренному примеру, можно дать следующую рекомендацию:
  1. Если аттрибут копируется в складскую проводку из исходного документа, то необходимо дополнить метод inventMovement.initInventTrans* инициализацией нового поля из вновь созданного метода класса InventMovement.
  2. Если аттрибут тем или иным образом рассчитывается в процессе выполнения логистической операции, следует поместить инициализацию этого аттрибута в методы соответствующего класса inventUpd_*.
Круть!!!

Блин, не тому респект добавил.

Денис, появись в этой ветке, пожалуйста.
Дай тебе спасибо сказать.
__________________
полезное на axForum, github, vk, coub.
Старый 24.05.2007, 01:25   #6  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от mazzy Посмотреть сообщение
Блин, не тому респект добавил.
Именно шта! Об том и спич... Отключить репу боту-железяке! Наф! (иг)
Старый 24.05.2007, 08:13   #7  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Конкуренции боитесь? Хай будет у него репутация, IMHO. Он же трудится. Для нас старается.
__________________
С уважением,
glibs®
Старый 24.05.2007, 09:06   #8  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от glibs Посмотреть сообщение
Конкуренции боитесь?
Да не то, чтобы... Скорее, переживаю, что железяка отнимает одно посадочное место у живого человека на первом экране списка пользователей... типа "уничтожает 30-го"
Старый 24.05.2007, 09:10   #9  
blokva is offline
blokva
Пенсионер
Аватар для blokva
SAP
NavAx Club
 
743 / 167 (7) ++++++
Регистрация: 04.06.2003
Адрес: Беларусь
Блин тоже не обратил внимания а Денису огромный респект...и:
Претендую на авторский экземпляр будущей книги от Дениса!
__________________
Законы природы еще никто не отменял!
А еще у меня растет 2 внучки!!! Кому интересно подробности тут:
http://www.baby-shine.com/
Старый 24.05.2007, 09:34   #10  
online
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,907 / 5717 (196) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Update: Когда готовил контрольный пример для статьи, забыл об одном интересном нюансе. Для того чтобы снятие резервов работало интуитивно понятно для пользователя, первыми внутри данного лота должны сниматься резервы с наиболее ранней датой автоматического снятия. Для того чтобы система действовала именно таким образом, необходимо в методе inventUpd_reservation.updateReserveLess поставить сортировку по дате автоматического снятия в те несколько запросов, которые отбирают строки inventTrans для перевода в статус "Заказанно".

Кстати - насчет копирования поля через salesParmTable - не очень уверен. Насколько я помню - эта таблица заполняется только в момент проведения каких-то документов по заказу, но никак не в момент резервирования. Если уж надо хранить историю изменения ответственного продавца, то по-моему, проще записывать ее в какую-то новую таблицу при обновлении шапки заказа.
За это сообщение автора поблагодарили: mazzy (20), KiselevSA (2), Garic (2), blokva (3), belugin (15), lev (1), e@gle (1), aidsua (1), konopello (1), gl00mie (6), player (1).
Старый 24.05.2007, 11:57   #11  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от fed Посмотреть сообщение
salesParmTable .. эта таблица заполняется .... но никак не в момент резервирования.
Э-м-м.
Да, согласен. Поторопился. Резервирование через salesParmTable протаскивать необязательно
__________________
полезное на axForum, github, vk, coub.
Теги
inventdim, inventsum, inventtrans, база данных, как правильно, логистика, себестоимость, складские отчеты, складские проводки

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Denis Fedotenko: Себестоимость и длинные производственные заказы Blog bot DAX Blogs 13 21.11.2013 16:57
Denis Fedotenko: Себестоимость и закрытие склада Blog bot DAX: База знаний и проекты 44 29.03.2010 14:54
Валютные курсы, новые поля. Alex_R2 DAX: Функционал 3 17.07.2008 15:31
Не создаются новые поля в базе Oracle Bega DAX: Администрирование 5 29.06.2006 16:51
Код аналитики 'Номер партии' отмечен в складских проводках со значением Antidot DAX: Программирование 9 29.07.2005 10:57

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 10:20.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.