/*
 * This file is part of the xTuple ERP: PostBooks Edition, a free and
 * open source Enterprise Resource Planning software suite,
 * Copyright (c) 1999-2009 by OpenMFG LLC, d/b/a xTuple.
 * It is licensed to you under the Common Public Attribution License
 * version 1.0, the full text of which (including xTuple-specific Exhibits)
 * is available at www.xtuple.com/CPAL.  By using this software, you agree
 * to be bound by its terms.
 */

#include "unpostedPurchaseOrders.h"

#include <QMenu>
#include <QMessageBox>
#include <QSqlError>
#include <QVariant>
#include <QWorkspace>

#include <metasql.h>
#include <parameter.h>

#include "purchaseOrder.h"
#include "printPurchaseOrder.h"
#include "guiclient.h"
#include "deliverPurchaseOrder.h"
#include "storedProcErrorLookup.h"

unpostedPurchaseOrders::unpostedPurchaseOrders(QWidget* parent, const char* name, Qt::WFlags fl)
    : XWidget(parent, name, fl)
{
    setupUi(this);

    connect(_allOpenOrders,SIGNAL(clicked()),	this,	SLOT(sFillList()));
    connect(_delete,	SIGNAL(clicked()),	this,	SLOT(sDelete()));
    connect(_edit,	SIGNAL(clicked()),	this,	SLOT(sEdit()));
    connect(_new,	SIGNAL(clicked()),	this,	SLOT(sNew()));
    connect(_pohead,	SIGNAL(populateMenu(QMenu *, QTreeWidgetItem *)),
						this,	SLOT(sPopulateMenu(QMenu*, QTreeWidgetItem *)));
    connect(_pohead,	SIGNAL(valid(bool)),	this,	SLOT(sHandleButtons()));
    connect(_post,	SIGNAL(clicked()),	this,	SLOT(sPost()));
    connect(_print,	SIGNAL(clicked()),	this,	SLOT(sPrint()));
    connect(_view,	SIGNAL(clicked()),	this,	SLOT(sView()));

    connect(omfgThis,	SIGNAL(purchaseOrdersUpdated(int, bool)),
						this,	SLOT(sFillList()));

    _pohead->addColumn(tr("P/O #"),     _orderColumn, Qt::AlignLeft,   true, "pohead_number" );
    _pohead->addColumn(tr("Vendor"),    -1,           Qt::AlignLeft,   true, "vend_name"   );
    _pohead->addColumn(tr("Due Date"),  _dateColumn,  Qt::AlignCenter, true, "min_duedate" );
    _pohead->addColumn(tr("Status"),    _ynColumn,    Qt::AlignCenter, true, "pohead_status" );
    _pohead->addColumn(tr("Printed"),   _ynColumn,    Qt::AlignCenter, true, "pohead_printed");

    _pohead->setSelectionMode(QAbstractItemView::ExtendedSelection);

    if (_privileges->check("MaintainPurchaseOrders"))
      _new->setEnabled(TRUE);

    sFillList();
}

unpostedPurchaseOrders::~unpostedPurchaseOrders()
{
  // no need to delete child widgets, Qt does it all for us
}

void unpostedPurchaseOrders::languageChange()
{
    retranslateUi(this);
}

void unpostedPurchaseOrders::sNew()
{
  ParameterList params;
  params.append("mode", "new");

  purchaseOrder *newdlg = new purchaseOrder();
  newdlg->set(params);
  omfgThis->handleNewWindow(newdlg);
}

void unpostedPurchaseOrders::sEdit()
{
  QList<QTreeWidgetItem*> list = _pohead->selectedItems();
  bool done = false;
  for (int i = 0; i < list.size(); i++)
  {
    if (((list[i]->text(3) == "U" && _privileges->check("MaintainPurchaseOrders")) ||
	(list[i]->text(3) == "O" && _privileges->check("MaintainPostedPurchaseOrders"))) &&
        (checkSitePrivs(((XTreeWidgetItem*)(list[i]))->id())))
    {
      ParameterList params;
      params.append("mode", "edit");
      params.append("pohead_id", ((XTreeWidgetItem*)(list[i]))->id());
  
      purchaseOrder *newdlg = new purchaseOrder();
      newdlg->set(params);
      omfgThis->handleNewWindow(newdlg);
      done = true;
      break;
    }
  }
  if (done)
    omfgThis->sPurchaseOrdersUpdated(-1, TRUE);
  else
    QMessageBox::information(this, tr("Nothing To Edit"),
			     tr("<p>There were no selected Purchase Orders "
				"that you could edit."),
			     QMessageBox::Ok|QMessageBox::Default);
}

void unpostedPurchaseOrders::sView()
{
  QList<QTreeWidgetItem*> list = _pohead->selectedItems();
  for (int i = 0; i < list.size(); i++)
  {
    if (checkSitePrivs(((XTreeWidgetItem*)(list[i]))->id()))
    {
      
      ParameterList params;
      params.append("mode", "view");
      params.append("pohead_id", ((XTreeWidgetItem*)(list[i]))->id());
    
      purchaseOrder *newdlg = new purchaseOrder();
      newdlg->set(params);
      omfgThis->handleNewWindow(newdlg);
      break;
    }
  }
}

void unpostedPurchaseOrders::sDelete()
{
  if ( QMessageBox::question(this, tr("Delete Selected Purchase Orders"),
                             tr("<p>Are you sure that you want to delete the "
			        "selected Purchase Orders?" ),
                             QMessageBox::Yes,
                             QMessageBox::No | QMessageBox::Default) == QMessageBox::Yes)
  {
    q.prepare("SELECT deletePo(:pohead_id) AS result;");

    QList<QTreeWidgetItem*> list = _pohead->selectedItems();
    bool done = false;
    for (int i = 0; i < list.size(); i++)
    {
      if (checkSitePrivs(((XTreeWidgetItem*)(list[i]))->id()))
      {
        if (list[i]->text(3) == "U")
        {
          q.bindValue(":pohead_id", ((XTreeWidgetItem*)(list[i]))->id());
          q.exec();
          if (q.first() && ! q.value("result").toBool())
              systemError(this, tr("<p>Only Unposted Purchase Orders may be "
                                   "deleted. Check the status of Purchase Order "
                                   "%1. If it is 'U' then contact your system "
                                   "Administrator.").arg(list[i]->text(0)),
                          __FILE__, __LINE__);
          else if (q.lastError().type() != QSqlError::NoError)
            systemError(this, q.lastError().databaseText(), __FILE__, __LINE__);
          else
            done = true;
        }
      }
    }
    if (done)
      omfgThis->sPurchaseOrdersUpdated(-1, TRUE);
    else
      QMessageBox::information(this, tr("Nothing To Delete"),
			       tr("<p>There were no selected Purchase Orders "
				  "that could be deleted."),
			       QMessageBox::Ok|QMessageBox::Default);
  }
}

void unpostedPurchaseOrders::sPrint()
{    
  QList<QTreeWidgetItem*> list = _pohead->selectedItems();
  for (int i = 0; i < list.size(); i++)
  {
    if (checkSitePrivs(((XTreeWidgetItem*)(list[i]))->id()))
    {
      ParameterList params;
      params.append("pohead_id", ((XTreeWidgetItem*)(list[i]))->id());
    
      printPurchaseOrder newdlg(this, "", TRUE);
      newdlg.set(params);
      newdlg.exec();
      break;
    }
  }
  sFillList();
}

void unpostedPurchaseOrders::sDeliver()
{
  QList<QTreeWidgetItem*> list = _pohead->selectedItems();
  for (int i = 0; i < list.size(); i++)
  {
    if (checkSitePrivs(((XTreeWidgetItem*)(list[i]))->id()))
    {
      ParameterList params;
      params.append("pohead_id", ((XTreeWidgetItem*)(list[i]))->id());
    
      deliverPurchaseOrder newdlg(this, "", TRUE);
      newdlg.set(params);
      newdlg.exec();
      break;
    }
  }
}

void unpostedPurchaseOrders::sPost()
{    
  if ( QMessageBox::warning( this, tr("Post Selected Purchase Orders"),
                             tr("<p>Are you sure that you want to post "
			        "the selected Purchase Orders?" ),
                             tr("&Yes"), tr("&No"), QString::null, 0, 1 ) == 0)
  {
    q.prepare("SELECT postPurchaseOrder(:pohead_id) AS result;");

    QList<QTreeWidgetItem*> list = _pohead->selectedItems();
    bool done = false;
    for (int i = 0; i < list.size(); i++)
    {
      if ((list[i]->text(3) == "U")
        && (_privileges->check("PostPurchaseOrders"))
        && (checkSitePrivs(((XTreeWidgetItem*)(list[i]))->id())))
      {
        q.bindValue(":pohead_id", ((XTreeWidgetItem*)(list[i]))->id());
        q.exec();
        if (q.first())
        {
          int result = q.value("result").toInt();
          if (result < 0)
            systemError(this, storedProcErrorLookup("postPurchaseOrder", result),
                        __FILE__, __LINE__);
          else
			done = true;
		}
        else if (q.lastError().type() != QSqlError::NoError)
          systemError(this, q.lastError().databaseText(), __FILE__, __LINE__);
      }
    }
    if (done)
      omfgThis->sPurchaseOrdersUpdated(-1, TRUE);
    else
      QMessageBox::information(this, tr("Nothing To Post"),
			       tr("<p>There were no selected Purchase Orders "
				  "to be posted."),
			       QMessageBox::Ok|QMessageBox::Default);
  }
}

void unpostedPurchaseOrders::sPopulateMenu(QMenu *pMenu, QTreeWidgetItem *pItem)
{
  int menuItem;

  bool canMaintain = (pItem->text(3) == "U" && _privileges->check("MaintainPurchaseOrders")) ||
		     (pItem->text(3) == "O" && _privileges->check("MaintainPostedPurchaseOrders"));

  menuItem = pMenu->insertItem(tr("Edit..."), this, SLOT(sEdit()), 0);
  pMenu->setItemEnabled(menuItem, canMaintain);

  menuItem = pMenu->insertItem(tr("View..."), this, SLOT(sView()), 0);
  pMenu->setItemEnabled(menuItem, canMaintain || _privileges->check("ViewPurchaseOrders"));

  menuItem = pMenu->insertItem(tr("Delete..."), this, SLOT(sDelete()), 0);
  pMenu->setItemEnabled(menuItem, (pItem->text(3) == "U" && _privileges->check("MaintainPurchaseOrders")));

  pMenu->insertSeparator();

  menuItem = pMenu->insertItem(tr("Print..."), this, SLOT(sPrint()), 0);
  pMenu->setItemEnabled(menuItem, canMaintain);

  if (_metrics->boolean("EnableBatchManager"))
  {
    menuItem = pMenu->insertItem(tr("Deliver..."), this, SLOT(sDeliver()), 0);
    pMenu->setItemEnabled(menuItem, canMaintain);
  }

  menuItem = pMenu->insertItem(tr("Post..."), this, SLOT(sPost()), 0);
  pMenu->setItemEnabled(menuItem, _privileges->check("PostPurchaseOrders") &&
				  pItem->text(3) == "U");
}

void unpostedPurchaseOrders::sHandleButtons()
{
  // see if the selected items list contains both unposted and open/posted items
  bool unposted = false;
  bool open = false;
  QList<QTreeWidgetItem*> list = _pohead->selectedItems();
  for (int i = 0; i < list.size(); i++)
  {
    if (! unposted && list[i]->text(3) == "U")
      unposted = true;
    if (! open && list[i]->text(3) == "O")
      open = true;
    if (open && unposted)
      break;
  }

  _delete->setEnabled(unposted && _privileges->check("MaintainPurchaseOrders"));
  _edit->setEnabled((unposted && _privileges->check("MaintainPurchaseOrders")) ||
		    (open && _privileges->check("MaintainPostedPurchaseOrders")));
  _post->setEnabled(unposted && _privileges->check("PostPurchaseOrders"));
  _print->setEnabled((unposted && _privileges->check("MaintainPurchaseOrders")) ||
		     (open && _privileges->check("MaintainPostedPurchaseOrders")));

  if ((unposted && _privileges->check("MaintainPurchaseOrders")) ||
      (open && _privileges->check("MaintainPostedPurchaseOrders")))
  {
    disconnect(_pohead, SIGNAL(itemSelected(int)), _view, SLOT(animateClick()));
    connect(_pohead, SIGNAL(itemSelected(int)), _edit, SLOT(animateClick()));
  }
  else
  {
    disconnect(_pohead, SIGNAL(itemSelected(int)), _edit, SLOT(animateClick()));
    connect(_pohead, SIGNAL(itemSelected(int)), _view, SLOT(animateClick()));
  }
}

void unpostedPurchaseOrders::sFillList()
{
  _pohead->clear();

  ParameterList params;
  if (_allOpenOrders->isChecked())
    params.append("showPosted");

  QString sql( "SELECT pohead_id, pohead_number, vend_name,"
               "       MIN(poitem_duedate) AS min_duedate, "
               "       pohead_status, pohead_printed "
               "FROM vend, pohead LEFT OUTER JOIN "
               "     poitem ON (poitem_pohead_id=pohead_id) "
               "WHERE ( (pohead_vend_id=vend_id)"
               "<? if exists(\"showPosted\") ?> "
               "  AND (pohead_status IN ('U', 'O') ) "
               "  AND (pohead_id NOT IN (SELECT vohead_pohead_id"
               "                         FROM vohead"
               "                         WHERE vohead_pohead_id IS NOT NULL))"
               "<? else ?> "
               "  AND (pohead_status='U') "
               "<? endif ?> "
               ") "
               "GROUP BY pohead_number, pohead_id, vend_name, pohead_status, "
               "         pohead_printed "
               "ORDER BY pohead_number;" );
  MetaSQLQuery mql(sql);
  q = mql.toQuery(params);
  if (q.lastError().type() != QSqlError::NoError)
  {
    systemError(this, q.lastError().databaseText(), __FILE__, __LINE__);
    return;
  }
  _pohead->populate(q);
}

bool unpostedPurchaseOrders::checkSitePrivs(int orderid)
{
  if (_preferences->boolean("selectedSites"))
  {
    XSqlQuery check;
    check.prepare("SELECT checkPOSitePrivs(:poheadid) AS result;");
    check.bindValue(":poheadid", orderid);
    check.exec();
    if (check.first())
    {
    if (!check.value("result").toBool())
      {
        QMessageBox::critical(this, tr("Access Denied"),
                              tr("<p>You may not view or edit this Purchase "
                                 "Order as it references a Site for which you "
                                 "have not been granted privileges.")) ;
        return false;
      }
    }
  }
  return true;
}
