add customer creation wizard (not fully working yet)
authorKonrad Rosenbaum <konrad@silmor.de>
Tue, 10 Jul 2012 17:39:35 +0000 (19:39 +0200)
committerKonrad Rosenbaum <konrad@silmor.de>
Tue, 10 Jul 2012 17:39:35 +0000 (19:39 +0200)
14 files changed:
pack
src/dialogs/customerdlg.cpp
src/dialogs/customerdlg.h
src/images/cancel.png [new file with mode: 0644]
src/images/done.png [new file with mode: 0644]
src/images/files.qrc
src/images/next.png [new file with mode: 0644]
src/images/prev.png [new file with mode: 0644]
wob/transact/customer.wolf
www/config.php.template
www/inc/machine/session.php
www/inc/wext/customer.php
www/inc/wext/transaction.php
www/machine.php

diff --git a/pack b/pack
index c5c37fa..883f8f6 160000 (submodule)
--- a/pack
+++ b/pack
@@ -1 +1 @@
-Subproject commit c5c37fac1ab6c56d4879d74808a6ae9f44384bda
+Subproject commit 883f8f6d0c8420b2ddae46b2345faa86e90a0230
index 64939c0..74d011c 100644 (file)
 #include "customerdlg.h"
 #include "msinterface.h"
 #include "misc.h"
+#include "lambda.h"
+#include "vlambda.h"
 
-#include "MTGetAllCustomerNames"
-#include "MTGetCustomer"
-#include "MTDeleteCustomer"
 #include "MTChangeCustomer"
 #include "MTChangeCustomerMail"
-#include "MTCreateCustomer"
-#include "MTResetCustomerPassword"
-#include "MTGetAllContactTypes"
 #include "MTCreateContactType"
 #include "MTCreateCountry"
-#include "MTGetAllCountries"
+#include "MTCreateCustomer"
+#include "MTDeleteCustomer"
 #include "MTGetAddress"
+#include "MTGetAllContactTypes"
+#include "MTGetAllCountries"
+#include "MTGetAllCustomerNames"
+#include "MTGetCreateCustomerHints"
+#include "MTGetCustomer"
+#include "MTResetCustomerPassword"
 
 #include <QBoxLayout>
 #include <QCheckBox>
 #include <QComboBox>
+#include <QDebug>
 #include <QApplication>
 #include <QDomElement>
 #include <QFormLayout>
@@ -43,6 +47,7 @@
 #include <QPushButton>
 #include <QSignalMapper>
 #include <QSortFilterProxyModel>
+#include <QStackedLayout>
 #include <QStandardItemModel>
 #include <QTableView>
 #include <QTextEdit>
@@ -153,9 +158,12 @@ MOCustomerInfo MCustomerListDialog::getCustomer()
 
 void MCustomerListDialog::newCustomer()
 {
-       MCustomerDialog cd(MOCustomer(),this);
-       if(cd.exec()==QDialog::Accepted)
-               updateList(cd.getCustomer().id());
+       MOCustomer c=MNewCustomerWizard::getNewCustomer(this);
+       if(c.isValid())
+               updateList(c.id());
+//     MCustomerDialog cd(MOCustomer(),this);
+//     if(cd.exec()==QDialog::Accepted)
+//             updateList(cd.getCustomer().id());
 }
 void MCustomerListDialog::editCustomer()
 {
@@ -439,6 +447,7 @@ void MContactTableDelegate::setEditorData(QWidget *editor, const QModelIndex &in
                }
                if(req->hasRight(req->RCreateContactType))
                        box->addItem(tr("(New Contact Type)"),-1);
+               box->setCurrentIndex(curidx);
        }
        if(c==1){//content
                ((QLineEdit*)editor)->setText(index.model()->data(index).toString());
@@ -732,6 +741,42 @@ MOAddress MAddressDialog::address()
        return m_addr;
 }
 
+//static
+MOCountry MAddressDialog::createNewCountry(QWidget* parent)
+{
+       QDialog d(parent);
+       d.setWindowTitle(tr("Create New Country"));
+       QVBoxLayout*vl;
+       QHBoxLayout*hl;
+       QFormLayout*fl;
+       QLineEdit*name,*abbr;
+       QPushButton*p;
+       d.setLayout(vl=new QVBoxLayout);
+       vl->addLayout(fl=new QFormLayout);
+       fl->addRow(tr("Country Name:"),name=new QLineEdit);
+       fl->addRow(tr("Abbreviation:"),abbr=new QLineEdit);
+       vl->addStretch(10);
+       vl->addLayout(hl=new QHBoxLayout,0);
+       hl->addStretch(10);
+       hl->addWidget(p=new QPushButton(tr("Ok")),0);
+       connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+       hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+       connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+       //wait and check
+       if(d.exec()!=QDialog::Accepted)return MOCountry();
+       if(name->text().trimmed()=="" || abbr->text().trimmed()==""){
+               QMessageBox::warning(parent,tr("Warning"),tr("The country name and abbreviation must contain something!"));
+               return MOCountry();
+       }
+       //create
+       MTCreateCountry cc=MTCreateCountry::query(abbr->text().trimmed(),name->text().trimmed());
+       if(cc.hasError()){
+               QMessageBox::warning(parent,tr("Warning"),tr("Error while creating country: %1").arg(cc.errorString()));
+               return MOCountry();
+       }
+       return cc.getcountry();
+}
+
 void MAddressDialog::selectCountry()
 {
        //get countries
@@ -744,7 +789,7 @@ void MAddressDialog::selectCountry()
                if(cntry[i].name().value() == curstr)cur=i;
        }
        if(req->hasRight(req->RCreateCountry))
-               clst<<tr(" Create New Country...","must contain leading space to distinguish it from genuine countries");
+               clst<<tr(" Create New Country...","this pseudo-entry must contain leading space to distinguish it from genuine countries");
        //display selection
        bool ok;
        QString it=QInputDialog::getItem(this,tr("Select Country"),tr("Please select a country:"),clst,cur,false,&ok);
@@ -759,37 +804,9 @@ void MAddressDialog::selectCountry()
                }
        }
        //not found: must be the create new entry
-       QDialog d(this);
-       d.setWindowTitle(tr("Create New Country"));
-       QVBoxLayout*vl;
-       QHBoxLayout*hl;
-       QFormLayout*fl;
-       QLineEdit*name,*abbr;
-       QPushButton*p;
-       d.setLayout(vl=new QVBoxLayout);
-       vl->addLayout(fl=new QFormLayout);
-       fl->addRow(tr("Country Name:"),name=new QLineEdit);
-       fl->addRow(tr("Abbreviation:"),abbr=new QLineEdit);
-       vl->addStretch(10);
-       vl->addLayout(hl=new QHBoxLayout,0);
-       hl->addStretch(10);
-       hl->addWidget(p=new QPushButton(tr("Ok")),0);
-       connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
-       hl->addWidget(p=new QPushButton(tr("Cancel")),0);
-       connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
-       //wait and check
-       if(d.exec()!=QDialog::Accepted)return;
-       if(name->text().trimmed()=="" || abbr->text().trimmed()==""){
-               QMessageBox::warning(this,tr("Warning"),tr("The country name and abbreviation must contain something!"));
-               return;
-       }
-       //create
-       MTCreateCountry cc=MTCreateCountry::query(abbr->text().trimmed(),name->text().trimmed());
-       if(cc.hasError()){
-               QMessageBox::warning(this,tr("Warning"),tr("Error while creating country: %1").arg(cc.errorString()));
-               return;
-       }
-       m_addr.setcountry(cc.getcountry());
+       MOCountry cc=createNewCountry(this);
+       if(cc.id().isNull())return;
+       m_addr.setcountry(cc);
        m_addr.setcountryid(m_addr.country().value().id());
        m_country->setText(m_addr.country().value().name());
 }
@@ -870,3 +887,190 @@ void MAddressChoiceDialog::unselect()
        m_unsel=true;
        accept();
 }
+
+/*****************************************************************************/
+
+MNewCustomerWizard::MNewCustomerWizard(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f)
+{
+       QWidget*w;
+       QHBoxLayout*hl;
+       QVBoxLayout*vl;
+       QGridLayout*gl;
+       QStackedLayout *sl;
+       setLayout(vl=new QVBoxLayout);
+       vl->addLayout(sl=new QStackedLayout);
+       //button bar
+       vl->addSpacing(15);
+       vl->addLayout(hl=new QHBoxLayout);
+       hl->addStretch(1);
+       QPushButton*p,*pprev,*pnext,*pdone;
+       hl->addWidget(p=new QPushButton(tr("Cancel")));
+       p->setIcon(QIcon(":/cancel.png"));
+       connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+       hl->addWidget(pprev=p=new QPushButton(tr("Back")));
+       p->setIcon(QIcon(":/prev.png"));
+       connect(p,SIGNAL(clicked()),new MLambda([=](){sl->setCurrentIndex(sl->currentIndex()-1);},sl),SLOT(call()));
+       hl->addWidget(pnext=p=new QPushButton(tr("Next")));
+       p->setIcon(QIcon(":/next.png"));
+       connect(p,SIGNAL(clicked()),new MLambda([=](){sl->setCurrentIndex(sl->currentIndex()+1);},sl),SLOT(call()));
+       hl->addWidget(pdone=p=new QPushButton(tr("Finish")));
+       p->setIcon(QIcon(":/done.png"));
+       connect(p,SIGNAL(clicked()),this,SLOT(save()));
+       auto pagechange=new MVLambda<void(int)>([=](int idx){
+               pprev->setEnabled(idx>0);
+               int max=sl->count()-1;
+               pnext->setEnabled(idx<max);
+               pdone->setEnabled(idx>=max);
+       },sl);
+       connect(sl,SIGNAL(currentChanged(int)),pagechange,SLOT(call(int)));
+       
+       //get helper data
+       MTGetCreateCustomerHints cch=req->queryGetCreateCustomerHints();
+       QStringList titles,cities,states;
+       if(!cch.hasError()){
+               m_countrylist=cch.getcountries();
+               m_typelist=cch.getcontacttypes();
+               titles=cch.gettitles();
+               cities=cch.getcities();
+               states=cch.getstates();
+       }else{
+               //try something else
+               m_countrylist=req->queryGetAllCountries().getcountries();
+               m_typelist=req->queryGetAllContactTypes().gettypes();
+       }
+       
+       //address page
+       sl->addWidget(w=new QWidget);
+       int row=0;
+       w->setLayout(gl=new QGridLayout);
+       gl->addWidget(new QLabel(tr("Please enter name and address information.\nPlease enter it also if it is not needed immediately.")),row,0,1,2);
+       gl->addWidget(new QLabel(tr("Name:")),++row,0);
+       gl->addLayout(hl=new QHBoxLayout,row,1);
+       hl->addWidget(m_title=new QComboBox,1);
+       m_title->setEditable(true);
+       m_title->lineEdit()->setPlaceholderText(tr("Title"));
+       for(const QString&tt:titles)m_title->addItem(tt);
+       hl->addWidget(m_name=new QLineEdit,2);
+       m_name->setPlaceholderText(tr("Family Name"));
+       hl->addWidget(m_fname=new QLineEdit,2);
+       m_fname->setPlaceholderText(tr("Given Name"));
+       gl->addWidget(new QLabel(tr("Address:")),++row,0);
+       gl->addWidget(m_addr1=new QLineEdit,row,1);
+       m_addr1->setPlaceholderText(tr("123 Example Street"));
+       gl->addWidget(new QLabel(tr("City:")),++row,0);
+       gl->addLayout(hl=new QHBoxLayout,row,1);
+       hl->addWidget(m_zipcode=new QLineEdit,0);
+       m_zipcode->setPlaceholderText(tr("Zip Code"));
+       hl->addWidget(m_city=new QComboBox,1);
+       m_city->setEditable(true);
+       m_city->lineEdit()->setPlaceholderText(tr("Chose City"));
+       for(const QString&ct:cities)m_city->addItem(ct);
+       gl->addWidget(new QLabel(tr("State:")),++row,0);
+       gl->addWidget(m_state=new QComboBox,row,1);
+       m_state->setEditable(true);
+       m_state->lineEdit()->setPlaceholderText(tr("State (optional)"));
+       for(const QString&st:states)m_state->addItem(st);
+       gl->addWidget(new QLabel(tr("Country:")),++row,0);
+       gl->addLayout(hl=new QHBoxLayout,row,1);
+       hl->addWidget(m_country=new QComboBox,1);
+       updateCountry();
+       if(req->hasRight(req->RCreateCountry)){
+               hl->addWidget(p=new QPushButton(tr("New...")));
+               connect(p,SIGNAL(clicked()),this,SLOT(newcountry()));
+       }
+       // ...spacing
+       gl->setColumnStretch(1,1);
+       gl->addWidget(new QFrame,++row,0,1,2);
+       gl->setRowStretch(row,1);
+       
+       //contacts page
+       QScrollArea*sa;
+       sl->addWidget(sa=new QScrollArea);
+       sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+       sa->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+       sa->setWidgetResizable(true);
+       sa->setWidget(w=new QWidget);
+       w->setLayout(gl=new QGridLayout);
+       gl->addWidget(new QLabel(tr("Please enter at least one way of contacting the customer.")),row=0,0,1,2);
+       for(const MOContactType&ct:m_typelist){
+               gl->addWidget(new QLabel(ct.contacttype()),++row,0);
+               QLineEdit*le;
+               gl->addWidget(le=new QLineEdit,row,1);
+               le->setPlaceholderText(tr("Please enter %1","%1=contact type name").arg(ct.contacttype()));
+               m_contact.append(le);
+       }
+       
+       // ...spacing
+       gl->setColumnStretch(1,1);
+       gl->addWidget(new QFrame,++row,0,1,2);
+       gl->setRowStretch(row,1);
+
+       //make sure buttons are initialized
+       pagechange->call(sl->currentIndex());
+       //make size changeable
+       setSizeGripEnabled(true);
+}
+
+void MNewCustomerWizard::save()
+{
+       //create customer
+       MOCustomer inp;
+       inp.setname(m_name->text());
+       inp.setfirstname(m_fname->text());
+       inp.settitle(m_title->currentText());
+       MOAddress adr;
+       adr.setaddr1(m_addr1->text());
+       adr.setcity(m_city->currentText());
+       adr.setstate(m_state->currentText());
+       adr.setzipcode(m_zipcode->text());
+       //handle country
+       qDebug()<<"Country Idx"<<m_country->currentIndex()<<"Name"<<m_country->currentText()<<"ID"<<m_country->itemData(m_country->currentIndex()).toString();
+       return;
+//     adr.setcountryid(m_country->);
+       //complete addr
+       inp.addaddresses(adr);
+       //create customer
+       MTCreateCustomer cc=req->queryCreateCustomer(inp);
+       if(QMessageBox::warning(this,tr("Warning"),tr("There was an error while creating the customer: %1").arg(cc.errorString()),QMessageBox::Abort|QMessageBox::Retry)==QMessageBox::Retry)return;
+       //close dialog
+       accept();
+}
+
+void MNewCustomerWizard::updateCountry(QString id)
+{
+       //sort data
+       qSort(m_countrylist.begin(),m_countrylist.end(),
+             [](const MOCountry&a,const MOCountry&b){
+                     return a.name().value()<b.name().value();
+             });
+       //remember which one to pre-select
+       if(id.isEmpty())id=m_country->itemData(m_country->currentIndex()).toString();
+       int idx=-1;
+       //clear
+       m_country->clear();
+       //add
+       for(MOCountry ct:m_countrylist){
+               if(ct.id()==id)idx=m_country->count();
+               m_country->addItem(ct.name(),ct.id().value());
+       }
+       //pre-select (last one shown or new one created)
+       if(idx>=0)m_country->setCurrentIndex(idx);
+}
+
+void MNewCustomerWizard::newcountry()
+{
+       //dialog
+       MOCountry co=MAddressDialog::createNewCountry(this);
+       if(co.id().isNull())return;
+       //add to list
+       m_countrylist.append(co);
+       updateCountry(co.id());
+}
+
+MOCustomer MNewCustomerWizard::getNewCustomer(QWidget*parent)
+{
+       //TODO: check which dialog to use
+       MNewCustomerWizard ncw(parent);
+       ncw.exec();
+       return ncw.customer();
+}
index 4342654..3e58725 100644 (file)
@@ -23,6 +23,7 @@
 #include "MOCustomerInfo"
 #include "MOCustomer"
 
+class QComboBox;
 class QHBoxLayout;
 class QLineEdit;
 class QListView;
@@ -233,6 +234,10 @@ class MAddressDialog:public QDialog
                
                /**returns the address*/
                MOAddress address();
+               
+               ///helper function to create a new country, used by MAddressDialog and MNewCustomerWizard
+               ///returns a valid country on success
+               static MOCountry createNewCountry(QWidget*parent=0);
        private slots:
                void selectCountry();
        private:
@@ -292,4 +297,28 @@ class MContactTableDelegate:public QItemDelegate
                mutable QList<MOContactType>m_typelist;
 };
 
+
+/**Wizard for creating a new customer.*/
+class MNewCustomerWizard:public QDialog
+{
+       Q_OBJECT
+       public:
+               MNewCustomerWizard(QWidget* parent = 0, Qt::WindowFlags f = 0);
+               
+               MOCustomer customer()const{return m_cust;}
+               
+               static MOCustomer getNewCustomer(QWidget*parent=0);
+       private slots:
+               void save();
+               void newcountry();
+               void updateCountry(QString id=QString());
+       private:
+               MOCustomer m_cust;
+               QComboBox*m_title,*m_city,*m_state,*m_country;
+               QLineEdit*m_name,*m_fname,*m_addr1,*m_zipcode;
+               QList<MOContactType>m_typelist;
+               QList<MOCountry>m_countrylist;
+               QList<QLineEdit*>m_contact;
+};
+
 #endif
diff --git a/src/images/cancel.png b/src/images/cancel.png
new file mode 100644 (file)
index 0000000..fd285bc
Binary files /dev/null and b/src/images/cancel.png differ
diff --git a/src/images/done.png b/src/images/done.png
new file mode 100644 (file)
index 0000000..dbfb948
Binary files /dev/null and b/src/images/done.png differ
index 24bb789..bb5e883 100644 (file)
@@ -3,12 +3,20 @@
 See COPYING.GPL for details. -->
 <RCC version="1.0">
     <qresource>
+        <!-- main app icon -->
         <file>icon.png</file>
+       <!-- my own arrows for print dialog -->
         <file>arrowright.png</file>
         <file>arrowleft.png</file>
         <file>arrowup.png</file>
         <file>arrowdown.png</file>
         <file>arrowdiag.png</file>
+       <!-- menu separator -->
         <file>separator.png</file>
+       <!-- arrows for next and prev actions, "stolen" from Qt (linguist and others) -->
+       <file>next.png</file>
+       <file>prev.png</file>
+       <file>cancel.png</file>
+       <file>done.png</file>
     </qresource>
 </RCC>
diff --git a/src/images/next.png b/src/images/next.png
new file mode 100644 (file)
index 0000000..7700d6f
Binary files /dev/null and b/src/images/next.png differ
diff --git a/src/images/prev.png b/src/images/prev.png
new file mode 100644 (file)
index 0000000..99dc873
Binary files /dev/null and b/src/images/prev.png differ
index 2710452..50e61b1 100644 (file)
                </Input>
                <Call lang="php" method="WOCustomer::resetPassword($this);"/>
        </Transaction>
+       
+       <Transaction name="GetCreateCustomerHints" updating="no">
+               <Doc>Returns all info that helps in creating customers, like common titles, cities, countries, etc.</Doc>
+               <Input/>
+               <Call lang="php" method="WOCustomer::createHints($this);"/>
+               <Output>
+                       <Var name="countries" type="List:Country"/>
+                       <Var name="titles" type="List:string"/>
+                       <Var name="cities" type="List:string"/>
+                       <Var name="states" type="List:string"/>
+                       <Var name="contacttypes" type="List:ContactType"/>
+               </Output>
+       </Transaction>
 </Wolf>
\ No newline at end of file
index 3b41285..2a88141 100644 (file)
@@ -62,6 +62,14 @@ $olddb->setCharacterSet("utf8");
 // */
 
 
+
+///////////
+//Development Options (comment these away in production systems)
+
+//WobTransaction::setDebugLevel(WobTransaction::DebugAll);
+
+
+
 ////////////
 //Dedicated Client Configuration
 
index df0798c..46ec1ab 100644 (file)
@@ -5,9 +5,7 @@
 
 
 /* TRANSLATOR php:: */
-//prune session cache
-global $db;
-$db->deleteRows("session","timeout<=".time());
+
 
 /**The session class*/
 class Session
@@ -18,6 +16,16 @@ class Session
        protected $rights=array();
        protected $flags=array();
        
+       ///initialize session sub-system
+       static public function initialize()
+       {
+               //prune session cache
+               global $db;
+               $db->beginTransaction();
+               $db->deleteRows("session","timeout<=".time());
+               $db->commitTransaction();
+       }
+       
        /**construct the session object, check validity*/
        public function __construct($trans)
        {
index e961aa7..89a8166 100644 (file)
@@ -592,6 +592,30 @@ class WOCustomer extends WOCustomerAbstract
                //go to checkout page
                redirectHome(array("mode"=>"checkout"));
        }
+       
+       static public function createHints($trans)
+       {
+               $trans->setcontacttypes( WOContactType::fromTableArraycontacttype( WTcontacttype::selectFromDB()));
+               $trans->setcountries( WOCountry::fromTableArraycountry( WTcountry::selectFromDB()));
+               global $db;
+               $tt=$db->select("customer","title","","GROUP BY title ORDER BY title");
+               if($tt!==false){
+                       $r=array();
+                       foreach($tt as $t)$r[]=$t["title"];
+                       $trans->settitles($r);
+               }
+               $csl=$db->select("address","state,city","","GROUP BY city,state");
+               if($csl!==false){
+                       $rs=array();
+                       $rc=array();
+                       foreach($csl as $cs){
+                               if(!in_array($cs["city"],$rc))$rc[]=$cs["city"];
+                               if(!in_array($cs["state"],$rs))$rs[]=$cs["state"];
+                       }
+                       $trans->setcities($rc);
+                       $trans->setstates($rs);
+               }
+       }
 };
 
 //eof
index 889b2c1..a3f9e10 100644 (file)
@@ -21,17 +21,20 @@ class MSmokeTransaction extends WobTransaction
        protected function startTransaction($updating)
        {
                global $db;
+               WobTransaction::debug("Starting MSmoke Transaction as ".($updating?"updating":"read only"),WobTransaction::DebugTransactions);
                $db->setTransactionUpdating($updating);
                $db->beginTransaction();
        }
        protected function commitTransaction()
        {
                global $db;
+               WobTransaction::debug("Comitting MSmoke Transaction",WobTransaction::DebugTransactions);
                $db->commitTransaction();
        }
        protected function abortTransaction()
        {
                global $db;
+               WobTransaction::debug("Aborting MSmoke Transaction",WobTransaction::DebugTransactions);
                $db->rollbackTransaction();
        }
        
index 89c3989..3caef30 100644 (file)
@@ -10,8 +10,12 @@ header("Content-Type: application/x-MagicSmoke");
 include("inc/loader.php");
 include("inc/loader_nonadmin.php");
 
+//init
+Session::initialize();
+
 //let wob do the rest
 MSmokeTransaction::handle();
+WobTransaction::printDebug();
 
 //done
 exit(0);