Commit 91c7b16c authored by jianghaiming's avatar jianghaiming

Merge branch 'develop' into test

parents 8f2a6787 12d5d538
...@@ -44,5 +44,6 @@ class GoodsException extends BaseException ...@@ -44,5 +44,6 @@ class GoodsException extends BaseException
30 => '当前商品已过期', 30 => '当前商品已过期',
31 => '当前商品锁定库存不足', 31 => '当前商品锁定库存不足',
32 => '当前商品已下单数量不足', 32 => '当前商品已下单数量不足',
33 => '售价不能为0',
]; ];
} }
\ No newline at end of file
...@@ -11,16 +11,13 @@ use Api\PhpUtils\Mysql\MysqlBase; ...@@ -11,16 +11,13 @@ use Api\PhpUtils\Mysql\MysqlBase;
*/ */
class Tcc extends MysqlBase class Tcc extends MysqlBase
{ {
const STATUS_T_SUCCESS = 1;
const STATUS_C1_SUCCESS = 2;
const STATUS_C2_SUCCESS = 3;
const TABLE_NAME = 'inventory_tcc_record'; const TABLE_NAME = 'inventory_tcc_record';
const CONFIG_INDEX = 'goods'; const CONFIG_INDEX = 'goods';
const STATUS_TRY = 1;// try
const STATUS_CONFIRM = 2;// confirm
const STATUS_CANCEL = 3;// cancel
const OPERATOR_RESULT_FAIL = 0;// 失败
const OPERATOR_RESULT_SUCCESS = 1;// 成功
public static function getRecord($where, $columns = []) public static function getRecord($where, $columns = [])
{ {
if (empty($columns)) { if (empty($columns)) {
......
...@@ -3,9 +3,7 @@ ...@@ -3,9 +3,7 @@
use App\Base\Base; use App\Base\Base;
use App\Exception\custom\GoodsException; use App\Exception\custom\GoodsException;
use \Validate\GoodsTccValidate; use \Validate\GoodsTccValidate;
use \Validate\GoodsTccIsFinishValidate; use \App\Services\tcc\Tcc2Service;
use \Validate\GoodsTccCancelValidate;
use \App\Services\tcc\TccService;
class TccController extends Base class TccController extends Base
...@@ -19,7 +17,7 @@ class TccController extends Base ...@@ -19,7 +17,7 @@ class TccController extends Base
{ {
(new GoodsTccValidate())->validate(); (new GoodsTccValidate())->validate();
$res = TccService::placeAnOrderTry($this->params["keys"], $this->params["tid"]); $res = Tcc2Service::placeAnOrderTry($this->params["keys"], $this->params["tid"]);
if ($res) { if ($res) {
$this->success(); $this->success();
} else { } else {
...@@ -36,7 +34,7 @@ class TccController extends Base ...@@ -36,7 +34,7 @@ class TccController extends Base
{ {
(new GoodsTccValidate())->validate(); (new GoodsTccValidate())->validate();
$res = TccService::placeAnOrderConfirm($this->params["keys"], $this->params["tid"]); $res = Tcc2Service::placeAnOrderConfirm($this->params["keys"], $this->params["tid"]);
if ($res) { if ($res) {
$this->success(); $this->success();
} else { } else {
...@@ -45,7 +43,7 @@ class TccController extends Base ...@@ -45,7 +43,7 @@ class TccController extends Base
} }
/** /**
* 下单商品 tcc cancel * 下单商品 cancel
* @throws \App\Exception\custom\ParamException * @throws \App\Exception\custom\ParamException
* @throws \App\Exception\custom\ParamException * @throws \App\Exception\custom\ParamException
*/ */
...@@ -53,24 +51,7 @@ class TccController extends Base ...@@ -53,24 +51,7 @@ class TccController extends Base
{ {
(new GoodsTccValidate())->validate(); (new GoodsTccValidate())->validate();
$res = TccService::placeAnOrderCancel($this->params["keys"], $this->params["tid"]); $res = Tcc2Service::placeAnOrderCancel($this->params["keys"], $this->params["tid"]);
if ($res) {
$this->success();
} else {
throw new GoodsException(["cus" => 27]);
}
}
/**
* 取消订单单 商品tcc try
* @throws \App\Exception\custom\ParamException
* @throws \App\Exception\custom\ParamException
*/
public function cancel_order_tryAction()
{
(new GoodsTccValidate())->validate();
$res = TccService::cancelOrderTry($this->params["keys"], $this->params["tid"]);
if ($res) { if ($res) {
$this->success(); $this->success();
} else { } else {
...@@ -80,47 +61,12 @@ class TccController extends Base ...@@ -80,47 +61,12 @@ class TccController extends Base
/** /**
* 取消订单单 商品tcc confirm * 取消订单单 商品tcc confirm
* @throws \App\Exception\custom\ParamException
* @throws \App\Exception\custom\ParamException
*/ */
public function cancel_order_confirmAction() public function cancel_order_confirmAction()
{ {
(new GoodsTccCancelValidate())->validate(); $res = Tcc2Service::cancelConfirm($this->params["keys"]);
$res = TccService::cancelOrderConfirm($this->params["keys"], $this->params["tid"], $this->params["type"]);
if ($res) {
$this->success();
} else {
throw new GoodsException(["cus" => 27]);
}
}
/**
* 取消订单单 商品tcc cancel
* @throws \App\Exception\custom\ParamException
* @throws \App\Exception\custom\ParamException
*/
public function cancel_order_cancelAction()
{
(new GoodsTccValidate())->validate();
$res = TccService::cancelOrderCancel($this->params["keys"], $this->params["tid"]);
if ($res) { if ($res) {
$this->success(); $this->success();
} else {
throw new GoodsException(["cus" => 27]);
} }
} }
/**
* 判断当前tcc是否执行完成
* @throws \App\Exception\custom\ParamException
*/
public function tcc_is_finishAction()
{
(new GoodsTccIsFinishValidate())->validate();
$res = TccService::tccIsFinish($this->params["goods_sku_id_str"], $this->params["tid"]);
$this->success(["result"=>$res]);
}
} }
\ No newline at end of file
...@@ -153,7 +153,7 @@ class ElasticGoodService ...@@ -153,7 +153,7 @@ class ElasticGoodService
$result["list"][$key]["life_account_id"] = $source["_source"]["life_account_id"]; $result["list"][$key]["life_account_id"] = $source["_source"]["life_account_id"];
$result["list"][$key]["life_account_name"] = $source["_source"]["life_account_name"]; $result["list"][$key]["life_account_name"] = $source["_source"]["life_account_name"];
$result["list"][$key]["life_account_icon"] = $source["_source"]["life_account_icon"]; $result["list"][$key]["life_account_icon"] = $source["_source"]["life_account_icon"];
$result["list"][$key]["distance"] = empty($source["sort"][0]) ? "" : round($source["sort"][0], 2) . "km"; $result["list"][$key]["distance"] = empty(end($source["sort"])) ? "" : round(end($source["sort"]), 2) . "km";
$result["list"][$key]["update_time"] = $source["_source"]["update_time"]; $result["list"][$key]["update_time"] = $source["_source"]["update_time"];
} }
} }
......
...@@ -176,6 +176,9 @@ class GoodsService ...@@ -176,6 +176,9 @@ class GoodsService
if ($skuData["expiration_time"] < date("Y-m-d H:i:s")) { if ($skuData["expiration_time"] < date("Y-m-d H:i:s")) {
throw new GoodsException(['cus' => 16]); throw new GoodsException(['cus' => 16]);
} }
if ($skuData["price"] <= 0) {
throw new GoodsException(['cus' => 33]);
}
$checkGoodsName = self::isHaveSensitive($skuData["goods_name"], 1); $checkGoodsName = self::isHaveSensitive($skuData["goods_name"], 1);
if ($checkGoodsName) { if ($checkGoodsName) {
throw new GoodsException(['cus' => 19]); throw new GoodsException(['cus' => 19]);
......
<?php
namespace App\Services\tcc;
use Api\PhpUtils\Common\BaseConvert;
use App\Exception\custom\GoodsException;
use App\Models\goods\mysql\GoodsSku;
use App\Models\goods\mysql\Tcc;
class Tcc2Service
{
const TCC_RESULT_FAIL = false;
const TCC_RESULT_SUCCESS = true;
/**
* 下单 商品tcc try
* @param $keys
* @param $tid
* @return bool
* @throws GoodsException
*/
public static function placeAnOrderTry($keys, $tid)
{
$goodsInfoList = json_decode($keys, true);
if (empty($goodsInfoList)) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds = $numList = [];
foreach ($goodsInfoList as $item) {
if (empty($item["goods_sku_id"]) || empty($item["num"])) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds[] = $item["goods_sku_id"];
$numList[$item["goods_sku_id"]] = $item["num"];
}
$tccInfo = self::getTccRecord($tid);
//有结果返回原来的结果,幂等
if (!empty($tccInfo["status"]) && $tccInfo["status"] == Tcc::STATUS_T_SUCCESS) {
return self::TCC_RESULT_SUCCESS;
}
//如果空 cancel,则直接成功
if (!empty($tccInfo["status"]) && in_array($tccInfo["status"], [Tcc::STATUS_C2_SUCCESS])) {
return self::TCC_RESULT_SUCCESS;
}
$skus = GoodsSku::getRecords(["goods_sku_id" => $goodsSkuIds]
, ["goods_sku_id", "inventory_rest", "inventory_lock", "online_status"]);
if (!empty($skus)) {
GoodsSku::beginTransaction();
foreach ($skus as $sku) {
$goodsSkuId = $sku["goods_sku_id"];
if ($sku["online_status"] == GoodsSku::ONLINE_STATUS_ONLINE) {
if (empty($numList[$goodsSkuId])) {
return self::TCC_RESULT_FAIL;
}
$num = $numList[$goodsSkuId];
//条件加上乐观锁
$rowCount = GoodsSku::save([
"inventory_lock" => $sku["inventory_lock"] + $num,
"inventory_rest" => $sku["inventory_rest"] - $num,
], ["goods_sku_id" => $goodsSkuId, "inventory_rest[>=]" => $num]);
if ($rowCount <= 0) {
GoodsSku::rollback();
throw new GoodsException(["cus" => 24]);
}
} else {
GoodsSku::rollback();
return self::TCC_RESULT_FAIL;
}
}
Tcc::save([
"tid" => $tid,
"goods_data" => $keys,
"status" => Tcc::STATUS_T_SUCCESS,
]);
if (!GoodsSku::commit()) {
GoodsSku::rollback();
return self::TCC_RESULT_FAIL;
}
}
return self::TCC_RESULT_SUCCESS;
}
/**
* 下单 商品tcc confirm
* @param $keys
* @param $tid
* @return int
*/
public static function placeAnOrderConfirm($keys, $tid)
{
$goodsInfoList = json_decode($keys, true);
if (empty($goodsInfoList)) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds = $numList = [];
foreach ($goodsInfoList as $item) {
if (empty($item["goods_sku_id"]) || empty($item["num"])) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds[] = $item["goods_sku_id"];
$numList[$item["goods_sku_id"]] = $item["num"];
}
$tccInfo = self::getTccRecord($tid);
//有结果返回原来的结果,幂等
if (!empty($tccInfo["status"]) && $tccInfo["status"] == Tcc::STATUS_C1_SUCCESS) {
return self::TCC_RESULT_SUCCESS;
}
//在confirm时候必须已经有try,如果没有就直接返回fail
if (!empty($tccInfo["status"]) && !in_array($tccInfo["status"], [Tcc::STATUS_T_SUCCESS])) {
return self::TCC_RESULT_FAIL;
}
//如果已经 cancel 成功, 则失败
if (!empty($tccInfo["status"]) && in_array($tccInfo["status"], [Tcc::STATUS_C2_SUCCESS])) {
return self::TCC_RESULT_FAIL;
}
$skus = GoodsSku::getRecords(["goods_sku_id" => $goodsSkuIds]
, ["goods_sku_id", "total_amount_order", "inventory_lock", "online_status"]);
if (!empty($skus)) {
GoodsSku::beginTransaction();
foreach ($skus as $sku) {
$goodsSkuId = $sku["goods_sku_id"];
if (!empty($sku["inventory_lock"]) && $sku["online_status"] == GoodsSku::ONLINE_STATUS_ONLINE) {
if (empty($numList[$goodsSkuId])) {
return self::TCC_RESULT_FAIL;
}
$num = $numList[$goodsSkuId];
//条件加上乐观锁
$rowCount = GoodsSku::save([
"inventory_lock" => $sku["inventory_lock"] - $num,
"total_amount_order" => $sku["total_amount_order"] + $num,
], ["goods_sku_id" => $goodsSkuId, "inventory_lock[>=]" => $num]);
if ($rowCount <= 0) {
GoodsSku::rollback();
throw new GoodsException(["cus" => 31]);
}
} else {
GoodsSku::rollback();
return self::TCC_RESULT_FAIL;
}
}
Tcc::save(["status" => Tcc::STATUS_C1_SUCCESS,], ["tid" => $tid]);
if (!GoodsSku::commit()) {
GoodsSku::rollback();
return self::TCC_RESULT_FAIL;
}
}
return self::TCC_RESULT_SUCCESS;
}
/**
* 下单 商品tcc cancel
* @param $keys
* @param $tid
* @return bool
* @throws GoodsException
*/
public static function placeAnOrderCancel($keys, $tid)
{
$goodsInfoList = json_decode($keys, true);
if (empty($goodsInfoList)) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds = $numList = [];
foreach ($goodsInfoList as $item) {
if (empty($item["goods_sku_id"]) || empty($item["num"])) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds[] = $item["goods_sku_id"];
$numList[$item["goods_sku_id"]] = $item["num"];
}
$tccInfo = self::getTccRecord($tid);
//允许空cancel(没有try情况)
//在cancel时候必须已经有try,如果没有就直接返回success
if (empty($tccInfo)) {
Tcc::save([
"tid" => $tid,
"goods_data" => $keys,
"status" => Tcc::STATUS_C2_SUCCESS,
]);
return self::TCC_RESULT_SUCCESS;
}
//有结果返回原来的结果,幂等
if (!empty($tccInfo["status"]) && $tccInfo["status"] == Tcc::STATUS_C2_SUCCESS) {
return self::TCC_RESULT_SUCCESS;
}
$skus = GoodsSku::getRecords(["goods_sku_id" => $goodsSkuIds]
, ["goods_sku_id", "inventory_rest", "inventory_lock", "total_amount_order", "online_status"]);
if (!empty($skus)) {
GoodsSku::beginTransaction();
foreach ($skus as $sku) {
$goodsSkuId = $sku["goods_sku_id"];
if (empty($numList[$goodsSkuId])) {
return self::TCC_RESULT_FAIL;
}
$num = $numList[$goodsSkuId];
//T时候执行C2,条件加上乐观锁
if ($tccInfo["status"] == Tcc::STATUS_T_SUCCESS) {
$rowCount = GoodsSku::save([
"inventory_lock" => $sku["inventory_lock"] - $num,
"inventory_rest" => $sku["inventory_rest"] + $num,
], ["goods_sku_id" => $goodsSkuId, "inventory_lock[>=]" => $num]);
if ($rowCount <= 0) {
GoodsSku::rollback();
throw new GoodsException(["cus" => 31]);
}
}
//T时候执行C2,条件加上乐观锁
if ($tccInfo["status"] == Tcc::STATUS_C1_SUCCESS) {
$rowCount = GoodsSku::save([
"total_amount_order" => $sku["total_amount_order"] - $num,
"inventory_rest" => $sku["inventory_rest"] + $num,
], ["goods_sku_id" => $goodsSkuId, "total_amount_order[>=]" => $num]);
if ($rowCount <= 0) {
GoodsSku::rollback();
throw new GoodsException(["cus" => 32]);
}
}
}
Tcc::save(["status" => Tcc::STATUS_C2_SUCCESS,], ["tid" => $tid]);
if (!GoodsSku::commit()) {
GoodsSku::rollback();
return self::TCC_RESULT_FAIL;
}
}
return self::TCC_RESULT_SUCCESS;
}
/**
* 取消订单,直接回退库存
* @param $keys
* @return bool
* @throws GoodsException
*/
public static function cancelConfirm($keys)
{
$goodsInfoList = json_decode($keys, true);
if (empty($goodsInfoList)) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds = $numList = [];
foreach ($goodsInfoList as $item) {
if (empty($item["goods_sku_id"]) || empty($item["num"])) {
return self::TCC_RESULT_FAIL;
}
$goodsSkuIds[] = $item["goods_sku_id"];
$numList[$item["goods_sku_id"]] = $item["num"];
}
$skus = GoodsSku::getRecords(["goods_sku_id" => $goodsSkuIds]
, ["goods_sku_id", "total_amount_order", "inventory_rest", "inventory_lock", "online_status"]);
if (!empty($skus)) {
GoodsSku::beginTransaction();
foreach ($skus as $sku) {
$goodsSkuId = $sku["goods_sku_id"];
if (empty($numList[$goodsSkuId])) {
return self::TCC_RESULT_FAIL;
}
$num = $numList[$goodsSkuId];
$params = [
"inventory_rest" => $sku["inventory_rest"] + $num,
"total_amount_order" => $sku["total_amount_order"] - $num,
];
$rowCount = GoodsSku::save($params, ["goods_sku_id" => $goodsSkuId, "total_amount_order[>=]" => $num]);
if ($rowCount <= 0) {
GoodsSku::rollback();
throw new GoodsException(["cus" => 32]);
}
}
if (!GoodsSku::commit()) {
GoodsSku::rollback();
}
}
return self::TCC_RESULT_SUCCESS;
}
/**
* 获取 tcc 数据记录
* @param $tid
* @return array
*/
private static function getTccRecord($tid)
{
$res = Tcc::selectForUpdate("*", ['tid' => $tid]);
$data = [];
if (!empty($res)) {
$data = $res[0];
}
return $data;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment