У физиков есть вечный двигатель, у алхимиков –
философский камень, у архитекторов 1С – всегда актуальный партионный
учет. Это такая реализация алгоритма распределения по партиям, когда не нужно
восстанавливать границу последовательности и распределение по партиям остается
актуальным при любом изменении документов задним числом.
Столько копий сломано вокруг этой темы, а идеал пока не
найден. Привлекательности теме добавляет интуитивное ощущение, что метод должен
существовать.
Вот и мне кажется, что я придумал наконец-то решение этой
древней проблемы. К сожалению, воплотить идею в коде не могу, т.к. нет
свободного времени. Поэтому предоставляю лавры исполнителя другому программисту,
себе оставляя скромную роль идейного вдохновителя.
Алгоритм получается сложнее, чем обычный партионный алгоритм, но сложнее не на порядок, а в
несколько раз, вполне под силу для реализации честолюбивому разработчику.
Идею позволили реализовать только новые механизмы,
которые появились в 1с8. Это регистры сведений и работа с ними через наборы
записей в базе данных.
На рисунке изображены два регистра, используемых для
партионного учета – классический и предлагаемый:
Классический регистр накопления для партионного
учета в УТ |
Предлагаемый регистр сведений для партионного
учета |
|
|
Рассмотрим некий демонстрационный пример, из которого
будет понятен принцип нового партионного учета. Рассмотрим некоторую историю
движения по товару:
1.06 поступило 100 штук по накладной ПНК1
2.06 продано 20 штук по накладной РНК1
20 штук списано с ПНК1, остаток по ПНК1 80 штук
3.06 поступило 30 штук по накладной ПНК2
4.06 продано 20 штук по накладной РНК2
20 штук списано с ПНК1, остаток по ПНК1 60 штук.
4.06 продано 70 штук по накладной РНК3
60 штук списано с ПНК1, остаток по ПНК1 0 штук.
10 штук списано с ПНК2, остаток по ПНК2 20 штук.
Как это списание осуществляется в классическом подходе с
регистром накопления, всем известно, поэтому расписываться не будет.
Вот как будут выглядеть записи регистра сведений в
предлагаемом подходе:
Дата |
Дата по |
Документ |
Документ оприходования |
Количество |
Остаток |
1.06 |
2.06 |
ПНК1 |
ПНК1 |
100 |
100 |
2.06 |
4.06 |
РНК1 |
ПНК1 |
-20 |
80 |
3.06 |
∞ |
ПНК2 |
ПНК2 |
30 |
30 |
4.06 |
4.06 |
РНК2 |
ПНК1 |
-20 |
60 |
4.06 |
4.06 |
РНК3 |
ПНК1 |
-60 |
0 |
4.06 |
∞ |
РНК3 |
ПНК2 |
-10 |
20 |
Поля Номенклатура, Склад,
Стоимость не рассматриваются для простоты изложения.
Документ оприходования – это
документ партии.
Документ – это документ, по которому происходит движение.
Количество – это количество по документу. Положительное – приход, отрицательное – расход.
Остаток – это остаток в партии после движения.
Дата – дата и время движения.
Дата по – это дата и время, до которой действует остаток.
Под бесконечностью можно взять любую большую дату, например 01.01.3000 года.
Чтобы получить остатки по регистру на некоторую
дату/время Д, нужно построить запрос, которые извлечет все записи регистра
сведений Р по условию:
Р.Дата> = Д И Д <= Р.ДатаПо
Возможно, нужно более аккуратно обдумать условия отбора,
с учетом того, что в 1С на одну дату может быть несколько документов.
Соответственно, мы получим набор записей регистра,
которые отражают остатки по партиям на указанную дату/время.
Чтобы провести некоторый документ с датой Д, нужно пересчитать все записи, которые находятся по дате
движения позднее Д. Это касается любого документа – приходного или расходного,
т.к. приходный документ увеличивает количество доступных партий, следовательно
картина списания меняется.
То же самое происходит и при отмене проведения документа.
У Вас, возможно, возникает вопрос – а в чем новизна
алгоритма? Ведь можно восстановить границу последовательности сразу после
проведения документа и в обычном случае. Правда, так никто не делает, потому что это долго.
Суть в том, что мы можем отобрать все движения после
текущего документа одной операцией чтения набора записей, быстро пересчитать их
в памяти, а затем одной операцией записи набора записей записать в базу данных.
Записи регистра сведений можно считывать
и записывать одной операцией чтения.
Считать записи регистра лучше всего запросом, т.к.:
1.
Запрос позволяет выполнять сортировку и группировку. Особенно это
актуально, если мы выполняем один запрос по нескольким товарам.
2.
Обход запроса можно осуществлять с помощью выборки, которая не грузит все
данные в память, соответственно можно обрабатывать сколь угодно большие наборы
движений.
Считанные записи обрабатываются алгоритмом партионного
распределения, вычисляется новое распределение, новые остатки и даты действия.
Записи последовательно записываются в набор записей. Если
набор записей получается очень большим, можно записывать его порциями.
Алгоритм получился быстродействующим. Перерасчитываются
только движения после движения документа. Предыдущие движения не меняются, не считываются и не перезаписываются. Чем дальше в прошлом
перепроводится документ, тем дольше длится восстановление картины партионного
распределения. Но зависимость не экспоненциальная, разница в скорости нарастает
очень медленно, т.к. всегда используется одно чтение и запись набора записей.
Прошу коллег высказать свое мнение об алгоритме. По-моему
вполне действенный алгоритм.