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