public function add()
 {
     $db = Database::getInstance();
     $session = Session::getInstance();
     $log = Log::getInstance();
     $amount = 0;
     $res = false;
     $user = $db->escape($session->userinfo['firstname'] . " " . $session->userinfo['lastname']);
     foreach ($this->detail as $detail) {
         $amount += $detail->price * $detail->quantity;
     }
     $sql = "INSERT INTO " . TBL_SELL . " " . "(`date`,date_created,date_modified," . "customer,amount,prepayment,payment_type," . "gloss,status,nit," . "storeid,created_by,updated_by)" . " VALUES " . "('{$this->date}',NOW(),NOW()," . "'" . $db->escape($this->customer) . "',{$amount},{$this->prepayment},{$this->paymentType}," . "'" . $db->escape($this->gloss) . "'," . PURCHASE_STATUS_PENDING . ",'" . $db->escape($this->nit) . "'," . "{$this->storeid},'{$user}','{$user}')";
     $db->startTransaction();
     $res = $db->query($sql);
     if (!$res) {
         $db->rollback();
         $log->addError("No se puedo agregar Venta, verifique los datos ingresados.");
         return false;
     }
     $sellid = $db->lastID();
     if ($this->paymentType == PAYMENT_TYPE_CASH) {
         $this->prepayment = $amount;
     }
     if ($this->prepayment > 0) {
         $sql = "INSERT INTO " . TBL_SELL_PAYMENT . " (sellid,line,`date`,amount,created_by,updated_by)" . " VALUES " . "({$sellid},1,NOW(),{$this->prepayment},'{$user}','{$user}')";
         $res = $db->query($sql);
         if (!$res) {
             $db->rollback();
             $log->addError("Problemas para agregar el anticipo de Venta especificado.");
             return false;
         }
     }
     foreach ($this->detail as $detail) {
         //if (!$detail->quantity || !$detail->price)
         //	continue;
         // Check available stock
         $sql = "SELECT stock,unidades units_per_box FROM " . TBL_LOT . " WHERE id={$detail->lotid}";
         $res = $db->query($sql);
         if (!$res) {
             $db->rollback();
             $log->addError("No se puede verificar stock disponible de lote {$detail->lotid}.");
             return false;
         }
         if ($db->rows($res) != 1) {
             $db->dispose($res);
             $db->rollback();
             $log->addError("Lote {$detail->lotid} no está disponible.");
             return false;
         }
         $row = $db->getRow($res);
         $quantity = $detail->quantity;
         $units = 1;
         if ($detail->unit == UNIT_TYPE_BOX) {
             $units = $row['units_per_box'];
             $quantity = $detail->quantity * $units;
         } else {
             if ($detail->unit == UNIT_TYPE_PACKAGE) {
                 // TODO
             }
         }
         if ($row['stock'] < $quantity) {
             $db->dispose($res);
             $db->rollback();
             $log->addError("Stock insuficiente en lote {$detail->lotid}.");
             return false;
         }
         // Update stock for lot
         $sql = "UPDATE " . TBL_LOT . " SET stock=stock-{$quantity} WHERE id={$detail->lotid}";
         $res = $db->query($sql);
         if (!$res) {
             $db->rollback();
             $log->addError("No se puede no se puede actualizar stock de lote {$detail->lotid}.");
             return false;
         }
         // Insert detail
         $item = Item::getFromLot($detail->lotid);
         $detail->description = $item->name;
         $sql = "INSERT INTO " . TBL_SELL_DETAIL . " (sellid,line,description,quantity,price,unit_type,units)" . " VALUES " . "({$sellid},{$detail->line},'{$detail->description}',{$detail->quantity},{$detail->price},'{$detail->unit}',{$units})";
         $res = $db->query($sql);
         if (!$res) {
             $db->rollback();
             $log->addError("Problemas para agregar el detalle de Venta especificado.");
             return false;
         }
     }
     if (!$db->commit()) {
         return false;
     }
     $this->id = $sellid;
     return true;
 }