示例#1
0
 protected function setUp()
 {
     // Products
     $taxCat = new TaxCat("Tax");
     $tax = new Tax(null, "Tax", stdtimefstr("2001-01-01 00:00:00"), 0.1);
     $taxCat->addTax($tax);
     $taxCat->id = TaxesService::createCat($taxCat);
     $cat = new Category(null, "Category", false, 1);
     $cat->id = CategoriesService::createCat($cat);
     $prd1 = new Product("REF", "product", 1.0, $cat->id, null, 1, $taxCat->id, true, true, 0.3, null, "12345", false, true, 0.2);
     $prd1->id = ProductsService::create($prd1);
     $prd2 = new Product("REF2", "product2", 2.0, $cat->id, null, 3, $taxCat->id, true, false);
     $prd2->id = ProductsService::create($prd2);
     $this->products = array($prd1, $prd2);
     // Locations
     $locSrv = new LocationsService();
     $loc1 = new Location("Location1");
     $loc1->id = $locSrv->create($loc1);
     $loc2 = new Location("Location2");
     $loc2->id = $locSrv->create($loc2);
     $this->locations = array($loc1, $loc2);
     // Stocks
     $lvl11 = new StockLevel($prd1->id, $loc1->id, null, null, 10);
     $lvl11->id = StocksService::createLevel($lvl11);
     $lvl12 = new StockLevel($prd1->id, $loc2->id, null, 5.2, null);
     $lvl12->id = StocksService::createLevel($lvl12);
     $lvl21 = new StockLevel($prd2->id, $loc1->id, null, 7, 20);
     $lvl21->id = StocksService::createLevel($lvl21);
     $move = new StockMove(stdtimefstr("2014-01-01 00:00:00"), StockMove::REASON_IN_BUY, $loc1->id, $prd1->id, null, 3.5, 2.1);
     StocksService::addMove($move);
     $this->levels = array($lvl11, $lvl12, $lvl21);
 }
示例#2
0
 protected function proceed()
 {
     switch ($this->action) {
         case 'getAll':
             $this->succeed(StocksService::getLevels($this->params['locationId']));
             break;
     }
 }
 static function delete($id)
 {
     $pdo = PDOBuilder::getPDO();
     $db = DB::get();
     $ticket = TicketsService::get($id);
     if ($ticket === null) {
         return false;
     }
     $cashSrv = new CashesService();
     $cash = $cashSrv->get($ticket->cashId);
     if ($cash === null || $cash->isClosed()) {
         return false;
     }
     $cashRegSrv = new CashRegistersService();
     $cashReg = $cashRegSrv->getFromCashId($cash->id);
     // As cash must be opened, cashregister location is considered accurate
     $locationId = $cashReg->locationId;
     $newTransaction = !$pdo->inTransaction();
     if ($newTransaction) {
         $pdo->beginTransaction();
     }
     // Delete ticket lines
     // Also check for prepayments refill
     $stmtLines = $pdo->prepare("DELETE FROM TICKETLINES " . "WHERE TICKET = :id");
     $stmtLines->bindParam(":id", $ticket->id);
     foreach ($ticket->lines as $line) {
         // Update stock
         if ($line->productId !== null) {
             $discountRate = $ticket->discountRate;
             $fullDiscount = $discountRate + $line->discountRate;
             $discountPrice = $line->price * (1.0 - $fullDiscount);
             $move = new StockMove($ticket->date, StockMove::REASON_IN_REFUND, $line->productId, $locationId, $line->attrSetInstId, $line->quantity, $discountPrice);
             if (StocksService::addMove($move) === false) {
                 if ($newTransaction) {
                     $pdo->rollback();
                 }
                 return false;
             }
         }
         // Check prepayment refill
         // Refill is not affected by discount
         $prepaidIds = ProductsService::getPrepaidIds();
         if ($ticket->customerId !== null && in_array($line->productId, $prepaidIds)) {
             $custSrv = new CustomersService();
             $ok = $custSrv->addPrepaid($ticket->customerId, -$line->price * $line->quantity);
             if ($ok === false) {
                 if ($newTransaction) {
                     $pdo->rollback();
                 }
                 return false;
             }
         }
     }
     if ($stmtLines->execute() === false) {
         if ($newTransaction) {
             $pdo->rollback();
         }
         return false;
     }
     // Delete payments
     // Also check for prepayment debit and debt
     $stmtPay = $pdo->prepare("DELETE FROM PAYMENTS WHERE RECEIPT = :id");
     $stmtPay->bindParam(":id", $ticket->id);
     foreach ($ticket->payments as $payment) {
         if ($payment->type == 'prepaid' || $payment->type == 'debt') {
             $custSrv = new CustomersService();
             if ($payment->type == 'prepaid') {
                 $ok = $custSrv->addPrepaid($ticket->customerId, $payment->amount);
             } else {
                 $ok = $custSrv->recoverDebt($ticket->customerId, $payment->amount);
             }
             if ($ok === false) {
                 if ($newTransaction) {
                     $pdo->rollback();
                 }
                 return false;
             }
         }
     }
     if ($stmtPay->execute() === false) {
         if ($newTransaction) {
             $pdo->rollback();
         }
         return false;
     }
     // Delete taxlines
     $stmtTax = $pdo->prepare("DELETE FROM TAXLINES WHERE RECEIPT = :id");
     $stmtTax->bindParam(":id", $ticket->id);
     if ($stmtTax->execute() === false) {
         if ($newTransaction) {
             $pdo->rollback();
         }
         return false;
     }
     //  Delete ticket
     $discountRate = $ticket->discountRate;
     $stmtTkt = $pdo->prepare("DELETE FROM TICKETS WHERE ID = :id");
     $stmtTkt->bindParam(':id', $ticket->id);
     if ($stmtTkt->execute() === false) {
         if ($newTransaction) {
             $pdo->rollback();
         }
         return false;
     }
     // Delete receipt
     $stmtRcpt = $pdo->prepare("DELETE FROM RECEIPTS WHERE ID = :id");
     $stmtRcpt->bindParam(":id", $ticket->id);
     if ($stmtRcpt->execute() === false) {
         if ($newTransaction) {
             $pdo->rollback();
         }
         return false;
     }
     if ($newTransaction) {
         $pdo->commit();
     }
     return true;
 }
 /** @depends testCreateMoveBuy
  * @depends testReadLevel
  */
 public function testReadQty()
 {
     $level = new StockLevel($this->products[0]->id, $this->locations[0]->id, null, 1.2, 15.6, 3.5);
     // Quantity is set matching to move
     $level->id = StocksService::createLevel($level);
     $move = new StockMove(stdtimefstr("2014-01-01 00:00:00"), StockMove::REASON_IN_BUY, $level->productId, $level->locationId, $level->attrSetInstId, $level->qty, 10);
     $move->id = StocksService::addMove($move);
     $read = StocksService::getLevel($move->productId, $move->locationId, $move->attrSetInstId);
     $this->checkEquality($read, $level);
 }
 /** @depends testSaveLine */
 function testSaveMultiLines()
 {
     $date = stdtimefstr("2013-01-01 00:00:00");
     $attrSetInst = new AttributeSetInstance($this->attrSet->id, "Value");
     $attrsId = TicketsService::createAttrSetInst($attrSetInst);
     $line1 = new TicketLine(1, $this->prd, $attrSetInst->id, 1, 12, $this->tax);
     $line2 = new TicketLine(2, $this->prd2, null, 2, 10, $this->tax2);
     $line3 = new TicketLine(3, $this->prd, null, 1.5, 10, $this->tax);
     $payment1 = new Payment("cash", 12, $this->currency->id, 14);
     $payment2 = new Payment("cheque", 25, $this->currency->id, 20);
     $ticket = new Ticket(Ticket::TYPE_SELL, $this->user->id, $date, array($line1, $line2, $line3), array($payment1, $payment2), $this->cash->id, null, null);
     $id = TicketsService::save($ticket, $this->location->id);
     $pdo = PDOBuilder::getPDO();
     $db = DB::get();
     // Check sale lines
     $stmtLines = $pdo->prepare("SELECT * FROM TICKETLINES");
     $this->assertNotEquals($stmtLines->execute(), false, "Ticket query failed");
     $toCheck = array($line1, $line2, $line3);
     $count = 0;
     while ($row = $stmtLines->fetch()) {
         $ref = null;
         $count++;
         if ($row['LINE'] == 1) {
             $ref = $line1;
         } else {
             if ($row['LINE'] == 2) {
                 $ref = $line2;
             } else {
                 if ($row['LINE'] == 3) {
                     $ref = $line3;
                 }
             }
         }
         $this->assertNotNull($ref, "Unknown line");
         $this->checkSaleEquality($id, $ref, $row);
         for ($i = 0; $i < count($toCheck); $i++) {
             $l = $toCheck[$i];
             if ($l->dispOrder == $ref->dispOrder) {
                 array_splice($toCheck, $i, 1);
                 break;
             }
         }
     }
     $this->assertEquals(3, $count, "Sale line count mismatch");
     $this->assertEquals(0, count($toCheck), "Duplicated sale lines");
     // Check tax lines
     $stmtTax = $pdo->prepare("SELECT * FROM TAXLINES");
     $this->assertNotEquals($stmtTax->execute(), false, "Tax lines query failed");
     $toCheck = array($this->tax->id, $this->tax2->id);
     for ($i = 0; $i < 2; $i++) {
         $row = $stmtTax->fetch();
         $this->assertNotEquals(false, $row, "Not enough tax line found");
         $ref = null;
         if ($row['TAXID'] == $this->tax->id) {
             $ref = $this->tax->id;
             $this->checkTaxEquality($id, $ref, 27, 2.7, $row);
         } else {
             if ($row['TAXID'] == $this->tax2->id) {
                 $ref = $this->tax2->id;
                 $this->checkTaxEquality($id, $ref, 20, 4, $row);
             }
         }
         $this->assertNotNull($ref, "Unknown tax line");
         foreach ($toCheck as $j => $taxId) {
             if ($ref == $taxId) {
                 array_splice($toCheck, $j, 1);
                 break;
             }
         }
     }
     $this->assertEquals(0, count($toCheck), "Duplicated tax lines");
     $row = $stmtTax->fetch();
     $this->assertFalse($row, "Too much tax lines found");
     // Check payment lines
     $toCheck = array($payment1, $payment2);
     $stmtPmt = $pdo->prepare("SELECT * FROM PAYMENTS");
     $this->assertNotEquals($stmtPmt->execute(), false, "Payment lines query failed");
     $count = 0;
     while ($row = $stmtPmt->fetch()) {
         $ref = null;
         $count++;
         if ($row['PAYMENT'] == "cash") {
             $ref = $payment1;
         } else {
             if ($row['PAYMENT'] == "cheque") {
                 $ref = $payment2;
             }
         }
         $this->assertNotNull($ref, "Unknown line");
         $this->checkPaymentEquality($id, $ref, $row);
         foreach ($toCheck as $i => $pmt) {
             if ($pmt->type == $ref->type) {
                 array_splice($toCheck, $i, 1);
                 break;
             }
         }
     }
     $this->assertEquals(2, $count, "Payment line count mismatch");
     $this->assertEquals(0, count($toCheck), "Duplicated payment lines");
     // Check stocks
     $level = StocksService::getLevel($this->prd->id, $this->location->id, null);
     $this->assertEquals(-1.5, $level->qty);
     $level = StocksService::getLevel($this->prd2->id, $this->location->id, null);
     $this->assertEquals(-2, $level->qty);
     $this->markTestIncomplete("Check stock level with attribute");
 }
 /** Create an inventory. If date, missingQty or unitValue is null they are
  * computed from current stock and current date. */
 public function create($inventory)
 {
     $pdo = PDOBuilder::getPDO();
     $db = DB::get();
     $newTransaction = !$pdo->inTransaction();
     if ($newTransaction) {
         $pdo->beginTransaction();
     }
     if ($inventory->date === null) {
         // Set date to now
         $inventory->date = time();
     }
     // Insert inventory
     $invStmt = $pdo->prepare("INSERT INTO STOCK_INVENTORY (DATE, " . "LOCATION_ID) VALUES (:date, :locId)");
     $invStmt->bindParam(":date", $db->dateVal($inventory->date));
     $invStmt->bindParam(":locId", $inventory->locationId);
     if ($invStmt->execute() !== false) {
         $id = $pdo->lastInsertId(static::$dbTable . "_" . static::$dbIdField . "_seq");
     } else {
         if ($newTransaction) {
             $pdo->rollback();
         }
         return false;
     }
     // Parse and insert items
     $stmt = $pdo->prepare("INSERT INTO STOCK_INVENTORYITEM (INVENTORY_ID, " . "PRODUCT_ID, ATTRSETINST_ID, QTY, LOSTQTY, DEFECTQTY, " . "MISSINGQTY, UNITVALUE) VALUES " . "(:id, :prdId, :attrId, :qty, :lostQty, :defectQty, " . ":missingQty, :unitValue)");
     $stmt->bindParam(":id", $id);
     foreach ($inventory->items as $item) {
         if ($item->missingQty === null) {
             // Check for missing count on current stock
             $lvl = StocksService::getLevel($item->productId, $inventory->locationId, $item->attrSetInstId);
             if ($lvl != null) {
                 $qty = $lvl->qty;
                 $invQty = $item->qty + $item->lostQty + $item->defectQty;
                 $item->missingQty = $qty - $invQty;
             } else {
                 $item->missingQty = 0;
             }
         }
         if ($item->unitValue === null) {
             // Compute average value
             $sql = "SELECT REASON, UNITS, PRICE FROM STOCKDIARY " . "WHERE LOCATION = :loc AND PRODUCT = :prd";
             if ($item->attrSetInstId !== null) {
                 $sql .= " AND ATTRIBUTESETINSTANCE_ID = :attr";
             } else {
                 $sql .= " AND ATTRIBUTESETINSTANCE_ID IS NULL";
             }
             $sql .= " ORDER BY DATENEW DESC";
             $stmtVal = $pdo->prepare($sql);
             $stmtVal->bindParam(":loc", $item->locationId);
             $stmtVal->bindParam(":prd", $item->productId);
             if ($item->attrSetInstId !== null) {
                 $stmtVal->bindParam(":attr", $item->attrSetInstId);
             }
             $stmtVal->execute();
             $units = 0;
             $expectedUnits = $item->getTotalQty();
             $price = 0.0;
             while ($row = $stmtVal->fetch() && $units != $expectedUnits) {
                 $units += $row['UNITS'];
                 if ($row['UNITS'] > 0) {
                     $price += $row['PRICE'];
                 } else {
                     $price -= $row['PRICE'];
                 }
             }
             if ($units != 0) {
                 $item->unitValue = $price / $units;
             } else {
                 $item->unitValue = 0;
             }
         }
         // Insert
         $stmt->bindParam(":prdId", $item->productId);
         $stmt->bindParam(":attrId", $item->attrSetInstId);
         $stmt->bindParam(":qty", $item->qty);
         $stmt->bindParam(":lostQty", $item->lostQty);
         $stmt->bindParam(":defectQty", $item->defectQty);
         $stmt->bindParam(":missingQty", $item->missingQty);
         $stmt->bindParam(":unitValue", $item->unitValue);
         if ($stmt->execute() === false) {
             var_dump($stmt->errorInfo());
             if ($newTransaction) {
                 $pdo->rollback();
             }
             return false;
         }
     }
     if ($newTransaction) {
         $pdo->commit();
     }
     return $id;
 }
 /** @depends testCreateFull */
 public function testCreateGuessMissing()
 {
     $move = new StockMove(stdtimefstr("2014-01-01 00:00:00"), StockMove::REASON_IN_BUY, $this->products[0]->id, $this->locations[0]->id, null, 10, 1);
     $move->id = StocksService::addMove($move);
     $item = new InventoryItem(null, $this->products[0]->id, null, 1, 2, 3, null, 5);
     $inv = new Inventory(stdtimefstr("2001-01-01 00:00:00"), $this->locations[0]->id);
     $inv->addItem($item);
     $srv = new InventoriesService();
     $id = $srv->create($inv);
     $this->assertNotEquals(false, $id, "Creation failed");
     $pdo = PDOBuilder::getPDO();
     $stmt = $pdo->prepare("SELECT * FROM STOCK_INVENTORYITEM");
     $this->assertNotEquals(false, $stmt->execute(), "Query failed");
     if ($row = $stmt->fetch()) {
         $this->assertEquals(4, $row["MISSINGQTY"]);
         $this->markTestIncomplete("Check unit value");
     } else {
         $this->assertTrue(false, "No inventory item found after creation");
     }
 }
示例#8
0
 static function getLevels($locationId)
 {
     $pdo = PDOBuilder::getPDO();
     $lvls = array();
     /* Start from LOCATIONS table to return a line with null everywhere
      * if there is no stocklevel and no line at all
      * if the location does not exist. */
     // Get security and max levels
     $sqlLvl = "SELECT STOCKLEVEL.ID, PRODUCT, STOCKSECURITY, STOCKMAXIMUM " . "FROM LOCATIONS " . "LEFT JOIN STOCKLEVEL ON STOCKLEVEL.LOCATION = LOCATIONS.ID " . "WHERE LOCATIONS.ID = :loc";
     $stmtLvl = $pdo->prepare($sqlLvl);
     $stmtLvl->bindParam(":loc", $locationId);
     $stmtLvl->execute();
     $locationExists = false;
     while ($row = $stmtLvl->fetch()) {
         $locationExists = true;
         if ($row['PRODUCT'] !== null) {
             $lvls[$row['PRODUCT']] = array($row['ID'], $row['STOCKSECURITY'], $row['STOCKMAXIMUM']);
         }
     }
     if (!$locationExists) {
         return null;
     }
     // Get quantities
     $qties = array();
     $sqlQty = "SELECT PRODUCT, ATTRIBUTESETINSTANCE_ID AS ATTR, UNITS " . "FROM STOCKCURRENT " . "WHERE LOCATION = :loc";
     $stmtQty = $pdo->prepare($sqlQty);
     $stmtQty->bindParam(':loc', $locationId);
     $stmtQty->execute();
     while ($row = $stmtQty->fetch()) {
         $prdId = $row['PRODUCT'];
         if (!isset($qties[$prdId])) {
             $qties[$prdId] = array();
         }
         $qties[$prdId][$row['ATTR']] = $row['UNITS'];
     }
     // Merge both ids
     $prdIds = array();
     foreach (array_keys($lvls) as $id) {
         $prdIds[] = $id;
     }
     foreach (array_keys($qties) as $id) {
         if (!in_array($id, $prdIds)) {
             $prdIds[] = $id;
         }
     }
     // Merge all data
     $levels = array();
     foreach ($prdIds as $id) {
         $row = array("PRODUCT" => $id, "LOCATION" => $locationId);
         if (isset($lvls[$id])) {
             $row['ID'] = $lvls[$id][0];
             $row['STOCKSECURITY'] = $lvls[$id][1];
             $row['STOCKMAXIMUM'] = $lvls[$id][2];
         } else {
             $row['ID'] = null;
             $row['STOCKSECURITY'] = null;
             $row['STOCKMAXIMUM'] = null;
         }
         if (isset($qties[$id])) {
             foreach ($qties[$id] as $attr => $qty) {
                 $row['ATTRIBUTESETINSTANCE_ID'] = $attr;
                 $row['UNITS'] = $qty;
                 $levels[] = StocksService::buildDBLevel($row);
             }
         } else {
             $row['ATTRIBUTESETINSTANCE_ID'] = null;
             $row['UNITS'] = null;
             $levels[] = StocksService::buildDBLevel($row);
         }
     }
     return $levels;
 }