customer management almost complete (contacts are missing)
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 4 Jan 2010 18:22:06 +0000 (18:22 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 4 Jan 2010 18:22:06 +0000 (18:22 +0000)
git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@402 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

15 files changed:
src/dialogs/customerdlg.cpp
src/dialogs/customerdlg.h
src/mwin/carttab.cpp
src/mwin/overview.cpp
src/wext/MOAddress.cpp
src/wext/MOAddress.h
src/wext/MOCustomer.cpp
src/wext/MOCustomer.h
src/wext/MOCustomerInfo.h
wob/customer.wolf
www/inc/db/db.php
www/inc/db/db_mysql.php
www/inc/wbase/transaction.php
www/inc/wext/autoload.php
www/inc/wext/customer.php [new file with mode: 0644]

index 58e772a..181dca4 100644 (file)
 #include <QComboBox>
 #include <QApplication>
 #include <QDomElement>
+#include <QFormLayout>
 #include <QGridLayout>
+#include <QInputDialog>
 #include <QLabel>
 #include <QLineEdit>
 #include <QListView>
 #include <QMessageBox>
 #include <QPushButton>
+#include <QSignalMapper>
 #include <QSortFilterProxyModel>
 #include <QStandardItemModel>
 #include <QTextEdit>
@@ -59,10 +62,10 @@ MCustomerListDialog::MCustomerListDialog(QWidget*par,bool isselect,qint64 presel
        connect(p,SIGNAL(clicked()),this,SLOT(editCustomer()));
        vl2->addWidget(p=new QPushButton(tr("Create new...")),0);
        connect(p,SIGNAL(clicked()),this,SLOT(newCustomer()));
-       p->setEnabled(req->hasRole("setcustomer"));
+       p->setEnabled(req->hasRight(req->RCreateCustomer));
        vl2->addWidget(p=new QPushButton(tr("Delete...")),0);
        connect(p,SIGNAL(clicked()),this,SLOT(deleteCustomer()));
-       p->setEnabled(req->hasRole("deletecustomer"));
+       p->setEnabled(req->hasRight(req->RDeleteCustomer));
        vl2->addStretch(2);
        vl->addSpacing(15);
        vl->addLayout(hl=new QHBoxLayout,0);
@@ -148,7 +151,7 @@ void MCustomerListDialog::editCustomer()
        //open dialog
        MCustomerDialog cd(gc.getcustomer().value(),this);
        if(cd.exec()==QDialog::Accepted)
-               updateList();
+               updateList(m_list[i].customerid());
 }
 void MCustomerListDialog::deleteCustomer()
 {
@@ -207,49 +210,382 @@ MCustomerDialog::MCustomerDialog(MOCustomer c,QWidget*par)
        
        //layout
        QGridLayout *gl;
-       setLayout(gl=new QGridLayout);
+       QVBoxLayout*vl,*vl2;
+       QHBoxLayout*hl;
+       QTabWidget*tab;
+       QPushButton*p;
+       QWidget*w;
+       
+       setLayout(vl=new QVBoxLayout);
+       vl->addWidget(tab=new QTabWidget);
+       tab->addTab(w=new QWidget,tr("Customer"));
+       
+       w->setLayout(gl=new QGridLayout);
        int lc=0;
        gl->addWidget(new QLabel(tr("Name:")),lc,0);
        gl->addWidget(m_name=new QLineEdit(m_cust.name()),lc,1);
-       gl->addWidget(new QLabel(tr("Address:")),++lc,0);
-       gl->addWidget(m_addr=new QTextEdit,lc,1);
-       m_addr->setPlainText(m_cust.address());
-       gl->addWidget(new QLabel(tr("Contact Information:")),++lc,0);
-       gl->addWidget(m_cont=new QTextEdit,lc,1);
-       //FIXME
-//     m_cont->setPlainText(m_cust.contact());
+       gl->addWidget(new QLabel(tr("First Name:")),++lc,0);
+       gl->addWidget(m_fname=new QLineEdit(m_cust.firstname()),lc,1);
+       gl->addWidget(new QLabel(tr("Title:")),++lc,0);
+       gl->addWidget(m_title=new QLineEdit(m_cust.title()),lc,1);
        gl->setRowMinimumHeight(++lc,10);
        gl->addWidget(new QLabel(tr("Web-Login/eMail:")),++lc,0);
        gl->addWidget(m_mail=new QLabel(m_cust.email()),lc,1);
+       gl->addWidget(p=new QPushButton(tr("Edit Login")),++lc,1);
+       p->setEnabled(false);//TODO: implement edit customer login
        gl->setRowMinimumHeight(++lc,10);
        gl->addWidget(new QLabel(tr("Comment:")),++lc,0,1,2);
        gl->addWidget(m_comm=new QTextEdit,++lc,0,1,2);
        m_comm->setPlainText(m_cust.comments());
+       gl->setRowStretch(lc,10);
        gl->setRowMinimumHeight(++lc,15);
-       QHBoxLayout*hl;
-       gl->addLayout(hl=new QHBoxLayout,++lc,0,1,2);
+       
+       tab->addTab(w=new QWidget,tr("Addresses"));
+       w->setLayout(vl2=new QVBoxLayout);
+       vl2->addWidget(m_addr=new MAddressListWidget(0,m_cust.addresses()),10);
+       vl2->addLayout(hl=new QHBoxLayout,0);
+       hl->addStretch(10);
+       hl->addWidget(p=new QPushButton(tr("Add Address")),0);
+       connect(p,SIGNAL(clicked()),m_addr,SLOT(createAddress()));
+       
+       tab->addTab(w=new QWidget,tr("Contact Information"));
+       w->setLayout(gl=new QGridLayout);
+       gl->addWidget(new QLabel(tr("Contact Information:")),++lc,0);
+       gl->addWidget(new QTextEdit,lc,1);
+       //FIXME
+//     m_cont->setPlainText(m_cust.contact());
+       
+       
+       vl->addLayout(hl=new QHBoxLayout,0);
        hl->addStretch(10);
-       QPushButton*p;
        hl->addWidget(p=new QPushButton(tr("Save")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+       //make sure saving is faster than closing the dialog
+       connect(p,SIGNAL(clicked()),this,SLOT(accept()),Qt::QueuedConnection);
        connect(p,SIGNAL(clicked()),this,SLOT(save()));
        hl->addWidget(p=new QPushButton(tr("Cancel")),0);
        connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+       
+       setSizeGripEnabled(true);
 }
 
 MOCustomer MCustomerDialog::getCustomer()
 {
        //copy data from input fields
        m_cust.setname(m_name->text());
-       //TODO: redo address editing
-       //m_cust.setaddress(m_addr->toPlainText());
+       m_cust.setfirstname(m_fname->text());
+       m_cust.settitle(m_title->text());
+       m_cust.setaddresses(m_addr->addressList());
        //m_cust.setcontact(m_cont->toPlainText());
        m_cust.setcomments(m_comm->toPlainText());
        return m_cust;
 }
 
 void MCustomerDialog::save()
-{/*TODO:
+{
        getCustomer();
-       m_cust.save();*/
+       if(m_cust.isValid()){
+               MTChangeCustomer cc=req->queryChangeCustomer(m_cust);
+               if(cc.hasError()){
+                       QMessageBox::warning(this,tr("Warning"),tr("Error while changing customer data: %1").arg(cc.errorString()));
+                       return;
+               }
+               m_cust=cc.getcustomer();
+       }else{
+               MTCreateCustomer cc=req->queryCreateCustomer(m_cust);
+               if(cc.hasError()){
+                       QMessageBox::warning(this,tr("Warning"),tr("Error while creating customer data: %1").arg(cc.errorString()));
+                       return;
+               }
+               m_cust=cc.getcustomer();
+       }
+}
+
+/*****************************************************************************/
+
+MAddressWidget::MAddressWidget(QWidget*parent,bool isselect)
+       :QFrame(parent)
+{
+       QVBoxLayout*vl;
+       QHBoxLayout*hl;
+       QPushButton*p;
+       setLayout(vl=new QVBoxLayout);
+       vl->addWidget(m_lab=new QLabel(" "),10);
+       vl->addLayout(hl=new QHBoxLayout,0);
+       if(isselect){
+               hl->addWidget(p=new QPushButton(tr("Select")));
+               connect(p,SIGNAL(clicked()),this,SLOT(selectClick()));
+               connect(this,SIGNAL(addrValid(bool)),p,SLOT(setEnabled(bool)));
+       }
+       hl->addWidget(p=new QPushButton(tr("Edit")));
+       connect(p,SIGNAL(clicked()),this,SLOT(editClick()));
+       connect(this,SIGNAL(addrValid(bool)),p,SLOT(setEnabled(bool)));
+       hl->addWidget(p=new QPushButton(tr("Delete")));
+       connect(p,SIGNAL(clicked()),this,SLOT(delClick()));
+       connect(this,SIGNAL(addrValid(bool)),p,SLOT(setEnabled(bool)));
+}
+
+MOAddress MAddressWidget::address()const{return m_addr;}
+
+void MAddressWidget::setAddress(const MOAddress&a)
+{
+       m_addr=a;
+       emit addrValid(!a.addressid().isNull());
+       setEnabled(!a.isdeleted().value());
+       redisplay();
+       emit addressChanged(m_addr);
+}
+
+void MAddressWidget::redisplay()
+{
+       m_lab->setText(m_addr.fullAddress());
+       m_lab->setMinimumSize(m_lab->sizeHint());
+       m_lab->adjustSize();
+       adjustSize();
+}
+
+void MAddressWidget::setAddress(qint64 id)
+{
+       setAddress(MTGetAddress::query(id).getaddress());
+}
+
+void MAddressWidget::clearAddress()
+{
+       m_addr=MOAddress();
+       emit addrValid(false);
+       setEnabled(false);
+       redisplay();
+       emit addressChanged(m_addr);
+}
+
+void MAddressWidget::editClick()
+{
+       MAddressDialog d(this,m_addr);
+       if(d.exec()==QDialog::Accepted){
+               m_addr=d.address();
+               emit addrValid(!m_addr.addressid().isNull());
+               setEnabled(!m_addr.isdeleted().value());
+               redisplay();
+               emit addressEdited(m_addr);
+               emit addressChanged(m_addr);
+       }
+}
+
+void MAddressWidget::delClick()
+{
+       if(QMessageBox::question(this,tr("Delete Address"),tr("Really delete this address?\n%1").arg(m_addr.fullAddress()),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)
+               return;
+       m_addr.setisdeleted(true);
+       setEnabled(false);
+       emit addressEdited(m_addr);
+       emit addressDeleted(m_addr);
+       emit addressChanged(m_addr);
+}
+
+void MAddressWidget::selectClick()
+{
+       emit addressSelected(m_addr);
+       emit addressSelected(m_addr.addressid());
+}
+
+/*****************************************************************************/
+
+//number of columns in the address list widget
+#define ADDRCOLS 3
+
+MAddressListWidget::MAddressListWidget(QWidget*parent,const QList<MOAddress>&addr,bool isselect)
+       :QScrollArea(parent),m_select(isselect)
+{
+       map=new QSignalMapper(this);
+       connect(map,SIGNAL(mapped(int)),this,SLOT(addrEdit(int)),Qt::DirectConnection);
+       QWidget*w;
+       setWidget(w=new QWidget);
+       setWidgetResizable(true);
+       QVBoxLayout*vl;
+       w->setLayout(vl=new QVBoxLayout);
+       vl->addLayout(m_layout=new QGridLayout,0);
+       vl->addStretch(10);
+       for(int i=0;i<addr.size();i++)
+               addAddr(addr[i]);
+}
+
+void MAddressListWidget::addrEdit(int id)
+{
+       qDebug("edited addr %i",id);
+       MAddressWidget*aw=qobject_cast<MAddressWidget*>(map->mapping(id));
+       if(aw==0)return;
+       qDebug("handling edit");
+       m_addr[id]=aw->address();
+       aw->adjustSize();
+       widget()->adjustSize();
+}
+
+void MAddressListWidget::addrSel(const MOAddress&a)
+{
+       m_sel=a;
+}
+
+void MAddressListWidget::addAddr(const MOAddress&addr,bool vis)
+{
+       //create
+       int id=m_addr.size();
+       m_addr<<addr;
+       MAddressWidget *aw=new MAddressWidget(this,m_select);
+       aw->setAddress(addr);
+       aw->setFrameStyle(QFrame::Box|QFrame::Raised);
+       map->setMapping(aw,id);
+       //display
+       m_layout->addWidget(aw,id/ADDRCOLS,id%ADDRCOLS);
+       aw->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::MinimumExpanding);
+       aw->adjustSize();
+       widget()->adjustSize();
+       if(vis)ensureWidgetVisible(aw);
+       //connections to myself
+       connect(aw,SIGNAL(addressEdited(const MOAddress&)),map,SLOT(map()),Qt::DirectConnection);
+       connect(aw,SIGNAL(addressSelected(const MOAddress&)),this,SLOT(addrSel(const MOAddress&)),Qt::DirectConnection);
+       //proxy connections
+       connect(aw,SIGNAL(addressEdited(const MOAddress&)),this,SIGNAL(addressEdited(const MOAddress&)),Qt::QueuedConnection);
+       connect(aw,SIGNAL(addressChanged(const MOAddress&)),this,SIGNAL(addressChanged(const MOAddress&)),Qt::QueuedConnection);
+       connect(aw,SIGNAL(addressDeleted(const MOAddress&)),this,SIGNAL(addressDeleted(const MOAddress&)),Qt::QueuedConnection);
+       connect(aw,SIGNAL(addressSelected(const MOAddress&)),this,SIGNAL(addressSelected(const MOAddress&)),Qt::QueuedConnection);
+       connect(aw,SIGNAL(addressSelected(qint64)),this,SIGNAL(addressSelected(qint64)),Qt::QueuedConnection);
+}
+
+void MAddressListWidget::preselect(int i)
+{
+       if(i<0 || i>=m_addr.size())return;
+       MAddressWidget*aw=qobject_cast<MAddressWidget*>(map->mapping(i));
+       if(!aw)return;
+       //set new selection
+       aw->setFrameStyle(QFrame::Box | QFrame::Plain);
+       aw->setLineWidth(2);
+       m_sel=m_addr[i];
+       //make sure it is visible
+       ensureWidgetVisible(aw);
+       aw->adjustSize();
+       widget()->adjustSize();
+}
+
+void MAddressListWidget::createAddress()
+{
+       MAddressDialog d(this);
+       if(d.exec()!=QDialog::Accepted)return;
+       addAddr(d.address());
+       emit addressCreated(m_addr[m_addr.size()-1]);
+}
+
+/*****************************************************************************/
+
+MAddressDialog::MAddressDialog(QWidget*parent,MOAddress addr)
+       :QDialog(parent),m_addr(addr)
+{
+       if(!m_addr.addressid().isNull())
+               setWindowTitle(tr("Edit Address"));
+       else
+               setWindowTitle(tr("Create Address"));
+       
+       QVBoxLayout*vl;
+       QHBoxLayout*hl;
+       QFormLayout*fl;
+       QPushButton*p;
+       setLayout(vl=new QVBoxLayout);
+       vl->addLayout(fl=new QFormLayout,0);
+       if(m_addr.isValid())
+               fl->addRow(tr("Last used:"),new QLabel(QDateTime::fromTime_t(m_addr.lastused()).toString()));
+       fl->addRow(tr("Name:"),m_name=new QLineEdit(m_addr.name()));
+       fl->addRow(tr("Address:"),m_addr1=new QLineEdit(m_addr.addr1()));
+       fl->addRow(tr("Address:"),m_addr2=new QLineEdit(m_addr.addr2()));
+       fl->addRow(tr("City:"),m_city=new QLineEdit(m_addr.city()));
+       fl->addRow(tr("State:"),m_state=new QLineEdit(m_addr.state()));
+       fl->addRow(tr("ZIP Code:"),m_zip=new QLineEdit(m_addr.zipcode()));
+       fl->addRow(tr("Country:"),hl=new QHBoxLayout);
+       hl->addWidget(m_country=new QLineEdit(m_addr.country().value().name()),10);
+       m_country->setReadOnly(true);
+       hl->addWidget(p=new QPushButton("..."),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(selectCountry()));
+       
+       vl->addStretch(10);
+       vl->addLayout(hl=new QHBoxLayout,0);
+       hl->addStretch(10);
+       hl->addWidget(p=new QPushButton(tr("Ok")),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+       hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+MOAddress MAddressDialog::address()
+{
+       //set pseudo-ID to make it appear valid to other widgets
+       if(m_addr.addressid().isNull())m_addr.setaddressid(-1);
+       //set properties
+       m_addr.setname(m_name->text());
+       m_addr.setaddr1(m_addr1->text());
+       m_addr.setaddr2(m_addr2->text());
+       m_addr.setcity(m_city->text());
+       m_addr.setstate(m_state->text());
+       m_addr.setzipcode(m_zip->text());
+       //country and countryid is set by selectCountry
+       
+       return m_addr;
+}
+
+void MAddressDialog::selectCountry()
+{
+       //get countries
+       QList<MOCountry>cntry=MTGetAllCountries::query().getcountries();
+       QStringList clst;
+       int cur=0;
+       QString curstr=m_country->text();
+       for(int i=0;i<cntry.size();i++){
+               clst<<cntry[i].name().value().trimmed();
+               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");
+       //display selection
+       bool ok;
+       QString it=QInputDialog::getItem(this,tr("Select Country"),tr("Please select a country:"),clst,cur,false,&ok);
+       if(!ok || it=="")return;
+       //get selection
+       for(int i=0;i<cntry.size();i++){
+               if(it == cntry[i].name().value()){
+                       m_addr.setcountry(cntry[i]);
+                       m_addr.setcountryid(cntry[i].id());
+                       m_country->setText(cntry[i].name());
+                       return;
+               }
+       }
+       //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());
+       m_addr.setcountryid(m_addr.country().value().id());
+       m_country->setText(m_addr.country().value().name());
 }
index 524ec69..bdd5a2c 100644 (file)
@@ -15,7 +15,9 @@
 
 #include <QString>
 #include <QDialog>
+#include <QFrame>
 #include <QList>
+#include <QScrollArea>
 
 #include "MOCustomerInfo.h"
 #include "MOCustomer.h"
@@ -59,6 +61,141 @@ class QLineEdit;
 class QTextEdit;
 class QLabel;
 
+/**displays exactly one address; even though it offers to edit or delete addresses, it does not actually do any change on the database*/
+class MAddressWidget:public QFrame
+{
+       Q_OBJECT
+       public:
+               /**creates the widget, if isselect==true a "select" button is shown*/
+               MAddressWidget(QWidget*parent=0,bool isselect=false);
+               
+               /**returns the currently shown address*/
+               MOAddress address()const;
+               
+       public slots:
+               /**sets the address to be shown, enables the buttons if it is valid*/
+               void setAddress(const MOAddress&);
+               
+               /**convenience method: sets the address to be shown, retrieves it from the database*/
+               void setAddress(qint64);
+               
+               /**clears the display, disables the buttons*/
+               void clearAddress();
+               
+       signals:
+               /**emitted if the address has changed, the parameter contains the current content;
+               this also emits if the address has changed or cleared programmatically, use addressEdited if you want only manual changes*/
+               void addressChanged(const MOAddress&);
+               
+               /**emitted if the address was changed by the user, contains the current address content*/
+               void addressEdited(const MOAddress&);
+               
+               /**emitted if the address was deleted by the user, addressEdited is also emitted*/
+               void addressDeleted(const MOAddress&);
+               
+               /**emitted if the user presses the "select" button, contains the address*/
+               void addressSelected(const MOAddress&);
+               
+               /**emitted if the user presses the "select" button, contains the address ID*/
+               void addressSelected(qint64);
+               
+               /**internal: used to activate or de-activate buttons*/
+               void addrValid(bool);
+               
+       private slots:
+               /**internal: the user clicked edit*/
+               void editClick();
+               /**internal: the user clicked delete*/
+               void delClick();
+               /**internal: the user clicked select*/
+               void selectClick();
+               /**internal: re-display the address*/
+               void redisplay();
+               
+       private:
+               MOAddress m_addr;
+               QLabel*m_lab;
+};
+
+class QSignalMapper;
+class QGridLayout;
+
+/**widget that displays a list of addresses, it uses MAddressWidget to display every single address*/
+class MAddressListWidget:public QScrollArea
+{
+       Q_OBJECT
+       public:
+               /**creates the widget*/
+               MAddressListWidget(QWidget*parent,const QList<MOAddress>&,bool isselect=false);
+               
+               /**returns the current list*/
+               QList<MOAddress> addressList()const{return m_addr;}
+               
+               /**returns the selected address*/
+               MOAddress selection()const{return m_sel;}
+               
+       signals:
+               /**emitted if the address has changed, the parameter contains the current content;
+               this also emits if the address has changed programmatically, use addressEdited if you want only manual changes*/
+               void addressChanged(const MOAddress&);
+               
+               /**emitted if the address was changed by the user, contains the current address content*/
+               void addressEdited(const MOAddress&);
+               
+               /**emitted if the address was deleted by the user, addressEdited is also emitted*/
+               void addressDeleted(const MOAddress&);
+               
+               /**emitted if the user presses the "select" button, contains the address*/
+               void addressSelected(const MOAddress&);
+               
+               /**emitted if the user presses the "select" button, contains the address ID*/
+               void addressSelected(qint64);
+               
+               /**emitted if the user creates a new address via createAddress()*/
+               void addressCreated(const MOAddress&);
+               
+       public slots:
+               /**asks the user for a new address*/
+               void createAddress();
+               
+               /**pre-selects an address by its position in the current address list, this method should only be called once!*/
+               void preselect(int);
+               
+       private slots:
+               /**internal: used to change an address after editing*/
+               void addrEdit(int);
+               
+               /**internal: used to remember the selected address*/
+               void addrSel(const MOAddress&);
+               
+               /**internal: add an address widget, if the boolean is true it is also made visible*/
+               void addAddr(const MOAddress&,bool v=false);
+               
+       private:
+               QList<MOAddress>m_addr;
+               MOAddress m_sel;
+               QSignalMapper *map;
+               bool m_select;
+               QGridLayout*m_layout;
+};
+
+/**dialog for editing exactly one address*/
+class MAddressDialog:public QDialog
+{
+       Q_OBJECT
+       public:
+               /**creates the dialog, if no valid address is given it displays as "create address" otherwise as "edit address"*/
+               MAddressDialog(QWidget*parent=0,MOAddress addr=MOAddress());
+               
+               /**returns the address*/
+               MOAddress address();
+       private slots:
+               void selectCountry();
+       private:
+               QLineEdit *m_name,*m_addr1,*m_addr2,*m_city,*m_state,*m_zip,*m_country;
+               MOAddress m_addr;
+};
+
 /**edit a specific customer*/
 class MCustomerDialog:public QDialog
 {
@@ -76,8 +213,9 @@ class MCustomerDialog:public QDialog
                
        private:
                MOCustomer m_cust;
-               QLineEdit*m_name;
-               QTextEdit*m_addr,*m_cont,*m_comm;
+               QLineEdit*m_name,*m_fname,*m_title;
+               QTextEdit*m_comm;
+               MAddressListWidget*m_addr;
                QLabel*m_mail;
 };
 
index b02fedb..3b1566e 100644 (file)
@@ -15,6 +15,7 @@
 #include "misc.h"
 #include "msinterface.h"
 #include "orderwin.h"
+#include "customerdlg.h"
 
 #include "carttab.h"
 
@@ -90,7 +91,7 @@ MCartTab::MCartTab(QString pk)
        connect(p,SIGNAL(clicked()),this,SLOT(initCart()));
        
        //fill tables
-       if(!req->hasRole("createorder")&&!req->hasRole("createsale")){
+       if(!req->hasRight(req->RCreateOrder)&&!req->hasRight(req->RCreateReservation)){
                setEnabled(false);
        }else{
                initCart();
@@ -140,11 +141,12 @@ void MCartTab::initCart()
 }
 
 void MCartTab::setCustomer()
-{/*TODO
-       MCustomerListDialog mcl(req,this,true,customer.customerID());
+{
+       MCustomerListDialog mcl(this,true,customer.id());
        if(mcl.exec()!=QDialog::Accepted)return;
        customer=mcl.getCustomer();
-       cartcustomer->setText(customer.getNameAddress());*/
+       //TODO: follow up with address dialog
+//     cartcustomer->setText(customer.getNameAddress());
 }
 
 static const int CART_TICKET=1;
index 3eb19ae..ddfd59e 100644 (file)
@@ -13,6 +13,7 @@
 #include "main.h"
 #include "msinterface.h"
 #include "passwdchg.h"
+#include "customerdlg.h"
 
 #include "overview.h"
 #include "eventstab.h"
@@ -140,7 +141,7 @@ MOverview::MOverview(QString pk)
                eventtab->setEnabled(false);
                tab->setTabEnabled(tab->indexOf(eventtab),false);
        }
-       if(!req->hasRight(req->RCreateOrder)){
+       if(!req->hasRight(req->RCreateOrder)&&!req->hasRight(req->RCreateReservation)){
                tab->setTabEnabled(tab->indexOf(carttab),false);
        }
        if(!req->hasRight(req->RGetOrderList)){
@@ -192,9 +193,9 @@ void MOverview::setMyPassword()
 }
 
 void MOverview::customerMgmt()
-{/*TODO
-       MCustomerListDialog mcl(req,this);
-       mcl.exec();*/
+{
+       MCustomerListDialog mcl(this);
+       mcl.exec();
 }
 
 void MOverview::editShipping()
@@ -397,13 +398,17 @@ void MOverview::webSettings(bool showdlg)
                QComboBox *log;
                gl->addWidget(new QLabel(tr("Log Level:")),1,0);
                gl->addWidget(log=new QComboBox,1,1);
+               log->addItem(tr("No Logging"),MSInterface::LogNone);
                log->addItem(tr("Minimal Logging"),MSInterface::LogMinimal);
+               log->addItem(tr("Medium Logging"),MSInterface::LogInfo);
                log->addItem(tr("Log Details on Error"),MSInterface::LogOnError);
                log->addItem(tr("Always Log Details"),MSInterface::LogDetailed);
                switch(lvl){
-                       case MSInterface::LogMinimal:log->setCurrentIndex(0);break;
-                       case MSInterface::LogOnError:log->setCurrentIndex(1);break;
-                       case MSInterface::LogDetailed:log->setCurrentIndex(2);break;
+                       case MSInterface::LogNone:log->setCurrentIndex(0);break;
+                       case MSInterface::LogMinimal:log->setCurrentIndex(1);break;
+                       case MSInterface::LogInfo:log->setCurrentIndex(2);break;
+                       case MSInterface::LogOnError:log->setCurrentIndex(3);break;
+                       case MSInterface::LogDetailed:log->setCurrentIndex(4);break;
                }
                gl->setRowMinimumHeight(2,15);
                gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
index 2f18aea..9a7d8cf 100644 (file)
 
 #include <QStringList>
 
+static int moaid=qRegisterMetaType<MOAddress>("MOAddress");
+
 QString MOAddress::fullAddress(QString nm)const
 {
-       //if not valid: return nothing
-       if(!isValid())return "";
        //collect lines
        QStringList rl;
        if(name().isNull()){
index 1aea6d9..8c21328 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "MOAddressAbstract.h"
 
+#include <QMetaType>
+
 class MOAddress:public MOAddressAbstract
 {
        WOBJECT(MOAddress);
@@ -22,9 +24,10 @@ class MOAddress:public MOAddressAbstract
                /**returns the full address, if name is given and the address does not have its own name, it is included as top line*/
                QString fullAddress(QString name=QString())const;
                
-               /**returns true if this is a valid address (ie. it has an address ID)*/
+               /**returns true if this is a valid address stored in the DB (ie. it has an address ID)*/
                bool isValid()const{return !addressid().isNull() && addressid().value()>=0;}
 };
 
+Q_DECLARE_METATYPE(MOAddress);
 
 #endif
index 93dec4d..587bc76 100644 (file)
@@ -11,6 +11,7 @@
 //
 
 #include "MOCustomer.h"
+#include "MOCustomerInfo.h"
 #include "msinterface.h"
 
 MOCustomer::MOCustomer(qint64 i)
@@ -20,6 +21,11 @@ MOCustomer::MOCustomer(qint64 i)
                operator=(gc.getcustomer().value());
 }
 
+MOCustomer::MOCustomer(const MOCustomerInfo&i)
+{
+       MOCustomer::MOCustomer(i.id());
+}
+
 QString MOCustomer::address(int i)
 {
        if(i<0)return "";
index 5a81583..95a61f3 100644 (file)
 
 #include "MOCustomerAbstract.h"
 
+class MOCustomerInfo;
+
 class MOCustomer:public MOCustomerAbstract
 {
        WOBJECT(MOCustomer);
        public:
                /**shortcut: gets the customer from the DB*/
                MOCustomer(qint64);
+               /**shortcut: extracts the ID from the info and retrieves the customer from the DB*/
+               MOCustomer(const MOCustomerInfo&);
                /**returns whether the customer is valid*/
                bool isValid(){return !id().isNull();}
                
+               /**alias for id()*/
+               Nullable<qint64> customerid()const{return id();}
+               
                /**returns the address of the customer*/
                QString address(int i=0);
+               
+               /**returns the full name (incl. title)*/
+               QString fullName()const{return title()+" "+name()+", "+firstname();}
 
 };
 
index cbf0a4e..dd6c7e9 100644 (file)
@@ -18,7 +18,11 @@ class MOCustomerInfo:public MOCustomerInfoAbstract
 {
        WOBJECT(MOCustomerInfo);
        public:
+               /**returns the full name (incl. title)*/
                QString fullName()const{return title()+" "+name()+", "+firstname();}
+               
+               /**alias for customerid()*/
+               Nullable<qint64> id()const{return customerid();}
 };
 
 #endif
index 152e3a0..5877844 100644 (file)
                <Column name="addressid" type="seq64" primarykey="yes"/>
                <Column name="customerid" type="int32" foreignkey="customer:customerid" notnull="yes"/>
                <Column name="lastused" type="int64" null="yes"/>
-               <Column name="name" type="string" notnull="yes"/>
-               <Column name="addr1" type="string" notnull="yes"/>
+               <Column name="name" type="string" null="yes"/>
+               <Column name="addr1" type="string" null="yes"/>
                <Column name="addr2" type="string" null="yes"/>
-               <Column name="city" type="string:64" notnull="yes"/>
+               <Column name="city" type="string:64" null="yes"/>
                <Column name="state" type="string:32" null="yes"/>
-               <Column name="zipcode" type="string:32" notnull="yes"/>
-               <Column name="countryid" type="string:3" notnull="yes" foreignkey="country:countryid"/>
+               <Column name="zipcode" type="string:32" null="yes"/>
+               <Column name="countryid" type="string:16" null="yes" foreignkey="country:countryid"/>
                <Column name="isdeleted" type="bool" notnull="yes" default="0"/>
        </Table>
        <Table name="contacttype" backup="yes">
        </Class>
        <Class name="Customer">
                <Abstract lang="qt"/>
+               <Abstract lang="php"/>
                <Property name="id" type="int"/>
                <Property name="title" type="string"/>
                <Property name="firstname" type="string"/>
                </Output>
        </Transaction>
        
+       <Transaction name="CreateCustomer">
+               <Input>
+                       <Var name="customer" type="Customer"/>
+               </Input>
+               <Call lang="php" method="WOCustomer::createCustomer($this);"/>
+               <Output>
+                       <Var name="customer" type="Customer"/>
+               </Output>
+       </Transaction>
+       
+       <Transaction name="ChangeCustomer">
+               <Input>
+                       <Var name="customer" type="Customer"/>
+               </Input>
+               <Call lang="php" method="WOCustomer::changeCustomer($this);"/>
+               <Output>
+                       <Var name="customer" type="Customer"/>
+               </Output>
+       </Transaction>
+       
        <Transaction name="DeleteCustomer">
                <Input>
                        <Var name="customerid" type="int"/>
                        <Var name="mergewithid" type="int"/>
                </Input>
        </Transaction>
+       
+       <Transaction name="GetAddress">
+               <Input>
+                       <Var name="addressid" type="int64"/>
+               </Input>
+               <Call lang="php" method="$this->setaddress(WOAddress::fromTableaddress(WTaddress::getFromDB($this->getaddressid())));"/>
+               <Output>
+                       <Var name="address" type="Address"/>
+               </Output>
+       </Transaction>
+       
+       <Transaction name="GetAllCountries">
+               <Input/>
+               <Call lang="php" method="$this->setcountries(WOCountry::fromTableArraycountry(WTcountry::selectFromDB()));"/>
+               <Output>
+                       <Var name="countries" type="List:Country"/>
+               </Output>
+       </Transaction>
+       
+       <Transaction name="CreateCountry">
+               <Input>
+                       <Var name="abbrev" type="astring"/>
+                       <Var name="name" type="astring"/>
+               </Input>
+               <!-- implemented in customer, since it is the only main object using this -->
+               <Call lang="php" method="WOCustomer::createCountry($this);"/>
+               <Output>
+                       <Var name="country" type="Country"/>
+               </Output>
+       </Transaction>
 </Wolf>
\ No newline at end of file
index 137317c..87462f0 100644 (file)
@@ -210,6 +210,9 @@ abstract class DbEngine
                        if($dbScheme->isBlobColumn($table,$k))
                                $val.=$this->escapeBlob($v);
                        else
+                       if($dbScheme->isBoolColumn($table,$k))
+                               $val.=$this->escapeBool($v);
+                       else
                                //don't know how to escape it...
                                $val.="NULL";
                }
index 83d13a8..3433025 100644 (file)
@@ -245,6 +245,15 @@ class MysqlEngine extends DbEngine
                if($s === false||$s===null) return "NULL";
                return "'".mysqli_real_escape_string($this->dbhdl,$s)."'";
        }
+       
+       /**escapes booleans, overwrites the orignal to use "0" and "1" instead of "FALSE" and "TRUE"*/
+       public function escapeBool($b)
+       {
+               $r=DbEngine::escapeBool($b);
+               if($r=="TRUE")return "1";
+               if($r=="FALSE")return "0";
+               return $r;
+       }
 };
 
 ?>
\ No newline at end of file
index 7d3de02..09f164d 100644 (file)
@@ -83,6 +83,12 @@ class WobTransactionBase {
                print("<WobResponse status=\"error\"><Error type=\"".xq($type)."\">".xq($text)."</Error></WobResponse>\n");
                exit();
        }
+       
+       /**called internally if a transaction is not implemented*/
+       protected function abortNotImplemented()
+       {
+               $this->abortWithError(tr("Transaction not implemented."));
+       }
 };
 
 ?>
\ No newline at end of file
index 5eadba0..82096e7 100644 (file)
@@ -12,6 +12,7 @@
 //
 
 $AUTOCLASS["WOArtist"]="inc/wext/artist.php";
+$AUTOCLASS["WOCustomer"]="inc/wext/customer.php";
 $AUTOCLASS["WOEventPrice"]="inc/wext/event.php";
 $AUTOCLASS["WOEvent"]="inc/wext/event.php";
 $AUTOCLASS["WOOrder"]="inc/wext/order.php";
diff --git a/www/inc/wext/customer.php b/www/inc/wext/customer.php
new file mode 100644 (file)
index 0000000..412df14
--- /dev/null
@@ -0,0 +1,161 @@
+<?
+//
+// PHP Implementation: customer
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2010
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+class WOCustomer extends WOCustomerAbstract
+{
+       /**called from CreateCustomer transaction*/
+       public static function createCustomer($trans)
+       {
+               global $db;
+               $cc=$trans->getcustomer();
+               if(!is_a($cc,"WOCustomer")){
+                       $trans->abortWithError(tr("Not a valid customer object."));
+                       return;
+               }
+               //create customer
+               $ct=WTcustomer::newRow();
+               $cc->toTablecustomer($ct);
+               $ct->revert("customerid");
+               $ct->insert();
+               $cc->set_id($ct->customerid);
+               //create addresses
+               foreach($cc->get_addresses() as $addr){
+                       //skip addresses that are deleted
+                       if($addr->get_isdeleted())continue;
+                       $at=WTaddress::newRow();
+                       $addr->toTableaddress($at);
+                       $at->revert("addressid");
+                       $at->customerid=$cc->get_id();
+                       if($at->insert()===false){
+                               $trans->abortWithError("Database Error: ".$db->lastError());
+                               return;
+                       }
+//                     print_r($at);
+               }
+               //create contacts
+               foreach($cc->get_contacts() as $cont){
+                       $cn=WTcontact::newRow();
+                       $cont->toTablecontact($cn);
+                       $cn->revert("contactid");
+                       $cn->customerid=$cc->get_id();
+                       $cn->insert();
+               }
+               
+               //return
+               $trans->setcustomer(WOCustomer::fromTablecustomer($ct));
+       }
+       
+       /**called from ChangeCustomer transaction*/
+       public static function changeCustomer($trans)
+       {
+               global $db;
+               $cc=$trans->getcustomer();
+               if(!is_a($cc,"WOCustomer")){
+                       $trans->abortWithError(tr("Not a valid customer object."));
+                       return;
+               }
+               $ct=WTcustomer::getFromDB($cc->get_id());
+               if(!is_a($ct,"WTcustomer")){
+                       $trans->abortWithError(tr("Customer does not exist in the database."));
+                       return;
+               }
+               //create customer
+               $cc->toTablecustomer($ct);
+               if($ct->isChanged())$ct->update();
+               //sync addresses
+               foreach($cc->get_addresses() as $addr){
+                       $at=WTaddress::getFromDB($addr->get_addressid());
+                       //new address?
+                       $na=false;
+                       if(!is_a($at,"WTaddress")){
+                               $na=true;
+                               $at=WTaddress::newRow();
+                       }
+                       if($at->customerid != $cc->get_id())$na=true;
+                       //push data
+                       $addr->toTableaddress($at);
+                       $at->revert("customerid");
+                       $at->revert("addressid");
+                       if($na){
+                               //its new, force insert
+                               $at->addressid=null;
+                               $at->isdeleted=0;
+                               $at->customerid=$cc->get_id();
+                               if($at->insert()===false){
+                                       $trans->abortWithError("Database Error: ".$db->lastError());
+                                       return;
+                               }
+                       }else{
+                               //its known
+                               if($at->isChanged())$at->update();
+                       }
+               }
+               //sync contacts
+               foreach($cc->get_contacts() as $cont){
+                       $cn=WTcontact::getFromDB($cont->get_contactid());
+                       //new one?
+                       $nc=false;
+                       if(!is_a($cn,"WTcontact")){
+                               $cn=WTcontact::newRow();
+                               $nc=true;
+                       }
+                       if($cn->customerid != $cc->get_id())$nc=true;
+                       //push data
+                       $cont->toTablecontact($cn);
+                       $cn->revert("contactid");
+                       $cn->revert("customerid");
+                       if($nc){
+                               //new one, insert
+                               $cn->customerid=$cc->get_id();
+                               $cn->insert();
+                       }else{
+                               //known one, update
+                               if($cn->isChanged())$cn->update();
+                       }
+               }
+               
+               //return
+               $trans->setcustomer(WOCustomer::fromTablecustomer($ct));
+       }
+
+       /**called from CreateCountry transaction*/
+       public static function createCountry($trans)
+       {
+               $id=trim($trans->getabbrev());
+               $nm=trim($trans->getname());
+               if($id=="" || $nm==""){
+                       $trans->abortWithError(tr("Country ID and name must contain values!"));
+                       return;
+               }
+               //check for existence
+               global $db;
+               $res=$db->select("country","*","countryid=".$db->escapeString($id));
+               if(count($res)>0){
+                       $trans->abortWithError(tr("Country ID exists!"));
+                       return;
+               }
+               $res=$db->select("country","*","countryname=".$db->escapeString($nm));
+               if(count($res)>0){
+                       $trans->abortWithError(tr("Country name exists!"));
+                       return;
+               }
+               //create
+               $tab=WTcountry::newRow();
+               $tab->countryid=$id;
+               $tab->countryname=$nm;
+               $tab->insert();
+               //return
+               $trans->setcountry(WOCountry::fromTablecountry($tab));
+       }
+};
+?>
\ No newline at end of file