Начисляем деньги. А если способ начисления изменится?

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Solo
Сообщения: 108
Зарегистрирован: 18 апр 2005, 04:05

Начисляем деньги. А если способ начисления изменится?

Сообщение Solo » 23 май 2005, 05:10

В приложении Delphi, базу которого я переношу из базы данных MS Access в FireBird, я использовал компоненты PascalScript. Если способ начисления денег за услуги менялся, клиенты меняли pascal=подобный скрипт для этой услуги, и с этого дня она рассчитывалась по-новому. Если они затруднялись, то объясняли мне проблему по телефону, я им высылал текст скрипта, который они Copy-Past в базу.

Вот я думаю: а возможно ли теперь отказаться от PascalScripta? Ведь хранимые процедуры - тоже типа скрипта, а менять их, кажется, можно, запуская из ISQL файлы "*.sql"

При начислении в старой программе скрипт мог следующие вещи:
операция "Case", перебор записей в цикле, арифметика (само-собой)... Каждый вид услуги имел свой способ расчета. Программа делала следующее: узнавала идентификатор способа расчета для данной услуги, брала по этому идентификатору из специальной таблицы сам способ (обычный паскаль-код в мемо-поле) и запускала этот паскаль-код на выполнение.

Стоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?

Dmitry Beloshistov
Сообщения: 41
Зарегистрирован: 27 окт 2004, 11:06

Re: Начисляем деньги. А если способ начисления изменится?

Сообщение Dmitry Beloshistov » 23 май 2005, 10:44

solo писал(а):При начислении в старой программе скрипт мог следующие вещи:
операция "Case", перебор записей в цикле, арифметика (само-собой)...
В FB 1.5x CASE благополучно можно использовать в текстах хранимых процедур. В ReleaseNotes написано, как. Кстати, запросы можно еще и динамически формировать через execute statement/varchar.
Каждый вид услуги имел свой способ расчета. Программа делала следующее: узнавала идентификатор способа расчета для данной услуги, брала по этому идентификатору из специальной таблицы сам способ (обычный паскаль-код в мемо-поле) и запускала этот паскаль-код на выполнение.
И что мешает использовать CASE и вызывать соответствующие куски кода? Кстати, вместо одной процедуры лучше (имхо) использовать несколько (на каждую услугу - свой) - значительно меньше времени зайиет исправление.
Стоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?
А тут каждый решает для себя сам. Многое зависит от привычки :)

mfasakhov
Сообщения: 5
Зарегистрирован: 26 май 2005, 14:38

Сообщение mfasakhov » 03 июн 2005, 12:18

Стоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?
Стоит однозначно. Клиентам тогда ничего не надо будет менять. Кроме того эти изменения будут затрагивать все клиентские приложения, т.е. не надо менять скрипты например в головной программе, а потом еще в куче других, если они есть (например отчеты).

Solo
Сообщения: 108
Зарегистрирован: 18 апр 2005, 04:05

История имеет продолжение

Сообщение Solo » 06 июн 2005, 12:16

mfasakhov писал(а): Стоит однозначно. Клиентам тогда ничего не надо будет менять. Кроме того эти изменения будут затрагивать все клиентские приложения, т.е. не надо менять скрипты например в головной программе, а потом еще в куче других, если они есть (например отчеты).
Спасибо. Заодно докладываю, что уже вовсю постигаю :)
Расчётные алгоритмы еще не сделал, но с помощью ХП прога выбирает из списка жильцов проживающих только в нужном периоде, верстает их, считает, скока дней каждый прожил. Также выхватывает из услуг необходимые и верстает записи с начислениями. Пока по умолчанию начисления ставлю 0. Все это делается по клике на кнопку "Начислить". Только начисление в этом случае производится по отдельной квартире.

Возникает интересный вопрос: если юзер не хочет постоянно ходить по квартирам и щелкать для каждого "Начислить"? Понятно, что можно сделать перебор в самой ХП:

Код: Выделить всё

for select "то, что квартира", делай такую-то процедуру
Я верно рассуждаю?
Если верно, то как вывести на клиента прогресс события? Если база большая - то поставить вместо курсора часики? И как долго они будут висеть?

Или сделать по типу 1С: там не прогресс показывается, а мелькают фамилии. Короче, какая-то деятельность имеет место быть.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 06 июн 2005, 12:25

Стандартная виндовая анимашка ака копирование файлов не подойдет? делается как 2 пальца... правда к прогрессу не имеет ни малейшего отношения. :)

MuirsheenDurkin
Сообщения: 44
Зарегистрирован: 21 янв 2005, 10:18

Сообщение MuirsheenDurkin » 06 июн 2005, 12:28

Если количество записей можно определить заранее, то event'ы можно слать по мере обработки и считать их.
Хотя ерунда все это, конечно.

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Re: История имеет продолжение

Сообщение sag » 06 июн 2005, 12:46

solo писал(а):Или сделать по типу 1С: там не прогресс показывается, а мелькают фамилии.
Можно и так сделать. Для этого надо хп сконструировать в расчетно-селектабильном стиле, обрабатываемые в данный момент "фамилии" возвращать по suspend-у. Только надо учесть нюансы. Может так сложиться, что "Иванов" будет "расчитан" за 2 секунды, а "Сидоров" за час. Еще надо учесть commit-но rollback-овые особенности селективных хп при возникновении исключений в процессе работы.

Solo
Сообщения: 108
Зарегистрирован: 18 апр 2005, 04:05

Сообщение Solo » 07 июн 2005, 06:03

MuirsheenDurkin писал(а):Если количество записей можно определить заранее, то event'ы можно слать по мере обработки и считать их.
Хотя ерунда все это, конечно.
1. Что ерунда и почему?

2. Количство можно определить, почему бы и нет?

Код: Выделить всё

Count where такое-то поле = :Параметр
, если не ошибаюсь... Вот бы примерчик какой, как слать эти eventы

3. Анимашка с копированием файлов тут не покатит. Не по теме. Нужен именно прогресс. Наиболее подходящий вариант, кажется, предложен MuirsheenDurkin-ом. И вообще, насколько надежно это все работает? Не начнется что-то типа "сервер принудительно разорвал и т.д."? Уже были такие случаи :? (FireBird 1.52)

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 07 июн 2005, 08:53

Как вариант
Стартовать в приложении 2 потока с разными транзакциями, в одном потоке запускем формирование отчета, в другом снимаем статистику.
Для каждого экземпляра программы на старте создавать собственный генератор ProgressGeneratorNNN. ХП формирующая твой отчет должна этот генератор наращивать по мере обработки, вторым потоком будешь снимать значения этого генератора по таймеру. Если первоначально подсчитать кол-во обрабатываемых записей, можно выводить и в процентах.

MuirsheenDurkin
Сообщения: 44
Зарегистрирован: 21 янв 2005, 10:18

Сообщение MuirsheenDurkin » 07 июн 2005, 10:11

solo писал(а): 1. Что ерунда и почему?
Не очень толково показывать пользователю детальный ход процесса, повлиять на который он все равно не в состоянии. Анимашка тут в самый раз, IMHO.

Чего ж не понять? У тебя сто записей к обработке. Получил 20 event'ов - выполнено на 20 процентов.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 07 июн 2005, 10:56

MuirsheenDurkin писал(а):Если количество записей можно определить заранее, то event'ы можно слать по мере обработки и считать их.
Коммиты тоже будешь делать по мере обрабоки ? Внутри SP ?
MuirsheenDurkin писал(а):Хотя ерунда все это, конечно.
Именно, в буквальном смысле :)

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 07 июн 2005, 10:59

MuirsheenDurkin писал(а):Чего ж не понять? У тебя сто записей к обработке. Получил 20 event'ов - выполнено на 20 процентов.
event-ы по commit-e ходют, закомитятся все действия хп и получишь все события нараз, все 100%

MuirsheenDurkin
Сообщения: 44
Зарегистрирован: 21 янв 2005, 10:18

Сообщение MuirsheenDurkin » 07 июн 2005, 13:05

sag писал(а):event-ы по commit-e ходют
Гм, действительно. Значит, вычеркиваем. Прошу считать меня недействительным.

Solo
Сообщения: 108
Зарегистрирован: 18 апр 2005, 04:05

Сообщение Solo » 08 июн 2005, 03:28

Ivan_Pisarevsky писал(а):Как вариант
Стартовать в приложении 2 потока с разными транзакциями, в одном потоке запускем формирование отчета, в другом снимаем статистику.
Для каждого экземпляра программы на старте создавать собственный генератор ProgressGeneratorNNN. ХП формирующая твой отчет должна этот генератор наращивать по мере обработки, вторым потоком будешь снимать значения этого генератора по таймеру. Если первоначально подсчитать кол-во обрабатываемых записей, можно выводить и в процентах.
1. Листинг - лучший хелп :D (Если не трудно особенно как снимать статистику, про генератор-то ясно) И не будет ли слишком это наворочено?

2. Насчет анимированого копирования файлов - учитывая, что TIB_StoredProc (я говорил, что таки-пользуюсь IBO 4.5?) вешает, пока процедура не закончится, HourGlass с буквами SQL, то нет смысла вешать анимашку, наверное...

А сервер не может отправлять на рабочую станцию какие-нибудь данные? Я еще не до конца понял, но, кажется, в ХП можно создавать исключения в случае ошибки и уведомлять станцию. Если так, то может, можно что-нибудь слать и без ошибки? типа 10, 20, 30?
Если не то говорю - не ржать!

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 08 июн 2005, 08:04

solo писал(а):Если не то говорю - не ржать!
Про исключения - это ты перемудрил, а про хп, похоже, ты еще не вкурил. Принцип простой, например:

Код: Выделить всё

create hp(...)
returns (<счетчик_прогресса> <тип>)
...
for select ...... do
begin
  <действия обсчета i/u/d>
  <счетчик_прогресса>=<счетчик_прогресса>+1;
  suspend;
end
и далее:

Код: Выделить всё

select <счетчик_прогресса> from hp...;
commit или rollback
Логику "правил игры" для <счетчика_прогресса> и визуализацию процесса продумать не сложно.
На мой взгляд, использование генератора ничем не лучше использования хп возвращающих данные в процессе обработки. Но при использовании любого из этих способов скорость (равномерность) продвижения "прогресса" довольно условна. Минусы использования генераторов для этой задачи очевидны (для меня).
P.S."HourGlass с буквами SQL" - это конечно крута, но нафига? Разве что для повышения своей важности в глазах пользователя в процессе разъяснения ему, что это за магическое заклинание "SQL".

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 08 июн 2005, 12:09

sag писал(а):
solo писал(а):

Код: Выделить всё

create hp(...)
returns (<счетчик_прогресса> <тип>)
...
for select ...... do
begin
  <действия обсчета i/u/d>
  <счетчик_прогресса>=<счетчик_прогресса>+1;
  suspend;
end
и далее:

Код: Выделить всё

select <счетчик_прогресса> from hp...;
commit или rollback
Генератор в многопользовательском режиме конечно лисапет на квадратных колёсах, но тут тоже есть один нюанец - счётчики будешь получать пачками в размере сетевого пакета, а не непрерывно. Навскидку не помню скока это будет в граммах для одного инта, наверное пара тысяч. Если цикл сам по себе длительный, то дискрет времени будет заметный. Для поштучного можно попробовать select for update, с процедурами сам не делал, если интересно, то нужен острый натурный эксперимент. Но это по любому на суммарном времени выполнения скажется не в лучшую сторону, опять же я не в курсах, дружит ли IBO с select for update, IBX точно требует доработки напильником. А вообще-то анимация - имхо не та тема, которой должны заморачиваться просвещённые в Дао. Если юзверь уж очень сильно скучает глядючи на рюмку с надписью SQL или без оной - покрутить ему порнушку с музычкой...

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 08 июн 2005, 12:32

Merlin писал(а):Для поштучного можно попробовать select for update, с процедурами сам не делал, если интересно, то нужен острый натурный эксперимент.
Теоретицкий интерес у меня есть, но слабый. Сейчас крайне озадачен выбором имени для собаки. Но может руки когда и дойдут до означенного выше эксперимента.
Merlin писал(а):А вообще-то анимация - имхо не та тема, которой должны заморачиваться просвещённые в Дао. Если юзверь уж очень сильно скучает глядючи на рюмку с надписью SQL или без оной - покрутить ему порнушку с музычкой...
Лет 12 назад в институте им.БончБр. мне понравилась анимашка часиков в виде рожицы лихо поедавшей арбузную дольку и расплевывавшая семечки.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 08 июн 2005, 13:56

sag писал(а): Сейчас крайне озадачен выбором имени для собаки.
Помницца, был у меня английский кокер Берримор :)

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 08 июн 2005, 14:32

Merlin писал(а):
sag писал(а): Сейчас крайне озадачен выбором имени для собаки.
Помницца, был у меня английский кокер Берримор :)
Фух. Ура, выбрал. Три дня думал, три дня мучений. Тебе проще было: Берримор - мальчик на "Бэ", мне надо было девочку на "Шэ". Выбирать из снадартных Шерри, Шекли, Шило (а список кличек на "Шэ" для сук очень и очень небольшой) - не хотел.
На радостях соорудил "острый натурный эксперимент". Докладаю: select for update по процедуре (без order by, есс-но) сделает счастливыми построителей "прогресс-градусников".

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 09 июн 2005, 09:56

Если юзверь уж очень сильно скучает глядючи на рюмку с надписью SQL или без оной - покрутить ему порнушку с музычкой...
Или пасьянсец разложить...

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

Можно сделать так: В основной программе растим специально обученый генератор и перед длительным запросом делаем
"селект каунт(*) фром блаблабла" чтоб прикинуть да каких пор расти этому самому генератору.
Далее делаем на дельфях(например) отдельную программу, соответственно компилить ее в отдельный экзешник, чтоб основной код всяким хламом не засорять. программа состоит из одной формы на которую положить: тибдатабэйз, тибтразакшн, тибквери (ну или любой компонент который будет базу вопрошать), ттаймер, тпрогрессбар, танимэйт. В качестве параметров командной строки программа должна получить имя генератора и число докуда он должен дорасти (можно еще скормить ей строку подключения к базе, для пущщей универсальности). Эту программу будет запускать основная программа, когда в ней будет нужда, а закрываться она сможет сама, когда придет к выводу, что генератор насчитал положеные тики. Программа стартует, цепляется к базе, стартует таймер и по ОнТаймеру делает селект из базы на счет изменился генератор или нет, далее кормить получеными значениями програссбар. А ну и в начале запустить какой-нидь ролик в анимэйте, чтоб веселей была картина. Вроде так :)

Ответить