From e22aac44426ce9648a6b915a1d8f374122d113dd Mon Sep 17 00:00:00 2001 From: konrad Date: Mon, 27 Dec 2010 22:41:58 +0000 Subject: [PATCH] order audit working git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@686 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- Makefile.unix | 1 + src/dialogs/dialogfiles.qrc | 8 ++ src/dialogs/dialogs.pri | 5 +- src/dialogs/orderauditdlg.cpp | 220 ++++++++++++++++++++++++++++++++++++++++- src/dialogs/orderauditdlg.h | 10 ++- src/dialogs/orderauditdlg.xml | 26 +++++ src/dialogs/orderauditdlg_p.h | 222 +++++++++++++++++++++++++++++++++++++++++ src/misc/formula.cpp | 57 +++++++++++ src/wext/order.h | 19 ++++ src/wext/orderinfo.h | 5 + src/wext/ticket.h | 5 + src/wext/voucher.h | 3 + 12 files changed, 576 insertions(+), 5 deletions(-) create mode 100644 src/dialogs/dialogfiles.qrc create mode 100644 src/dialogs/orderauditdlg.xml create mode 100644 src/dialogs/orderauditdlg_p.h diff --git a/Makefile.unix b/Makefile.unix index 8bc78e6..c5b918f 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -75,6 +75,7 @@ sdoc: cd pack/phpbase ; $(DOXYGEN) cd pack/qtbase ; $(DOXYGEN) cd tzone ; $(DOXYGEN) Doxyfile + cd elam/src ; $(DOXYGEN) Doxyfile install: install-client install-server install-doc diff --git a/src/dialogs/dialogfiles.qrc b/src/dialogs/dialogfiles.qrc new file mode 100644 index 0000000..7462539 --- /dev/null +++ b/src/dialogs/dialogfiles.qrc @@ -0,0 +1,8 @@ + + + + + orderauditdlg.xml + + diff --git a/src/dialogs/dialogs.pri b/src/dialogs/dialogs.pri index 1b40913..944c269 100644 --- a/src/dialogs/dialogs.pri +++ b/src/dialogs/dialogs.pri @@ -12,7 +12,8 @@ HEADERS += \ dialogs/aclwin.h \ dialogs/flagedit.h \ dialogs/wizard.h \ - dialogs/orderauditdlg.h + dialogs/orderauditdlg.h \ + dialogs/orderauditdlg_p.h SOURCES += \ dialogs/configdialog.cpp \ @@ -30,4 +31,6 @@ SOURCES += \ dialogs/wizard.cpp \ dialogs/orderauditdlg.cpp +RESOURCES += dialogs/dialogfiles.qrc + INCLUDEPATH += ./dialogs \ No newline at end of file diff --git a/src/dialogs/orderauditdlg.cpp b/src/dialogs/orderauditdlg.cpp index a055453..a8465a5 100644 --- a/src/dialogs/orderauditdlg.cpp +++ b/src/dialogs/orderauditdlg.cpp @@ -10,10 +10,226 @@ // // -#include "orderauditdlg.h" +#include "orderauditdlg_p.h" -MOrderAuditDialog::MOrderAuditDialog(const MTGetOrderAudit& audit, QWidget* parent) +#include "formula.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class MOAAuditList:public QList +{ + public: + void addOrders(const QList&o) + {for(int i=0;i&o) + {for(int i=0;i&o) + {for(int i=0;ihasValue(c); + return mcontext->hasValue(c); + } + return false; + } + QVariant getConstant(QString c)const{ +// qDebug()<<"getting const"<hasValue(c)) + return mcontext->getValue(c); + } + return MElamEngine::getConstant(c); + } +}; + +class DPTR_CLASS_NAME(MOrderAuditDialog) +{ +protected: + friend class MOrderAuditDialog; + QTreeView*mdata; + QStandardItemModel*mmodel; + QComboBox*mprofile; + QDomDocument mprofiledoc; + MOAAuditList maudit; + MOAFormula formula; +}; +DEFINE_DPTR(MOrderAuditDialog); + +MOrderAuditDialog::MOrderAuditDialog(MTGetOrderAudit& audit, QWidget* parent) : QDialog(parent) { + //init + QListorders=audit.getorder(); + setWindowTitle(tr("Order Audit [%1]").arg(orders.value(0).orderid())); + setSizeGripEnabled(true); + d->formula.setParent(this); + //init list + d->maudit.addOrders(orders); + d->maudit.addTickets(audit.gettickets()); + d->maudit.addVouchers(audit.getvouchers()); + qSort(d->maudit); + qDebug()<<"# audit items:"<maudit.size(); + //accumulate prices + calcPrices(); + //get profiles + getProfiles(); + //display + QVBoxLayout*vl; + setLayout(vl=new QVBoxLayout); + vl->addWidget(d->mprofile=new QComboBox,0); + QDomNodeList nl=d->mprofiledoc.elementsByTagName("Report"); + for(int i=0;improfile->addItem(el.attribute("name"),i); + } + vl->addWidget(d->mdata=new QTreeView,1); + d->mdata->setModel(d->mmodel=new QStandardItemModel); + d->mdata->setEditTriggers(QAbstractItemView::NoEditTriggers); + drawdata(); +} + +MOrderAuditDialog::~MOrderAuditDialog() +{ +} + +void MOrderAuditDialog::drawdata() +{ + //clear + d->mmodel->clear(); + //get profile + QDomNodeList nl=d->mprofiledoc.elementsByTagName("Report"); + if(nl.size()<1)return; + int pid=d->mprofile->itemData(d->mprofile->currentIndex()).toInt(); + if(pid<0||pid>=nl.size())return; + QDomElement profile=nl.at(pid).toElement(); + //set size + d->mmodel->insertRows(0,d->maudit.size()); + int numcols=profile.attribute("columns").toInt(); + d->mmodel->insertColumns(0,numcols); + //set header + nl=profile.elementsByTagName("Header"); + for(int i=0;immodel->setHeaderData(el.attribute("col").toInt(),Qt::Horizontal,el.text()); + } + //get profile formulae + QDomNodeList suml=profile.elementsByTagName("Summary"); + QDomNodeList ordl=profile.elementsByTagName("Order"); + QDomNodeList tckl=profile.elementsByTagName("Ticket"); + QDomNodeList voul=profile.elementsByTagName("Voucher"); + //set data + for(int i=0;imaudit.size();i++){ + MOAParcel pc=d->maudit.value(i); + d->formula.setContext(&pc); + for(int k=0;kmmodel->index(i,sum.attribute("col").toInt()); + QVariant v=d->formula.evaluate(sum.text()); + if(v.userType()==ELAM::Exception::metaTypeId()) + qDebug()<<"Exception in summary formula. Formula:"<(); + d->mmodel->setData(idx,v); + } + QModelIndex pidx=d->mmodel->index(i,0); + d->mmodel->insertRows(0,pc.size(),pidx); + d->mmodel->insertColumns(0,numcols,pidx); + for(int j=0;jformula.setContext(&itm); + switch(itm.itemType()){ + case MOAItem::Order:nl=ordl;break; + case MOAItem::Ticket:nl=tckl;break; + case MOAItem::Voucher:nl=voul;break; + default:continue; + } + for(int k=0;kmmodel->index(j,el.attribute("col").toInt(),pidx); + QVariant v=d->formula.evaluate(el.text()); + if(v.userType()==ELAM::Exception::metaTypeId()) + qDebug()<<"Exception in formula. Formula:"<(); + d->mmodel->setData(idx,v); + } + } + d->formula.setContext(0); + } + for(int i=0;immodel->columnCount();i++) + d->mdata->resizeColumnToContents(i); +} +void MOrderAuditDialog::calcPrices() +{ + QMapprclist; + for(int i=0;imaudit.size();i++){ + //accumulate items + for(int j=0;jmaudit[i].size();j++){ + MOAItem itm=d->maudit[i][j]; + QString id=itm.itemTypeString()+itm.itemID(); + switch(itm.itemType()){ + case MOAItem::Order: + prclist.insert(id,itm.order().shippingcosts()); + break; + case MOAItem::Voucher: + prclist.insert(id,itm.voucher().price()); + break; + case MOAItem::Ticket: + prclist.insert(id,itm.ticket().amountToPay()); + break; + default:break; + } + } + //calculate current price + qint64 prc=0; + QStringList k=prclist.keys(); + for(int j=0;jmaudit[i].setPrice(prc); + } +} + +void MOrderAuditDialog::getProfiles() +{ + QFile fd(dataDir+"/orderaudit.xml"); + if(fd.exists() && fd.open(QIODevice::ReadOnly)){ + qDebug()<<"loading main config"<mprofiledoc.setContent(&fd)) + return; + } + fd.setFileName(":/orderaudit.xml"); + if(fd.exists() && fd.open(QIODevice::ReadOnly)){ + d->mprofiledoc.setContent(&fd); + qDebug()<<"loading backup config"; + } } diff --git a/src/dialogs/orderauditdlg.h b/src/dialogs/orderauditdlg.h index 1e4a6d1..3af456e 100644 --- a/src/dialogs/orderauditdlg.h +++ b/src/dialogs/orderauditdlg.h @@ -14,14 +14,20 @@ #define MAGICSMOKE_ORDERAUDITDLG_H #include +#include class MTGetOrderAudit; - class MOrderAuditDialog:public QDialog { Q_OBJECT + DECLARE_DPTR(d); public: - MOrderAuditDialog(const MTGetOrderAudit&audit,QWidget*parent=0); + MOrderAuditDialog(MTGetOrderAudit&audit,QWidget*parent=0); + virtual ~MOrderAuditDialog(); + private slots: + void getProfiles(); + void calcPrices(); + void drawdata(); }; #endif diff --git a/src/dialogs/orderauditdlg.xml b/src/dialogs/orderauditdlg.xml new file mode 100644 index 0000000..46be292 --- /dev/null +++ b/src/dialogs/orderauditdlg.xml @@ -0,0 +1,26 @@ + + +
Date, Time ID
+
User Name Item Type
+
Transaction Type Item Data
+
Total Price Item Price
+
Amount Paid Info
+ unix2datetime(auditTime) + auditUser + auditTransaction + toMoney(totalPrice)+" (total)" + itemID + itemTypeString + "Payment: "+paytype+"; "+paydata + toMoney(shippingcosts)+" (shipping)" + toMoney(amountpaid) + itemID + itemTypeString + toMoney(amountToPay) + itemID + itemTypeString + "current value: "+toMoney(value) + toMoney(price) + comment +
+
\ No newline at end of file diff --git a/src/dialogs/orderauditdlg_p.h b/src/dialogs/orderauditdlg_p.h new file mode 100644 index 0000000..1f3c441 --- /dev/null +++ b/src/dialogs/orderauditdlg_p.h @@ -0,0 +1,222 @@ +// +// C++ Interface: orderaudit dialog +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2010-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_ORDERAUDITDLG_P_H +#define MAGICSMOKE_ORDERAUDITDLG_P_H + +#include "orderauditdlg.h" + +#include +#include +#include + +static bool hasMetaValue(QObject*obj,QString n) +{ + const QMetaObject*mobj=obj->metaObject(); + //look for property + int id=mobj->indexOfProperty(n.toAscii().data()); + if(id>=0)return true; + //look for method + id=mobj->indexOfMethod(n.toAscii().data()); + if(id<0)return false; + QMetaMethod mm=mobj->method(id); + if(mm.parameterNames().size()!=0)return false; + if(QString(mm.typeName()).isEmpty())return false; + return true; +} + +static QVariant getMetaValue(QObject*obj,QString n) +{ + const QMetaObject*mobj=obj->metaObject(); + //look for property + int id=mobj->indexOfProperty(n.toAscii().data()); + if(id>=0)return mobj->property(id).read(obj); + //look for method + id=mobj->indexOfMethod(n.toAscii().data()); + if(id<0)return QVariant(); + QMetaMethod mm=mobj->method(id); + if(mm.parameterNames().size()!=0)return QVariant(); + if(QString(mm.typeName()).isEmpty())return QVariant(); + //try to invoke + int dataid=QMetaType::type(mm.typeName()); + void *data=QMetaType::construct(dataid); + QVariant ret; + if(mm.invoke(obj, Qt::DirectConnection, QGenericReturnArgument(mm.typeName(),data))) + ret=QVariant(dataid,data); + QMetaType::destroy(dataid,data); + return ret; +} + +class MOADynamicObject:public QObject +{ + public: + virtual bool hasValue(QString n){return hasMetaValue(this,n);} + virtual QVariant getValue(QString n){return getMetaValue(this,n);} +}; + +class MOAItem:public MOADynamicObject +{ + Q_OBJECT + Q_PROPERTY(qint64 auditTime READ auditTime) + Q_PROPERTY(QString auditUser READ auditUser) + Q_PROPERTY(QString auditTransaction READ auditTransaction) + Q_PROPERTY(QString itemID READ itemID) + Q_PROPERTY(QString itemTypeString READ itemTypeString) + public: + enum ItemType{None,Order,Ticket,Voucher}; + ItemType itemType()const{return mtype;} + + MOAItem(){mtype=None;} + MOAItem(const MOOrderAudit&a){morder=a;mtype=Order;} + MOAItem(const MOTicketAudit&a){mticket=a;mtype=Ticket;} + MOAItem(const MOVoucherAudit&a){mvoucher=a;mtype=Voucher;} + MOAItem(const MOAItem&i){operator=(i);} + MOAItem&operator=(const MOAItem&i) + { + mtype=i.mtype; + morder=i.morder;mticket=i.mticket;mvoucher=i.mvoucher; + return *this; + } + + virtual bool hasValue(QString n){ + if(hasMetaValue(this,n))return true; + switch(mtype){ + case Order:return hasMetaValue(&morder,n); + case Ticket:return hasMetaValue(&mticket,n); + case Voucher:return hasMetaValue(&mvoucher,n); + default: return false; + } + } + virtual QVariant getValue(QString n){ + if(hasMetaValue(this,n))return getMetaValue(this,n); + switch(mtype){ + case Order:return getMetaValue(&morder,n); + case Ticket:return getMetaValue(&mticket,n); + case Voucher:return getMetaValue(&mvoucher,n); + default: return false; + } + } + public slots: + MOOrderAudit order()const{return morder;} + MOTicketAudit ticket()const{return mticket;} + MOVoucherAudit voucher()const{return mvoucher;} + + qint64 auditTime()const{switch(mtype){ + case Order:return (qint64)morder.audittime(); + case Ticket:return (qint64)mticket.audittime(); + case Voucher:return (qint64)mvoucher.audittime(); + default: return 0; + }} + QString auditUser()const{switch(mtype){ + case Order:return morder.audituname(); + case Ticket:return mticket.audituname(); + case Voucher:return mvoucher.audituname(); + default: return QString(); + }} + QString auditTransaction()const{switch(mtype){ + case Order:return morder.audittransaction(); + case Ticket:return mticket.audittransaction(); + case Voucher:return mvoucher.audittransaction(); + default: return QString(); + }} + + bool isSameTransaction(const MOAItem&i)const{ + if(mtype==None || i.mtype==None)return false; + return auditTime() == i.auditTime() && + auditUser() == i.auditUser() && + auditTransaction() == i.auditTransaction(); + } + + QString itemID()const{switch(mtype){ + case Order:return QString::number(morder.orderid()); + case Ticket:return mticket.ticketid(); + case Voucher:return mvoucher.voucherid(); + default:return QString(); + }} + + QString itemTypeString()const{switch(mtype){ + case Order:return QCoreApplication::translate("MOAItem","Order"); + case Ticket:return QCoreApplication::translate("MOAItem","Ticket"); + case Voucher:return QCoreApplication::translate("MOAItem","Voucher"); + default:return QString(); + }} + + private: + ItemType mtype; + MOOrderAudit morder; + MOTicketAudit mticket; + MOVoucherAudit mvoucher; +}; + +class MOAParcel:public MOADynamicObject +{ + Q_OBJECT + Q_PROPERTY(qint64 auditTime READ auditTime) + Q_PROPERTY(QString auditUser READ auditUser) + Q_PROPERTY(QString auditTransaction READ auditTransaction) + Q_PROPERTY(qint64 size READ size) + Q_PROPERTY(qint64 totalPrice READ totalPrice) + public: + MOAParcel(){mprice=0;} + MOAParcel(const MOAParcel&p){mitems=p.mitems;mprice=p.mprice;} + MOAParcel(const MOAItem&i){mitems<0)return mitems[0].auditTime(); + else return 0; + } + QString auditUser()const{ + if(mitems.size()>0)return mitems[0].auditUser(); + else return QString(); + } + QString auditTransaction()const{ + if(mitems.size()>0)return mitems[0].auditTransaction(); + else return QString(); + } + + bool isSameTransaction(const MOAItem&i)const{ + if(mitems.size()!=0) + return mitems[0].isSameTransaction(i); + else + return true; + } + bool addItem(const MOAItem&i){ + if(isSameTransaction(i)){ + mitems<mitems; + qint64 mprice; +}; + +#endif diff --git a/src/misc/formula.cpp b/src/misc/formula.cpp index 92bcaf5..188aefe 100644 --- a/src/misc/formula.cpp +++ b/src/misc/formula.cpp @@ -14,6 +14,7 @@ #include "misc.h" #include +#include using namespace ELAM; @@ -62,6 +63,51 @@ static QVariant unix2DateFunc(const QList&args,Engine&){return unix2DT static QVariant unix2TimeFunc(const QList&args,Engine&){return unix2DTFunc(args,1);} static QVariant unix2DateTimeFunc(const QList&args,Engine&){return unix2DTFunc(args,2);} +static QVariant nullintCast(const QVariant&orig,const Engine&) +{ + if(orig.userType()==qMetaTypeId >()){ + Nullable ni=orig.value >(); + if(ni.isNull())return QVariant(); + else return (qlonglong)ni.value(); + } + if(orig.userType()==qMetaTypeId >()){ + Nullable ni=orig.value >(); + if(ni.isNull())return QVariant(); + else return (qlonglong)ni.value(); + } + if(orig.userType()==qMetaTypeId >()){ + Nullable ni=orig.value >(); + if(ni.isNull())return QVariant(); + else return (qlonglong)ni.value(); + } + if(orig.userType()==qMetaTypeId >()){ + Nullable ni=orig.value >(); + if(ni.isNull())return QVariant(); + else return (qlonglong)ni.value(); + } + return orig; +} + +static QVariant nullstrCast(const QVariant&orig,const Engine&) +{ + if(orig.userType()==qMetaTypeId >()){ + Nullable ni=orig.value >(); + if(ni.isNull())return QVariant(); + else return ni.value(); + } + return orig; +} + +static QVariant nullboolCast(const QVariant&orig,const Engine&) +{ + if(orig.userType()==qMetaTypeId >()){ + Nullable ni=orig.value >(); + if(ni.isNull())return QVariant(); + else return ni.value(); + } + return orig; +} + MElamEngine::MElamEngine(QObject* parent): Engine(parent) { //configure character classes @@ -88,4 +134,15 @@ MElamEngine::MElamEngine(QObject* parent): Engine(parent) setFunction("unix2date",unix2DateFunc); setFunction("unix2time",unix2TimeFunc); setFunction("unix2datetime",unix2DateTimeFunc); + //register casts for nullable + setAutoCast(qMetaTypeId(), + QList() + < >() + < >() + < >() + < >(), + nullintCast + ); + setAutoCast(qMetaTypeId(),QList()< >(), nullstrCast); + setAutoCast(qMetaTypeId(),QList()< >(), nullboolCast); } diff --git a/src/wext/order.h b/src/wext/order.h index 2410d08..d00f36f 100644 --- a/src/wext/order.h +++ b/src/wext/order.h @@ -24,6 +24,25 @@ class MOOrder:public MOOrderAbstract Q_OBJECT WOBJECT(MOOrder) WOSCRIPT(MOOrder) + Q_PROPERTY(bool isValid READ isValid) + Q_PROPERTY(bool isReservation READ isReservation) + Q_PROPERTY(bool isSent READ isSent) + Q_PROPERTY(QString orderStatusString READ orderStatusString) + Q_PROPERTY(QString totalPriceString READ totalPriceString) + Q_PROPERTY(bool needsPayment READ needsPayment) + Q_PROPERTY(bool needsRefund READ needsRefund) + Q_PROPERTY(int amountToPay READ amountToPay) + Q_PROPERTY(QString amountToPayStr READ amountToPayStr) + Q_PROPERTY(int amountToRefund READ amountToRefund) + Q_PROPERTY(QString amountToRefundStr READ amountToRefundStr) + Q_PROPERTY(QString orderDateTimeStr READ orderDateTimeStr) + Q_PROPERTY(TimeStamp oderDateTime READ orderDateTime) + Q_PROPERTY(TimeStamp sentDateTime READ sentDateTime) + Q_PROPERTY(QString sentDateTimeStr READ sentDateTimeStr) + Q_PROPERTY(QString orderDateStr READ orderDateStr) + Q_PROPERTY(QString sentDateStr READ sentDateStr) + Q_PROPERTY(QString fullInvoiceAddress READ fullInvoiceAddress) + Q_PROPERTY(QString fullDeliveryAddress READ fullDeliveryAddress) public: /**create order by id, retrieves it automatically from the database*/ MOOrder(qint64); diff --git a/src/wext/orderinfo.h b/src/wext/orderinfo.h index 7046d21..deaa67a 100644 --- a/src/wext/orderinfo.h +++ b/src/wext/orderinfo.h @@ -21,6 +21,11 @@ class MOOrderInfo:public MOOrderInfoAbstract Q_OBJECT WOBJECT(MOOrderInfo) WOSCRIPT(MOOrderInfo) + Q_PROPERTY(bool isReservation READ isReservation) + Q_PROPERTY(bool isSent READ isSent) + Q_PROPERTY(bool isCancelled READ isCancelled) + Q_PROPERTY(bool needsPayment READ needsPayment) + Q_PROPERTY(bool needsRefund READ needsRefund) public: QString totalPriceString()const{return cent2str(totalprice());} QString amountPaidString()const{return cent2str(amountpaid());} diff --git a/src/wext/ticket.h b/src/wext/ticket.h index 9188232..7591786 100644 --- a/src/wext/ticket.h +++ b/src/wext/ticket.h @@ -22,6 +22,11 @@ class MOTicket:public MOTicketAbstract Q_OBJECT WOBJECT(MOTicket) WOSCRIPT(MOTicket) + Q_PROPERTY(int amountToPay READ amountToPay) + Q_PROPERTY(QString priceString READ priceString) + Q_PROPERTY(QString statusString READ statusString) + Q_PROPERTY(QString priceCategoryName READ priceCategoryName) + Q_PROPERTY(QString priceCategoryShort READ priceCategoryShort) public: /**returns the amount to be paid for this ticket; this may be 0 even if there is a price attached*/ int amountToPay()const{if(status()&MaskPay)return price();else return 0;} diff --git a/src/wext/voucher.h b/src/wext/voucher.h index eceacd4..70f6a9d 100644 --- a/src/wext/voucher.h +++ b/src/wext/voucher.h @@ -21,6 +21,9 @@ class MOVoucher:public MOVoucherAbstract Q_OBJECT WOBJECT(MOVoucher) WOSCRIPT(MOVoucher) + Q_PROPERTY(QString valueString READ valueString) + Q_PROPERTY(QString statusString READ statusString) + Q_PROPERTY(QString priceString READ priceString) public: /**returns whether this is a valid voucher object (ie. it has a voucher ID)*/ bool isValid()const{return !voucherid().isNull();} -- 1.7.2.5