Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2006.12.10;
Скачать: [xml.tar.bz2];

Вниз

Продажа билетов несколькими кассирами   Найти похожие ветки 

 
alabama01   (2006-09-26 07:09) [0]

Здравствуйте.
Есть программа для продажи билетов в транспортные средства, с соответсвующей БД. При продаже билета на форме кассира обновляется combobox со списком свободных мест и автоматически подставляется  первое свободное место. (сделано для скорости). При работе нескольких кассиров, у них у всех происходит то же самое. Поэтому приходится проверять не продал ли кто билет на это место, а если продал, то выводить предупреждение, чтобы выбирали другое место. Это очень неудобно. Обновление combobox"ов у всех кассиров происходит при оформлении чека любым из кассиров Вопрос: как лучше организовать раздачу свободных мест при продаже на один и тот же рейс несколькими кассирами без малейшей возможности продажи двух и более билетов на одно место?


 
Бугага ©   (2006-09-26 07:15) [1]

Первый выбирает место, лочит, пытается зарегистрировать билет. Пока он его регистрирует, место залочено. Регистрация успешна? -> место ушло, не успешна -> место разлочено


 
vodvorezlaya   (2006-09-26 08:22) [2]

1.Сделать столбик базы данных уникальным, и ловить исключение.

2.Сделать поле ключевым, и ловить исключение либо делать поиск FindKey;


 
ЮЮ ©   (2006-09-26 09:02) [3]


> vodvorezlaya   (26.09.06 08:22) [2]


Уже книжек начитался, гляжу :) И в каких только таких "терминов" нахватался? :)


 
evvcom ©   (2006-09-26 09:05) [4]

> [3] ЮЮ ©   (26.09.06 09:02)

Ну дай ему орлом себя почувствовать... :-o)


 
atruhin ©   (2006-09-26 09:46) [5]

С MSSQL не работал, а в FB можно при выборе места делать холостой апдейт, после чего данная запись будет заблокированна, для второго кассира, простым перебором ищем незаблокированные записи, + event на блокировку для синхронизации конецформыначалоформыcombobox"ов.
При закрытии пргораммы, обрыве коннекта, транзакция через некоторое время (настраивается) откатывается и запись разблокируется.
Думаю в MSSQL есть что то подобное.


 
Бугага ©   (2006-09-26 09:59) [6]

> И в каких только таких "терминов" нахватался? :)

Архангельский? :)


 
alabama01   (2006-09-26 10:21) [7]


> Бугага ©   (26.09.06 07:15) [1]

Пока так и есть. Если запись залочена, то второму кассиру выводим сообщение, и он выбирает другое место. Вопрос когда лочить.

atruhin предлагает, как я понял,  лочить когда первый кассир  выбрал место, но не оформляет билет. В таком случае, что делать если этот билет последний и второй кассир хочет его продать, а первый пошел покурить?

Кроме того, у нас свободные билеты хранятся в одном числе по битам. Залочить запись проблематично.


 
ЮЮ ©   (2006-09-26 10:29) [8]

Я бы разделил операции на
"забронировать для оформления" N мест
"выбрать N мест"
"оформление билетов на выбранные места"

Ибо, сначала покупатель говорит : Мне 3 билета на рейс ХХХ

Затем отдает документы, из когорых становится ясно, что нужен 1 бзрослый и 2 детских места, выясняется в каком вагоне(классе, ряду) нужно место

Вносится информация из документов, печатаются билеты, производится оплата.

Первая операция позволяет сразу сказать есть нужное количество мест или нет. Выполняется без блокировки. Может сказать "Извините", если мест "на лету" стало меньше. Не требует много времени кассира

Вторая выполняется в порядке поступления блокировок. Тоже не требует много времени у кассира. Но надо разлуривать "уснувшего" кассира.

Третья, самая длительная по времени, выполняется в уже комфортных условиях, когда никто тебя уже не торопит и все определились с местами.

З.Ы. Сам таких систем не писал. Как работают реально действующие - не представляю. Так что, извиняйте :)


 
Бугага ©   (2006-09-26 10:29) [9]


> Вопрос когда лочить

Лочим при начале оформления.

Насчет
> если этот билет последний и второй кассир хочет его продать,
> а первый пошел покурить?

административные меры


> Кроме того, у нас свободные билеты хранятся в одном числе
> по битам. Залочить запись проблематично.

не понял. конец рабочего дня дает знать...


 
evvcom ©   (2006-09-26 10:30) [10]

> [7] alabama01   (26.09.06 10:21)

Имеется оптимистический вариант блокирования и пессимистический. Поскольку

> у нас свободные билеты хранятся в одном числе по битам

тебе оптимизм не подойдет. А пессимистический делается так:
select ... from ... where ... for update
Вызываешь это, когда кассир уже покурил и нажал кнопку "Выдать билет". Следом за этим в программном блоке Delphi делаешь проверку, а не изменился ли уже нужный тебе бит, если не изменился, то меняешь и тут же update с коммитом, если изменился - rollback и соответствующее сообщение долго курящему кассиру выдаешь. И пофиг, какой кассир и как долго ходил курить, другим он не помешает.


 
ЮЮ ©   (2006-09-26 10:31) [11]

свободные билеты хранятся в одном числе по битам

Это что за средство передвижения такое: маловместимое и с большой конкуренцией на ресурсы? :)


 
Бугага ©   (2006-09-26 10:32) [12]

понял про хранение билетов... а зачем такой гемор?

:)
> Вызываешь это, когда кассир уже покурил и нажал кнопку "Выдать
> билет".

т.е. один кассир занял это место, второй тоже, а там кто успеет?


 
Ega23 ©   (2006-09-26 10:35) [13]

А я бы комбики обновлял не принудительно, а только тогда, когда данный кассир пытается что-то продать.


 
evvcom ©   (2006-09-26 10:40) [14]

> [12] Бугага ©   (26.09.06 10:32)
> т.е. один кассир занял это место, второй тоже, а там кто
> успеет?

Занял - это когда смог обновить запись в базе и распечатать билет. Все остальное - это только мысли занять. Я расписывал классику обновления записей, где вероятность ошибки должна быть сведена к 0. Если же интересует вопрос удобства работы кассиры, это уже другой вопрос. Например, [8] вроде неплохая идея (я тоже не писал такой задачи). А успеть на одно место всегда может только один. Ну прям горец получается :)


 
Бугага ©   (2006-09-26 10:47) [15]

в том то и фишка подобных систем что классика здесь вряд ли подойдет.
[8] пропустил, мне тоже понравилось


 
Виталий Панасенко   (2006-09-26 11:26) [16]

А у кассира есть возможность менять номер места ? Или всегда только первый из комбобокса берется ?


 
atruhin ©   (2006-09-26 11:26) [17]

> atruhin предлагает, как я понял,  лочить когда первый кассир
> выбрал место, но не оформляет билет. В таком случае, что
> делать если этот билет последний и второй кассир хочет его
> продать, а первый пошел покурить?

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

> Кроме того, у нас свободные билеты хранятся в одном числе
> по битам. Залочить запись проблематично.

А вот тут лучше поменять структуру базы, пока не поздно.


 
dr Gonzo ©   (2006-09-26 11:31) [18]

Сам механизм блокировки реализовать как запись ID билета(номера) в спец-ю таблицу или что хуже простановка атрибута у записи.

Собственно блокировать(пытаться заблокировать) на время оформления по выходу из ComboBox"а. Или если это множественный выбор, то нужно  сделать контейнер (типа TListBox"а) для "набивки" заказа билетами из другого списка и делать блокировку при добавлении каждого билета в этот контейнер.

Второй вариант более предпочтителен - т.к. тут более осмысленное действие для кассира.

Все делается за счет 1 ступени блокировки.

Делать сообщения о создании/снятии блокировки. Так же я предложу сделать сообщения более информативными - не просто что то поменялось, а поменялось то то и то то (в идеале снята/поставлена блокировка, ID объекта и т.д. - тогда не нужно будет все время делать Refresh из базы).

Сразу скажу какие минусы у этого способа. Тетя Маша выбрала для заявки 1 - NN билетов, клиент отказался, она ушла пить чай/курить/cпать при этом не закрыв заказ - заказ висит заблокированный, другие пользрователи не могут ничего с этими билетами делать.


 
evvcom ©   (2006-09-26 11:33) [19]

> [15] Бугага ©   (26.09.06 10:47)
> в том то и фишка подобных систем что классика здесь вряд
> ли подойдет

Обоснуй, а лучше не гони. Придумаешь, что-то принципиально новое? Для этого должна быть поддержка СУБД.

> [8] пропустил, мне тоже понравилось

я не говорю, что понравилось, просто как вариант, далекий от идеального


 
Desdechado ©   (2006-09-26 11:45) [20]

хранение в битах - глупость, которая не дает нормально развернуться методам реляционной алгебры
ведь БД - это все-таки реляционный механизм

ЗЫ кстати, как в таком случае разруливается ситуация с разным количеством мест в разных транспортных средствах?


 
Val ©   (2006-09-26 11:47) [21]

>[10] evvcom ©   (26.09.06 10:30)
мне кажется - все-таки в данном случае воспользоваться оптимистической блокировкой. чем мешает это поле, поясните?
пока первый кассир курит - место считается свободным, поскольку транзакция не завершена. при оптимистическом подходе у второго кассира получится вставить запись без проблем. первый вернется из курилки попробует закончить операцию - получит отказ и откат, поскольку запись с таким местом в базе уже будет.
for update - разве есть в MSSQL?


 
evvcom ©   (2006-09-26 11:51) [22]

> [20] Desdechado ©   (26.09.06 11:45)

Если достаточно только признака продано/не продано, то вполне нормально, имхо. А реляционная алгебра... а что из нее здесь нужно? Для количества можно использовать, что угодно, поддерживающее достаточную длину, в том числе нуль-байты. Если писать нечто универсальное, а не для автобуса на 30 мест, то кроме блоба что-то больше ничего не приходит в голову.


 
evvcom ©   (2006-09-26 11:56) [23]

> [21] Val ©   (26.09.06 11:47)
Оптимистическая:
update tab set mesta = :mesta where id = :id and mesta = :old_mesta

Если кассиров много будет выдавать билеты на автобус/поезд id, то с битовым подходом занятости мест mesta очень часто не будут совпадать с :old_mesta. Решать, конечно, барину.


 
Desdechado ©   (2006-09-26 12:03) [24]

> А реляционная алгебра... а что из нее здесь нужно? Для количества можно
> использовать, что угодно, поддерживающее достаточную длину
Главное преимущество реляционного подхода - это возможность складировать в столбик то, что часто просится складироваться в отдельных полях строки (или в битах чиста, или в блобе).
Т.е. проданные билеты просто появляются в таблице отдельными строками, а в справочнике транспортного средства хранится его емкость. Непроданные записывать смысла нет. Количество свободных легко считается, их номера тоже легко (про занятые уже не говорю).


 
Val ©   (2006-09-26 12:16) [25]

>[23] evvcom ©   (26.09.06 11:56)
можно использовать and mesta = :old_mesta не напрямую, а и через функцию, которая возвращает признак что данное место свободно.


 
Виталий Панасенко   (2006-09-26 12:37) [26]

А нельзя ли кассирам дать диапазон №№ ?


 
evvcom ©   (2006-09-26 12:41) [27]

> [24] Desdechado ©   (26.09.06 12:03)

Ну да, в общем-то согласен. Но если кроме флага "продано/не продано" больше ничего хранить не надо, я бы все ж не стал делать доп.табличку. Имхо.

> [25] Val ©   (26.09.06 12:16)

Да, так согласен. Кстати,

> [21] Val ©   (26.09.06 11:47)
> for update - разве есть в MSSQL?

Есть, конечно.


 
Val ©   (2006-09-26 12:46) [28]

>[27] evvcom ©   (26.09.06 12:41)
> Есть, конечно.

спасибо.


 
clickmaker ©   (2006-09-26 14:57) [29]


> у нас свободные билеты хранятся в одном числе по битам

32, ну максимум 64 места? Что за транспорт?


 
Desdechado ©   (2006-09-26 15:16) [30]

в продолжение Desdechado ©   (26.09.06 12:03) [24]
если нужно будет к проданному билету (месту) прилепить еще что (например, льготу или фамилию), то это как раз очень удобно делается таким подходом
а вот к биту прилепить только перректально
кстати, если транспортное средство не со сквозной нумерацией мест (например, в поезде вагон-место), то биты идут лесом, т.к. кол-во вагонов произвольное, да и их номера не всегда подряд


 
ANB ©   (2006-09-26 15:27) [31]


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

дамс. видимо на одной автостанции подобная прога уже стоит. Продали мне билет на место номер 7. залезаю в автобус - а места с таким номером нету :) Пришлось согнать нафиг кондуктора и ехать на ее месте.


 
Sergey13 ©   (2006-09-26 15:28) [32]

> [31] ANB ©   (26.09.06 15:27)

7 - счастливый номер. На нем водитель сидит. 8-)


 
alabama01   (2006-09-27 02:28) [33]

> ЮЮ ©   (26.09.06 10:29) [8]

Идея неплохая. Надо обмозговать.

> evvcom ©   (26.09.06 10:30) [10]

> тебе оптимизм не подойдет. А пессимистический делается так:
>
> select ... from ... where ... for update
> Вызываешь это, когда кассир уже покурил и нажал кнопку "Выдать
> билет". Следом за этим в программном блоке Delphi делаешь
> проверку, а не изменился ли уже нужный тебе бит, если не
> изменился, то меняешь и тут же update с коммитом, если изменился
> - rollback и соответствующее сообщение долго курящему кассиру
> выдаешь. И пофиг, какой кассир и как долго ходил курить,
>  другим он не помешает.


Так и так сейчас делается. И, в данном случае, не имеет значения "уснул" ли кассир или он колотит билеты один за другим!

> ЮЮ ©   (26.09.06 10:31) [11]
> свободные билеты хранятся в одном числе по битам
>
> Это что за средство передвижения такое: маловместимое и
> с большой конкуренцией на ресурсы? :)

Автобусы пригородных сообщений, максимум 60 мест.


> Бугага ©   (26.09.06 10:32) [12]
> понял про хранение билетов... а зачем такой гемор?

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


> Ega23 ©   (26.09.06 10:35) [13]
> А я бы комбики обновлял не принудительно, а только тогда,
>  когда данный кассир пытается что-то продать

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

> Виталий Панасенко   (26.09.06 11:26) [16]
> А у кассира есть возможность менять номер места ? Или всегда
> только первый из комбобокса берется ?

Конечно. Кассир может выбрать любое место из всего диапазона свободных.


> atruhin ©   (26.09.06 11:26) [17]
> > что делать если этот билет последний и второй кассир хочет
> его  продать, а первый пошел покурить?
>
> Во первых административные меры, во вторых для забывчивых,
>  таймер на окно выписки билета, при неактивности кассира,
>  закрывается запись разблокируется.

Про таймер отличная мысль. Особенно, если применить вместе с принудительным обновлением комбобоксов.


> dr Gonzo ©   (26.09.06 11:31) [18]


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


> Desdechado ©   (26.09.06 11:45) [20]
> хранение в битах - глупость, которая не дает нормально развернуться
> методам реляционной алгебры
> ведь БД - это все-таки реляционный механизм

Думаю, если этого достаточно, почему бы и нет?

>
> ЗЫ кстати, как в таком случае разруливается ситуация с разным
> количеством мест в разных транспортных средствах?


Заполнением нулями соответствующих битов.


> evvcom ©   (26.09.06 11:56) [23]
> > [21] Val ©   (26.09.06 11:47)
> Оптимистическая:
> update tab set mesta = :mesta where id = :id and mesta =
> :old_mesta
>
> Если кассиров много будет выдавать билеты на автобус/поезд
> id, то с битовым подходом занятости мест mesta очень часто
> не будут совпадать с :old_mesta. Решать, конечно, барину.
>


> Обновление combobox"ов у всех кассиров происходит при оформлении
> чека любым из кассиров



> Виталий Панасенко   (26.09.06 12:37) [26]
> А нельзя ли кассирам дать диапазон №№ ?

Нельзя. Все  продают всё.


> Desdechado ©   (26.09.06 12:03) [24]

Естественно, такой вариант рассматривался как самый простой и в первую очередь.

> Desdechado ©   (26.09.06 15:16) [30]

В числе хранятся только свободные места. При продаже все атрибуты, включая номер места, id рейсов, кассиров, дата и время продажи, скидки, накидки, суммы, фамилии, номера документов и т.д пишутся в таблицу продаж.


> ANB ©   (26.09.06 15:27) [31]
>
> > кстати, если транспортное средство не со сквозной нумерацией
>
> > мест (например, в поезде вагон-место), то биты идут лесом,
>
> >  т.к. кол-во вагонов произвольное, да и их номера не всегда
>
> > подряд
>
> дамс. видимо на одной автостанции подобная прога уже стоит.
>  Продали мне билет на место номер 7. залезаю в автобус -
>  а места с таким номером нету :) Пришлось согнать нафиг
> кондуктора и ехать на ее месте.

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


 
atruhin ©   (2006-09-27 05:48) [34]

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


 
alabama01   (2006-09-27 07:42) [35]


> atruhin ©   (27.09.06 05:48) [34]

К сожалению, выбор места требует заказчик. Если бы автоматом, проблем бы не было.


 
Sergey13 ©   (2006-09-27 08:28) [36]

> [33] alabama01   (27.09.06 02:28)

> Если писать в таблицу все продажи (одна запись  - одна продажа)
> , через год (если не удалять продажи) поиск свободного места
> будет занимать довольно приличное время особенно на слабеньком
> сервере

Придумываешь ты. 100 автобусов в день по 60 человек 365 дней в году = 2190000 записей. Детский лепет при наличии индексов.


 
evvcom ©   (2006-09-27 08:28) [37]

> [33] alabama01   (27.09.06 02:28)
> > Если кассиров много будет выдавать билеты на автобус/поезд
> > id, то с битовым подходом занятости мест mesta очень часто
> > не будут совпадать с :old_mesta. Решать, конечно, барину.
> >
>
> Обновление combobox"ов у всех кассиров происходит при
> оформлении чека любым из кассиров

Т.е. сервер асинхронно извещает всех своих подписчиков (кассиров) о проданном месте? Хорошая фича.


 
MsGuns ©   (2006-09-27 13:26) [38]

Все эти "лочания" незаметно превращаются в "глючения".
Прежде чем решать подобные проблемы неплохо хотя б в общих чертах познакомиться с подобными системами. Хотя бы просто поинтересовавшись как функционирует бронирование в гостинницах например у администратора. Или в тех же ж/д кассах.
Ключевое слово - "резервирование" или его варианты.


 
Desdechado ©   (2006-09-27 15:48) [39]

> В числе хранятся только свободные места. При продаже все атрибуты,
> включая номер места, id рейсов, кассиров, дата и время продажи, скидки,
> накидки, суммы, фамилии, номера документов и т.д пишутся в таблицу продаж.
Зачем тогда дублировать информацию? Это же лишние проблемы.


 
Anatoly Podgoretsky ©   (2006-09-27 16:03) [40]

Не надо ничего блокировать, надо резервировать для продажи. Срок резервирования ограничить.



Страницы: 1 2 вся ветка

Форум: "Базы";
Текущий архив: 2006.12.10;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.59 MB
Время: 0.041 c
15-1164033526
Beavercrazy
2006-11-20 17:38
2006.12.10
Живо ли еще разрешение 800*600?


15-1163770520
Сало
2006-11-17 16:35
2006.12.10
С днём студента!


2-1164199029
Виктор1
2006-11-22 15:37
2006.12.10
Получение компонентов окна


2-1164263223
mmms
2006-11-23 09:27
2006.12.10
Можно ли в EhDbGrid одну колонку сделать постояно видимой?


15-1164271599
wamp
2006-11-23 11:46
2006.12.10
cmd





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский