BiTel

Форум BiTel
bgbilling.ru     docs.bitel.ru     wiki.bitel.ru     dbinfo.bitel.ru     bgcrm.ru     billing.bitel.ru     bitel.ru    
Текущее время: 24 июн 2025, 02:14

Часовой пояс: UTC + 5 часов [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 24 ] 
Автор Сообщение
СообщениеДобавлено: 13 сен 2010, 15:08 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Сделан новый алгоритм смены статусов. Есть возможность задавать приоритет у статуса, чтобы некоторые статусы не перетирались. Сейчас выложу два кусочка документации.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 13 сен 2010, 15:10 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Смена статусов в случае использования приоритетов статусов и неперекрывающихся статусов

Ахтунг! Сейчас уже неактуально!

Имеется возможность усложнить логику автоматического перетирания статусов путём установки для каждого статуса некоего приоритета. Сделать это можно для трёх отдельных случаев:
1) для случая смены статуса руками из клиента,
2) для случая смены статуса сервером,
3) для случая смены статуса пользователем из web (речь о возможности приостановить договор).

Статусы устанавливаются именно на каждый из шести статусов, а не на каждый временной промежуток каждого договора.

Возможность включается прописываением в конфигурации сервера нескольких параметров.

Код:
#
# Приоритеты статусов для смены статусов бОльшая цифра - бОльший приоритет. Статус с меньшим приоритетом не перетирает статус с бОльшим. С одинаковыми - перетираются.
# Шесть цифр подряд, через запятую, соотвественно для статусов:
#CONTRACT_STATUS_ACTIVE = 0
#CONTRACT_STATUS_IN_DISCONNECT = 1
#CONTRACT_STATUS_DISCONNECTED = 2
#CONTRACT_STATUS_CLOSED = 3
#CONTRACT_STATUS_SUSPENDED = 4
#CONTRACT_STATUS_IN_CONNECT = 5
# по умолчанию все нули, т.е. все приоритетные одинаково, всё работает как было - все всех перетирают.
# для смены вручную менеджером
contract.status.user.priority=0,0,0,0,1,0
# для автоматической смены сервером
contract.status.server.priority=0,0,0,0,1,0
# для смены юзером через web
contract.status.web.priority=0,0,0,0,1,0
#


Без каких-либо параметров (всех трёх или каждого по-отдельности) все приоритеты считаются равными 0, то есть поведение будет как описано в оригинальной документации - все друг друга перетирают.

После настройки этих параметров статусы будут перетираться избирательно. Кроме того, усложняется логика событий и скриптов.

В случае наличия неперекрывающихся статусов возможны ситуации, когда изначальный статус укорачивается, разбивается другим промежутком(-ами) на несколько частей или совсем вырождается, если перекрывается уже находящимся промежутком с высоким приотиретом.

Обратите внимание, что в события передаётся изначальный статус, без учёта разбиений или иных изменений изначального статуса. В событии ContractStatusChangingEvent также существует поле, содержащее список всех кусочков изначального статуса после обработки операции перекрытия промежутков разных статусов.

Код:
   /**
    * Возвращает кусочки исходного статуса, они будут отличаться от основного,
    * если статус был разбит при пересечении с разными кусками неперетираемых
    * статусов.
    *
    * @return коллекция объектов ContractStatus.
    */
    public Collection<ContractStatus> getStatusParts();


Учёт того, что, возможно, устанавливаемый статус не начал действовать или вообще никогда не начнёт надо делать вручную, внутри скрипта, опираясь на список этих кусочков.

Более подробно о алгоритме и логике метода -- ниже.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 13 сен 2010, 15:22 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 20 апр 2009, 12:03
Сообщения: 3092
Откуда: Иркутск
Карма: 338
ИзображениеИзображениеИзображение


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 13 сен 2010, 15:30 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Алгоритм установки статуса

Ахтунг! Сейчас уже неактуально!

Ниже приведены алгоритмические подробности, для более глубокого понимания логики установки статуса, что необходимо для изучения этого вопроса и написания качественных скриптов поведения.
В целом описание алгоритма несёт мало пользы, но может помочь понять в какой момент происходит генерация событий и что именно туда попадает.

Для начала рассмотрим общую сигнатуру метода.

Код:
    /**
     * Смена статуса договора. При этом происходит корректное перекрытие
     * существующих на моменты времени статусов, с тем,
     * чтобы на каждый день была активна только одна запись о статусе.
     *
     * @param newStatus новый статус с периодом.
     * @param userId ид юзера. если будет null, то это эквивалентно 0.
     * @param processEvent проводить ли события.
     * @param isweb если смена проходит из веба.
     */
     public void changeStatus( ContractStatus newStatus, Integer userId, boolean processEvent, boolean isweb ) throws SQLException


Далее алгоритм. Многие технические части намеренно опущены.

* Для каждого из случаев (клиент, сервер, web) выбирается из конфига 6 чисел -- приоритеты статусов.
* Запоминается оригинальный_статус, ибо устанавливаемый newStatus подготавливается к постепенному видоизменению.
* Из устанавливаемого статуса берётся cid, получается соответствующий договор. Если договора нет - молча на выход.
* Создаётся список кусочки_нового_статуса
* Берутся все промежутки статусов для этого договора (в реальности только те, что не раньше того момента, откуда самое раннее будет действовать новый статус; но это непринципиально) по ним делается цикл.
{
* выбранный_статус - статус текущей итерации (один из промежутков статуса договора).
* если приоритет выбранного_статуса меньше либо равен приоритета оригинального_статуса, то помечаем (флажок), что старый_статус_перетираемый.
То есть в этом случае отличий от классического алгоритма не будет. иначе будет учитываться, что выбранный_статус нельзя перетереть оригинальным_статусом.
// далее следует логика учёта перекрытий статусов
* Если статусы (newStatus и выбранный_статус) вообще не перекрываются
{
то возвращается к очередной итерации цикла (continue).
}
* Если newStatus полностью перекрыл выбранный_статус то
{
// полное перекрытие статуса
// old .......!*****?.....
// new ......!************
//
// old .......!*****!.....
// new .....!*********!...
если старый_статус_перетираемый то удаляем из списка выбранный_статус.
иначе (если старый статус нельзя перетереть устанавливаемым) newStatus бьётся на две части.
// old .......!*****!.....
// new .....!].......[*?..
левый кусочек добавляется в список кусочки_нового_статуса, а правый становится новым newStatus и мы его дальше используем в следующих итерациях.
}
* Если происходит разрыв статусом выбранного_статуса
{
// old .....[*****].....
// new ......[**!.......
если старый_статус_перетираемый то разрываем его на два кусочка и пишем оба в БД. новый не меняется.
иначе (если старый статус нельзя перетереть устанавливаемым) то выходит, что newStatus вообще вырождается окончательно, делаем newStatus=null и выходим из цикла.
}
*перекрытие старого статуса (выбранного_статуса) "слева"
{
// old ........!*****]..
// new .....?******!....
если старый_статус_перетираемый то делаем как раньше - двигаем старый до следующего дня после нового
// old .............!]..
// new .....?******!....
иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый конец назад, до предыдущего к старому
// old ........!*****]..
// new .....?*!.........
}
*перекрытие старого статуса (выбранного_статуса) "справа"
{
// old ....[*****]......
// new ......[******]...
если старый_статус_перетираемый то делаем как раньше - двигаем старый до предыдущего дня до нового
// old ....[]...........
// new ......[******]...
иначе (если старый статус нельзя перетереть устанавливаемым), то мы наоборот, двигаем новый начало вперёд, до следующего к старому
// old ....[*****]......
// new ...........[*]...
}
}
* Закончили цикл, если newStatus остался ещё (то есть newStatus!=null), то кладём его тоже в кусочки_нового_статуса, это будет самый правый кусочек исходного статуса.
Легко видеть, что если у нас вообще нет никаких неперетираемых статусо итд, то этот кусочек как раз будет единственным в списке и будет равен оригинальному_статусу.
* Далее, готовим событие ContractStatusChangingEvent, куда кладём оригинальный_статус (!) и плюс все кусочки_нового_статуса.
То есть всё останется как и было, кроме того случая, когда включаются приоритеты статусов, тогда, возможно, нужно будет учитывать кусочки в скрипте.
* Здесь самое интересное начинается. как известно, в скрипте можно изменить статус с бывшего на другой. в случае равноправных промежутков всё понятно - новый изменённый статус так и пишется.
Сейчас статус это список кусочков.
Так вот, смотрится оригинальный_статус и статус, побывавший в событии. Если статус был изменён, то меняется статус всех кусочков_нового_статуса.
После этого все кусочки пишутся в БД.
То есть логика здесь такая - можно взять и поменять статус в скрипте у отдельных кусочков. Но если поменян статус у целого контрактстатуса, то он распространится на все кусочки.
* При этом всём смотрится каждый кусочек и проверяется, что попадает на сегодня. Если это так, то устанавливается статус договора. После этого генерируется событие ContractStatusChangedEvent.
Внимание: в событие попадает не оригинальный статус, а кусочек соответствующий... не уверен пока что так надо.
* Записывается лог смены статусов. Если что-то меняется, то в комментарий лога смены статусов добавится, что статус был подрезан или разбит или выродился.
* Если договор - супердоговор
{
вызывается changeStatus для всех субдоговоров с зависимым балансом, куда передаётся оригинальный_статус.
если установлен independ.subcontract.status.change, то и для субдоговоров с независимым - тоже самое.
}

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 13 сен 2010, 15:59 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Сборку выложил. Если приоритеты статусов вообще не прописывать, то сломаться не должно ничего, всё будет как раньше. Но неперетираемые статусы надо ещё некоторое время тестировать, пишите если что-то не то.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 06 окт 2010, 15:56 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
:facepalm: Это всё неправильно оказалось, шатко, вызывало недоумение и было чревато непониманиями и подводными камнями. Всё убрано, будет смена статусов через скрипт :)

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 13 окт 2010, 12:33 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Всё, теперь смена статусов через скрипт:

http://wiki.bgbilling.ru/index.php/%D0% ... 0%BE%D0%B2

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 мар 2012, 11:47 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 20 апр 2009, 12:03
Сообщения: 3092
Откуда: Иркутск
Карма: 338
Решил наконец воспользоваться фичей.

Проблема такая:
У клиента несколько точек, оформленных в виде зависимых субдоговоров.
Одна из них по просьбе клиента приостанавливается (статус="приостановлен").
При этом статус супердоговора может быть любой. Но если мы его меняем, то теряем приостановление на субдоговоре.

Нужно сделать так, чтобы перетереть статус "приостановлен" зависимого субдоговора можно было только изменяя статус этого субдоговора, но не супердоговора. При этом остальные статусы для зависимых субдоговоров перетираются как обычно.

В событии ContractSetStatusLogicEvent нет способа узнать, задаётся ли статус на субдоговоре индивидуально или сработал каскадом от супердоговора.

Как быть?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 мар 2012, 19:48 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
И как это сделать?

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 11:57 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
А можно на зависимом субдоговоре по его типу как нибудь запретить перетирать статус активен статусом отключен? но разрешить перетирать статусами приостановлен, активен все остальное?

Есть просто у клиента несколько субдоговоров - один из них телефонный. а его по закону только после 21го числа отключать можно. Баланс единый у абонентов, работают в минус. Чтобы оператором понятнее было че с абонентом - есть скриптик который дергает статус абонента сравнивая его с лимитом.. Получается засада с абонентами у которых есть телефония - им вроде и надо статус поменять, чтобы инет перестал работать, но телефонию трогать не надо. Независимым договором тоже не сделаешь - нужен единый баланс.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 13:36 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
Хочу чтобы на договоре на котором висит этот скрипт не выставлялся статус отключено.
Код:
public void onEvent( event1, setup, con, conSlave )
{
   ContractSetStatusLogicEvent event = (ContractSetStatusLogicEvent)event1;
   print( "do change status!" );
 
   // старый статус
   ContractStatus status = event.getStatus1();
   // Приходящий статус
   ContractStatus newStatus = event.getStatus2();
   // Самый что ни на есть оригинальный статус
   ContractStatus originalStatus = event.getOriginalStatus();
    if(newStatus.getStatus()==2)
   {
      print ("Disable overwrite");
      event.setProcessed( true );
      return;
   }
}


Функция выполняется, в логах
Код:
GENERATE_TIME: 15.03.12 15:33:34
EXECUTION_STOP_TIME: 15.03.12 15:33:34
PROCESS_TIME: 2

OUT:
do change status!
Disable overwrite

но статус устанавливается. в настройках сервера use.event.set.status.logic=1 стоит, сервер перезапускал. нид хэлп энд экспланейшн =)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 16:30 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
версии

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 16:36 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Кстати, он что, только один раз вызывается? Вы же понимаете логику его работы? Скрипт должен вызваться несколько раз, равное количеству уже существующих промежутков статусов на договоре? Т.е. применяется ко всем промежуткам оттуда новый статус.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 16:47 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
dimOn писал(а):
Кстати, он что, только один раз вызывается? Вы же понимаете логику его работы? Скрипт должен вызваться несколько раз, равное количеству уже существующих промежутков статусов на договоре? Т.е. применяется ко всем промежуткам оттуда новый статус.

я текущим числом это пробовал делать на субдоговоре договоре который сегодня создал. будущих статусов на нем нет.

Сервер: вер. 5.1 сборка 774 от 15.03.2012 13:16:18
os: SunOS; java: Java HotSpot(TM) Server VM, v.1.6.0_24

update - вызывается количество раз столько, сколько периодов действия статусов пересекает, но получается некрасиво - в скринах приложил. если выставлять статус любой кроме отключен - все норм работает. Почему у меня вообще отрабатывает статус отключен и устанавливается? Я вроде думал он должен по такому скрипту игнорировать любые движения с отключенным статусом


Вложения:
Комментарий к файлу: а тут прошлым числом еще статус отключен поставил
4.png
4.png [ 138.41 КБ | Просмотров: 13610 ]
Комментарий к файлу: Суб договор - после перетирания статуса у супер договора тут получилась беда с тем что будущий статус осталсяи отключен тоже установился
4_1.png
4_1.png [ 95.55 КБ | Просмотров: 13610 ]
Комментарий к файлу: Супер договор. Было задано будущим числом состояние, текущим выставил - все перетерлось, нормально.
4_2.png
4_2.png [ 90.3 КБ | Просмотров: 13610 ]


Последний раз редактировалось Феанор 15 мар 2012, 16:58, всего редактировалось 1 раз.
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 16:58 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Ну я понял вас, НО: всё не так. Скрипт должен МОДИФИЦИРОВАТЬ статус. Тот, который приходит нам, новый. Он в конце работы этого цикла (который обходит все статусы) всегда сохраняется. Т.е. если вы его не изменили, то ничего и не изменится - он запишется как есть. А те статусы, которые есть в БД можно (нужно?) в этом же скрипте модифицировать тоже, но уже через БД напрямую. (поглядите на вики пример стандартной работы кода в виде этого же скрипта). Если вы хотите просто проигнорировать этот статус, то вам и в БД ничего не надо менять, но и этот статус ВЫРОДИТЬ. Ну и плюс поставить, конечно, этот флаг отработанности. Он влияет только на то, что в конкретном цикле (=одному запуску скрипта) произойдёт continue и не выполнится дельнейший стандартный код.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:00 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
dimOn писал(а):
Ну я понял вас, НО: всё не так. Скрипт должен МОДИФИЦИРОВАТЬ статус. Тот, который приходит нам, новый. Он в конце работы этого цикла (который обходит все статусы) всегда сохраняется. Т.е. если вы его не изменили, то ничего и не изменится - он запишется как есть. А те статусы, которые есть в БД можно (нужно?) в этом же скрипте модифицировать тоже, но уже через БД напрямую. (поглядите на вики пример стандартной работы кода в виде этого же скрипта). Если вы хотите просто проигнорировать этот статус, то вам и в БД ничего не надо менять, но и этот статус ВЫРОДИТЬ. Ну и плюс поставить, конечно, этот флаг отработанности. Он влияет только на то, что в конкретном цикле (=одному запуску скрипта) произойдёт continue и не выполнится дельнейший стандартный код.

как я понял мне надо сделать newStatus=status? т.е. новый статус оставить таким же как и было? но так не работает :)


Последний раз редактировалось Феанор 15 мар 2012, 17:02, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:02 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Как выродить: поставить у этого нового статуса date2 предыдущим днём от date1, например. Попробуйте так.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:06 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Феанор писал(а):
dimOn писал(а):
Ну я понял вас, НО: всё не так. Скрипт должен МОДИФИЦИРОВАТЬ статус. Тот, который приходит нам, новый. Он в конце работы этого цикла (который обходит все статусы) всегда сохраняется. Т.е. если вы его не изменили, то ничего и не изменится - он запишется как есть. А те статусы, которые есть в БД можно (нужно?) в этом же скрипте модифицировать тоже, но уже через БД напрямую. (поглядите на вики пример стандартной работы кода в виде этого же скрипта). Если вы хотите просто проигнорировать этот статус, то вам и в БД ничего не надо менять, но и этот статус ВЫРОДИТЬ. Ну и плюс поставить, конечно, этот флаг отработанности. Он влияет только на то, что в конкретном цикле (=одному запуску скрипта) произойдёт continue и не выполнится дельнейший стандартный код.

как я понял мне надо сделать newStatus=status? т.е. новый статус оставить таким же как и было? но так не работает :)

нет, статус второй вы никак не измените. этот статус УЖЕ ЕСТЬ в БД, это просто один из статусов в истории. смысл скрипта (который фактически замещает стандартный код) - просто решить как изменить новый статус , чтобы подвинуть его границы перед сохранением. либо же двигаем границы того что лежит уже в БД.
если у вас лежит уже статус в БД
01.01.2012 - бесконечность,
а вы ставите статус например 15.03.2012-бесконечность.
то стандартный код двигает то что есть и записывает в БД. а потом этот новый статус (он стандатрным кодом не меняется) тоже в конце-концов кладёт в БД.

ваш же скрипт который вы выложили испортит базу - он и старый не трогает, и новый не меняет. так что у вас окажется новый статус который конфликтует с периодам тем что уже есть. скрипт не может "ничего не делать". это довольно низкоуровневый скрипт и пользоваться им надо аккуратно.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:09 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
dimOn писал(а):
Как выродить: поставить у этого нового статуса date2 предыдущим днём от date1, например. Попробуйте так.

newStatus.setDateTo(TimeUtils.getPrevDay(newStatus.getDateFrom));
Перетирает все как стандартной логикой.

update - поэтому я все и делаю на тестовой базе, которую не жалко

update2 - в коде который в начале сообщения пробовал - ошибка была, поэтому и не работало, обращался к полю а не к методу
newStatus.setDateTo(TimeUtils.getPrevDay(newStatus.getDateFrom())) - делает то что мне надо на первый взгляд. тестировать уже завтра буду


Последний раз редактировалось Феанор 15 мар 2012, 17:10, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:10 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Ваш скрипт должен либо поправить БД чтобы предыдущий там изменить. либо изменить newStatus, и сделать его таким, который в итоге попадёт в БД.
Если вы хотите чтобы в БД осталось всё что лежало, а новый вообще проигнорировался, то БД не трогаете, а новый грохаете, т.е. вырождаете как я написал.

Но учтите, что у вас это ведь по некоторым условиям выполняется, то есть если эти условия не наступили, вам надо позаботиться чтобы нормально подвинулись статусы, чтобы не произошло казуса как я выше описал. В вашем случае проще всего тогда для этого случая не менять ни пришедший ни лежащий в БД, и установить обработанность=фалсе, чтобы стандартный код дальше сделал чо надо для этой пары статусов.

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:11 
Не в сети
Аватара пользователя

Зарегистрирован: 30 май 2008, 15:51
Сообщения: 6055
Карма: 244
Феанор писал(а):
dimOn писал(а):
Как выродить: поставить у этого нового статуса date2 предыдущим днём от date1, например. Попробуйте так.

newStatus.setDateTo(TimeUtils.getPrevDay(newStatus.getDateFrom));
Перетирает все как стандартной логикой.

update - поэтому я все и делаю на тестовой базе, которую не жалко

update2 - в коде который в начале сообщения пробовал - ошибка была, поэтому и не работало, обращался к полю а не к методу
newStatus.setDateTo(TimeUtils.getPrevDay(newStatus.getDateFrom())) - делает то что мне надо на первый взгляд. тестировать уже завтра буду

сейчас подумаю..........

_________________
I'm clever. I've got a computer.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:15 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
он кстати в логах действий пишет : статус изменился (последний промежуток: 15.03.2012-14.03.2012: отключен)(т.е. выродился), но периоды при этом нормально остаются, остальными статусами перетираются, статус отключен никак не влияет на периоды


Вложения:
Комментарий к файлу: во как - внизу видно что устанавливал статус отключен разными числами и все ок - периоды не поменялись
ok.png
ok.png [ 163.43 КБ | Просмотров: 13619 ]
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 мар 2012, 17:20 
Не в сети
Клиент

Зарегистрирован: 30 мар 2009, 17:51
Сообщения: 431
Карма: 23
Cromeshnic писал(а):
Решил наконец воспользоваться фичей.

Проблема такая:
У клиента несколько точек, оформленных в виде зависимых субдоговоров.
Одна из них по просьбе клиента приостанавливается (статус="приостановлен").
При этом статус супердоговора может быть любой. Но если мы его меняем, то теряем приостановление на субдоговоре.

Нужно сделать так, чтобы перетереть статус "приостановлен" зависимого субдоговора можно было только изменяя статус этого субдоговора, но не супердоговора. При этом остальные статусы для зависимых субдоговоров перетираются как обычно.

В событии ContractSetStatusLogicEvent нет способа узнать, задаётся ли статус на субдоговоре индивидуально или сработал каскадом от супердоговора.

Как быть?

я бы это попробовал сделать так - на договоре сделал параметр типа флаг - в функции скрипта проверял бы - супердоговор это или нет.
если супер то апдейтил бы флаг, а если суб и флаг супера установлен в заданный таймаут (5-10 секунд), то игнорировал бы статусы (как игнорировать статусы - в топике выше, у меня эта задача была)... костыль конечно, но почему бы и нет:)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 мар 2012, 12:44 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 20 апр 2009, 12:03
Сообщения: 3092
Откуда: Иркутск
Карма: 338
Феанор писал(а):
я бы это попробовал сделать так - на договоре сделал параметр типа флаг


Спасибо. Сделал флаг по-другому: добавил префикс в комментарий "С супердоговора: ". В событии ContractStatusChangingEvent ставим этот префикс, если событие сработало на супердоговоре.
В событии ContractSetStatusLogicEvent, если status=4 и в originalStatus есть префикс, а в status префикса нет, то включаем нашу логику.

Написал, побаловался на тестовом биллинге, сейчас запилю в продакшн, посмотрим.

Код:
package ru.dsi.bgbilling.kernel.scripts;

import bitel.billing.server.contract.bean.Contract;
import bitel.billing.server.contract.bean.ContractManager;
import bitel.billing.server.contract.bean.ContractStatus;
import ru.bitel.bgbilling.kernel.event.events.ContractStatusChangingEvent;
import ru.bitel.bgbilling.kernel.script.server.dev.EventScriptBase;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.sql.ConnectionSet;

public class SubcontractFlagContractStatusChangingEvent
   extends EventScriptBase<ContractStatusChangingEvent>
{
   public static String subcontractCommentPrefix = "С супердоговора: ";
   
   @Override
   public void onEvent( ContractStatusChangingEvent event, Setup setup, ConnectionSet connectionSet )
      throws Exception
   {
      int cid = event.getContractId();
      ContractManager cm = new ContractManager(connectionSet.getConnection());
      Contract c = cm.getContractById(cid);
      if(null==c){
         return;
      }
      if(c.isSuper()){
         ContractStatus cs = event.getOriginalStatus();
         if(cs!=null){
            String comment = cs.getComment();
            if(null==comment){comment="";}
            cs.setComment(subcontractCommentPrefix+comment);
         }
      }

   }

}


Код:
package ru.dsi.bgbilling.kernel.scripts;

import java.util.Calendar;

import bitel.billing.common.TimeUtils;
import bitel.billing.server.contract.bean.ContractStatus;
import bitel.billing.server.contract.bean.ContractStatusManager.ContractStatusManager4Script;
import ru.bitel.bgbilling.kernel.event.events.ContractSetStatusLogicEvent;
import ru.bitel.bgbilling.kernel.script.server.dev.EventScriptBase;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.sql.ConnectionSet;

public class MyContractSetStatusLogicEvent
   extends EventScriptBase<ContractSetStatusLogicEvent>
{
   @Override
   public void onEvent( ContractSetStatusLogicEvent event, Setup setup, ConnectionSet connectionSet )
      throws Exception
   {
      ContractStatus originalStatus = event.getOriginalStatus();
      this.print("status="+event.getStatus1());

      String comment = originalStatus.getComment();
      if(comment!=null){
         if(comment.startsWith(SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix)){
            //Если комментарий статуса начинается с SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix
            //и мы - субдоговор, то считаем, что статус устанавливается с супердоговора =>
            // => не перекрываем островки статуса "приостановлен"
            // старый статус
            ContractStatus status = event.getStatus1();
            // Приходящий статус
            ContractStatus newStatus = event.getStatus2();
            String statusComment = status.getComment();
            if(statusComment==null){statusComment="";}
            //Обрабатываем только статус 4 ("приостановлен"), установленный на конкретном субдоговоре (не спущенный сверху)
            if(status.getStatus()==4 && !statusComment.startsWith(SubcontractFlagContractStatusChangingEvent.subcontractCommentPrefix)){
               // менеджер ContractStatusManager, оптимизированный для этого скрипта
               ContractStatusManager4Script csm = new ContractStatusManager4Script( connectionSet.getConnection() );
               
               //Предыдущий день перед началом нового статуса
               Calendar prevDay = Calendar.getInstance();
               prevDay.setTime( newStatus.getDateFrom() );
               prevDay.add( Calendar.DAY_OF_MONTH, -1 );
            
                // следующий день после конца нового статуса (или null)
               Calendar nextDay = null;
               if( originalStatus.getDateTo() != null )
               {
                  nextDay = Calendar.getInstance();
                  nextDay.setTime( newStatus.getDateTo() );
                  nextDay.add( Calendar.DAY_OF_YEAR, 1 );
               }
               
               Calendar tmpprev = Calendar.getInstance();
               tmpprev.setTime(status.getDateFrom());
               tmpprev.add( Calendar.DAY_OF_MONTH, -1 );
               
               Calendar tmpnext = Calendar.getInstance();
               if(status.getDateTo()!=null){
                  tmpnext.setTime(status.getDateTo());
                  tmpnext.add( Calendar.DAY_OF_MONTH, 1 );
               }else{
                  tmpnext=null;
               }
               
               /* 1.
                * status:...[4444]
                * new:....[***********?
                * ->
                * status:...[4444]
                * new:....[]......[***?
                *
                * и да, мы теряем первый кусок от newStatus, поэтому сразу же его апдейтим (хоть и вне стандартной логики и без ContractStatusChangingEvent)
               */
               if( TimeUtils.dateBeforeOrEq( newStatus.getDateFrom(), status.getDateFrom() ) && status.getDateTo() != null &&
                         (newStatus.getDateTo() == null || TimeUtils.dateBeforeOrEq( status.getDateTo(), newStatus.getDateTo() )  ) )
                  {
                  //Запиливаем первый кусочек:
                  if(TimeUtils.dateBefore(newStatus.getDateFrom(), tmpprev.getTime())){
                     ContractStatus tmp = newStatus.clone();
                     tmp.setDateTo(tmpprev.getTime());
                     if(ContractStatusManager4Script.isStatusPeriodValid(tmp)){
                        csm.updateStatus(tmp, event.getUserId());
                     }
                  }
                  //Меняем date1 второго кусочка newStatus
                  newStatus.setDateFrom(tmpnext.getTime());
                  }else
               
               /* 2.
                * status:..[444]
                * new:.......[******?
                * ->
                * status:..[444]
                * new:..........[***?
                */
               if(status.getDateTo() != null && TimeUtils.dateBeforeOrEq(status.getDateFrom(),newStatus.getDateFrom())){
                  newStatus.setDateFrom(tmpnext.getTime());
               }else
               
               /* 3.
                * status:.....[444444?
                * new:.....[*****]
                * ->
                * status:.....[444444?
                * new:.....[*]
                */
               if(newStatus.getDateTo()!=null && TimeUtils.dateBeforeOrEq(status.getDateFrom(), newStatus.getDateTo())){
                  newStatus.setDateTo(tmpprev.getTime());
               }else
               
               /* 4.
                * status:.....[4444!
                * new:.....[*******?
                * or
                * status:.....[4444!
                * new:..........[**?
                * ->
                * status:.....[4444!
                * new:.....[*]
                * or
                * status:.....[4444!
                * new:..............
                */
               if(status.getDateTo()==null){
                  //либо статус обрезается до кусочка перед нашим диапазоном, либо вырождается
                  newStatus.setDateTo(tmpprev.getTime());
               }
               
               event.setProcessed( true );
            }
         }
      }
      
   }

}


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 24 ] 

Часовой пояс: UTC + 5 часов [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
POWERED_BY
Русская поддержка phpBB
[ Time : 0.086s | 67 Queries | GZIP : On ]