static function save($ticket) { $pdo = PDOBuilder::getPDO(); $db = DB::get(); $cashRegSrv = new CashRegistersService(); $cashReg = $cashRegSrv->getFromCashId($ticket->cashId); if ($cashReg === null) { return false; } $locationId = $cashReg->locationId; $newTransaction = !$pdo->inTransaction(); if ($newTransaction) { $pdo->beginTransaction(); } $id = md5(time() . rand()); $stmtRcpt = $pdo->prepare("INSERT INTO RECEIPTS\t(ID, MONEY, DATENEW) " . "VALUES (:id, :money, :date)"); $stmtRcpt->bindParam(":id", $id); $stmtRcpt->bindParam(":money", $ticket->cashId); $stmtRcpt->bindParam(":date", $db->dateVal($ticket->date)); if ($stmtRcpt->execute() === false) { if ($newTransaction) { $pdo->rollback(); } return false; } // Get next ticket number if ($ticket->ticketId === null) { $nextNum = $cashReg->nextTicketId; $cashRegSrv->incrementNextTicketId($cashReg->id); $ticket->ticketId = $nextNum; } // Insert ticket $discountRate = $ticket->discountRate; $stmtTkt = $pdo->prepare("INSERT INTO TICKETS (ID, TICKETID, " . "TICKETTYPE, PERSON, CUSTOMER, CUSTCOUNT, TARIFFAREA, " . "DISCOUNTRATE, DISCOUNTPROFILE_ID) VALUES " . "(:id, :tktId, :tktType, :person, :cust, :custcount, :taId, " . ":discRate, :discProfId)"); $stmtTkt->bindParam(':id', $id, \PDO::PARAM_STR); $stmtTkt->bindParam(':tktId', $ticket->ticketId, \PDO::PARAM_INT); $stmtTkt->bindParam(":tktType", $ticket->type); $stmtTkt->bindParam(':person', $ticket->userId); $stmtTkt->bindParam(':cust', $ticket->customerId); $stmtTkt->bindParam(":custcount", $ticket->custCount); $stmtTkt->bindParam(":taId", $ticket->tariffAreaId); $stmtTkt->bindParam(":discRate", $ticket->discountRate); $stmtTkt->bindParam(":discProfId", $ticket->discountProfileId); if ($stmtTkt->execute() === false) { if ($newTransaction) { $pdo->rollback(); } return false; } // Insert ticket lines // Also check for prepayments refill $stmtLines = $pdo->prepare("INSERT INTO TICKETLINES (TICKET, LINE, " . "PRODUCT, ATTRIBUTESETINSTANCE_ID, UNITS, PRICE, TAXID, " . "DISCOUNTRATE, ATTRIBUTES) VALUES (:id, :line, :prdId, " . ":attrSetInstId, :qty, :price, :taxId, :discRate, :attrs)"); foreach ($ticket->lines as $line) { $fullDiscount = $discountRate + $line->discountRate; $discountPrice = $line->price * (1.0 - $fullDiscount); $stmtLines->bindParam(":id", $id); $stmtLines->bindParam(":line", $line->dispOrder); $stmtLines->bindParam(":prdId", $line->productId); $stmtLines->bindParam(":attrSetInstId", $line->attrSetInstId); $stmtLines->bindParam(":qty", $line->quantity); $stmtLines->bindParam(":price", $line->price); $stmtLines->bindParam(":taxId", $line->taxId); $stmtLines->bindParam(":discRate", $line->discountRate); $stmtLines->bindParam(":attrs", $line->attributes); if ($stmtLines->execute() === false) { if ($newTransaction) { $pdo->rollback(); } return false; } // Update stock if ($line->productId !== null) { $move = new StockMove($ticket->date, StockMove::REASON_OUT_SELL, $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; } } } // Insert payments // Also check for prepayment debit and debt recovery $stmtPay = $pdo->prepare("INSERT INTO PAYMENTS (ID, RECEIPT, PAYMENT, " . "TOTAL, CURRENCY, TOTALCURRENCY, PAIRED_WITH) VALUES " . "(:id, :rcptId, :type, :amount, :currId, :currAmount, " . ":pair)"); foreach ($ticket->payments as $payment) { $paymentId = md5(time() . rand()); $stmtPay->bindParam(":id", $paymentId); $stmtPay->bindParam(":rcptId", $id); $stmtPay->bindParam(":type", $payment->type); $stmtPay->bindParam(":amount", $payment->amount); $stmtPay->bindParam(":currId", $payment->currencyId); $stmtPay->bindParam(":currAmount", $payment->currencyAmount); $stmtPay->bindValue(":pair", null); if ($stmtPay->execute() === false) { if ($newTransaction) { $pdo->rollback(); } return false; } // Insert back payment if any if ($payment->backType !== null) { $backId = md5(time() . rand()); $currSrv = new CurrenciesService(); $defaultCurrencyId = $currSrv->getDefault()->id; $stmtPay->bindParam(":id", $backId); $stmtPay->bindParam(":type", $payment->backType); $stmtPay->bindParam(":amount", $payment->backAmount); $stmtPay->bindParam(":currId", $defaultCurrencyId); $stmtPay->bindParam(":currAmount", $payment->backAmount); $stmtPay->bindValue(":pair", $paymentId); // :rcptId is already bound if ($stmtPay->execute() === false) { if ($newTransaction) { $pdo->rollback(); } return false; } } // Check prepaid if ($payment->type == 'prepaid') { $custSrv = new CustomersService(); $ok = $custSrv->addPrepaid($ticket->customerId, $payment->amount * -1); if ($ok === false) { if ($newTransaction) { $pdo->rollback(); } return false; } } else { if ($payment->type == "debt") { // Debtpaid is a negative total of all payments $custSrv = new CustomersService(); $ok = $custSrv->addDebt($ticket->customerId, $payment->amount, $ticket->date); if ($ok === false) { if ($newTransaction) { $pdo->rollback(); } return false; } } else { if ($payment->type == "debtpaid") { // Debtpaid is a negative total of all payments $custSrv = new CustomersService(); $ok = $custSrv->recoverDebt($ticket->customerId, $payment->amount * -1); if ($ok === false) { if ($newTransaction) { $pdo->rollback(); } return false; } } } } } // Insert taxlines $stmtTax = $pdo->prepare("INSERT INTO TAXLINES (ID, RECEIPT, TAXID, " . "BASE, AMOUNT) VALUES (:id, :rcptId, " . ":taxId, :base, :amount)"); foreach ($ticket->getTaxAmounts() as $ta) { $taxId = md5(time() . rand()); $stmtTax->bindParam(":id", $taxId); $stmtTax->bindParam(":rcptId", $id); $stmtTax->bindParam(":taxId", $ta->taxId); $stmtTax->bindParam(":base", $ta->base); $stmtTax->bindParam(":amount", $ta->getAmount()); if ($stmtTax->execute() === false) { if ($newTransaction) { $pdo->rollback(); } return false; } } if ($newTransaction) { $pdo->commit(); } return $id; }