Skip to content

Commit

Permalink
Gestion du statut des transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
apuyou committed Oct 29, 2013
1 parent 22d1b4b commit 7603110
Show file tree
Hide file tree
Showing 9 changed files with 425 additions and 9 deletions.
16 changes: 11 additions & 5 deletions src/Payutc/Bom/Purchase.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static function getNbSell($obj_id, $fun_id, $start=null, $end=null, $tick
->innerJoin('pur', 't_transaction_tra', 'tra', 'pur.tra_id = tra.tra_id')
->where('pur.obj_id = :obj_id')->setParameter('obj_id', $obj_id)
->andWhere('tra.fun_id = :fun_id')->setParameter('fun_id', $fun_id)
->andWhere("tra.tra_status = 'V'")
->andWhere('pur.pur_removed = 0');

if($start != null) {
Expand Down Expand Up @@ -73,6 +74,7 @@ public static function getRevenue($fun_id, $app_id=null, $start=null, $end=null,
->from('t_purchase_pur', 'pur')
->innerJoin('pur', 't_transaction_tra', 'tra', 'pur.tra_id = tra.tra_id')
->andWhere('tra.fun_id = :fun_id')->setParameter('fun_id', $fun_id)
->andWhere("tra.tra_status = 'V'")
->andWhere('pur.pur_removed = 0');

if($app_id != null) {
Expand Down Expand Up @@ -105,10 +107,11 @@ public static function getRevenue($fun_id, $app_id=null, $start=null, $end=null,
public static function getPurchaseById($pur_id)
{
$qb = Dbal::createQueryBuilder();
$qb->select('*', 'tra.tra_date')
->from('t_purchase_pur', 'pur')
->innerJoin('pur', 't_transaction_tra', 'tra', 'pur.tra_id = tra.tra_id')
->where('pur.pur_id = :pur_id')
$qb->select('*', 'tra.tra_date')
->from('t_purchase_pur', 'pur')
->innerJoin('pur', 't_transaction_tra', 'tra', 'pur.tra_id = tra.tra_id')
->where('pur.pur_id = :pur_id')
->andWhere("tra.tra_status = 'V'")
->setParameter('pur_id', $pur_id);
return $qb->execute()->fetch();
}
Expand Down Expand Up @@ -158,7 +161,8 @@ public static function transaction($usr_id_buyer, $items, $app_id, $fun_id, $usr
'usr_id_seller' => $usr_id_seller,
'app_id' => $app_id,
'fun_id' => $fun_id,
'tra_ip' => $pur_ip,
'tra_status' => 'V',
'tra_ip' => $pur_ip,
));
$transactionId = $conn->lastInsertId();

Expand Down Expand Up @@ -204,6 +208,7 @@ public static function getRank($fun_id, $obj_id, $start, $end, $top, $sort_by) {
->innerJoin('pur', 't_transaction_tra', 'tra', 'pur.tra_id = tra.tra_id')
->where('usr.usr_id = tra.usr_id_buyer')
->andWhere('tra.fun_id = :fun_id')->setParameter('fun_id', $fun_id)
->andWhere("tra.tra_status = 'V'")
->andWhere('pur.pur_removed = 0');

if($obj_id != null) {
Expand Down Expand Up @@ -247,6 +252,7 @@ public static function getPurchasesForUser($usr_id, $time_limit=null)
->from('t_purchase_pur', 'pur')
->innerJoin('pur', 't_transaction_tra', 'tra', 'pur.tra_id = tra.tra_id')
->Where('usr_id_buyer = :usr_id')
->andWhere("tra.tra_status = 'V'")
->andWhere('pur_removed = 0')
->setParameter('usr_id', $usr_id);
if ($time_limit) {
Expand Down
194 changes: 192 additions & 2 deletions src/Payutc/Bom/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,158 @@
namespace Payutc\Bom;

use \Payutc\Log;
use \Payutc\Bom\User;
use \Payutc\Db\Dbal;
use \Payutc\Exception\NotEnoughMoney;
use \Payutc\Exception\TransactionAborted;
use \Payutc\Exception\TransactionNotFound;
use \Payutc\Exception\TransactionAlreadyValidated;

class Transaction {
protected $id;
protected $date;
protected $validatedDate;
protected $buyerId;
protected $sellerId;
protected $appId;
protected $funId;
protected $purchases;
protected $status;
protected $callbackUrl;
protected $returnUrl;
protected $token;

// --- Simple getters

public function getId(){
return $this->id;
}

public function getDate(){
return $this->date;
}

public function getValidatedDate(){
return $this->validatedDate;
}

public function getBuyerId(){
return $this->buyerId;
}

public function getSellerId(){
return $this->sellerId;
}

public function getFunId(){
return $this->funId;
}

public function getPurchases(){
return $this->purchases;
}

public function getStatus(){
return $this->status;
}

public function getCallbackUrl(){
return $this->callbackUrl;
}

public function getReturnUrl(){
return $this->returnUrl;
}

public function getToken(){
// TODO
}

public function setEmail(){
// TODO + throw exception if invalid
}

// --- Helpers

public function getMontantTotal(){
$total = 0;
foreach($this->purchases as $purchase){
$total += $purchase['pur_price'];
}
return $total;
}

public function validate(){
if($this->status == 'V'){
throw new TransactionAlreadyValidated();
}

if($this->status == 'A'){
throw new TransactionAborted();
}

$conn = Dbal::conn();
$conn->beginTransaction();

try {
// Set the status to validated
$now = new \DateTime();
$rows = $conn->update('t_transaction_tra',
array('tra_status' => 'V',
'tra_validated' => $now),
array('tra_id' => $this->id),
array("string", "datetime", "integer")
);

// Check that the transaction exists (this should never happen as object is instanciated)
if ($rows == 0) {
Log::error("Transaction: Transaction $idTrans not found when validating");
throw new TransactionNotFound("La transaction $idTrans n'existe pas");
}

// Remove stock for each product
foreach($this->purchases as $purchase){
Product::decStockById($purchase['obj_id'], $purchase['pur_qte']);
}

// Remove money from user
if($this->buyerId != null){
$total = $this->getMontantTotal();
$buyer = User::getById($this->buyerId);

if($total > User::getCreditById($this->buyerId)){
throw new NotEnougMoney();
}

User::decCreditById($this->buyerId, $this->getMontantTotal());
}
else {
// TODO Check that payline payment equals transaction total amount
}

$conn->commit();
}
catch (\Exception $e) {
$conn->rollback();
throw $e;
}

// Updated the BOM
$this->validatedDate = $now;
$this->status = 'V';

// Send callback if any
// TODO
}

// --- Generators

static public function getById($idTrans){
Log::debug("Transaction: getById($idTrans)");

$query = Dbal::createQueryBuilder()
->select('tra.tra_id', 'tra.tra_date', 'tra.usr_id_buyer', 'tra.usr_id_seller', 'tra.poi_id',
->select('tra.tra_id', 'tra.tra_date', 'tra.tra_validated', 'tra.usr_id_buyer', 'tra.usr_id_seller', 'tra.app_id',
'tra.tra_status', 'tra.tra_callback_url', 'tra.tra_return_url', 'tra.tra_token',
'tra.fun_id', 'pur.pur_id', 'pur.obj_id', 'pur.pur_qte', 'pur.pur_unit_price',
'pur.pur_price', 'pur.pur_removed')
->from('t_transaction_tra', 'tra')
Expand All @@ -61,7 +184,7 @@ static public function getById($idTrans){

// Check that the transaction exists
if ($query->rowCount() == 0) {
Log::debug("Transaction: Transaction $idTrans not found");
Log::warn("Transaction: Transaction $idTrans not found");
throw new TransactionNotFound("La transaction $idTrans n'existe pas");
}

Expand All @@ -71,9 +194,15 @@ static public function getById($idTrans){
$transaction = new Transaction();
$transaction->id = $don['tra_id'];
$transaction->date = $don['tra_date'];
$transaction->validatedDate = $don['tra_validated'];
$transaction->buyerId = $don['usr_id_buyer'];
$transaction->sellerId = $don['usr_id_seller'];
$transaction->appId = $don['app_id'];
$transaction->funId = $don['fun_id'];
$transaction->status = $don['tra_status'];
$transaction->callbackUrl = $don['tra_callback_url'];
$transaction->returnUrl = $don['tra_return_url'];
$transaction->token = $don['tra_token'];
$transaction->purchases = array();
do {
$transaction->purchases[] = array(
Expand All @@ -89,5 +218,66 @@ static public function getById($idTrans){
return $transaction;
}

static public function create($buyerId, $sellerId, $appId, $funId, $items, $callbackUrl = null, $returnUrl = null){
$conn = Dbal::conn();
// TODO check que les articles existent et que leurs prix sont ok (cf poss3)

try {
$conn->beginTransaction();

// Insert the transaction
$conn->insert('t_transaction_tra', array(
'tra_date' => new \DateTime(),
'usr_id_buyer' => $buyerId,
'usr_id_seller' => $sellerId,
'app_id' => $appId,
'fun_id' => $funId,
'tra_status' => 'W',
'tra_callback_url' => $callbackUrl,
'tra_return_url' => $returnUrl
), array("datetime", "integer", "integer", "integer", "integer", "string", "string", "string", "string"));

$transactionId = $conn->lastInsertId();

// Build the purchases (transaction ID is required here)
foreach ($items as $itm) {
$conn->insert('t_purchase_pur', array(
'tra_id' => $transactionId,
'obj_id' => $itm['id'],
'pur_qte' => $itm['qte'],
'pur_price' => $itm['price'] * $itm['qte'],
'pur_unit_price' => $itm['price'],
), array("integer", "integer", "integer", "integer", "integer"));
}

$conn->commit();
}
catch (\Exception $e) {
$conn->rollback();
throw $e;
}

return self::getById($transactionId);
}

static public function createAndValidate($buyerId, $sellerId, $appId, $funId, $items, $callbackUrl = null, $returnUrl = null){
$conn = Dbal::conn();

try {
// This is the only real transaction, all other nested transactions are virtual
// See http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/transactions.html
$conn->beginTransaction();

$transaction = self::create($buyerId, $sellerId, $appId, $funId, $items, $callbackUrl, $returnUrl);
$transaction->validate();

$conn->commit();
}
catch (\Exception $e){
$conn->rollback();
throw $e;
}

return $transaction;
}
}
5 changes: 5 additions & 0 deletions src/Payutc/Exception/NotEnoughMoney.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

namespace Payutc\Exception;

class NotEnoughMoney extends PayutcException {}
5 changes: 5 additions & 0 deletions src/Payutc/Exception/TransactionAborted.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

namespace Payutc\Exception;

class TransactionAborted extends PayutcException {}
5 changes: 5 additions & 0 deletions src/Payutc/Exception/TransactionAlreadyValidated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

namespace Payutc\Exception;

class TransactionAlreadyValidated extends PayutcException {}
8 changes: 7 additions & 1 deletion src/Payutc/Migrations/Version20131029002712.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ class Version20131029002712 extends AbstractMigration
public function up(Schema $schema)
{
$this->addSql("ALTER TABLE `t_transaction_tra`
ADD `tra_validated` DATETIME NULL COMMENT 'Time when transaction was validated' AFTER `tra_date`,
ADD `tra_status` ENUM('W', 'V', 'A') NOT NULL DEFAULT 'W' COMMENT 'Transaction status' AFTER `fun_id`,
ADD `tra_callback_url` VARCHAR(200) NULL COMMENT 'URL to call when status changes' AFTER `tra_status`,
ADD `tra_return_url` VARCHAR(200) NULL COMMENT 'Return URL at the end of the transaction' AFTER `tra_callback_url`,
ADD `tra_token` VARCHAR(32) NULL COMMENT 'Transaction token for WEBSALE' AFTER `tra_return_url`,
CHANGE `poi_id` `app_id` INT(11) unsigned NOT NULL COMMENT 'ID of the application that created this transaction',
CHANGE `usr_id_buyer` `usr_id_buyer` INT(11) UNSIGNED NULL COMMENT 'Identifiant de l\'acheteur',
CHANGE `usr_id_seller` `usr_id_seller` INT(11) UNSIGNED NULL COMMENT 'Identifiant du vendeur',
ADD INDEX (`tra_status`)");

$this->addSql("ALTER TABLE `t_paybox_pay`
Expand Down Expand Up @@ -49,10 +52,13 @@ public function down(Schema $schema)

$this->addSql("ALTER TABLE `t_transaction_tra`
DROP INDEX `tra_status`,
DROP `tra_validated`,
DROP `tra_status`,
DROP `tra_callback_url`,
DROP `tra_return_url`,
DROP `tra_token`,
CHANGE `app_id` `poi_id` int(11) unsigned NOT NULL COMMENT 'Identifiant du point de vente'");
CHANGE `app_id` `poi_id` int(11) unsigned NOT NULL COMMENT 'Identifiant du point de vente',
CHANGE `usr_id_buyer` `usr_id_buyer` INT(11) UNSIGNED NOT NULL COMMENT 'Identifiant de l\'acheteur',
CHANGE `usr_id_seller` `usr_id_seller` INT(11) UNSIGNED NOT NULL COMMENT 'Identifiant du vendeur'");
}
}
2 changes: 1 addition & 1 deletion tests/TransactionRodbTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function testRetrieve(){
}

/**
* Test the user is not blocked in all Payutc
* Test retrieving an unknown transaction
*
* @expectedException \Payutc\Exception\TransactionNotFound
* @expectedExceptionMessage La transaction 742 n'existe pas
Expand Down
Loading

0 comments on commit 7603110

Please sign in to comment.