export order report to ODS
authorKonrad Rosenbaum <konrad@silmor.de>
Sat, 31 Aug 2013 13:45:02 +0000 (15:45 +0200)
committerKonrad Rosenbaum <konrad@silmor.de>
Sat, 31 Aug 2013 13:45:02 +0000 (15:45 +0200)
src/mwin/orderstab.cpp
src/mwin/orderstab.h

index 9e7113d..eda2cb6 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <TimeStamp>
 
+#include <Zip>
+
 #include "MTGetOrder"
 #include "MTGetOrderList"
 #include "MTGetMyOrders"
@@ -36,6 +38,8 @@
 #include <QComboBox>
 #include <QDateTimeEdit>
 #include <QDebug>
+#include <QDomDocument>
+#include <QDomElement>
 #include <QFormLayout>
 #include <QInputDialog>
 #include <QLabel>
@@ -46,6 +50,7 @@
 #include <QSpinBox>
 #include <QStandardItemModel>
 #include <QTableView>
+#include <QFileDialog>
 
 #define ORDERNONE      0
 #define ORDERALL       0xff
@@ -504,8 +509,8 @@ qint64 MOrdersByUserDlg::oldest() const
        return QDateTime::currentDateTime().toTime_t() - (d*86400);
 }
 
-MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent, Qt::WindowFlags f)
-        : QDialog(parent, f)
+MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& aorders, QWidget* parent, Qt::WindowFlags f)
+        : QDialog(parent, f), orders(aorders)
 {
         setSizeGripEnabled(true);
         setWindowTitle(tr("Order Report"));
@@ -516,7 +521,6 @@ MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent
         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"));
@@ -535,7 +539,7 @@ MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent
         otable->setEditTriggers(QAbstractItemView::NoEditTriggers);
         otable->setSelectionMode(QAbstractItemView::NoSelection);
         byord->setHorizontalHeaderLabels(QStringList()
-          <<tr("Order ID")<<tr("Number Tickets")<<tr("Number Vouchers")
+          <<tr("Order ID")<<tr("State")<<tr("Number Tickets")<<tr("Number Vouchers")
           <<tr("Price")<<tr("Paid")<<tr("Due") );
 
         //tab: by day
@@ -548,22 +552,100 @@ MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent
           <<tr("Number Orders")<<tr("Number Tickets")<<tr("Number Vouchers")
           <<tr("Price")<<tr("Paid")<<tr("Due") );
         
-        qDebug()<<"reporting on"<<orders.size()<<"orders";
+        //tab: audit
+        if(req->hasRight(req->RGetOrderAudit)){
+                tab->addTab(atable=new QTableView,tr("Financial"));
+                atable->setModel(audit=new QStandardItemModel);
+                atable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+                atable->setSelectionMode(QAbstractItemView::NoSelection);
+                audit->setHorizontalHeaderLabels(QStringList()
+                <<tr("Order ID")<<tr("Action")<<tr("User")<<tr("Date")
+                <<tr("Price")<<tr("Paid")<<tr("Due")<<tr("Moved") );
+                
+        }
+        
         //buttons
         vl->addSpacing(10);
         vl->addLayout(hl=new QHBoxLayout);
         hl->addStretch(1);
         QPushButton*p;
+        hl->addWidget(p=new QPushButton(tr("Save as...")));
+        connect(p,SIGNAL(clicked(bool)),this,SLOT(saveAs()));
+        hl->addSpacing(15);
         hl->addWidget(p=new QPushButton(tr("Close")));
         connect(p,SIGNAL(clicked(bool)),this,SLOT(accept()));
+        p->setDefault(true);
 
         //create display
+        drawAllOrders();
+        drawDayOrders();
+        drawOrderSums();
+        drawAudit();
+}
+
+void MOrdersReport::drawAllOrders()
+{
+        byord->removeRows(0,byord->rowCount());
+        for(const MOOrderInfo&ord:orders){
+                //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.orderStatusString());
+                byord->setData(byord->index(cl,2),ord.amounttickets().value());
+                byord->setData(byord->index(cl,3),ord.amountvouchers().value());
+                byord->setData(byord->index(cl,4),ord.totalPriceString());
+                byord->setData(byord->index(cl,5),ord.amountPaidString());
+                byord->setData(byord->index(cl,6),ord.amountDueString());
+        }
+        //adjust
+        otable->resizeColumnsToContents();
+
+}
+
+void MOrdersReport::drawDayOrders()
+{
         QMap<QDate,QList<MOOrderInfo>>dayorders;
+        byday->removeRows(0,byday->rowCount());
+        //sort by day
+        for(const MOOrderInfo&ord:orders){
+                const QDate date=QDateTime::fromTime_t(ord.ordertime().value()).date();
+                if(!dayorders.contains(date))dayorders.insert(date,QList<MOOrderInfo>());
+                dayorders[date].append(ord);
+        }
+        //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));
+        }
+
+        dtable->resizeColumnsToContents();
+}
+
+void MOrdersReport::drawOrderSums()
+{
         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;
+        sum->removeRows(0,sum->rowCount());
         for(const MOOrderInfo&ord:orders){
                 //total sums
                 summoney+=ord.totalprice();
@@ -600,19 +682,6 @@ MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent
                         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){
@@ -631,34 +700,105 @@ MOrdersReport::MOrdersReport(const QList< MOOrderInfo >& orders, QWidget* parent
         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();
+
+        stable->resizeColumnsToContents();
+}
+
+void MOrdersReport::drawAudit()
+{
+        if(atable==nullptr || audit==nullptr)return;
+}
+
+
+static const QByteArray odsmetainf(
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+        "<manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" manifest:version=\"1.2\">\n"
+        " <manifest:file-entry manifest:full-path=\"/\" manifest:version=\"1.2\" manifest:media-type=\"application/vnd.oasis.opendocument.spreadsheet\"/>\n"
+        " <manifest:file-entry manifest:full-path=\"content.xml\" manifest:media-type=\"text/xml\"/>\n"
+        "</manifest:manifest>"
+);
+
+static inline void exportTable(QDomDocument&doc, QDomElement&sheet, QStandardItemModel*model, QString title)
+{
+        //basics
+        QDomElement table=doc.createElement("table:table"); 
+        table.setAttribute("table:name",title);
+        QDomElement cols=doc.createElement("table:table-column");
+        cols.setAttribute("table:number-columns-repeated",model->columnCount());
+        table.appendChild(cols);
+        //headers
+        QDomElement row=doc.createElement("table:table-row");
+        for(int c=0;c<model->columnCount();c++){
+                QDomElement cell=doc.createElement("table:table-cell");
+                cell.setAttribute("office:value-type","string");
+                QDomElement p=doc.createElement("text:p");
+                p.appendChild(doc.createTextNode(model->headerData(c,Qt::Horizontal).toString()));
+                cell.appendChild(p);
+                row.appendChild(cell);
+        }
+        table.appendChild(row);
+        //data
+        for(int r=0;r<model->rowCount();r++){
+                row=doc.createElement("table:table-row");
+                for(int c=0;c<model->columnCount();c++){
+                        QDomElement cell=doc.createElement("table:table-cell");
+                        cell.setAttribute("office:value-type","string");
+                        QDomElement p=doc.createElement("text:p");
+                        p.appendChild(doc.createTextNode(model->data(model->index(r,c)).toString()));
+                        cell.appendChild(p);
+                        row.appendChild(cell);
                 }
-                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));
+                table.appendChild(row);
         }
-        //adjust
-        stable->resizeColumnsToContents();
-        dtable->resizeColumnsToContents();
-        otable->resizeColumnsToContents();
+        //done
+        sheet.appendChild(table);
 }
 
 void MOrdersReport::saveAs()
 {
+        QFileDialog fdlg(this,tr("Save Report"));
+        fdlg.setAcceptMode(QFileDialog::AcceptSave);
+        fdlg.setDefaultSuffix("ods");
+        fdlg.setFileMode(QFileDialog::AnyFile);
+        fdlg.setDirectory(currentDir());
+        if(!fdlg.exec())return;
+        const QString fn=fdlg.selectedFiles().value(0);
+        if(fn.isEmpty())return;
+        setCurrentDir(fn);
         //TODO: use template if available
+        //create file
+        QFile fd(fn);
+        if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+                QMessageBox::warning(this,tr("Warning"),tr("Unable to create file '%1'.").arg(fn));
+                return;
+        }
+        Zip zip;
+        if(!zip.open(&fd)){
+                QMessageBox::warning(this,tr("Warning"),tr("Ooops. Unable to create ZIP structure in file '%1'.").arg(fn));
+                fd.close();
+                fd.remove();
+                return;
+        }
+        //metadata
+        zip.storeFile("mimetype",QByteArray("application/vnd.oasis.opendocument.spreadsheet"));
+        zip.storeFile("META-INF/manifest.xml",odsmetainf);
+        //generate content
+        QDomDocument doc;
+        QDomElement root=doc.createElement("office:document-content");
+        root.setAttribute("xmlns:office","urn:oasis:names:tc:opendocument:xmlns:office:1.0"); root.setAttribute("xmlns:text","urn:oasis:names:tc:opendocument:xmlns:text:1.0"); root.setAttribute("xmlns:table","urn:oasis:names:tc:opendocument:xmlns:table:1.0");
+        root.setAttribute("office:version","1.2");
+        QDomElement body=doc.createElement("office:body");
+        QDomElement sheet=doc.createElement("office:spreadsheet");
+        exportTable(doc,sheet,sum,tr("Sums"));
+        exportTable(doc,sheet,byord,tr("Orders"));
+        exportTable(doc,sheet,byday,tr("By Day"));
+        if(audit)
+                exportTable(doc,sheet,audit,tr("Financial"));
+        body.appendChild(sheet);
+        root.appendChild(body);
+        doc.appendChild(root);
+        //store
+        zip.storeFile("content.xml",doc.toByteArray());
+        zip.close();
+        fd.close();
 }
index 0e5142a..dbbc213 100644 (file)
@@ -123,7 +123,14 @@ class MOrdersReport:public QDialog
         private slots:
                 void saveAs();
         private:
-                QStandardItemModel*sum,*byord,*byday;
+                QStandardItemModel*sum,*byord,*byday,*audit=nullptr;
+                QTableView*stable,*otable,*dtable,*atable=nullptr;
+                const QList<MOOrderInfo>orders;
+                
+                void drawAllOrders();
+                void drawDayOrders();
+                void drawOrderSums();
+                void drawAudit();
 };
 
 #endif