From 5e9f3f127798e26b621c8ecff5373142b18287e3 Mon Sep 17 00:00:00 2001 From: konrad Date: Wed, 6 Jan 2010 17:39:14 +0000 Subject: [PATCH] *qt side of cart should be pretty much complete now *php side of createOrder/Reservation started, but still lacks: - verification of vouchers - creation of objects in DB git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@406 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- src/mwin/carttab.cpp | 329 ++++++++++++++++++++++++++++++++++++++------- src/mwin/carttab.h | 32 ++++- wob/basics.wolf | 2 +- wob/cart.wolf | 32 +++-- wob/order.wolf | 16 ++- www/inc/wext/autoload.php | 1 + www/inc/wext/cart.php | 243 +++++++++++++++++++++++++++++++++ www/inc/wext/order.php | 3 + 8 files changed, 589 insertions(+), 69 deletions(-) create mode 100644 www/inc/wext/cart.php diff --git a/src/mwin/carttab.cpp b/src/mwin/carttab.cpp index 89d29ee..5676552 100644 --- a/src/mwin/carttab.cpp +++ b/src/mwin/carttab.cpp @@ -71,16 +71,19 @@ MCartTab::MCartTab(QString pk) vl2->addWidget(p=new QPushButton(tr("Customer:")),0); connect(p,SIGNAL(clicked()),this,SLOT(setCustomer())); vl2->addWidget(cartcustomer=new QLabel("...")); + cartcustomer->setAutoFillBackground(true); vl2->addWidget(frm=new QFrame,0); frm->setFrameShape(QFrame::HLine); vl2->addWidget(p=new QPushButton(tr("Invoice Address:")),0); connect(p,SIGNAL(clicked()),this,SLOT(setInvoiceAddr())); vl2->addWidget(invoiceaddr=new QLabel("...")); + invoiceaddr->setAutoFillBackground(true); vl2->addWidget(frm=new QFrame,0); frm->setFrameShape(QFrame::HLine); vl2->addWidget(p=new QPushButton(tr("Delivery Address:")),0); connect(p,SIGNAL(clicked()),this,SLOT(setDeliveryAddr())); vl2->addWidget(deliveryaddr=new QLabel("...")); + deliveryaddr->setAutoFillBackground(true); vl2->addWidget(frm=new QFrame,0); frm->setFrameShape(QFrame::HLine); vl2->addSpacing(10); @@ -100,7 +103,7 @@ MCartTab::MCartTab(QString pk) connect(p,SIGNAL(clicked()),this,SLOT(cartOrder())); hl->addWidget(p=new QPushButton(tr("Reserve"))); p->setEnabled(req->hasRight(req->RCreateReservation)); - connect(p,SIGNAL(clicked()),this,SLOT(cartOrder())); + connect(p,SIGNAL(clicked()),this,SLOT(cartReserve())); hl->addWidget(p=new QPushButton(tr("Clear"))); connect(p,SIGNAL(clicked()),this,SLOT(initCart())); @@ -118,7 +121,8 @@ QMenu*MCartTab::menu() QMenu*m=new QMenu(tr("C&art")); m->addAction(tr("Add &Ticket"),this,SLOT(cartAddTicket())); m->addAction(tr("Add &Voucher"),this,SLOT(cartAddVoucher())); - m->addAction(tr("&Remove Item"),this,SLOT(cartRemoveItem())); + m->addAction(tr("Add &Shop-Item"),this,SLOT(cartAddItem())); + m->addAction(tr("&Remove Line"),this,SLOT(cartRemoveItem())); m->addAction(tr("&Abort Shopping"),this,SLOT(initCart())); m->addSeparator(); m->addAction(tr("&Update Shipping Options"),this,SLOT(updateShipping())); @@ -137,13 +141,16 @@ void MCartTab::updateShipping() QListship=sh.getshipping(); for(int i=0;iaddItem(ship[i].description(),(int)ship[i].shipid()); + QPalette pal2=QComboBox().palette(); + cartship->setPalette(pal2); + cartship->setToolTip(QString()); } void MCartTab::initCart() { //clear cart cartmodel->clear(); - cartmodel->setHorizontalHeaderLabels(QStringList()<setHorizontalHeaderLabels(QStringList()<setText(""); @@ -155,6 +162,30 @@ void MCartTab::initCart() cartcomment->setPlainText(""); //clear shipping cartship->setCurrentIndex(0); + //reset colors + resetColor(); +} + +void MCartTab::resetColor(bool addronly) +{ + QPalette pal=QLabel().palette(); + cartcustomer->setPalette(pal); + cartcustomer->setToolTip(QString()); + invoiceaddr->setPalette(pal); + invoiceaddr->setToolTip(QString()); + deliveryaddr->setPalette(pal); + deliveryaddr->setToolTip(QString()); + if(!addronly){ + for(int i=0;irowCount();i++) + for(int j=0;jcolumnCount();j++){ + QModelIndex idx=cartmodel->index(i,j); + cartmodel->setData(idx,QVariant(),Qt::ToolTipRole); + cartmodel->setData(idx,QVariant(),Qt::BackgroundRole); + } + QPalette pal2=QComboBox().palette(); + cartship->setPalette(pal2); + cartship->setToolTip(QString()); + } } void MCartTab::setCustomer() @@ -167,6 +198,7 @@ void MCartTab::setCustomer() deliveryaddr->setText(""); invoiceaddr->setText(""); deliveryaddrid=invoiceaddrid=-1; + resetColor(true); //follow up with address dialog if(!customer.customerid().isNull()) setInvoiceAddr(); @@ -183,6 +215,8 @@ void MCartTab::setDeliveryAddr() customer=d.customer(); deliveryaddr->setText(d.address().fullAddress(customer.fullName())); deliveryaddrid=d.addressId(); + deliveryaddr->setPalette(QLabel().palette()); + deliveryaddr->setToolTip(QString()); } void MCartTab::setInvoiceAddr() @@ -198,6 +232,8 @@ void MCartTab::setInvoiceAddr() customer=d.customer(); invoiceaddr->setText(d.address().fullAddress(customer.fullName())); invoiceaddrid=d.addressId(); + invoiceaddr->setPalette(QLabel().palette()); + invoiceaddr->setToolTip(QString()); } static const int CART_TICKET=1; @@ -205,6 +241,7 @@ static const int CART_VOUCHER=2; static const int CART_IDROLE=Qt::UserRole;//ticket id static const int CART_PRICEROLE=Qt::UserRole;//voucher price +static const int CART_PRICEIDROLE=CART_PRICEROLE;//for tickets: price category id static const int CART_VALUEROLE=Qt::UserRole+1;//voucher value static const int CART_TYPEROLE=Qt::UserRole+2;//which is it? ticket or voucher? @@ -233,22 +270,67 @@ void MCartTab::cartAddTicket() hl->addWidget(p=new QPushButton(tr("Cancel")),0); connect(p,SIGNAL(clicked()),&dlg,SLOT(reject())); //wait for it - if(dlg.exec()==QDialog::Accepted){ - //get selection - QModelIndex idx=tv->currentIndex(); - if(!idx.isValid())return; - int id=eventmodel->data(eventmodel->index(idx.row(),0),Qt::UserRole).toInt(); - if(id<0)return; - //copy to cart - int cr=cartmodel->rowCount(); - cartmodel->insertRows(cr,1); - cartmodel->setData(cartmodel->index(cr,0),1); - cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE); - cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE); - cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(idx.row(),1))); - cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(idx.row(),0))); - carttable->resizeColumnsToContents(); + if(dlg.exec()!=QDialog::Accepted)return; + //get selection + QModelIndex idx=tv->currentIndex(); + if(!idx.isValid())return; + int id=eventmodel->data(eventmodel->index(idx.row(),0),Qt::UserRole).toInt(); + if(id<0)return; + addTicketForEvent(id); +} + +void MCartTab::addTicketForEvent(qint64 id) +{ + //get event + MTGetEvent ge=MTGetEvent::query(id); + if(ge.hasError()){ + QMessageBox::warning(this,tr("Warning"),tr("Error getting event, please try again.")); + return; } + MOEvent ev=ge.getevent(); + //get Price Category + QList ep=ev.price(); + if(ep.size()==0){ + QMessageBox::warning(this,tr("Warning"),tr("This event has no prices associated. Cannot sell tickets.")); + return; + } + int pcidx=0; + if(ep.size()>1){ + QDialog d(this); + d.setWindowTitle(tr("Select Price Category")); + QVBoxLayout*vl; + QHBoxLayout*hl; + QComboBox*box; + QPushButton*p; + d.setLayout(vl=new QVBoxLayout); + vl->addWidget(new QLabel(tr("Please chose a price category:"))); + vl->addWidget(box=new QComboBox); + for(int i=0;iaddItem(ep[i].pricecategory().value().name().value()+": "+cent2str(ep[i].price())); + box->setEditable(false); + vl->addSpacing(10); + vl->addStretch(10); + vl->addLayout(hl=new QHBoxLayout); + hl->addStretch(10); + hl->addWidget(p=new QPushButton(tr("Ok"))); + connect(p,SIGNAL(clicked()),&d,SLOT(accept())); + hl->addWidget(p=new QPushButton(tr("Cancel"))); + connect(p,SIGNAL(clicked()),&d,SLOT(reject())); + if(d.exec()!=QDialog::Accepted)return; + pcidx=box->currentIndex(); + } + //copy to cart + int cr=cartmodel->rowCount(); + cartmodel->insertRows(cr,1); + cartmodel->setData(cartmodel->index(cr,0),1); + cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE); + cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE); + cartmodel->setData(cartmodel->index(cr,0),ep[pcidx].pricecategoryid().value(),CART_PRICEIDROLE); + cartmodel->setData(cartmodel->index(cr,1),ev.title().value()); + cartmodel->setData(cartmodel->index(cr,2),ev.startTimeString()); + QString pcn=cent2str(ep[pcidx].price())+" ("+ep[pcidx].pricecategory().value().name().value()+")"; + cartmodel->setData(cartmodel->index(cr,3),pcn); + carttable->resizeColumnsToContents(); } void MCartTab::eventOrderTicket() @@ -258,14 +340,7 @@ void MCartTab::eventOrderTicket() //activate order tab emit requestFocus(); //insert event into table - int cr=cartmodel->rowCount(); - cartmodel->insertRows(cr,1); - cartmodel->setData(cartmodel->index(cr,0),1); - cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE); - cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE); - cartmodel->setData(cartmodel->index(cr,1),emit currentEventTitle()); - cartmodel->setData(cartmodel->index(cr,2),emit currentEventStart()); - carttable->resizeColumnsToContents(); + addTicketForEvent(id); } void MCartTab::cartAddVoucher() @@ -323,7 +398,8 @@ void MCartTab::cartAddVoucher() cartmodel->setData(cartmodel->index(cr,0),price,CART_PRICEROLE); cartmodel->setData(cartmodel->index(cr,0),value,CART_VALUEROLE); cartmodel->setData(cartmodel->index(cr,0),CART_VOUCHER,CART_TYPEROLE); - cartmodel->setData(cartmodel->index(cr,1),tr("Voucher (price: %1, value %2)").arg(cent2str(price)).arg(cent2str(value))); + cartmodel->setData(cartmodel->index(cr,1),tr("Voucher (value %1)").arg(cent2str(value))); + cartmodel->setData(cartmodel->index(cr,3),cent2str(price)); carttable->resizeColumnsToContents(); } } @@ -342,20 +418,11 @@ void MCartTab::cartRemoveItem() cartmodel->removeRow(idx.row()); } -void MCartTab::cartOrder() +void MCartTab::cartOrder(bool isreserve) { //sanity checks - if(cartmodel->rowCount()<1){ - QMessageBox::warning(this,tr("Error"),tr("There is nothing in the order. Ignoring it.")); - return; - } - if(!customer.isValid()){ - QMessageBox::warning(this,tr("Error"),tr("Please chose a customer first!")); - return; - } - if(cartship->currentIndex()>0 && deliveryaddrid<0 && invoiceaddrid<0){ - if(QMessageBox::question(this,tr("Shipping"),tr("You have chosen a shipping method, but no address. Are you sure you want to continue?"),QMessageBox::Yes|QMessageBox::No) != QMessageBox::Yes)return; - } + if(!canorder(isreserve))return; + resetColor(false); /////////////// //create order MOCartOrder cord; @@ -367,6 +434,67 @@ void MCartTab::cartOrder() QString s=cartcomment->toPlainText().trimmed(); if(s!="")cord.setcomment(s); //scan tickets & scan vouchers + cartTableToOrder(cord); + //set shipping info + if(cartship->currentIndex()>0) + cord.setshippingtypeid(cartship->itemData(cartship->currentIndex()).toInt()); + ///// + //send + MOOrder ord; + if(!orderExecute(cord,ord,isreserve))return; + ///// + //everything ok, move on + if(!ord.orderid().isNull()){ + initCart(); + MOrderWindow *ow=new MOrderWindow(window(),ord); + ow->show(); + return; + } + ///// + //something went wrong: verify cart + QMessageBox::warning(this,tr("Warning"),tr("There are problems with the contents of the cart, please check and then try again.")); + //verify customer + verifyOrderCustomer(cord); + //verify tickets + verifyOrderTickets(cord.tickets()); + verifyOrderVouchers(cord.vouchers()); + verifyOrderItems(cord.items()); +} + +void MCartTab::cartReserve() +{ + cartOrder(true); +} + +bool MCartTab::canorder(bool isreserve) +{ + //basics + if(cartmodel->rowCount()<1){ + QMessageBox::warning(this,tr("Error"),tr("There is nothing in the order. Ignoring it.")); + return false; + } + if(!customer.isValid()){ + QMessageBox::warning(this,tr("Error"),tr("Please chose a customer first!")); + return false; + } + if(cartship->currentIndex()>0 && deliveryaddrid<0 && invoiceaddrid<0){ + if(QMessageBox::question(this,tr("Shipping"),tr("You have chosen a shipping method, but no address. Are you sure you want to continue?"),QMessageBox::Yes|QMessageBox::No) != QMessageBox::Yes)return false; + } + //if for a reservation: tickets only please + if(isreserve) + for(int i=0;irowCount();i++){ + int tp=cartmodel->data(cartmodel->index(i,0),CART_TYPEROLE).toInt(); + if(tp!=CART_TICKET){ + QMessageBox::warning(this,tr("Warning"),tr("Reservations can only contain tickets.")); + return false; + } + } + //all clear + return true; +} + +void MCartTab::cartTableToOrder(MOCartOrder&cord) +{ for(int i=0;irowCount();i++){ QModelIndex idx=cartmodel->index(i,0); int tp=cartmodel->data(idx,CART_TYPEROLE).toInt(); @@ -374,6 +502,8 @@ void MCartTab::cartOrder() MOCartTicket ct; ct.setamount(cartmodel->data(idx).toInt()); ct.seteventid(cartmodel->data(idx,CART_IDROLE).toInt()); + ct.setpricecategoryid(cartmodel->data(idx,CART_PRICEIDROLE).toInt()); + ct.setcartlineid(i); cord.addtickets(ct); }else if(tp==CART_VOUCHER){ @@ -381,21 +511,122 @@ void MCartTab::cartOrder() cv.setamount(cartmodel->data(idx).toInt()); cv.setprice(cartmodel->data(idx,CART_PRICEROLE).toInt()); cv.setvalue(cartmodel->data(idx,CART_VALUEROLE).toInt()); + cv.setcartlineid(i); cord.addvouchers(cv); } //TODO: product/items } - //set shipping info - cord.setshippingtypeid(cartship->itemData(cartship->currentIndex()).toInt()); - //send - MTCreateOrder co=req->queryCreateOrder(cord); - if(co.hasError()){ - QMessageBox::warning(this,tr("Warning"),tr("Error while creating order: %1").arg(co.errorString())); - return; +} + +bool MCartTab::orderExecute(MOCartOrder&cord,MOOrder&ord,bool isreserve) +{ + if(isreserve){ + MTCreateReservation co=req->queryCreateReservation(cord); + if(co.hasError()){ + QMessageBox::warning(this,tr("Warning"),tr("Error while creating reservation: %1").arg(co.errorString())); + return false; + } + ord=co.getorder(); + cord=co.getcart(); + }else{ + MTCreateOrder co=req->queryCreateOrder(cord); + if(co.hasError()){ + QMessageBox::warning(this,tr("Warning"),tr("Error while creating order: %1").arg(co.errorString())); + return false; + } + ord=co.getorder(); + cord=co.getcart(); + } + return true; +} + +void MCartTab::verifyOrderCustomer(MOCartOrder&cord) +{ + QPalette red=QLabel().palette();red.setColor(QPalette::Window,Qt::red); + if(cord.customerid() != customer.customerid()){ + customer=MOCustomer(); + cartcustomer->setPalette(red); + cartcustomer->setToolTip(tr("The customer is not valid, please chose another one.")); + } + if(deliveryaddrid>=0 && cord.deliveryaddressid() != deliveryaddrid){ + deliveryaddrid=-1; + deliveryaddr->setPalette(red); + deliveryaddr->setToolTip(tr("The delivery address is not valid, please chose another one.")); + } + if(invoiceaddrid>=0 && cord.invoiceaddressid() != invoiceaddrid){ + invoiceaddrid=-1; + invoiceaddr->setPalette(red); + invoiceaddr->setToolTip(tr("The invoice address is not valid, please chose another one.")); + } + if(cartship->currentIndex()>0 && cord.shippingtypeid().isNull()){ + QPalette red2=QComboBox().palette();red2.setColor(QPalette::Window,Qt::red); + cartship->setPalette(red2); + cartship->setToolTip(tr("Shipping Type does not exist or you do not have permission to use it.")); + } +} + +void MCartTab::verifyOrderTickets(const QList&ticks) +{ + for(int i=0;i=cartmodel->rowCount())continue; + QModelIndex idx0=cartmodel->index(j,0); + if(cartmodel->data(idx0,CART_TYPEROLE).toInt() != CART_TICKET)continue; + QModelIndex idx1=cartmodel->index(j,1); + cartmodel->setData(idx1,Qt::red,Qt::BackgroundRole); + //check state, color it + switch(ticks[i].status().value()){ + case MOCartTicket::EventOver: + cartmodel->setData(idx1,tr("The event is already over, please remove this entry."),Qt::ToolTipRole); + break; + case MOCartTicket::TooLate: + cartmodel->setData(idx1,tr("You cannot order tickets for this event anymore, ask a more privileged user."),Qt::ToolTipRole); + break; + case MOCartTicket::Exhausted:{ + cartmodel->setData(idx0,Qt::red,Qt::BackgroundRole); + QString tt=tr("The event is (almost) sold out, there are %1 tickets left.").arg(ticks[i].maxamount()); + cartmodel->setData(idx0,tt,Qt::ToolTipRole); + cartmodel->setData(idx1,tt,Qt::ToolTipRole); + break;} + case MOCartTicket::Invalid: + cartmodel->setData(idx1,tr("The event does not exist or there is another serious problem, please remove this entry."),Qt::ToolTipRole); + break; + default:break;//ignore all others + } + } + } +} + +void MCartTab::verifyOrderVouchers(const QList&voucs) +{ + for(int i=0;i=cartmodel->rowCount())continue; + QModelIndex idx0=cartmodel->index(j,0); + if(cartmodel->data(idx0,CART_TYPEROLE).toInt() != CART_VOUCHER)continue; + QModelIndex idx1=cartmodel->index(j,1); + cartmodel->setData(idx1,Qt::red,Qt::BackgroundRole); + //check state, color it + switch(voucs[i].status().value()){ + case MOCartVoucher::InvalidValue: + cartmodel->setData(idx1,tr("You do not have permission to create vouchers with this value, please remove it."),Qt::ToolTipRole); + break; + case MOCartVoucher::InvalidPrice: + cartmodel->setData(idx1,tr("The price tag of this voucher is not valid, please remove and recreate it."),Qt::ToolTipRole); + break; + default:break;//ignore all others + } + } } - initCart(); - MOrderWindow *ow=new MOrderWindow(window(),co.getorder()); - ow->show(); +} + +void MCartTab::verifyOrderItems(const QList&) +{ + //TODO: implement items } /********************************************************************************/ diff --git a/src/mwin/carttab.h b/src/mwin/carttab.h index 99a2365..0435247 100644 --- a/src/mwin/carttab.h +++ b/src/mwin/carttab.h @@ -35,6 +35,12 @@ class QTextEdit; class MSInterface; +class MOCartOrder; +class MOCartItem; +class MOCartTicket; +class MOCartVoucher; +class MOOrder; + /**Main Overview Window: cart tab*/ class MCartTab:public QWidget { @@ -87,8 +93,12 @@ class MCartTab:public QWidget void cartAddItem(); /**remove item from the cart*/ void cartRemoveItem(); - /**check the order on the server*/ - void cartOrder(); + /**create the order on the server*/ + void cartOrder(bool isreserve=false); + /**create a reservation on the server*/ + void cartReserve(); + /**reset the colors of the tab*/ + void resetColor(bool addronly=false); private: //the profile associated with this session @@ -102,6 +112,24 @@ class MCartTab:public QWidget //cart MOCustomer customer; qint64 deliveryaddrid,invoiceaddrid; + + /**helper for order: returns true if an order can be sent*/ + bool canorder(bool isreserve); + /**helper for order: turns the cart table into order items*/ + void cartTableToOrder(MOCartOrder&); + /**helper for order: makes the actual order or reserve; returns the result in the first two parameters; returns false if the transaction was aborted and processing should stop here*/ + bool orderExecute(MOCartOrder&cart,MOOrder&order,bool isreserve); + /**helper for order: verifies customer properties*/ + void verifyOrderCustomer(MOCartOrder&); + /**helper for order: verifies tickets*/ + void verifyOrderTickets(const QList&); + /**helper for order: verifies vouchers*/ + void verifyOrderVouchers(const QList&); + /**helper for order: verifies product items*/ + void verifyOrderItems(const QList&); + + /**helper for cartAddTicket and eventOrderTicket: choses a price category and then adds the ticket*/ + void addTicketForEvent(qint64); }; /**Helper class for shopping cart: allow editing amount, but nothing else*/ diff --git a/wob/basics.wolf b/wob/basics.wolf index 30a7715..d686019 100644 --- a/wob/basics.wolf +++ b/wob/basics.wolf @@ -14,7 +14,7 @@ - + diff --git a/wob/cart.wolf b/wob/cart.wolf index 426c967..0fd5a81 100644 --- a/wob/cart.wolf +++ b/wob/cart.wolf @@ -48,14 +48,16 @@ - - - - - + The tickets can be sold + The event is already over + The event is not yet over, but normal sale is no longer possible, you need the CreateOrder:LateSale privilege + There are not enough tickets for this event + There is an inherent mismatch in the ticket (eg. non-existent event or price category), it can't possibly be sold. + optional property that can be used by the calling process to distinguish lines in the cart, the server must preserve it unchanged + @@ -64,24 +66,27 @@ - - - + The voucher can be sold + The value is not one of the allowed ones and you do not have the privilege to set an arbitrary one, or the value is negative. + The price is negative, the price property is ignored if you do not have the privilege to chose a price that differs from the value + optional property that can be used by the calling process to distinguish lines in the cart, the server must preserve it unchanged + + + - - - - + The cart has been processed successfully + There are problems with the cart, it cannot be processed - + optional ID for the cart itself, the calling process can use this to distinguish different carts, the server must preserve it between input and output + set by the server to reflect the processing state of the cart @@ -89,5 +94,6 @@ + \ No newline at end of file diff --git a/wob/order.wolf b/wob/order.wolf index d82b43a..c10c8ed 100644 --- a/wob/order.wolf +++ b/wob/order.wolf @@ -414,21 +414,29 @@ CreateOrder creates orders that are queued to be executed immediately, they may contain tickets, vouchers, or shopping items users with this privilege can create vouchers with arbitrary value users with this privilege can create vouchers with a price (what the customer pays) different from its value (what the customer can buy with it) + users with this privilege can sell tickets until the event is over, otherwise a configurable limit applies + users with this privilege can sell tickets for past events - be careful to give this privilege only to very few special users, it is an invitation to mistakes! - + The cart contents + - + If successful: the created order + If unsuccessful: the cart with annotations Reservations are orders that are not executed right away. They may only contain tickets that block some seats for a limited time. They cannot contain any shopping items or vouchers. + users with this right can make reservations right up to the start of the event, otherwise a configured limit applies - + The cart contents + + - + If successful: the created order + If unsuccessful: the cart with annotations diff --git a/www/inc/wext/autoload.php b/www/inc/wext/autoload.php index 82096e7..1dbec32 100644 --- a/www/inc/wext/autoload.php +++ b/www/inc/wext/autoload.php @@ -12,6 +12,7 @@ // $AUTOCLASS["WOArtist"]="inc/wext/artist.php"; +$AUTOCLASS["WOCartOrder"]="inc/wext/cart.php"; $AUTOCLASS["WOCustomer"]="inc/wext/customer.php"; $AUTOCLASS["WOEventPrice"]="inc/wext/event.php"; $AUTOCLASS["WOEvent"]="inc/wext/event.php"; diff --git a/www/inc/wext/cart.php b/www/inc/wext/cart.php new file mode 100644 index 0000000..d0b4040 --- /dev/null +++ b/www/inc/wext/cart.php @@ -0,0 +1,243 @@ +, (C) 2010 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +class WOCartOrder extends WOCartOrderAbstract +{ + const LateSale=-1; + const AfterSale=-2; + + /**called by the CreateOrder and CreateReservation transactions*/ + public static function createOrder($trans) + { + //get cart object + $cart=$trans->getcart(); + if(!is_a($cart,"WOCartOrder")){ + $trans->abortWithError(tr("Not a valid cart object.")); + return; + } + //get permissions + global $db; + $isreserve=false; + $vanyval=false; + $vdiffprice=false; + $tsalestop=0; + if(is_a($trans,"WTrCreateOrder")){ + $vanyval=$trans->havePrivilege(WTrCreateOrder::Priv_AnyVoucherValue); + $vdiffprice=$trans->havePrivilege(WTrCreateOrder::Priv_DiffVoucherValuePrice); + $tsalestop=$db->getConfig("OrderStop")+0; + if($tsalestop<0)$tsalestop=0; + if($trans->havePrivilege(WTrCreateOrder::Priv_LateSale)) + $tsalestop=self::LateSale; + if($trans->havePrivilege(WTrCreateOrder::Priv_AfterTheFactSale)) + $tsalestop=self::AfterSale; + }else + if(is_a($trans,"WTrCreateReservation")){ + $isreserve=true; + $tsalestop=$db->getConfig("ReserveStop")+0; + if($tsalestop<0)$tsalestop=0; + if($trans->havePrivilege(WTrCreateReservation::Priv_LateReserve)) + $tsalestop=0; + }else{ + $trans->abortWithError(tr("CreateSale called from an unknown transaction.")); + return; + } + //verify necessary elements and content + $very=true; + $very&=$cart->verifyCustomer($trans); + $very&=$cart->verifyShipping($trans); + + $very&=$cart->verifyTickets($trans,$tsalestop); + if($isreserve){ + if(count($cart->get_vouchers())>0 || count($cart->get_items())>0){ + $trans->abortWithError(tr("Reservations must not contain anything but tickets.")); + return; + } + }else{ + $very&=$cart->verifyVouchers($trans,$vanyval,$vdiffprice); + $very&=$cart->verifyItems($trans); + } + //verification successful? + if(!$very){ + //no: set verified cart and return to caller + $cart->set_status(WOCartOrder::Invalid); + $trans->setcart($cart); + return; + } + $cart->set_status(WOCartOrder::Ok); + //create order + $ord=$cart->createOrderOnDB($isreserve); + + //return verified cart and order + $trans->setorder($ord); + $trans->setcart($cart); + } + + /**helper function for createOrder: verifies customer settings*/ + private function verifyCustomer($trans) + { + //check customer exists + $cust=WTcustomer::getFromDB($this->prop_customerid); + if(!is_a($cust,"WTcustomer")){ + $this->prop_customerid=null; + $this->prop_deliveryaddressid=null; + $this->prop_invoiceaddressid=null; + return false; + } + //check addresses belong to customer + $ret=true; + if($this->prop_invoiceaddressid!==null){ + $addr=WTaddress::getFromDB($this->prop_invoiceaddressid); + if(!is_a($addr,"WTaddress")){ + $this->prop_invoiceaddressid=null; + $ret=false; + }else{ + if($addr->customerid != $this->prop_customerid){ + $this->prop_invoiceaddressid=null; + $ret=false; + } + } + } + if($this->prop_deliveryaddressid!==null){ + $addr=WTaddress::getFromDB($this->prop_deliveryaddressid); + if(!is_a($addr,"WTaddress")){ + $this->prop_deliveryaddressid=null; + $ret=false; + }else{ + if($addr->customerid != $this->prop_customerid){ + $this->prop_deliveryaddressid=null; + $ret=false; + } + } + } + return $ret; + } + + /**helper function for createOrder: verifies customer settings*/ + private function verifyShipping($trans) + { + if($this->prop_shippingtypeid !== null){ + $ship=WTshipping::getFromDB($this->prop_shippingtypeid); + if(!is_a($ship,"WTshipping")){ + $this->prop_shippingtypeid=null; + return false; + } + } + return true; + } + + /**helper for helper verifyTickets: gets statistics about sold tickets*/ + private function eventTicketStatistics($evid,$cap) + { + global $db; + $ret=array("all"=>$cap); + $epcs=WTeventprice::selectFromDB("eventid=".$db->escapeInt($evid)); + foreach($epcs as $pc){ + $ret[$pc->pricecategoryid]=$pc->maxavailable; + } + $ticks=WTticket::selectFromDB("eventid=".$db->escapeInt($evid)); + foreach($ticks as $t){ + if(($t & WTticket::MaskBlock)==0)continue; + $ret["all"]--; + if($t->pricecategoryid !== null) + $ret[$t->pricecategoryid]--; + } + return $ret; + } + + /**helper function for createOrder: verifies customer settings*/ + private function verifyTickets($trans,$salestop) + { + $ret=true; + $evseats=array(); + $now=time(); + if($salestop>0)$now+=$salestop*3600; + foreach($this->prop_tickets as &$tick){ + //assume ok + $tick->set_status(WOCartTicket::Ok); + //check event exists + $evid=$tick->get_eventid(); + $ev=WTevent::getFromDB($evid); + if(!is_a($ev,"WTevent")){ + $tick->set_status(WOCartTicket::Invalid); + $ret=false; + continue; + } + if(!array_key_exists($evid,$evseats)) + $evseats[$evid]=$this->eventTicketStatistics($evid,$ev->capacity); + //verify price category + $pcid=$tick->get_pricecategoryid(); + if(!array_key_exists($pcid,$evseats[$evid])){ + $tick->set_status(WOCartTicket::Invalid); + $ret=false; + continue; + } + //check enough seats for event + if($tick->get_amount() > $evseats[$evid]["all"]){ + $tick->set_status(WOCartTicket::Exhausted); + $tick->set_amount($evseats[$evid]["all"]); + $ret=false; + } + $evseats[$evid]["all"]-=$tick->get_amount(); + //check enough seats for category + if($tick->get_amount() > $evseats[$evid][$pcid]){ + $tick->set_status(WOCartTicket::Exhausted); + $tick->set_amount($evseats[$evid][$pcid]); + $ret=false; + } + $evseats[$evid][$pcid]-=$tick->get_amount(); + //check sale time + if($salestop==self::AfterSale)continue; + if($salestop==self::LateSale){ + if($now>$ev->endtime){ + $tick->set_status(WOCartTicket::TooLate); + $ret=false; + } + }else{ + if($now>$ev->starttime){ + $tick->set_status(WOCartTicket::TooLate); + $ret=false; + } + } + } + return $ret; + } + + /**helper function for createOrder: verifies customer settings*/ + private function verifyVouchers($trans,$vanyval,$vdiffprice) + { + //TODO: implement + return true; + } + + /**helper function for createOrder: verifies customer settings*/ + private function verifyItems($trans) + { + //TODO: implement items + return true; + } + + /**helper function for createOrder: creates the order on the database*/ + private function createOrderOnDB($trans) + { + //create order + $ord=WTorder::newRow(); + //create tickets + //create vouchers + //create items + //update address use + //return created order + return WOOrder::fromTableorder($ord); + } +}; + +?> \ No newline at end of file diff --git a/www/inc/wext/order.php b/www/inc/wext/order.php index 123fb37..3c77a78 100644 --- a/www/inc/wext/order.php +++ b/www/inc/wext/order.php @@ -118,6 +118,9 @@ class WOOrderInfo extends WOOrderInfoAbstract } }; + + +/**full order class*/ class WOOrder extends WOOrderAbstract { /**analyses itself and returns price*/ -- 1.7.2.5