Алгоритм установки статуса в системе
Материал из BiTel WiKi
(Различия между версиями)
DimOn (Обсуждение | вклад) |
DimOn (Обсуждение | вклад) |
||
Строка 23: | Строка 23: | ||
* Берутся все промежутки статусов для этого договора (в реальности только те, что не раньше того момента, откуда самое раннее будет действовать новый статус; но это непринципиально) по ним делается цикл: | * Берутся все промежутки статусов для этого договора (в реальности только те, что не раньше того момента, откуда самое раннее будет действовать новый статус; но это непринципиально) по ним делается цикл: | ||
{ | { | ||
- | * | + | * 'выбранный_статус' (status) - статус текущей итерации (один из промежутков статуса договора). |
- | * если newStatus выродился (может быть только за счёт изменения в скрипте, ибо стандартной логикой он не изменяется), то выйти из цикла | + | * если newStatus выродился (может быть только за счёт изменения в скрипте, ибо стандартной логикой он не изменяется), то выйти из цикла |
- | * если useEventSetStatusLogic, то запускаем событие задания логики перетирания ContractSetStatusLogicEvent. | + | * если useEventSetStatusLogic, то запускаем событие задания логики перетирания ContractSetStatusLogicEvent. |
- | * если в скрипте был установлен флаг isProcessed, то вернуться в следующей итерации цикла (continue). иначе продолжим итерацию цикла далее. | + | * если в скрипте был установлен флаг isProcessed, то вернуться в следующей итерации цикла (continue). иначе продолжим итерацию цикла далее. |
- | // далее следует логика учёта перекрытий статусов | + | // далее следует логика учёта перекрытий статусов |
- | * Если статусы ( | + | * Если статусы ('newStatus' и 'выбранный_статус' (status)) вообще не перекрываются |
- | { | + | { |
+ | то возвращается к очередной итерации цикла (continue). | ||
- | + | } | |
- | + | * Если 'newStatus' полностью перекрыл 'выбранный_статус' то | |
- | + | { | |
- | * Если | + | // полное перекрытие статуса |
- | { | + | // old .......!*****?..... |
- | + | // new ......!************ | |
- | // полное перекрытие статуса | + | // |
- | // old .......!*****?..... | + | // old .......!*****!..... |
- | // new ......!************ | + | // new .....!*********!... |
- | // | + | удаляем из списка и из БД 'выбранный_статус'. |
- | // old .......!*****!..... | + | } |
- | // new .....!*********!... | + | * Если происходит разрыв статусом 'выбранного_статуса' |
- | удаляем из списка и из БД | + | { |
- | + | // old .....[*****]..... | |
- | } | + | // new ......[**!....... |
- | * Если происходит разрыв статусом | + | разрываем старый_статус на два кусочка и пишем оба в БД. новый не меняется. |
- | { | + | } |
- | // old .....[*****]..... | + | * перекрытие старого статуса ('выбранного_статуса') "слева" |
- | // new ......[**!....... | + | { |
- | разрываем старый_статус на два кусочка и пишем оба в БД. новый не меняется. | + | // old ........!*****].. |
- | } | + | // new .....?******!.... |
- | * перекрытие старого статуса ( | + | двигаем старый до следующего дня после нового |
- | { | + | // old .............!].. |
- | // old ........!*****].. | + | // new .....?******!.... |
- | // new .....?******!.... | + | } |
- | двигаем старый до следующего дня после нового | + | *перекрытие старого статуса ('выбранного_статуса') "справа" |
- | // old .............!].. | + | { |
- | // new .....?******!.... | + | // old ....[*****]...... |
- | } | + | // new ......[******]... |
- | *перекрытие старого статуса ( | + | двигаем старый до предыдущего дня до нового |
- | { | + | // old ....[]........... |
- | // old ....[*****]...... | + | // new ......[******]... |
- | // new ......[******]... | + | } |
- | двигаем старый до предыдущего дня до нового | + | |
- | // old ....[]........... | + | |
- | // new ......[******]... | + | |
- | } | + | |
} | } | ||
Версия 13:09, 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)