From: konrad Date: Sat, 29 Mar 2008 10:15:22 +0000 (+0000) Subject: entrance scan/control works X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=cc1e88a4f03674eac2e19c0ad144012f53890320;p=konrad%2Fsmoke.git entrance scan/control works git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@146 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/doc/prog_protocol.html b/doc/prog_protocol.html index 6469b99..ce6177d 100644 --- a/doc/prog_protocol.html +++ b/doc/prog_protocol.html @@ -545,6 +545,33 @@ The getorderlist transaction can be used to get a list of all currently +

Tickets

+ +

Getting Tickets

+ +The getticket transaction can be used to get information about a ticket. The request contains only the ticketID, the response looks like:

+ +

+<Ticket id="ticketid" status="ticketstate" order="orderid" event="eventid" price="priceincent" orderpaystate="status of the order" />
+
+ +The attribute orderid may be <0 if the ticket is not attached to an order.

+ + + + + +
AttributeDescription
statuscan be any of reserved, bought, used, refund, error (see getorder above for details)
orderpaystatethe payment status of the order, it can be "none" if the order is invalid or the ticket is not attached to one, "ok" if the order has been paid correctly, "cancelled" if the order was cancelled, "needpayment" if the order is not fully paid yet, or "needrefund" if too much has been paid
+ +

Using Tickets

+ +The useticket transaction marks a ticket as used. The request contains only the ticket ID, the response has status ok and no body if the action succeeded, it has status error and an explanatory text if it failed.

+ +Only tickets that have status "bought" and whose order have payment status "ok" or "needrefund" can be used. The transaction fails for all other tickets. + +

Templates

Templates are used for printouts and documents. There are several types of templates:

diff --git a/src/order.cpp b/src/order.cpp index fbdebf2..f27fcc0 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -352,11 +352,32 @@ MTicket::MTicket() m_eventid=m_orderid=-1; m_price=0; m_status=Invalid; + m_paystate=PSUnknown; +} + +MTicket::MTicket(MWebRequest*r,QString t) +{ + req=r; + m_eventid=m_orderid=-1; + m_price=0; + m_status=Invalid; + m_paystate=PSUnknown; + if(!req->request("getticket",t.toAscii()))return; + if(req->responseStatus()!=MWebRequest::Ok)return; + QDomDocument doc; + if(!doc.setContent(req->responseBody()))return; + scanXml(doc.documentElement()); } MTicket::MTicket(MWebRequest*r,const QDomElement&e) { req=r; + m_paystate=PSUnknown; + scanXml(e); +} + +void MTicket::scanXml(const QDomElement&e) +{ m_eventid=e.attribute("event","-1").toInt(); m_orderid=e.attribute("order","-1").toInt(); m_id=e.attribute("id"); @@ -374,6 +395,13 @@ MTicket::MTicket(MWebRequest*r,const QDomElement&e) if(st=="cancelled")m_status=CheckFailCancelled;else if(st=="invalid")m_status=CheckFailEventInvalid; else m_status=Invalid; + st=e.attribute("orderpaystate"); + if(st=="none")m_paystate=PSNone;else + if(st=="cancelled")m_paystate=PSCancelled;else + if(st=="ok")m_paystate=PSOk;else + if(st=="needpayment")m_paystate=PSNeedPayment;else + if(st=="needrefund")m_paystate=PSNeedRefund; + else m_paystate=PSUnknown; } MTicket::MTicket(const MTicket&t) @@ -389,6 +417,7 @@ MTicket& MTicket::operator=(const MTicket&t) m_price=t.m_price; m_status=t.m_status; m_id=t.m_id; + m_paystate=t.m_paystate; return *this; } @@ -454,6 +483,26 @@ QString MTicket::statusString()const } } + +MTicket::PaymentStatus MTicket::paymentStatus() +{ + if(m_paystate!=PSUnknown)return m_paystate; + if(!isValid())return PSUnknown; + if(!req->request("getticket",m_id.toAscii()))return PSUnknown; + if(req->responseStatus()!=MWebRequest::Ok)return PSUnknown; + QDomDocument doc; + if(!doc.setContent(req->responseBody()))return PSUnknown; + scanXml(doc.documentElement()); + return m_paystate; +} + +QString MTicket::markUsed() +{ + if(!req->request("useticket",m_id.toAscii()))return QCoreApplication::translate("MTicket","Cannot execute request."); + if(req->responseStatus()==MWebRequest::Ok)return ""; + return QCoreApplication::translate("MTicket",req->responseBody().data()); +} + void MTicket::setOrderID(qint32 o) { m_orderid=o; diff --git a/src/order.h b/src/order.h index 186fd9a..750b4ba 100644 --- a/src/order.h +++ b/src/order.h @@ -30,6 +30,8 @@ class MTicket public: /**creates an invalid ticket*/ MTicket(); + /**gets the ticket from the database*/ + MTicket(MWebRequest*,QString); /**creates a ticket from XML*/ MTicket(MWebRequest*,const QDomElement&); /**copies a ticket*/ @@ -99,6 +101,28 @@ class MTicket /**returns the ticket status as string*/ QString statusString()const; + /**payment state of the order*/ + enum PaymentStatus{ + /**yet unknown, need to retrieve it*/ + PSUnknown, + /**no order state (no order)*/ + PSNone, + /**order has been paid ok*/ + PSOk, + /**order is cancelled*/ + PSCancelled, + /**order needs payment*/ + PSNeedPayment, + /**order needs refund*/ + PSNeedRefund + }; + + /**returns the payment state of the order (may check database)*/ + PaymentStatus paymentStatus(); + + /**marks the ticket as used in the database; returns empty string on success, error on failure*/ + QString markUsed(); + protected: friend class MOrder; /**sets the order-ID of the ticket, used by MOrder*/ @@ -108,8 +132,12 @@ class MTicket MWebRequest*req; qint32 m_eventid,m_orderid,m_price; TicketStatus m_status; + PaymentStatus m_paystate; QString m_id; mutable MEvent m_event; + + /**helper: scan XML data*/ + void scanXml(const QDomElement&); }; class MOrder diff --git a/src/overview.cpp b/src/overview.cpp index d5a307c..df5d240 100644 --- a/src/overview.cpp +++ b/src/overview.cpp @@ -825,23 +825,53 @@ void MOverview::tabChanged() void MOverview::entranceValidate() { - //TODO: actually ask the server + //check content + QString tid=entrancescan->text().trimmed(); + //avoid spurious events + if(tid=="")return; + //avoid double scans + QDateTime now=QDateTime::currentDateTime(); + if(tid==lastbarcode && lastbcscan.addSecs(20)>=now){ + entrancescan->setText(""); + return; + } + lastbarcode=tid; + lastbcscan=now; + //ask the server + MTicket tick(req,tid); + //decide what to do QPalette pal=entrancelabel->palette(); QPalette::ColorRole rl=QPalette::Window; - switch(rand()%3){ - case 0: - entrancelabel->setText(tr("Ticket Ok")); - pal.setColor(rl,Qt::green); - break; - case 1: - entrancelabel->setText(tr("Ticket Already Used")); - pal.setColor(rl,Qt::magenta); - break; - case 2: - entrancelabel->setText(tr("Ticket Not Paid")); - pal.setColor(rl,Qt::red); - break; + if(!tick.isValid()){ + entrancelabel->setText(tr("Ticket \"%1\" Not Valid").arg(tid)); + pal.setColor(rl,Qt::red); + }else + if(tick.status()==MTicket::Used){ + entrancelabel->setText(tr("Ticket \"%1\" has already been used").arg(tid)); + pal.setColor(rl,Qt::magenta); + }else + if(tick.status()!=MTicket::Bought){ + entrancelabel->setText(tr("Ticket \"%1\" has not been bought.").arg(tid)); + pal.setColor(rl,Qt::red); + }else + if(tick.paymentStatus()==MTicket::PSOk){ + entrancelabel->setText(tr("Ticket \"%1\" Ok").arg(tid)); + pal.setColor(rl,Qt::green); + tick.markUsed(); + }else + if(tick.paymentStatus()==MTicket::PSNeedRefund){ + entrancelabel->setText(tr("Ticket \"%1\" Ok; the Order has a refund").arg(tid)); + pal.setColor(rl,Qt::green); + tick.markUsed(); + }else + if(tick.paymentStatus()==MTicket::PSNeedPayment){ + entrancelabel->setText(tr("Ticket \"%1\" is not paid for!").arg(tid)); + pal.setColor(rl,Qt::red); + }else{ + entrancelabel->setText(tr("Ticket \"%1\" cannot be accepted, please check the order!").arg(tid)); + pal.setColor(rl,Qt::red); } + entrancelabel->setPalette(pal); entrancescan->setFocus(Qt::OtherFocusReason); entrancescan->setText(""); @@ -930,7 +960,7 @@ MPasswordChange::MPasswordChange(QWidget*par,QString user) if(user=="") setWindowTitle(tr("Change my password")); else - setWindowTitle(tr("Reset password of user %1").arg(user)); + setWindowTitle(tr("Reset password of user \"%1\"").arg(user)); QGridLayout*gl; setLayout(gl=new QGridLayout); if(user==""){ diff --git a/src/overview.h b/src/overview.h index d82abe3..a0f4c66 100644 --- a/src/overview.h +++ b/src/overview.h @@ -13,10 +13,11 @@ #ifndef MAGICSMOKE_OVERVIEW_H #define MAGICSMOKE_OVERVIEW_H -#include -#include +#include #include #include +#include +#include #include "customer.h" @@ -136,6 +137,9 @@ class MOverview:public QMainWindow QLineEdit*entrancescan; //cart MCustomer customer; + //barcode cache + QString lastbarcode; + QDateTime lastbcscan; }; /**Helper dialog for changing passwords*/ diff --git a/www/inc/classes/order.php b/www/inc/classes/order.php index d2a352a..91265e8 100644 --- a/www/inc/classes/order.php +++ b/www/inc/classes/order.php @@ -349,6 +349,31 @@ class Order $xml->appendChild($doc); print($xml->saveXml()); } + + /**returns the current status of the order*/ + public function getStatus() + { + return $this->status; + } + + /**helper function: returns whether the order has outstanding payments/refunds*/ + public function getPaymentStatus() + { + global $db; + //calculate amount due + $totalprice=0; + $res=$db->select("ticket","ticketid","orderid=".$db->escapeInt($this->orderid)); + if(count($res)>0) + foreach($res as $tc){ + $tick=new Ticket($tc["ticketid"]); + if($tick->mustBePaid())$totalprice+=$tick->getPrice(); + } + //TODO: add vouchers + //compare with what has been paid + if($totalprice==$this->amountpaid)return "ok"; + if($totalprice<$this->amountpaid)return "needrefund"; + else return "needpayment"; + } }; function createOrderXml($xmldata,$action) diff --git a/www/inc/classes/ticket.php b/www/inc/classes/ticket.php index 77c719d..f355b6e 100644 --- a/www/inc/classes/ticket.php +++ b/www/inc/classes/ticket.php @@ -109,7 +109,7 @@ class Ticket } } - /**returns whether the ticket must be paid*/ + /**returns whether the ticket must be paid (or is already paid)*/ public function mustBePaid() { return ($this->status & TICKET_MBLOCK) != 0; @@ -159,7 +159,83 @@ class Ticket return true; } + /**dumps the ticket as XML*/ + public function dumpXml() + { + $xml=new DomDocument; + $doc=$xml->createElement("Ticket"); + $doc->setAttribute("id",$this->ticketid); + $doc->setAttribute("status",$this->xmlStatus()); + $doc->setAttribute("order",$this->orderid); + $doc->setAttribute("event",$this->eventid); + $doc->setAttribute("price",$this->price); + $doc->setAttribute("orderpaystate",$this->orderPayStateXml()); + $xml->appendChild($doc); + print($xml->saveXml()); + } + + /**helper: gets the status of the order for dumpXml*/ + protected function orderPayStateXml() + { + if($this->orderid<0)return "none"; + $ord=new Order($this->orderid); + if(!$ord->isValid())return "none"; + if($ord->getStatus()==ORDER_CLOSED)return "ok"; + if($ord->getStatus()==ORDER_CANCELLED)return "cancelled"; + return $ord->getPaymentStatus(); + } + /**tries to mark the ticket as used*/ + public function markUsedXml() + { + if(!$this->isValid()){ + header("X-MagicSmoke-Status: Error"); + die(tr("The ticket is not valid.")); + } + if($this->status==TICKET_USED){ + header("X-MagicSmoke-Status: Error"); + die(tr("The ticket has already been used.")); + } + if($this->status!=TICKET_BOUGHT){ + header("X-MagicSmoke-Status: Error"); + die(tr("The ticket has not been bought or is cancelled.")); + } + $ps=$this->orderPayStateXml(); + if($ps=="needpayment"){ + header("X-MagicSmoke-Status: Error"); + die(tr("The ticket has not been paid.")); + } + if($ps!="ok" && $ps!="needrefund"){ + header("X-MagicSmoke-Status: Error"); + die(tr("The tickets order is in an invalid state or does not exist.")); + } + $this->status=TICKET_USED; + global $db; + $db->update("ticket",array("status"=>TICKET_USED),"ticketid=".$db->escapeInt($this->ticketid)); + } }; +function getTicketXml($tid) +{ + $tick=new Ticket($tid); + if($tick->isValid()){ + header("X-MagicSmoke-Status: Ok"); + $tick->dumpXml(); + }else{ + header("X-MagicSmoke-Status: Error"); + die(tr("Unable to find this ticket.")); + } +} + +function useTicketXml($tid) +{ + $tick=new Ticket($tid); + if($tick->isValid()) + $tick->markUsedXml(); + else{ + header("X-MagicSmoke-Status: Error"); + die(tr("Unable to find this ticket.")); + } +} + ?> \ No newline at end of file diff --git a/www/machine.php b/www/machine.php index 1614254..381da55 100644 --- a/www/machine.php +++ b/www/machine.php @@ -24,6 +24,7 @@ $ALLOWEDREQUESTS=array( tr("getroomdata"),tr("setroomdata"),//room infos tr("getcustomerlist"),tr("getcustomer"),tr("setcustomer"), //customer info tr("checkorder"),tr("createorder"),tr("createsale"),tr("getorderlist"),tr("getorder"), //sell/order stuff + tr("getticket"),tr("useticket"),//ticket management tr("gettemplatelist"),tr("gettemplate"),tr("settemplate") //templates ); /**contains the low-level request name from the client*/ @@ -286,6 +287,16 @@ if($SMOKEREQUEST=="getorder"){ exit(); } +//get a ticket +if($SMOKEREQUEST=="getticket"){ + getTicketXml(trim($REQUESTDATA)); + exit(); +} +//mark a ticket as used +if($SMOKEREQUEST=="useticket"){ + useTicketXml(trim($REQUESTDATA)); + exit(); +} //EOF header("X-MagicSmoke-Status: Error");