simple report for oder list
authorKonrad Rosenbaum <konrad@silmor.de>
Sat, 31 Aug 2013 09:44:25 +0000 (11:44 +0200)
committerKonrad Rosenbaum <konrad@silmor.de>
Sat, 31 Aug 2013 09:44:25 +0000 (11:44 +0200)
src/mwin/orderstab.cpp
src/mwin/orderstab.h
src/mwin/overview.cpp
src/wext/orderinfo.h

index 04090b2..9e7113d 100644 (file)
@@ -39,6 +39,7 @@
 #include <QFormLayout>
 #include <QInputDialog>
 #include <QLabel>
+#include <QMenu>
 #include <QMessageBox>
 #include <QPushButton>
 #include <QSettings>
@@ -77,6 +78,7 @@ MOrdersTab::MOrdersTab(QString pk)
        vl->addWidget(ordertable=new QTableView);
        ordertable->setModel(ordermodel=new QStandardItemModel(this));
        ordertable->setSelectionMode(QAbstractItemView::SingleSelection);
+        ordertable->setSelectionBehavior(QAbstractItemView::SelectRows);
        ordertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
        connect(ordertable,SIGNAL(doubleClicked(const QModelIndex&)),this,SLOT(orderDetails()));
        hl->addLayout(vl=new QVBoxLayout,0);
@@ -117,6 +119,36 @@ MOrdersTab::MOrdersTab(QString pk)
        }
 }
 
+QList< QMenu* > MOrdersTab::menu()
+{
+        //menu
+        QList<QMenu*>ret;
+        QMenu*m=new QMenu(tr("&Order List"));
+        ret<<m;
+        m->addAction(tr("Update Order &List"),this,SLOT(updateOrders()));
+        m->addSeparator();
+        m->addAction(tr("Order &Details..."),this,SLOT(orderDetails()))
+         ->setEnabled(req->hasRight(req->RGetOrder));
+        m->addSeparator();
+        m->addAction(tr("Orders &since..."),this,SLOT(orderSinceDate()))
+         ->setEnabled(req->hasRight(req->RGetOrderList));
+        m->addSeparator();
+        m->addAction(tr("Find by &Ticket..."),this,SLOT(orderByTicket()))
+         ->setEnabled(req->hasRight(req->RGetOrderByBarcode));
+        m->addAction(tr("Find by &Event..."),this,SLOT(orderByEvent()))
+         ->setEnabled(req->hasRight(req->RGetOrdersByEvents));
+        m->addAction(tr("Find by &Customer..."),this,SLOT(orderByCustomer()))
+         ->setEnabled(req->hasRight(req->RGetOrdersByCustomer));
+        m->addAction(tr("Find by &User..."),this,SLOT(orderByUser()))
+         ->setEnabled(req->hasRight(req->RGetOrdersByUser) || req->hasRight(req->RGetMyOrders));
+        m->addAction(tr("Find by &Order ID..."),this,SLOT(orderByOrder()))
+         ->setEnabled(req->hasRight(req->RGetOrder));
+        m->addSeparator();
+        m->addAction(tr("Generate &Report..."),this,SLOT(genReport()));
+        //return menu
+        return ret;
+}
+
 qint64 MOrdersTab::oldestOrderStamp(OrderTimeStampMode mode,int age)
 {
        if(age<0){//age not given, get configuration
@@ -150,7 +182,7 @@ static inline bool candoUpdateOrders(int omode,const MOOrderInfo&ord)
        //do not show cancelled ones per default
        if(ord.isCancelled())return false;
        //select by mask: not yet sent and reserved...
-       if((omode&ORDERUNSENT)!=0 && !ord.isSent())return true;
+       if((omode&ORDERUNSENT)!=0 && !ord.isSent() && !ord.isReservation())return true;
        if((omode&ORDERRESERVE)!=0 && ord.isReservation())return true;
        //no match: ignore the entry
        return false;
@@ -160,10 +192,12 @@ void MOrdersTab::resetModel()
 {
        ordermodel->clear();
        ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+        m_orders.clear();
 }
 
 void MOrdersTab::addOrderToModel(const MOOrderInfo&ord,const QList<MOCustomerInfo>&cust)
 {
+        m_orders.append(ord);
        int cl=0;
        ordermodel->insertRow(cl);
        ordermodel->setHeaderData(cl,Qt::Vertical,ord.orderid().value());
@@ -391,6 +425,11 @@ void MOrdersTab::orderByUser()
        ordermode->setCurrentIndex(ordermode->count()-1);
 }
 
+void MOrdersTab::genReport()
+{
+        MOrdersReport(m_orders,this).exec();
+}
+
 MOrdersByUserDlg::MOrdersByUserDlg(int olddef,QWidget* parent, Qt::WindowFlags f): QDialog(parent, f)
 {
        setWindowTitle(tr("Select User Criteria"));
@@ -417,7 +456,9 @@ MOrdersByUserDlg::MOrdersByUserDlg(int olddef,QWidget* parent, Qt::WindowFlags f
        fl->addRow(tr("Maximum Age (days):"),m_days=new QSpinBox);
        m_days->setRange(0,9999);
        m_days->setValue(olddef);
-       fl->addRow(tr("Limit:"),m_incall=new QCheckBox(tr("Include all orders the user touched")));
+       fl->addRow(tr("Limit:"),m_incall=new QComboBox);
+        m_incall->addItem(tr("Orders that the user created"),false);
+        m_incall->addItem(tr("Include all orders the user touched"),true);
        //init and preselect
        if(req->hasRight(req->RGetOrdersByUser)){
                //try to get all user names
@@ -443,7 +484,7 @@ MOrdersByUserDlg::MOrdersByUserDlg(int olddef,QWidget* parent, Qt::WindowFlags f
 
 bool MOrdersByUserDlg::includeAll() const
 {
-       return m_incall->isChecked();
+       return m_incall->itemData(m_incall->currentIndex()).toBool();
 }
 
 bool MOrdersByUserDlg::mySelfOnly() const
@@ -462,3 +503,162 @@ qint64 MOrdersByUserDlg::oldest() const
        if(d<=0)return 0;
        return QDateTime::currentDateTime().toTime_t() - (d*86400);
 }
+
+MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent, Qt::WindowFlags f)
+        : QDialog(parent, f)
+{
+        setSizeGripEnabled(true);
+        setWindowTitle(tr("Order Report"));
+        
+        QVBoxLayout*vl;
+        QHBoxLayout*hl;
+        QTabWidget*tab;
+        setLayout(vl=new QVBoxLayout);
+        
+        vl->addWidget(tab=new QTabWidget,1);
+        QTableView*stable,*otable,*dtable;
+        
+        //tab: sums ( #orders, # tickets, #vouchers, $money, $paid, $for tickets, ...)
+        tab->addTab(stable=new QTableView,tr("Sums"));
+        stable->setModel(sum=new QStandardItemModel);
+        stable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+        stable->setSelectionMode(QAbstractItemView::NoSelection);
+        sum->setHorizontalHeaderLabels(QStringList()
+          <<tr("Category")<<tr("Number Orders")
+          <<tr("Number Tickets")<<tr("Number Vouchers")
+          <<tr("Sum Money")<<tr("Sum Paid")<<tr("Sum Due")
+        );
+        
+        //tab: by order (status, money in, money paid, tickets, vouchers)
+        tab->addTab(otable=new QTableView,tr("By Order"));
+        otable->setModel(byord=new QStandardItemModel);
+        otable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+        otable->setSelectionMode(QAbstractItemView::NoSelection);
+        byord->setHorizontalHeaderLabels(QStringList()
+          <<tr("Order ID")<<tr("Number Tickets")<<tr("Number Vouchers")
+          <<tr("Price")<<tr("Paid")<<tr("Due") );
+
+        //tab: by day
+        tab->addTab(dtable=new QTableView,tr("By Day"));
+        dtable->setModel(byday=new QStandardItemModel);
+        dtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+        dtable->setSelectionMode(QAbstractItemView::NoSelection);
+        byday->setHorizontalHeaderLabels(QStringList()
+          <<tr("Date")
+          <<tr("Number Orders")<<tr("Number Tickets")<<tr("Number Vouchers")
+          <<tr("Price")<<tr("Paid")<<tr("Due") );
+        
+        qDebug()<<"reporting on"<<orders.size()<<"orders";
+        //buttons
+        vl->addSpacing(10);
+        vl->addLayout(hl=new QHBoxLayout);
+        hl->addStretch(1);
+        QPushButton*p;
+        hl->addWidget(p=new QPushButton(tr("Close")));
+        connect(p,SIGNAL(clicked(bool)),this,SLOT(accept()));
+
+        //create display
+        QMap<QDate,QList<MOOrderInfo>>dayorders;
+        qint64 sumtickets=0,sumvouchers=0,summoney=0,sumpaid=0,sumdue=0,
+                sumreserve=0,sumreservemoney=0,sumreservetick=0,sumreservevou=0,sumreservepaid=0,sumreservedue=0,
+                sumcancel=0,sumcancelmoney=0,sumcanceltick=0,sumcancelvou=0,sumcancelpaid=0,sumcanceldue=0,
+                sumsent=0,sumsentmoney=0,sumsenttick=0,sumsentvou=0,sumsentpaid=0,sumsentdue=0,
+                sumplaced=0,sumplacedmoney=0,sumplacedtick=0,sumplacedvou=0,sumplacedpaid=0,sumplaceddue=0;
+        for(const MOOrderInfo&ord:orders){
+                //total sums
+                summoney+=ord.totalprice();
+                sumtickets+=ord.amounttickets();
+                sumvouchers+=ord.amountvouchers();
+                sumpaid+=ord.amountpaid();
+                sumdue+=ord.amountdue();
+                //part sums
+                if(ord.isReservation()){
+                        sumreserve++;sumreservemoney+=ord.totalprice();
+                        sumreservetick+=ord.amounttickets();
+                        sumreservevou+=ord.amountvouchers();
+                        sumreservepaid+=ord.amountpaid();
+                        sumreservedue+=ord.amountdue();
+                }
+                if(ord.isCancelled()){
+                        sumcancel++;sumcancelmoney+=ord.totalprice();
+                        sumcanceltick+=ord.amounttickets();
+                        sumcancelvou+=ord.amountvouchers();
+                        sumcancelpaid+=ord.amountpaid();
+                        sumcanceldue+=ord.amountdue();
+                }
+                if(ord.isSent()){
+                        sumsent++;sumsentmoney+=ord.totalprice();
+                        sumsenttick+=ord.amounttickets();
+                        sumsentvou+=ord.amountvouchers();
+                        sumsentpaid+=ord.amountpaid();
+                        sumsentdue+=ord.amountdue();
+                }
+                if(ord.isPlaced()){
+                        sumplaced++;sumplacedmoney+=ord.totalprice();
+                        sumplacedtick+=ord.amounttickets();
+                        sumplacedvou+=ord.amountvouchers();
+                        sumplacedpaid+=ord.amountpaid();
+                        sumplaceddue+=ord.amountdue();
+                }
+                //order table
+                const int cl=byord->rowCount();
+                byord->insertRow(cl);
+                byord->setData(byord->index(cl,0),ord.orderid().value());
+                byord->setData(byord->index(cl,1),ord.amounttickets().value());
+                byord->setData(byord->index(cl,2),ord.amountvouchers().value());
+                byord->setData(byord->index(cl,3),ord.totalPriceString());
+                byord->setData(byord->index(cl,4),ord.amountPaidString());
+                byord->setData(byord->index(cl,5),ord.amountDueString());
+                //sort by day
+                const QDate date=QDateTime::fromTime_t(ord.ordertime().value()).date();
+                if(!dayorders.contains(date))dayorders.insert(date,QList<MOOrderInfo>());
+                dayorders[date].append(ord);
+        }
+        //fill total sum tab
+        auto sumline=[&](QString title,int num,qint64 tick,qint64 vou,qint64 summ,qint64 paid,qint64 due){
+                const int cl=sum->rowCount();
+                sum->insertRow(cl);
+                sum->setData(sum->index(cl,0),title);
+                sum->setData(sum->index(cl,1),num);
+                sum->setData(sum->index(cl,2),tick);
+                sum->setData(sum->index(cl,3),vou);
+                sum->setData(sum->index(cl,4),cent2str(summ));
+                sum->setData(sum->index(cl,5),cent2str(paid));
+                sum->setData(sum->index(cl,6),cent2str(due));
+        };
+        sumline(tr("Total Orders"), orders.size(), sumtickets, sumvouchers, summoney, sumpaid, sumdue);
+        sumline(tr("Reserved Orders"), sumreserve, sumreservetick, sumreservevou, sumreservemoney, sumreservepaid, sumreservedue);
+        sumline(tr("Cancelled"), sumcancel, sumcanceltick, sumcancelvou, sumcancelmoney, sumcancelpaid, sumcanceldue);
+        sumline(tr("Placed"), sumplaced, sumplacedtick, sumplacedvou, sumplacedmoney, sumplacedpaid, sumplaceddue);
+        sumline(tr("Sent"), sumsent, sumsenttick, sumsentvou, sumsentmoney, sumsentpaid, sumsentdue);
+        //fill date tab
+        for(const QDate&date:dayorders.keys()){
+                const int cl=byday->rowCount();
+                byday->insertRow(cl);
+                byday->setData(byday->index(cl,0),date.toString());
+                const QList<MOOrderInfo>&day=dayorders[date];
+                byday->setData(byday->index(cl,1),day.size());
+                qint64 ticks=0,vous=0,money=0,paid=0,due=0;
+                for(const MOOrderInfo&ord:day){
+                        ticks+=ord.amounttickets();
+                        vous+=ord.amountvouchers();
+                        money+=ord.totalprice();
+                        paid+=ord.amountpaid();
+                        due+=ord.amountdue();
+                }
+                byday->setData(byday->index(cl,2),ticks);
+                byday->setData(byday->index(cl,3),vous);
+                byday->setData(byday->index(cl,4),cent2str(money));
+                byday->setData(byday->index(cl,5),cent2str(paid));
+                byday->setData(byday->index(cl,6),cent2str(due));
+        }
+        //adjust
+        stable->resizeColumnsToContents();
+        dtable->resizeColumnsToContents();
+        otable->resizeColumnsToContents();
+}
+
+void MOrdersReport::saveAs()
+{
+        //TODO: use template if available
+}
index 9615d95..0e5142a 100644 (file)
 
 #include <QDialog>
 
+#include <MOOrder>
+#include <MOOrderInfo>
+
 class QAction;
 class QCheckBox;
 class QComboBox;
 class QLabel;
 class QLineEdit;
+class QMenu;
 class QPushButton;
 class QSpinBox;
 class QStandardItemModel;
@@ -38,6 +42,9 @@ class MOrdersTab:public QWidget
                /**construct the window with QSettings-key for current profile*/
                MOrdersTab(QString);
                
+                /**create menu for this tab*/
+                QList<QMenu*>menu();
+                
        private slots:
                /**get all orders, update list*/
                void updateOrders();
@@ -56,6 +63,9 @@ class MOrdersTab:public QWidget
                void orderSinceDate();
                ///find and display orders by user who created it
                void orderByUser();
+                
+                ///generate the report
+                void genReport();
                
        signals:
                /**needs to be connected to the event tab*/
@@ -84,6 +94,7 @@ class MOrdersTab:public QWidget
                QTableView*ordertable;
                QStandardItemModel*ordermodel;
                QComboBox*ordermode;
+                QList<MOOrderInfo>m_orders;
 };
 
 class MOrdersByUserDlg:public QDialog
@@ -98,9 +109,21 @@ class MOrdersByUserDlg:public QDialog
                qint64 oldest()const;
                
        private:
-               QComboBox*m_uname;
-               QCheckBox*m_myself,*m_incall;
+               QComboBox*m_uname,*m_incall;
+               QCheckBox*m_myself;
                QSpinBox*m_days;
 };
 
+class MOrdersReport:public QDialog
+{
+        Q_OBJECT
+        public:
+                explicit MOrdersReport(const QList<MOOrderInfo>&orders,QWidget* parent = 0, Qt::WindowFlags f = 0);
+                
+        private slots:
+                void saveAs();
+        private:
+                QStandardItemModel*sum,*byord,*byday;
+};
+
 #endif
index 4652fd2..4ca1eec 100644 (file)
@@ -165,7 +165,8 @@ MOverview::MOverview(QString pk,std::function<void(int,QString)>initUpdate)
        
        //Order List Tab
         if(initUpdate)initUpdate(40,tr("Getting Orders..."));
-       addTab(ordertab=new MOrdersTab(pk),tr("Order List"));
+        ordertab=new MOrdersTab(pk);
+       addTab(ordertab, tr("Order List"), ordertab->menu());
        connect(ordertab,SIGNAL(selectEventIds(QList<int>&)), eventtab,SLOT(selectEventIds(QList<int>&)), Qt::DirectConnection);
        
        //Entrance Control Tab
index 91cf8c3..570d018 100644 (file)
@@ -29,6 +29,7 @@ class MOOrderInfo:public MOOrderInfoAbstract
        public:
                QString totalPriceString()const{return cent2str(totalprice());}
                QString amountPaidString()const{return cent2str(amountpaid());}
+               QString amountDueString()const{return cent2str(amountdue());}
                QString orderStatusString()const{return OrderState2locstr(status());}
                
                bool needsPayment()const{return amountpaid()<totalprice();}
@@ -36,6 +37,7 @@ class MOOrderInfo:public MOOrderInfoAbstract
                bool isSent()const{return status()==Sent;}
                bool isReservation()const{return status()==Reserved;}
                bool isCancelled()const{return status()==Cancelled;}
+               bool isPlaced()const{return status()==Placed;}
 };
 
 Q_DECLARE_METATYPE(MOOrderInfo)