From: konrad Date: Sun, 30 Mar 2008 14:09:31 +0000 (+0000) Subject: *implement payment and refunds X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=cf5806a218da5e29592a9c397f8599e167593650;p=web%2Fkonrad%2Fsmoke.git *implement payment and refunds *implement ticket price change *move order/sale to orderwindow *make orders/sales with changed ticket prices possible git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@149 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/doc/prog_protocol.html b/doc/prog_protocol.html index ce6177d..5c8705c 100644 --- a/doc/prog_protocol.html +++ b/doc/prog_protocol.html @@ -492,17 +492,18 @@ The request is an order object without most fields filled in, the response is a - - + +
ElementAttributes in RequestAttributes in Response
Ordercustomerid(1), customer, seller(3), ordertime(1,4), totalprice(5), paid(1), status(6), senttime(2,4)
Ticketeventevent, id(1), price, status(6)
Vouchervaluevalue, price, id(1)
Ticketevent, price(7)event, id(1), price, status(6)
Vouchervalue, price(7)value, price, id(1)
DeliveryAddress--
Comment--
-(1)field is optional for checks and has no meaning there.
+(1)field is optional for checks and has no meaning there, it is recommended the server returns a dummy ID for checks
(2)the field only exists for sales
(3)the seller is automatically taken to be the session user
(4)time stamps are automatically filled in with the current server time
(5)the total price is the accumulated price of all tickets and vouchers in the order
-(6)the status fields have special meanings for checks, see below

+(6)the status fields have special meanings for checks, see below
+(7)the price field will only be honoured in the request, if the user also has the privilege to use the changeticketprice transaction

Order status for checks: @@ -542,6 +543,10 @@ The getorderlist transaction can be used to get a list of all currently (this is a small subset of the full order object) +

Paying/Refunding Orders

+ +The orderpay transaction is used to add to the amount paid in an order. The orderrefund transaction is used to subtract from the amount paid of an order. In both cases the request consists of two positive numbers separated by a space: the order-ID and the amount in cent. The response contains the new amount paid after the transaction in the case of success and status error plus an explanation in case of any problem. + @@ -569,6 +574,10 @@ The useticket transaction marks a ticket as used. The request contains 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. +

Changing Ticket Prices

+ +The changeticketprice transaction can be used to change the price of a ticket. The request contains the ticket-ID and the new price in cent separated by a newline. The response is empty. + diff --git a/src/order.cpp b/src/order.cpp index f27fcc0..940a140 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -15,6 +15,7 @@ #include #include +#include MOrder::MOrder() { @@ -85,6 +86,26 @@ MOrder::OrderStatus MOrder::orderStatus()const return m_status; } +bool MOrder::isStored()const +{ + return (m_status&Mask)==MaskIsStored; +} + +bool MOrder::isCheck()const +{ + return (m_status&Mask)==MaskIsChecked; +} + +bool MOrder::canOrder()const +{ + return m_status==CheckOk || m_status==CheckOrderOnly; +} + +bool MOrder::canSell()const +{ + return m_status==CheckOk || m_status==CheckSaleOnly; +} + QString MOrder::orderStatusString()const { switch(m_status){ @@ -224,8 +245,7 @@ void MOrder::parseXml(const QDomElement&e) if(st=="fail")m_status=CheckFail; else m_status=Invalid; //complete stuff - if(!e.hasAttribute("seller"))return; - m_complete=true; + if(e.hasAttribute("seller"))m_complete=true; m_otime=e.attribute("ordertime","0").toInt(); m_stime=e.attribute("senttime","0").toInt(); m_seller=e.attribute("seller"); @@ -279,6 +299,7 @@ QDateTime MOrder::orderDateTime() QString MOrder::orderDateTimeStr() { makeComplete(); + if(m_otime==0)return ""; return QDateTime::fromTime_t(m_otime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd hh:mm ap","date/time format")); } @@ -291,6 +312,7 @@ QDate MOrder::orderDate() QString MOrder::orderDateStr() { makeComplete(); + if(m_otime==0)return ""; return QDateTime::fromTime_t(m_otime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd","date format")); } @@ -303,6 +325,7 @@ QDateTime MOrder::sentDateTime() QString MOrder::sentDateTimeStr() { makeComplete(); + if(m_stime==0)return ""; return QDateTime::fromTime_t(m_stime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd hh:mm ap","date/time format")); } @@ -315,6 +338,7 @@ QDate MOrder::sentDate() QString MOrder::sentDateStr() { makeComplete(); + if(m_stime==0)return ""; return QDateTime::fromTime_t(m_stime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd","date format")); } @@ -342,6 +366,68 @@ QList MOrder::tickets() return m_tickets; } +void MOrder::setAmountPaid(int p) +{ + m_paid=p; +} + +void MOrder::updateTicketPrice(QString tid,int price) +{ + for(int i=0;irequest(type,doc.toByteArray())==false){ + QMessageBox::warning(0,QCoreApplication::translate("MOrder","Error"),QCoreApplication::translate("MOrder","The request failed.")); + return MOrder(); + } + if(req->responseStatus()!=MWebRequest::Ok){ + QMessageBox::warning(0,QCoreApplication::translate("MOrder","Error"),QCoreApplication::translate("MOrder","A problem occurred during the order: %1").arg(QCoreApplication::translate("MOrder",req->responseBody()))); + return MOrder(); + } + //parse result + QDomDocument rdoc; + rdoc.setContent(req->responseBody()); + return MOrder(req,rdoc.documentElement()); +} + +MOrder MOrder::createSale() +{ + return createOrder("createsale"); +} + /****************************************************************************** * Ticket ******************************************************************************/ @@ -404,6 +490,14 @@ void MTicket::scanXml(const QDomElement&e) else m_paystate=PSUnknown; } +void MTicket::xmlForOrder(QDomDocument&doc,QDomElement&root) +{ + QDomElement tc=doc.createElement("Ticket"); + tc.setAttribute("event",m_eventid); + tc.setAttribute("price",m_price); + root.appendChild(tc); +} + MTicket::MTicket(const MTicket&t) { operator=(t); @@ -465,6 +559,16 @@ MTicket::TicketStatus MTicket::status()const return m_status; } +bool MTicket::isStored()const +{ + return (m_status&Mask)==MaskIsStored; +} + +bool MTicket::isCheck()const +{ + return (m_status&Mask)==MaskIsChecked; +} + QString MTicket::statusString()const { switch(m_status){ @@ -507,3 +611,18 @@ void MTicket::setOrderID(qint32 o) { m_orderid=o; } + +void MTicket::updatePrice(int p) +{ + if(p<0 || p==m_price)return; + //it only makes sense to contact the DB if it can be found there + if(isStored()){ + if(req==0)return; + //send request + QByteArray rq=m_id.toAscii()+"\n"+QByteArray::number(p); + if(!req->request("changeticketprice",rq))return; + if(req->responseStatus()!=MWebRequest::Ok)return; + } + //update locally + m_price=p; +} diff --git a/src/order.h b/src/order.h index 750b4ba..16902ce 100644 --- a/src/order.h +++ b/src/order.h @@ -22,6 +22,7 @@ #include "event.h" class MWebRequest; +class QDomDocument; class QDomElement; /**this class represents a single ticket*/ @@ -98,6 +99,12 @@ class MTicket /**returns the status of the ticket*/ TicketStatus status()const; + /**returns whether this order is stored in the DB*/ + bool isStored()const; + + /**returns whether this order object is the result of a check operation*/ + bool isCheck()const; + /**returns the ticket status as string*/ QString statusString()const; @@ -123,10 +130,15 @@ class MTicket /**marks the ticket as used in the database; returns empty string on success, error on failure*/ QString markUsed(); + /**updates the price of this ticket, calls DB*/ + void updatePrice(int); + protected: friend class MOrder; /**sets the order-ID of the ticket, used by MOrder*/ void setOrderID(qint32); + /**used by createOrder to generate XML elements for each ticket*/ + void xmlForOrder(QDomDocument&,QDomElement&); private: MWebRequest*req; @@ -198,6 +210,18 @@ class MOrder /**returns the status of the order*/ OrderStatus orderStatus()const; + /**returns whether this order is stored in the DB*/ + bool isStored()const; + + /**returns whether this order object is the result of a check operation*/ + bool isCheck()const; + + /**returns whether this order object can be used to generate an order (to be delivered later)*/ + bool canOrder()const; + + /**returns whether this order object can be used to generate a sale (delivered and paid immediately)*/ + bool canSell()const; + /**returns the status of the order as localized string*/ QString orderStatusString()const; @@ -270,6 +294,18 @@ class MOrder /**returns the list of tickets of this order*/ QList tickets(); + /**used by payment and refund routines: updates the amount paid for this instance*/ + void setAmountPaid(int); + + /**used to update the price of a ticket, calls DB*/ + void updateTicketPrice(QString,int); + + /**create a new order in the DB; returns it*/ + MOrder createOrder(QString type="createorder"); + + /**create a sale in the DB; returns it*/ + MOrder createSale(); + private: MWebRequest*req; int m_orderid,m_customer,m_price,m_paid,m_otime,m_stime; diff --git a/src/orderwin.cpp b/src/orderwin.cpp index c93c804..828f53e 100644 --- a/src/orderwin.cpp +++ b/src/orderwin.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -33,24 +34,37 @@ #include #include +#include + MOrderWindow::MOrderWindow(QWidget*par,MWebRequest*r,const MOrder&o) :QMainWindow(par),req(r),m_order(o) { setWindowTitle(tr("Order Details")); + setAttribute(Qt::WA_DeleteOnClose); m_changed=false; QMenuBar*mb=menuBar(); QMenu *m=mb->addMenu(tr("&Order")); - m->addAction(tr("&Order...")); - m->addAction(tr("&Sell...")); + m->addAction(tr("&Order..."),this,SLOT(createOrder())) + ->setEnabled(req->hasRole("createorder")&&o.canOrder()); + m->addAction(tr("&Sell..."),this,SLOT(createSale())) + ->setEnabled(req->hasRole("createsale")&&o.canSell()); + m->addSeparator(); + m->addAction(tr("C&ancel Order...")) + ->setEnabled(req->hasRole("cancelorder")&&o.isStored()); m->addSeparator(); - m->addAction(tr("C&ancel Order...")); + m->addAction(tr("Ch&ange Ticket-Price..."),this,SLOT(changeTicket())) + ->setEnabled(req->hasRole("changeticketprice")); m->addSeparator(); m->addAction(tr("&Close"),this,SLOT(close())); m=mb->addMenu(tr("&Payment")); - m->addAction(tr("Receive &Payment...")); - m->addAction(tr("&Refund...")); + m->setEnabled(o.isStored()); + m->addAction(tr("Receive &Payment..."),this,SLOT(payment())) + ->setEnabled(req->hasRole("orderpay")); + m->addAction(tr("&Refund..."),this,SLOT(refund())) + ->setEnabled(req->hasRole("orderrefund")); m=mb->addMenu(tr("P&rinting")); + m->setEnabled(o.isStored()); m->addAction(tr("Print &Bill..."),this,SLOT(printBill())); m->addAction(tr("Save Bill &as file..."),this,SLOT(saveBill())); m->addSeparator(); @@ -77,9 +91,9 @@ MOrderWindow::MOrderWindow(QWidget*par,MWebRequest*r,const MOrder&o) gl->addWidget(new QLabel(tr("Sold by:")),++rw,0); gl->addWidget(new QLabel(m_order.seller()),rw,1); gl->addWidget(new QLabel(tr("Total Price:")),++rw,0); - gl->addWidget(new QLabel(m_order.totalPriceString()),rw,1); + gl->addWidget(m_total=new QLabel(m_order.totalPriceString()),rw,1); gl->addWidget(new QLabel(tr("Already Paid:")),++rw,0); - gl->addWidget(new QLabel(m_order.amountPaidString()),rw,1); + gl->addWidget(m_paid=new QLabel(m_order.amountPaidString()),rw,1); gl->addWidget(new QLabel(tr("Order State:")),++rw,0); gl->addWidget(m_state=new QLabel(m_order.orderStatusString()),rw,1); gl->setColumnStretch(0,0); @@ -100,6 +114,7 @@ void MOrderWindow::updateTable() QList events; if(tickets.size()>0) events=req->getAllEvents(); + m_ticketmodel->clear(); m_ticketmodel->setHorizontalHeaderLabels(QStringList()<insertRows(0,tickets.size()); for(int i=0;irequest("orderpay",rq)){ + QMessageBox::warning(this,tr("Warning"),tr("Unable to submit payment request.")); + return; + } + if(req->responseStatus()!=MWebRequest::Ok){ + QMessageBox::warning(this,tr("Warning"),tr("Error whily trying to pay: %1").arg(tr(req->responseBody()))); + return; + } + m_order.setAmountPaid(req->responseBody().trimmed().toInt()); + m_paid->setText(m_order.amountPaidString()); +} + +void MOrderWindow::refund() +{ + if(!m_order.isValid())return; + //get value + bool ok; + double rt=QInputDialog::getDouble(this,tr("Enter Refund"),tr("Please enter the amount that will be refunded:"),m_order.amountToRefund()/100.0,0,m_order.amountToRefund()/100.0,2,&ok); + if(!ok)return; + int pay=rt*100.0; + if(pay<=0)return; + //submit + QByteArray rq=QByteArray::number(m_order.orderID())+" "+QByteArray::number(pay); + if(!req->request("orderrefund",rq)){ + QMessageBox::warning(this,tr("Warning"),tr("Unable to submit refund request.")); + return; + } + if(req->responseStatus()!=MWebRequest::Ok){ + QMessageBox::warning(this,tr("Warning"),tr("Error whily trying to refund: %1").arg(tr(req->responseBody()))); + return; + } + m_order.setAmountPaid(req->responseBody().trimmed().toInt()); + m_paid->setText(m_order.amountPaidString()); +} + +void MOrderWindow::changeTicket() +{ + if(!m_order.isValid())return; + //get ticket selection + QModelIndexList lst=m_tickettable->selectionModel()->selectedIndexes(); + if(lst.size()<1)return; + QModelIndex idx=m_ticketmodel->index(lst[0].row(),0); + QString id=m_ticketmodel->data(idx).toString(); + if(id=="")return; + //find ticket + QListtickets=m_order.tickets(); + MTicket tick; + for(int i=0;isetText(m_order.totalPriceString()); + updateTable(); +} + +void MOrderWindow::cancelOrder() +{} + +void MOrderWindow::createOrder(bool issale) +{ + MOrder ord; + if(issale)ord=m_order.createSale(); + else ord=m_order.createOrder(); + if(!ord.isValid())return; + //display final order + MOrderWindow *ow=new MOrderWindow(parentWidget(),req,ord); + ow->show(); + //undisplay self + close(); +} + + +void MOrderWindow::createSale() +{ + createOrder(true); +} /*************************************************************************************/ diff --git a/src/orderwin.h b/src/orderwin.h index 6711807..549ad7f 100644 --- a/src/orderwin.h +++ b/src/orderwin.h @@ -59,12 +59,28 @@ class MOrderWindow:public QMainWindow /**callback for bill generator: loop variables; see MOdtSignalRenderer for details*/ void getLoopVariable(QString loopname,int iteration,QString varname,QString&value); + /**received payment*/ + void payment(); + /**generate a refund*/ + void refund(); + + /**change a ticket price*/ + void changeTicket(); + + /**cancel the order*/ + void cancelOrder(); + + /**create a new order*/ + void createOrder(bool issale=false); + + /**create a sale*/ + void createSale(); private: MWebRequest*req; MOrder m_order; bool m_changed; - QLabel *m_orderid,*m_orderdate,*m_sentdate,*m_state; + QLabel *m_orderid,*m_orderdate,*m_sentdate,*m_state,*m_paid,*m_total; QTableView *m_tickettable; QStandardItemModel *m_ticketmodel; }; diff --git a/src/overview.cpp b/src/overview.cpp index df5d240..9d31860 100644 --- a/src/overview.cpp +++ b/src/overview.cpp @@ -153,11 +153,8 @@ MOverview::MOverview(MWebRequest*mw,QString pk) vl->addLayout(hl=new QHBoxLayout,0); hl->addStretch(10); hl->addWidget(p=new QPushButton(tr("Order Items"))); - p->setEnabled(req->hasRole("createorder")); + p->setEnabled(req->hasRole("checkorder")); connect(p,SIGNAL(clicked()),this,SLOT(cartOrder())); - hl->addWidget(p=new QPushButton(tr("Sell Items"))); - p->setEnabled(req->hasRole("createsale")); - connect(p,SIGNAL(clicked()),this,SLOT(cartSell())); hl->addWidget(p=new QPushButton(tr("Clear"))); connect(p,SIGNAL(clicked()),this,SLOT(initCart())); @@ -746,7 +743,7 @@ void MOverview::cartRemoveItem() cartmodel->removeRow(idx.row()); } -void MOverview::cartOrder(QString otype) +void MOverview::cartOrder() { //sanity checks if(cartmodel->rowCount()<1){ @@ -789,7 +786,7 @@ void MOverview::cartOrder(QString otype) } doc.appendChild(root); //send - if(req->request(otype,doc.toByteArray())==false){ + if(req->request("checkorder",doc.toByteArray())==false){ QMessageBox::warning(this,tr("Error"),tr("The request failed.")); return; } @@ -800,12 +797,9 @@ void MOverview::cartOrder(QString otype) //parse result QDomDocument rdoc; rdoc.setContent(req->responseBody()); - //TODO: do something with it -} - -void MOverview::cartSell() -{ - cartOrder("createsale"); + //display order and give user chance to actually order it + MOrderWindow *ow=new MOrderWindow(this,req,MOrder(req,rdoc.documentElement())); + ow->show(); } void MOverview::customerMgmt() diff --git a/src/overview.h b/src/overview.h index a0f4c66..372c6d9 100644 --- a/src/overview.h +++ b/src/overview.h @@ -103,10 +103,8 @@ class MOverview:public QMainWindow //void cartAddVoucher(); /**remove item from the cart*/ void cartRemoveItem(); - /**send the order to the server*/ - void cartOrder(QString otype="createorder"); - /**send the order to the server as sold*/ - void cartSell(); + /**check the order on the server*/ + void cartOrder(); /**manage customers*/ void customerMgmt(); diff --git a/www/inc/classes/order.php b/www/inc/classes/order.php index 91265e8..12357be 100644 --- a/www/inc/classes/order.php +++ b/www/inc/classes/order.php @@ -36,6 +36,7 @@ class Order private $senttime=false; //to be submitted private $newtickets; + private $newticketamounts; private $newvouchers; /**instantiates an existing order with the given orderid or creates a new one if orderid===false*/ @@ -59,6 +60,7 @@ class Order $this->senttime=$res[0]["senttime"]; } $this->newtickets=array(); + $this->newticketamounts=array(); $this->newvouchers=array(); } @@ -88,10 +90,8 @@ class Order $eid=$tc->getEventId(); $amt=$tc->getAmount(); $tc->changeAmount(0); - if(isset($this->newtickets[$eid])) - $this->newtickets[$eid]+=$amt; - else - $this->newtickets[$eid]=$amt; + for($i=0;$i<$amt;$i++) + $this->newtickets[$eid][]=-1; } //TODO: get vouchers @@ -102,12 +102,9 @@ class Order } /**used by XML functions: add a single ticket for an event*/ - public function addTicket($eid) + public function addTicket($eid,$price=-1) { - if(isset($this->newtickets[$eid])) - $this->newtickets[$eid]+=1; - else - $this->newtickets[$eid]=1; + $this->newtickets[$eid][]=$price; } /**sets the customer of this order; returns true on success, false on failure*/ @@ -156,10 +153,12 @@ class Order } //insert tickets $totalprice=0; - foreach($this->newtickets as $evid=>$amount){ + foreach($this->newtickets as $evid=>$tcs){ + $amount=count($tcs); for($i=0;$i<$amount;$i++){ $tick=new Ticket; $tick->setEventId($evid); + if($tcs[$i]>=0)$tick->setPrice($tcs[$i]); $tick->addToOrder($this->orderid); $totalprice+=$tick->getPrice(); //TODO: check return code of addToOrder @@ -200,8 +199,10 @@ class Order $orderstop=($db->getConfig("OrderStop")+0)*3600; $salestop=($db->getConfig("SaleStop")+0)*3600; $curtime=time(); - foreach($this->newtickets as $evid => $amount){ - + $totalprice=0; + $ftid=0; + foreach($this->newtickets as $evid => $tcs){ + $amount=count($tcs); $evt=new Event($evid); if(!$evt->exists()){ if($dumpxml===false)return false; @@ -209,6 +210,7 @@ class Order $ev=$xml->createElement("Ticket"); $ev->setAttribute("event",$evid); $ev->setAttribute("status","invalid"); + $ev->setAttribute("id",$ftid++); $ord->appendChild($ev); $ret=false; $ostat="fail"; @@ -229,6 +231,7 @@ class Order $ev=$xml->createElement("Ticket"); $ev->setAttribute("event",$evid); $ev->setAttribute("status",$estat); + $ev->setAttribute("id",$ftid++); $ord->appendChild($ev); if($ostat=="ok")$ostat=$estat; else if($ostat!=$estat)$ostat="fail"; @@ -241,6 +244,7 @@ class Order $ev=$xml->createElement("Ticket"); $ev->setAttribute("event",$evid); $ev->setAttribute("status","cancelled"); + $ev->setAttribute("id",$ftid++); $ord->appendChild($ev); $ret=false; continue; @@ -254,12 +258,15 @@ class Order $ev->setAttribute("event",$evid); $ev->setAttribute("status","ok"); $ev->setAttribute("price",$evt->getDefaultPrice()); + $ev->setAttribute("id",$ftid++); $ord->appendChild($ev); + $totalprice+=$evt->getDefaultPrice(); } //create only one bad ticket $ev=$xml->createElement("Ticket"); $ev->setAttribute("event",$evid); $ev->setAttribute("status","exhausted"); + $ev->setAttribute("id",$ftid++); $ord->appendChild($ev); $ret=false; continue; @@ -270,7 +277,9 @@ class Order $ev->setAttribute("event",$evid); $ev->setAttribute("status","ok"); $ev->setAttribute("price",$evt->getDefaultPrice()); + $ev->setAttribute("id",$ftid++); $ord->appendChild($ev); + $totalprice+=$evt->getDefaultPrice(); } } @@ -281,6 +290,7 @@ class Order $ord->appendChild($xml->createElement("DeliveryAddress",$this->deliveryaddress)); $ord->appendChild($xml->createElement("Comment",$this->comment)); $ord->setAttribute("status",$ostat); + $ord->setAttribute("totalprice",$totalprice); $xml->appendChild($ord); print($xml->saveXml()); } @@ -385,9 +395,16 @@ function createOrderXml($xmldata,$action) $doc=$xml->documentElement; $cust=$doc->getAttribute("customer")+0; $order->setCustomerId($cust); + global $session; + $canprice=$session->canExecute("changeticketprice"); //get tickets foreach($doc->getElementsByTagName("Ticket") as $tc){ - $order->addTicket($tc->getAttribute("event")+0); + if($canprice){ + $price=trim($tc->getAttribute("price")); + if($price=="" || !is_numeric($price))$price=-1; + else $price=$price+0; + }else $price=-1; + $order->addTicket($tc->getAttribute("event")+0,$price); } //TODO: get vouchers @@ -395,8 +412,8 @@ function createOrderXml($xmldata,$action) switch($action){ case "check": // check order - $order->validateOrder(true); header("X-MagicSmoke-Status: Ok"); + $order->validateOrder(true); break; case "order": // create order @@ -484,4 +501,49 @@ function getOrderXml($oid) } } +//pay or refund +function orderPayXml($data,$factor) +{ + //split data + $dlst=explode(" ",trim($data)); + if(count($dlst)!=2){ + header("X-MagicSmoke-Status: Error"); + die(tr("Expected 2 arguments.")); + } + //check that order id is int + $oid=$dlst[0]+0; + if(!is_numeric($dlst[0])||$oid<0){ + header("X-MagicSmoke-Status: Error"); + die(tr("Invalid Order ID")." $oid $dlst[0]"); + } + //check amount + $amt=round($dlst[1]+0); + if($amt<=0){ + header("X-MagicSmoke-Status: Error"); + die(tr("Expected positive amount.")); + } + //check that order exists + global $db; + $db->beginTransaction(); + $res=$db->select("order","amountpaid,status","orderid=".$db->escapeInt($oid)); + if(count($res)<1){ + $db->rollbackTransaction(); + header("X-MagicSmoke-Status: Error"); + die(tr("Order does not exist.")); + } + //check status + if($res[0]["status"]==ORDER_CLOSED){ + $db->rollbackTransaction(); + header("X-MagicSmoke-Status: Error"); + die(tr("Order cannot be changed, it is closed.")); + } + //correct DB + $amt2=$res[0]["amountpaid"]+($amt*$factor); + $db->update("order",array("amountpaid"=>$amt2),"orderid=".$db->escapeInt($oid)); + $db->commitTransaction(); + //output + header("X-MagicSmoke-Status: Ok"); + echo $amt2; +} + ?> \ No newline at end of file diff --git a/www/inc/classes/ticket.php b/www/inc/classes/ticket.php index f355b6e..1d5dc45 100644 --- a/www/inc/classes/ticket.php +++ b/www/inc/classes/ticket.php @@ -86,6 +86,12 @@ class Ticket return $this->price; } + /**overwrites the price stored in this object (used by order before the ticket is stored to the DB)*/ + public function setPrice($p) + { + $this->price=$p; + } + /**returns the ticket status*/ public function getStatus() { @@ -238,4 +244,36 @@ function useTicketXml($tid) } } +function changeTicketPriceXml($data) +{ + //split + $lst=explode("\n",$data); + if(count($lst)!=2){ + header("X-MagicSmoke-Status: Error"); + die(tr("Malformed request.")); + } + //check price + if(!is_numeric(trim($lst[1]))){ + header("X-MagicSmoke-Status: Error"); + die(tr("Price must be a number.")); + } + $prc=trim($lst[1])+0; + if($prc<0){ + header("X-MagicSmoke-Status: Error"); + die(tr("Price must be positive.")); + } + //get ticket + global $db; + $db->beginTransaction(); + $res=$db->select("ticket","ticketid","ticketid=".$db->escapeString(trim($lst[0]))); + if(count($res)<1){ + $db->rollbackTransaction(); + header("X-MagicSmoke-Status: Error"); + die(tr("Unable to find this ticket.")); + } + $db->update("ticket",array("price"=>$prc),"ticketid=".$db->escapeString(trim($lst[0]))); + $db->commitTransaction(); + header("X-MagicSmoke-Status: Ok"); +} + ?> \ No newline at end of file diff --git a/www/machine.php b/www/machine.php index 381da55..a210415 100644 --- a/www/machine.php +++ b/www/machine.php @@ -23,8 +23,8 @@ $ALLOWEDREQUESTS=array( tr("geteventlist"),tr("geteventdata"),tr("seteventdata"),tr("eventsummary"), //event infos 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("checkorder"),tr("createorder"),tr("createsale"),tr("getorderlist"),tr("getorder"),tr("orderpay"),tr("orderrefund"), //sell/order stuff + tr("getticket"),tr("useticket"),tr("changeticketprice"),//ticket management tr("gettemplatelist"),tr("gettemplate"),tr("settemplate") //templates ); /**contains the low-level request name from the client*/ @@ -286,6 +286,16 @@ if($SMOKEREQUEST=="getorder"){ getOrderXml(trim($REQUESTDATA)+0); exit(); } +//pay for an order +if($SMOKEREQUEST=="orderpay"){ + orderPayXml($REQUESTDATA,1); + exit(); +} +//refund an order +if($SMOKEREQUEST=="orderrefund"){ + orderPayXml($REQUESTDATA,-1); + exit(); +} //get a ticket if($SMOKEREQUEST=="getticket"){ @@ -297,6 +307,11 @@ if($SMOKEREQUEST=="useticket"){ useTicketXml(trim($REQUESTDATA)); exit(); } +//change the price of a ticket +if($SMOKEREQUEST=="changeticketprice"){ + changeTicketPriceXml(trim($REQUESTDATA)); + exit(); +} //EOF header("X-MagicSmoke-Status: Error");