Алгоритм установки статуса в системе

Материал из BiTel WiKi

(Различия между версиями)
Перейти к: навигация, поиск
м
Строка 19: Строка 19:
Далее алгоритм. Многие технические части намеренно опущены.
Далее алгоритм. Многие технические части намеренно опущены.
-
* Для каждого из случаев (клиент, сервер, web) выбирается из конфига 6 чисел -- приоритеты статусов.
+
* Проверяется нужно ли нам будет использовать событие для логики перетирания статусов - '''флаг useEventSetStatusLogic'''
* Запоминается '''оригинальный_статус''', ибо устанавливаемый '''newStatus''' подготавливается к постепенному видоизменению.
* Запоминается '''оригинальный_статус''', ибо устанавливаемый '''newStatus''' подготавливается к постепенному видоизменению.
* Из устанавливаемого статуса берётся cid, получается соответствующий '''договор'''. Если договора нет - молча на выход.
* Из устанавливаемого статуса берётся cid, получается соответствующий '''договор'''. Если договора нет - молча на выход.
-
* Создаётся список '''кусочки_нового_статуса'''
+
* Берутся все промежутки статусов для этого договора (в реальности только те, что не раньше того момента, откуда самое раннее будет действовать новый статус; но это непринципиально) по ним делается цикл:
-
* Берутся все промежутки статусов для этого договора (в реальности только те, что не раньше того момента, откуда самое раннее будет действовать новый статус; но это непринципиально) по ним делается цикл.
+
{
{
-
* '''выбранный_статус''' - статус текущей итерации (один из промежутков статуса договора).
+
* '''выбранный_статус''' (status) - статус текущей итерации (один из промежутков статуса договора).
-
* если приоритет [b]выбранного_статуса[/b] меньше либо равен приоритета [b]оригинального_статуса[/b], то помечаем (флажок), что [b]старый_статус_перетираемый[/b]. то есть в этом случае отличий от классического алгоритма не будет. иначе будет учитываться, что [b]выбранный_статус[/b] нельзя перетереть [b]оригинальным_статусом[/b].
+
* если newStatus выродился (может быть только за счёт изменения в скрипте, ибо стандартной логикой он не изменяется), то выйти из цикла
-
// далее следует логика учёта перекрытий статусов  
+
 
-
* Если статусы ([b]newStatus[/b] и [b]выбранный_статус[/b]) вообще не перекрываются
+
* если useEventSetStatusLogic, то запускаем событие задания логики перетирания ContractSetStatusLogicEvent.
-
{
+
* если в скрипте был установлен флаг isProcessed, то вернуться в следующей итерации цикла (continue). иначе продолжим итерацию цикла далее.
-
то возвращается к очередной итерации цикла (continue).
+
 
-
}
+
// далее следует логика учёта перекрытий статусов  
-
* Если [b]newStatus[/b] полностью перекрыл [b]выбранный_статус[/b] то
+
* Если статусы ([b]newStatus[/b] и [b]выбранный_статус[/b] (status)) вообще не перекрываются
-
{
+
{
-
// полное перекрытие статуса
+
то возвращается к очередной итерации цикла (continue).
-
// old .......!*****?.....
+
}
-
// new ......!************
+
 
-
//
+
 
-
// old .......!*****!.....
+
* Если [b]newStatus[/b] полностью перекрыл [b]выбранный_статус[/b] то
-
// new .....!*********!...
+
{
-
если [b]старый_статус_перетираемый[/b] то удаляем из списка [b]выбранный_статус[/b].
+
// полное перекрытие статуса
-
иначе (если старый статус нельзя перетереть устанавливаемым) newStatus бьётся на две части.
+
// old .......!*****?.....
-
// old .......!*****!.....
+
// new ......!************
-
// new .....!].......[*?..
+
//
-
левый кусочек добавляется в список [b]кусочки_нового_статуса[/b], а правый становится новым [b]newStatus[/b] и мы его дальше используем в следующих итерациях.
+
// old .......!*****!.....
-
}
+
// new .....!*********!...
-
* Если происходит разрыв статусом [b]выбранного_статуса[/b]
+
если [b]старый_статус_перетираемый[/b] то удаляем из списка [b]выбранный_статус[/b].
-
{
+
иначе (если старый статус нельзя перетереть устанавливаемым) newStatus бьётся на две части.
-
// old .....[*****].....
+
// old .......!*****!.....
-
// new ......[**!.......
+
// new .....!].......[*?..
-
если [b]старый_статус_перетираемый[/b] то разрываем его на два кусочка и пишем оба в БД. новый не меняется.
+
левый кусочек добавляется в список [b]кусочки_нового_статуса[/b], а правый становится новым [b]newStatus[/b] и мы его дальше используем в следующих итерациях.
-
иначе (если старый статус нельзя перетереть устанавливаемым) то выходит, что [b]newStatus[/b] вообще вырождается окончательно, делаем newStatus=null и выходим из цикла.
+
}
-
}
+
* Если происходит разрыв статусом [b]выбранного_статуса[/b]
-
*перекрытие старого статуса ([b]выбранного_статуса[/b]) "слева"
+
{
-
{
+
// old .....[*****].....
-
// old ........!*****]..
+
// new ......[**!.......
-
// new .....?******!....
+
если [b]старый_статус_перетираемый[/b] то разрываем его на два кусочка и пишем оба в БД. новый не меняется.
-
если [b]старый_статус_перетираемый[/b] то делаем как раньше - двигаем старый до следующего дня после нового
+
иначе (если старый статус нельзя перетереть устанавливаемым) то выходит, что [b]newStatus[/b] вообще вырождается окончательно, делаем newStatus=null и выходим из цикла.
-
// old .............!]..
+
}
-
// new .....?******!....
+
*перекрытие старого статуса ([b]выбранного_статуса[/b]) "слева"
-
иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый конец назад, до предыдущего к старому
+
{
-
// old ........!*****]..
+
// old ........!*****]..
-
// new .....?*!.........
+
// new .....?******!....
-
}
+
если [b]старый_статус_перетираемый[/b] то делаем как раньше - двигаем старый до следующего дня после нового
-
*перекрытие старого статуса ([b]выбранного_статуса[/b]) "справа"
+
// old .............!]..
-
{
+
// new .....?******!....
-
// old ....[*****]......
+
иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый конец назад, до предыдущего к старому
-
// new ......[******]...
+
// old ........!*****]..
-
если [b]старый_статус_перетираемый[/b] то делаем как раньше - двигаем старый до предыдущего дня до нового
+
// new .....?*!.........
-
// old ....[]...........
+
}
-
// new ......[******]...
+
*перекрытие старого статуса ([b]выбранного_статуса[/b]) "справа"
-
иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый начало вперёд, до следующего к старому
+
{
-
// old ....[*****]......
+
// old ....[*****]......
-
// new ...........[*]...
+
// new ......[******]...
-
}
+
если [b]старый_статус_перетираемый[/b] то делаем как раньше - двигаем старый до предыдущего дня до нового
 +
// old ....[]...........
 +
// new ......[******]...
 +
иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый начало вперёд, до следующего к старому
 +
// old ....[*****]......
 +
// new ...........[*]...
 +
}
}
}
* Закончили цикл, если [b]newStatus[/b] остался ещё (то есть newStatus!=null), то кладём его тоже в [b]кусочки_нового_статуса[/b], это будет самый правый кусочек исходного статуса. Легко видеть, что если у нас вообще нет никаких неперетираемых статусо итд, то этот кусочек как раз будет единственным в списке и будет равен [b]оригинальному_статусу[/b].  
* Закончили цикл, если [b]newStatus[/b] остался ещё (то есть newStatus!=null), то кладём его тоже в [b]кусочки_нового_статуса[/b], это будет самый правый кусочек исходного статуса. Легко видеть, что если у нас вообще нет никаких неперетираемых статусо итд, то этот кусочек как раз будет единственным в списке и будет равен [b]оригинальному_статусу[/b].  

Версия 08:33, 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). иначе продолжим итерацию цикла далее.

// далее следует логика учёта перекрытий статусов

  • Если статусы ([b]newStatus[/b] и [b]выбранный_статус[/b] (status)) вообще не перекрываются

{ то возвращается к очередной итерации цикла (continue). }


  • Если [b]newStatus[/b] полностью перекрыл [b]выбранный_статус[/b] то

{ // полное перекрытие статуса // old .......!*****?..... // new ......!************ // // old .......!*****!..... // new .....!*********!... если [b]старый_статус_перетираемый[/b] то удаляем из списка [b]выбранный_статус[/b]. иначе (если старый статус нельзя перетереть устанавливаемым) newStatus бьётся на две части. // old .......!*****!..... // new .....!].......[*?.. левый кусочек добавляется в список [b]кусочки_нового_статуса[/b], а правый становится новым [b]newStatus[/b] и мы его дальше используем в следующих итерациях. }

  • Если происходит разрыв статусом [b]выбранного_статуса[/b]

{ // old .....[*****]..... // new ......[**!....... если [b]старый_статус_перетираемый[/b] то разрываем его на два кусочка и пишем оба в БД. новый не меняется. иначе (если старый статус нельзя перетереть устанавливаемым) то выходит, что [b]newStatus[/b] вообще вырождается окончательно, делаем newStatus=null и выходим из цикла. }

  • перекрытие старого статуса ([b]выбранного_статуса[/b]) "слева"

{ // old ........!*****].. // new .....?******!.... если [b]старый_статус_перетираемый[/b] то делаем как раньше - двигаем старый до следующего дня после нового // old .............!].. // new .....?******!.... иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый конец назад, до предыдущего к старому // old ........!*****].. // new .....?*!......... }

  • перекрытие старого статуса ([b]выбранного_статуса[/b]) "справа"

{ // old ....[*****]...... // new ......[******]... если [b]старый_статус_перетираемый[/b] то делаем как раньше - двигаем старый до предыдущего дня до нового // 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)

Личные инструменты