Алгоритм установки статуса в системе
Материал из BiTel WiKi
(Различия между версиями)
DimOn (Обсуждение | вклад) |
DimOn (Обсуждение | вклад) |
||
Строка 18: | Строка 18: | ||
<source lang="xml"> | <source lang="xml"> | ||
- | * Проверяется нужно ли нам будет использовать событие для логики перетирания статусов - | + | * Проверяется нужно ли нам будет использовать событие для логики перетирания статусов - <флаг useEventSetStatusLogic> |
* Запоминается '''оригинальный_статус''', ибо устанавливаемый '''newStatus''' подготавливается к постепенному видоизменению. | * Запоминается '''оригинальный_статус''', ибо устанавливаемый '''newStatus''' подготавливается к постепенному видоизменению. | ||
* Из устанавливаемого статуса берётся cid, получается соответствующий '''договор'''. Если договора нет - молча на выход. | * Из устанавливаемого статуса берётся cid, получается соответствующий '''договор'''. Если договора нет - молча на выход. |
Версия 13:06, 1 декабря 2010
Ниже приведены алгоритмические подробности, для более глубокого понимания логики установки статуса, что необходимо для изучения этого вопроса и написания качественных скриптов поведения. В целом описание алгоритма несёт мало пользы, но может помочь понять в какой момент происходит генерация событий и что именно туда попадает.
Для начала рассмотрим общую сигнатуру метода.
/** * Смена статуса договора. При этом происходит корректное перекрытие * существующих на моменты времени статусов, с тем, * чтобы на каждый день была активна только одна запись о статусе. * * @param newStatus новый статус с периодом. * @param userId ид юзера. если будет null, то это эквивалентно 0. * @param processEvent проводить ли события. */ public void changeStatus( ContractStatus newStatus, Integer userId, boolean processEvent ) throws SQLException
Далее алгоритм. Многие технические части намеренно опущены.
* Проверяется нужно ли нам будет использовать событие для логики перетирания статусов - <флаг useEventSetStatusLogic>
* Запоминается '''оригинальный_статус''', ибо устанавливаемый '''newStatus''' подготавливается к постепенному видоизменению.
* Из устанавливаемого статуса берётся cid, получается соответствующий '''договор'''. Если договора нет - молча на выход.
* Берутся все промежутки статусов для этого договора (в реальности только те, что не раньше того момента, откуда самое раннее будет действовать новый статус; но это непринципиально) по ним делается цикл:
{
* '''выбранный_статус''' (status) - статус текущей итерации (один из промежутков статуса договора).
* если newStatus выродился (может быть только за счёт изменения в скрипте, ибо стандартной логикой он не изменяется), то выйти из цикла
* если useEventSetStatusLogic, то запускаем событие задания логики перетирания ContractSetStatusLogicEvent.
* если в скрипте был установлен флаг isProcessed, то вернуться в следующей итерации цикла (continue). иначе продолжим итерацию цикла далее.
// далее следует логика учёта перекрытий статусов
* Если статусы ('''newStatus''' и '''выбранный_статус''' (status)) вообще не перекрываются
{
то возвращается к очередной итерации цикла (continue).
}
* Если '''newStatus''' полностью перекрыл '''выбранный_статус''' то
{
// полное перекрытие статуса
// old .......!*****?.....
// new ......!************
//
// old .......!*****!.....
// new .....!*********!...
удаляем из списка и из БД '''выбранный_статус'''.
}
* Если происходит разрыв статусом '''выбранного_статуса'''
{
// old .....[*****].....
// new ......[**!.......
разрываем старый_статус на два кусочка и пишем оба в БД. новый не меняется.
}
* перекрытие старого статуса ('''выбранного_статуса''') "слева"
{
// old ........!*****]..
// new .....?******!....
двигаем старый до следующего дня после нового
// old .............!]..
// new .....?******!....
}
*перекрытие старого статуса ('''выбранного_статуса''') "справа"
{
// old ....[*****]......
// new ......[******]...
двигаем старый до предыдущего дня до нового
// old ....[]...........
// new ......[******]...
}
}
* Закончили цикл, если [b]newStatus[/b] остался ещё (то есть newStatus!=null), то кладём его тоже в [b]кусочки_нового_статуса[/b], это будет самый правый кусочек исходного статуса. Легко видеть, что если у нас вообще нет никаких неперетираемых статусо итд, то этот кусочек как раз будет единственным в списке и будет равен [b]оригинальному_статусу[/b].
* Далее, готовим событие ContractStatusChangingEvent, куда кладём [b]оригинальный_статус[/b] (!) и плюс все [b]кусочки_нового_статуса[/b]. То есть всё останется как и было, кроме того случая, когда включаются приоритеты статусов, тогда, возможно, нужно будет учитывать кусочки в скрипте.
* Здесь самое интересное начинается. как известно, в скрипте можно изменить статус с бывшего на другой. в случае равноправных промежутков всё понятно - новый изменённый статус так и пишется. сейчас статус это список кусочков.
Так вот, смотрится [b]оригинальный_статус[/b] и статус, побывавший в событии. Если статус был изменён, то меняется статус всех [b]кусочков_нового_статуса[/b]. После Этого все кусочки пишутся в БД.
То есть логика здесь такая - можно взять и поменять статус в скрипте у отдельных кусочков. Но если поменян статус у целого контрактстатуса, то он распространится на все кусочки.
* При этом всём смотрится каждый кусочек и проверяется, что попадает на сегодня. Если это так, то устанавливается статус договора. После этого генерируется событие ContractStatusChangedEvent.
Внимание: в событие попадает не оригинальный статус, а кусочек соответствующий... не уверен пока что так надо.
* Записывается лог смены статусов. Если что-то меняется, то в комментарий лога смены статусов добавится, что статус был подрезан или разбит или выродился.
* Если договор - супердоговор
{
вызывается changeStatus для всех субдоговоров с зависимым балансом, куда передаётся [b]оригинальный_статус[/b].
если установлен independ.subcontract.status.change, то и для субдоговоров с независимым - тоже самое.
}
--dimOn 11:52, 26 ноября 2010 (UTC)