Начисляем деньги. А если способ начисления изменится?
Модератор: kdv
Начисляем деньги. А если способ начисления изменится?
В приложении Delphi, базу которого я переношу из базы данных MS Access в FireBird, я использовал компоненты PascalScript. Если способ начисления денег за услуги менялся, клиенты меняли pascal=подобный скрипт для этой услуги, и с этого дня она рассчитывалась по-новому. Если они затруднялись, то объясняли мне проблему по телефону, я им высылал текст скрипта, который они Copy-Past в базу.
Вот я думаю: а возможно ли теперь отказаться от PascalScripta? Ведь хранимые процедуры - тоже типа скрипта, а менять их, кажется, можно, запуская из ISQL файлы "*.sql"
При начислении в старой программе скрипт мог следующие вещи:
операция "Case", перебор записей в цикле, арифметика (само-собой)... Каждый вид услуги имел свой способ расчета. Программа делала следующее: узнавала идентификатор способа расчета для данной услуги, брала по этому идентификатору из специальной таблицы сам способ (обычный паскаль-код в мемо-поле) и запускала этот паскаль-код на выполнение.
Стоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?
Вот я думаю: а возможно ли теперь отказаться от PascalScripta? Ведь хранимые процедуры - тоже типа скрипта, а менять их, кажется, можно, запуская из ISQL файлы "*.sql"
При начислении в старой программе скрипт мог следующие вещи:
операция "Case", перебор записей в цикле, арифметика (само-собой)... Каждый вид услуги имел свой способ расчета. Программа делала следующее: узнавала идентификатор способа расчета для данной услуги, брала по этому идентификатору из специальной таблицы сам способ (обычный паскаль-код в мемо-поле) и запускала этот паскаль-код на выполнение.
Стоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?
-
- Сообщения: 41
- Зарегистрирован: 27 окт 2004, 11:06
Re: Начисляем деньги. А если способ начисления изменится?
В FB 1.5x CASE благополучно можно использовать в текстах хранимых процедур. В ReleaseNotes написано, как. Кстати, запросы можно еще и динамически формировать через execute statement/varchar.solo писал(а):При начислении в старой программе скрипт мог следующие вещи:
операция "Case", перебор записей в цикле, арифметика (само-собой)...
И что мешает использовать CASE и вызывать соответствующие куски кода? Кстати, вместо одной процедуры лучше (имхо) использовать несколько (на каждую услугу - свой) - значительно меньше времени зайиет исправление.Каждый вид услуги имел свой способ расчета. Программа делала следующее: узнавала идентификатор способа расчета для данной услуги, брала по этому идентификатору из специальной таблицы сам способ (обычный паскаль-код в мемо-поле) и запускала этот паскаль-код на выполнение.
А тут каждый решает для себя сам. Многое зависит от привычкиСтоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?
Стоит однозначно. Клиентам тогда ничего не надо будет менять. Кроме того эти изменения будут затрагивать все клиентские приложения, т.е. не надо менять скрипты например в головной программе, а потом еще в куче других, если они есть (например отчеты).Стоит ли пытаться сделать что подобное с помощью ХП прямо на сервере или проще использовать PascalScript на клиенте, как в старом приложении?
История имеет продолжение
Спасибо. Заодно докладываю, что уже вовсю постигаюmfasakhov писал(а): Стоит однозначно. Клиентам тогда ничего не надо будет менять. Кроме того эти изменения будут затрагивать все клиентские приложения, т.е. не надо менять скрипты например в головной программе, а потом еще в куче других, если они есть (например отчеты).
Расчётные алгоритмы еще не сделал, но с помощью ХП прога выбирает из списка жильцов проживающих только в нужном периоде, верстает их, считает, скока дней каждый прожил. Также выхватывает из услуг необходимые и верстает записи с начислениями. Пока по умолчанию начисления ставлю 0. Все это делается по клике на кнопку "Начислить". Только начисление в этом случае производится по отдельной квартире.
Возникает интересный вопрос: если юзер не хочет постоянно ходить по квартирам и щелкать для каждого "Начислить"? Понятно, что можно сделать перебор в самой ХП:
Код: Выделить всё
for select "то, что квартира", делай такую-то процедуру
Если верно, то как вывести на клиента прогресс события? Если база большая - то поставить вместо курсора часики? И как долго они будут висеть?
Или сделать по типу 1С: там не прогресс показывается, а мелькают фамилии. Короче, какая-то деятельность имеет место быть.
-
- Заслуженный разработчик
- Сообщения: 644
- Зарегистрирован: 15 фев 2005, 11:34
-
- Сообщения: 44
- Зарегистрирован: 21 янв 2005, 10:18
Re: История имеет продолжение
Можно и так сделать. Для этого надо хп сконструировать в расчетно-селектабильном стиле, обрабатываемые в данный момент "фамилии" возвращать по suspend-у. Только надо учесть нюансы. Может так сложиться, что "Иванов" будет "расчитан" за 2 секунды, а "Сидоров" за час. Еще надо учесть commit-но rollback-овые особенности селективных хп при возникновении исключений в процессе работы.solo писал(а):Или сделать по типу 1С: там не прогресс показывается, а мелькают фамилии.
1. Что ерунда и почему?MuirsheenDurkin писал(а):Если количество записей можно определить заранее, то event'ы можно слать по мере обработки и считать их.
Хотя ерунда все это, конечно.
2. Количство можно определить, почему бы и нет?
Код: Выделить всё
Count where такое-то поле = :Параметр
3. Анимашка с копированием файлов тут не покатит. Не по теме. Нужен именно прогресс. Наиболее подходящий вариант, кажется, предложен MuirsheenDurkin-ом. И вообще, насколько надежно это все работает? Не начнется что-то типа "сервер принудительно разорвал и т.д."? Уже были такие случаи (FireBird 1.52)
-
- Заслуженный разработчик
- Сообщения: 644
- Зарегистрирован: 15 фев 2005, 11:34
Как вариант
Стартовать в приложении 2 потока с разными транзакциями, в одном потоке запускем формирование отчета, в другом снимаем статистику.
Для каждого экземпляра программы на старте создавать собственный генератор ProgressGeneratorNNN. ХП формирующая твой отчет должна этот генератор наращивать по мере обработки, вторым потоком будешь снимать значения этого генератора по таймеру. Если первоначально подсчитать кол-во обрабатываемых записей, можно выводить и в процентах.
Стартовать в приложении 2 потока с разными транзакциями, в одном потоке запускем формирование отчета, в другом снимаем статистику.
Для каждого экземпляра программы на старте создавать собственный генератор ProgressGeneratorNNN. ХП формирующая твой отчет должна этот генератор наращивать по мере обработки, вторым потоком будешь снимать значения этого генератора по таймеру. Если первоначально подсчитать кол-во обрабатываемых записей, можно выводить и в процентах.
-
- Сообщения: 44
- Зарегистрирован: 21 янв 2005, 10:18
-
- Сообщения: 44
- Зарегистрирован: 21 янв 2005, 10:18
1. Листинг - лучший хелп (Если не трудно особенно как снимать статистику, про генератор-то ясно) И не будет ли слишком это наворочено?Ivan_Pisarevsky писал(а):Как вариант
Стартовать в приложении 2 потока с разными транзакциями, в одном потоке запускем формирование отчета, в другом снимаем статистику.
Для каждого экземпляра программы на старте создавать собственный генератор ProgressGeneratorNNN. ХП формирующая твой отчет должна этот генератор наращивать по мере обработки, вторым потоком будешь снимать значения этого генератора по таймеру. Если первоначально подсчитать кол-во обрабатываемых записей, можно выводить и в процентах.
2. Насчет анимированого копирования файлов - учитывая, что TIB_StoredProc (я говорил, что таки-пользуюсь IBO 4.5?) вешает, пока процедура не закончится, HourGlass с буквами SQL, то нет смысла вешать анимашку, наверное...
А сервер не может отправлять на рабочую станцию какие-нибудь данные? Я еще не до конца понял, но, кажется, в ХП можно создавать исключения в случае ошибки и уведомлять станцию. Если так, то может, можно что-нибудь слать и без ошибки? типа 10, 20, 30?
Если не то говорю - не ржать!
Про исключения - это ты перемудрил, а про хп, похоже, ты еще не вкурил. Принцип простой, например:solo писал(а):Если не то говорю - не ржать!
Код: Выделить всё
create hp(...)
returns (<счетчик_прогресса> <тип>)
...
for select ...... do
begin
<действия обсчета i/u/d>
<счетчик_прогресса>=<счетчик_прогресса>+1;
suspend;
end
Код: Выделить всё
select <счетчик_прогресса> from hp...;
commit или rollback
На мой взгляд, использование генератора ничем не лучше использования хп возвращающих данные в процессе обработки. Но при использовании любого из этих способов скорость (равномерность) продвижения "прогресса" довольно условна. Минусы использования генераторов для этой задачи очевидны (для меня).
P.S."HourGlass с буквами SQL" - это конечно крута, но нафига? Разве что для повышения своей важности в глазах пользователя в процессе разъяснения ему, что это за магическое заклинание "SQL".
Генератор в многопользовательском режиме конечно лисапет на квадратных колёсах, но тут тоже есть один нюанец - счётчики будешь получать пачками в размере сетевого пакета, а не непрерывно. Навскидку не помню скока это будет в граммах для одного инта, наверное пара тысяч. Если цикл сам по себе длительный, то дискрет времени будет заметный. Для поштучного можно попробовать select for update, с процедурами сам не делал, если интересно, то нужен острый натурный эксперимент. Но это по любому на суммарном времени выполнения скажется не в лучшую сторону, опять же я не в курсах, дружит ли IBO с select for update, IBX точно требует доработки напильником. А вообще-то анимация - имхо не та тема, которой должны заморачиваться просвещённые в Дао. Если юзверь уж очень сильно скучает глядючи на рюмку с надписью SQL или без оной - покрутить ему порнушку с музычкой...sag писал(а):solo писал(а):и далее:Код: Выделить всё
create hp(...) returns (<счетчик_прогресса> <тип>) ... for select ...... do begin <действия обсчета i/u/d> <счетчик_прогресса>=<счетчик_прогресса>+1; suspend; end
Код: Выделить всё
select <счетчик_прогресса> from hp...; commit или rollback
Теоретицкий интерес у меня есть, но слабый. Сейчас крайне озадачен выбором имени для собаки. Но может руки когда и дойдут до означенного выше эксперимента.Merlin писал(а):Для поштучного можно попробовать select for update, с процедурами сам не делал, если интересно, то нужен острый натурный эксперимент.
Лет 12 назад в институте им.БончБр. мне понравилась анимашка часиков в виде рожицы лихо поедавшей арбузную дольку и расплевывавшая семечки.Merlin писал(а):А вообще-то анимация - имхо не та тема, которой должны заморачиваться просвещённые в Дао. Если юзверь уж очень сильно скучает глядючи на рюмку с надписью SQL или без оной - покрутить ему порнушку с музычкой...
Фух. Ура, выбрал. Три дня думал, три дня мучений. Тебе проще было: Берримор - мальчик на "Бэ", мне надо было девочку на "Шэ". Выбирать из снадартных Шерри, Шекли, Шило (а список кличек на "Шэ" для сук очень и очень небольшой) - не хотел.Merlin писал(а):Помницца, был у меня английский кокер Берриморsag писал(а): Сейчас крайне озадачен выбором имени для собаки.
На радостях соорудил "острый натурный эксперимент". Докладаю: select for update по процедуре (без order by, есс-но) сделает счастливыми построителей "прогресс-градусников".
-
- Заслуженный разработчик
- Сообщения: 644
- Зарегистрирован: 15 фев 2005, 11:34
Или пасьянсец разложить...Если юзверь уж очень сильно скучает глядючи на рюмку с надписью SQL или без оной - покрутить ему порнушку с музычкой...
Если развить тему про генераторы, хочь это и квадратноколесный лисапет, ну раз уж назвался груздем...
Можно сделать так: В основной программе растим специально обученый генератор и перед длительным запросом делаем
"селект каунт(*) фром блаблабла" чтоб прикинуть да каких пор расти этому самому генератору.
Далее делаем на дельфях(например) отдельную программу, соответственно компилить ее в отдельный экзешник, чтоб основной код всяким хламом не засорять. программа состоит из одной формы на которую положить: тибдатабэйз, тибтразакшн, тибквери (ну или любой компонент который будет базу вопрошать), ттаймер, тпрогрессбар, танимэйт. В качестве параметров командной строки программа должна получить имя генератора и число докуда он должен дорасти (можно еще скормить ей строку подключения к базе, для пущщей универсальности). Эту программу будет запускать основная программа, когда в ней будет нужда, а закрываться она сможет сама, когда придет к выводу, что генератор насчитал положеные тики. Программа стартует, цепляется к базе, стартует таймер и по ОнТаймеру делает селект из базы на счет изменился генератор или нет, далее кормить получеными значениями програссбар. А ну и в начале запустить какой-нидь ролик в анимэйте, чтоб веселей была картина. Вроде так