<?php
namespace Lm\Engine\EC\Entity;
use Lm\Engine\EC\Entity\Goods\ColorNumberLabel;
use Lm\Engine\EC\Entity\Goods\Label;
use Lm\Engine\EC\Entity\Item\Item;
use Lm\Engine\EC\UT;
use Lm\Engine\SokujitsuHassou\SokujitsuHassou;
use Lm\Engine\Zaiko\Entity\SkuExtended;
use Lm\Entity\Category;
use Lm\Engine\EC\Entity\Goods\CategoryListIconLabel;
use Lm\Engine\EC\Entity\Goods\TargetGenderLabel;
use Lm\Engine\EC\Entity\Goods\VendingStatusLabel;
use Lm\Entity\GoodsSetPurchase;
use Lm\Service\Cache\CacheService;
use Lm\Service\Db\SqlService;
use Lm\Entity\Goods;
class GoodsWithRelated extends GoodsExtended
{
const REVIEW_GET_MAX = 50;
/**
* @var CategoryWithRelated
*/
protected $mainCategory;
/**
* @var CategoryWithRelated
*/
protected $canonicalCategory;
/**
* @var array
*/
protected $schemaOrgProduct;
/**
* @var array
*/
protected $schemaOrgAggregateOffer;
/**
* @var array
*/
protected $schemaOrgAggregateRating;
/**
* @var array
*/
protected $schemaOrgReviewList;
/**
* @var array
*/
protected $reviewList;
/**
* @var array
*/
protected $reviewSummary;
/**
* @var Item
*/
protected $item;
/**
* @var TargetGenderLabel
*/
protected $targetGenderLabel;
/**
* @var CategoryListIconLabel
*/
protected $categoryListIconLabel;
/**
* @var VendingStatusLabel
*/
protected $vendingStatusLabel;
/**
* @var ColorNumberLabel
*/
protected $colorNumberLabel;
/**
* @var Label[]
*/
protected $labelList;
/**
* @var bool
*/
protected $isSokujitsuHassouAvailable;
/**
* @return string
*
*/
public function getItemUrl()
{
//
$ut = UT::getBaseInfo();
//
return sprintf("%s/item/%s.html", $ut->getShopUrl(), $this->getItemId());
}
/**
* @return CategoryWithRelated|null
*/
public function getMainCategory()
{
return self::compute($this->canonicalCategory, function () {
//
return self::getMainCategoryById($this->goodsId);
});
}
/**
* @param $goodsId
* @return CategoryWithRelated|null
*/
public static function getMainCategoryById($goodsId)
{
//
$mainCategory = (new SqlService())
->Sql("SELECT
main_category_main_category_webname
, main_category_webname
, COUNT(DISTINCT category_id) AS `ctCount`
FROM (
SELECT main_category_id
, main_category_main_category_webname
, main_category_webname
, category_id
FROM goods_table
INNER JOIN goods_category_table ON goods_id = gc_goods
INNER JOIN category_table ON category_id = gc_category AND category_status = :category_status
INNER JOIN main_category_table ON main_category_id = category_main_category AND main_category_status = :main_category_status
WHERE goods_id = :goods_id
UNION ALL
SELECT main_category_id
, main_category_main_category_webname
, main_category_webname
, 0 AS category_id
FROM goods_table
INNER JOIN goods_main_category_table ON goods_id = gmc_goods
INNER JOIN main_category_table ON main_category_id = gmc_main_category AND main_category_status = :main_category_status
WHERE goods_id = :goods_id
) AS `mc`
GROUP BY
main_category_id
ORDER BY
`ctCount` DESC
, main_category_webname
LIMIT 1")
->Params([
'goods_id' => $goodsId,
'category_status' => Category::STATUS_AVAILABLE,
'main_category_status' => Category::STATUS_AVAILABLE,
])
->Fetch()
;
//
if (!empty($mainCategory)) {
//
return new CategoryWithRelated($mainCategory['main_category_webname'], null, $mainCategory['main_category_main_category_webname']);
} else {
//
return null;
}
}
/**
* @return CategoryWithRelated|null
*/
public function getCanonicalCategory()
{
return self::compute($this->canonicalCategory, function () {
//
if ($mainCategory = $this->getMainCategory()) {
//
if ($mainCategory->hasMainCategories()) {
//
return $mainCategory;
}
}
});
}
/**
* @return array
* @throws \Exception
*/
public function getStockListForMatrix() {
//
$result = [
'stockList' => [],
'direct' => '',
'janList' => [],
];
//
$goodsId = $this->getGoodsId();
//
$skuList = SkuExtended::getInstanceList($goodsId);
//
foreach($skuList as $sku){
//
$gclId = $sku->getGclId();
$gpId = $sku->getGpId();
//
if (!isset($result['stockList'][$goodsId])) {
//
$result['stockList'][$goodsId] = [];
}
//
if (!isset($result['stockList'][$goodsId][$gclId])) {
//
$result['stockList'][$goodsId][$gclId] = [];
}
//
$nyukaDateComment = $sku->getNyukaDateComment();
$nyukaDate = $sku->getNyukaDate();
$comment = '';
if (strstr(trim($nyukaDateComment), "次回生産予定無し")) {
$comment = '<span style="color: #138a19;">入荷予定日<br />未定</span>';
} elseif (strstr(trim($nyukaDateComment), "生産中止")) {
$comment = '<span style="color: #696969;">生産中止</span>';
} elseif (strstr(trim($nyukaDateComment), "生産中")) {
$comment = '<span style="color: #138a19;">生産中</span>';
} elseif ($nyukaDate != null) {
$comment = '<span style="color: #138a19;">入荷予定日<br />' . date("n月j日", strtotime("{$nyukaDate}")) . '</span>';
}
//
$result['stockList'][$goodsId][$gclId][$gpId] = [
'stock_other' => $sku->getStockOther(),
'stock' => $sku->getStockTotal(),
];
//
if ($stock3 = $sku->getStockBichiku()) {
//
if ($bichikuNyukaDate = $sku->getBichikuNyukaDate()) {
$result['stockList'][$goodsId][$gclId][$gpId]['stock3'] = sprintf('<div class="nyuka-yotei" style="font-size:12px;">入荷予定日<br />%s</div>', date("n月j日", strtotime("{$bichikuNyukaDate} +1 day")));
} else {
$result['stockList'][$goodsId][$gclId][$gpId]['stock3'] = sprintf("<span style=\"color:red;\">(即日発送 %s)</span>", $stock3);
}
}
//
if (true) {
$result['stockList'][$goodsId][$gclId][$gpId]['nodisp'] = $sku->getNoDisp();
}
//
if (!empty($nyukaDate)) {
$result['stockList'][$goodsId][$gclId][$gpId]['zdate'] = (new \DateTime($nyukaDate))->format('n月j日');
$result['stockList'][$goodsId][$gclId][$gpId]['nyuuka_yoteibi'] = (new \DateTime($nyukaDate))->format('Y-m-d H:i:s');
}
//
if (!empty($comment)) {
$result['stockList'][$goodsId][$gclId][$gpId]['comment'] = $comment;
}
//
if (!isset($result['janList'][$gclId])) {
//
$result['janList'][$gclId] = [];
}
$result['janList'][$gclId][$gpId] = $sku->getBichikuNyukaDate() ?: $sku->getNyukaDate();
}
//
return $result;
}
/**
* @param int $goodsId
* @return array
* @throws Exception
*/
function LM_chokusouCheckAll2($goodsId) {
return (array)(new \Lm\Engine\SokujitsuHassou\SokujitsuHassou())
->check($goodsId, true);
}
protected function getStockList() {
//
$result = array();
//
$goodsId = $this->getGoodsId();
// 84: チトセの場合は、在庫数 + 外部倉庫
// $is_chitose = false;
// $strSql = sprintf("SELECT DISTINCT gp_kataban FROM jancode_table INNER JOIN goods_price_table ON jan_price = gp_id WHERE jan_goods = %d", $goodsId);
// if ($res = $model->getDatas($db, $strSql)) {
// $tmp = explode('-', $res[0]['gp_kataban']);
// if ($tmp[0] == '84') {
// $is_chitose = true;
// }
// }
$is_chitose = $this->isChitose();
// 在庫マトリクス高速化対応
// TODO: 直送チェック用のリストを取得
$sokujitsuFlgList = $this->LM_chokusouCheckAll2($goodsId);
// 在庫情報を取得
// $strSql = $this->getCheckStockSelectByIdSql($goodsId);
// $stockList = $model->getDatas($db, $strSql);
$stockList = (array)$this->getCheckStockList();
foreach ($stockList as $stock) {
if (is_numeric($stock['stock'])) {
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock_other'] = intval($stock['jan_stock4']) + intval($stock['jan_stock5']) + intval($stock['jan_stock6']) + intval($stock['jan_stock7']) + intval($stock['jan_stock8']) + intval($stock['jan_stock3']);
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock'] = $stock['stock'] + $result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock_other'];
} else {
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock'] = $stock['stock'];
}
if ($is_chitose && $stock['jan_stock9']) {
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock'] += $stock['jan_stock9'];
}
if($stock['jan_stock3']!="" and $stock['jan_stock3']>0 and $stock['jan_stock3_nyuka_date']==""){
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock3'] = "<span style='color:red;'>(即日発送 ".$stock['jan_stock3'].")</span>";
}elseif($stock['jan_stock3']!="" and $stock['jan_stock3']>0 and $stock['jan_stock3_nyuka_date']!=""){
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock3'] = '<div class="nyuka-yotei" style="font-size:12px;">入荷予定日<br />' . date("n月j日", strtotime($stock['jan_stock3_nyuka_date']." +1 day")) . '</div>';
}elseif(isset($sokujitsuFlgList[$stock['jan_color']][$stock['jan_price']]) && $sokujitsuFlgList[$stock['jan_color']][$stock['jan_price']]){
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock3'] = "<span style='color:red;'>(即日発送 ".$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['stock'].")</span>";
}
$result[$goodsId][$stock['jan_color']][$stock['jan_price']]['nodisp'] = $stock['nodisp'];
}
// 入荷予定情報を取得
// $strSql = $model->getGoodsArrivalDateSelectSql($goodsId);
// $zeroList = $model->getDatas($db, $strSql);
$zeroList = (array)$this->getGoodsArrivalDate($goodsId);
foreach ($zeroList as $zero) {
// // $result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['stock'] = 0;
if ($result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['stock'] === '*') {
// 在庫「*」の場合、「在庫0指定」(=予約注文)を優先
$result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['stock'] = 0;
} else if (empty($result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['stock_other'])) {
// 仕入先在庫のみ存在するの場合、「在庫0指定」(=予約注文)を優先
$result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['stock'] = 0;
}
//
$result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['zdate'] = $zero['zdate'];
$result[$goodsId][$zero['zero_gcl']][$zero['zero_gp']]['nyuuka_yoteibi'] = $zero['nyuuka_yoteibi'];
}
// 欠品情報を取得(入荷未定、入荷予定日あり、生産中、生産中止)
// $strSql = $model->getGoodsStockoutSelectSql($goodsId);
// $keppinList = $model->getDatas($db, $strSql);
$keppinList = (array)$this->getGoodsStockout();
foreach ((array)$keppinList as $keppin) {
// // $result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['stock'] = 0;
if ($result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['stock'] === '*') {
// 在庫「*」の場合、「欠品登録」(=予約注文)を優先
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['stock'] = 0;
} else if (empty($result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['stock_other'])) {
// 仕入先在庫のみ存在するの場合、「欠品登録」(=予約注文)を優先
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['stock'] = 0;
}
//
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['zdate'] = date('n月j日', strtotime($keppin['ki_date']));
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['nyuuka_yoteibi'] = $keppin['ki_date'];
if (strstr(trim($keppin['ki_comment']), "次回生産予定無し")) {
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['comment'] = '<span style="color: #138a19;">入荷予定日<br />未定</span>';
} elseif (strstr(trim($keppin['ki_comment']), "生産中止")) {
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['comment'] = '<span style="color: #696969;">生産中止</span>';
} elseif (strstr(trim($keppin['ki_comment']), "生産中")) {
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['comment'] = '<span style="color: #138a19;">生産中</span>';
} elseif ($keppin['ki_date'] != null) {
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['comment'] = '<span style="color: #138a19;">入荷予定日<br />' . date("n月j日", strtotime("{$keppin['ki_date']} +1 day")) . '</span>';
} else {
$result[$goodsId][$keppin['ki_gcl']][$keppin['ki_gp']]['comment'] = "";
}
}
return $result;
}
/**
* @return array|null
*/
public function getCheckStockList ()
{
return self::getCheckStockListById($this->getGoodsId());
}
/**
* @link https://bitbucket.org/lm91/front/src/e4bda25c7a8fce8f116c87adb8646ee8f9635f6f/app/html/application/modules/default/models/commons/BaseLibraryModel.php#lines-523:529
* @param $goodsId
* @return array|null
*/
public static function getCheckStockListById($goodsId)
{
//
return (new SqlService())
->Select("
jan_color
, jan_price
, coalesce( jan_stock, '*' ) AS stock
, coalesce( jan_stock3, 0 ) AS jan_stock3
, jan_stock3_nyuka_date
, coalesce( jan_stock4, 0 ) AS jan_stock4
, coalesce( jan_stock5, 0 ) AS jan_stock5
, coalesce( jan_stock6, 0 ) AS jan_stock6
, coalesce( jan_stock7, 0 ) AS jan_stock7
, coalesce( jan_stock8, 0 ) AS jan_stock8
, coalesce( jan_stock9, 0 ) AS jan_stock9
, coalesce( jan_stock9, 0 ) AS jan_stock9
, jan_nodisplay AS nodisp
, MIN(COALESCE(jan_stock3_nyuka_date, T2.zero_period, T1.ki_date)) AS `nyuuka_yoteibi`
")
->Table("jancode_table")
->Join("keppin_item_table", "T.jan_goods = T1.ki_goods AND T.jan_color = T1.ki_gcl AND T.jan_price = T1.ki_gp AND T1.ki_date > NOW()", "LEFT")
->Join("zero_stock_table", "T.jan_goods = T2.zero_goods AND T.jan_color = T2.zero_gcl AND T.jan_price = T2.zero_gp AND T2.zero_period > NOW()", "LEFT")
->Set("jan_goods", $goodsId)
->GroupBy('T.jan_id')
->FindAll()
;
}
/**
* 在庫入荷予定日
* @return array|null
*/
public function getGoodsArrivalDate ()
{
return self::getGoodsArrivalDateById($this->getGoodsId());
}
/**
* 在庫入荷予定日
* @link https://bitbucket.org/lm91/front/src/e4bda25c7a8fce8f116c87adb8646ee8f9635f6f/app/html/application/modules/default/models/commons/BaseLibraryModel.php#lines-1281:1304
* @param int $goodsId
* @return array|null
*/
public static function getGoodsArrivalDateById ($goodsId)
{
return (new SqlService())
->Sql("SELECT *, date_format( date_add( zero_period, interval 1 day ), '%c月%e日' ) AS zdate,(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN cp_price ELSE ROUND(gp_price2 * (1+ 10/100)) END) as gp_price, date_add( zero_period, interval 1 day ) AS nyuuka_yoteibi
FROM zero_stock_table
INNER JOIN goods_table ON zero_goods = goods_id
LEFT JOIN goods_price_table ON zero_gp = gp_id
LEFT JOIN size_table ON gp_size_id = size_id
LEFT JOIN goods_color_table ON zero_gcl = gcl_id
LEFT JOIN color_table ON gcl_color_id = color_id
LEFT JOIN campaign_price_table ON cp_gp = gp_id AND `cp_end_datetime` >= NOW() and `cp_start_datetime` <= NOW()
LEFT JOIN jancode_table ON jan_goods = goods_id AND jan_color = gcl_id AND jan_price = gp_id
WHERE zero_goods = :goods_id
AND zero_period >= NOW()
AND ( jan_stock5 IS NULL OR jan_stock5 = 0 )
AND ( jan_stock6 IS NULL OR jan_stock6 = 0 )
AND ( jan_stock7 IS NULL OR jan_stock7 = 0 )
AND ( jan_stock8 IS NULL OR jan_stock8 = 0 )
AND ( jan_stock9 IS NULL OR jan_stock9 = 0 )
AND ( gp_display IS NULL OR ( gp_display IS NOT NULL AND gp_display != 99 ) )
AND gcl_display_status = 1
ORDER BY gcl_display, color_display,gp_display,size_display")
->Params([
'goods_id' => $goodsId,
])
->FetchAll()
;
}
/**
* 欠品情報
* @param string|null $fromDatetime
* @return array|null
*/
public function getGoodsStockout ($fromDatetime = null)
{
return self::getGoodsStockoutById($this->getGoodsId(), $fromDatetime);
}
//
/**
* 欠品情報
* @link https://bitbucket.org/lm91/front/src/e4bda25c7a8fce8f116c87adb8646ee8f9635f6f/app/html/application/modules/default/models/commons/BaseLibraryModel.php#lines-1306:1330
* @param int $goodsId
* @param string|null $fromDatetime
* @return array|null
*/
public static function getGoodsStockoutById ($goodsId, $fromDatetime = null)
{
//
if ($fromDatetime === null) {
$fromDatetime = date('Y-m-d 00:00:00');
}
//
return (new SqlService())
->Sql("SELECT *, date_format( ki_date, '%Y/%m/%d' ) AS kdate
FROM keppin_item_table AS a
INNER JOIN goods_table ON ki_goods = goods_id
LEFT JOIN goods_price_table ON ki_gp = gp_id
LEFT JOIN size_table ON gp_size_id = size_id
LEFT JOIN goods_color_table ON ki_gcl = gcl_id
LEFT JOIN color_table ON gcl_color_id = color_id
WHERE NOT EXISTS (
SELECT * FROM keppin_item_table AS b
WHERE a.ki_id < b.ki_id
AND a.ki_goods = b.ki_goods
AND ( a.ki_gp = b.ki_gp OR b.ki_gp IS NULL )
AND ( a.ki_gcl = b.ki_gcl OR b.ki_gcl IS NULL )
)
AND a.ki_goods = :goods_id
AND ( a.ki_date >= :from_datetime OR a.ki_date IS NULL )
AND a.ki_comment IS NOT NULL
AND ( gp_display IS NULL OR ( gp_display IS NOT NULL AND gp_display != 99 ) )
AND gcl_display_status = 1
ORDER BY gcl_display, color_display,gp_display,size_display")
->Params([
'goods_id' => $goodsId,
'from_datetime' => $fromDatetime,
])
->FetchAll()
;
}
public function getSchemaOrgProduct()
{
return self::compute($this->schemaOrgProduct, function () {
//
if ($category = $this->getMainCategory()) {
//
$category = $category->getMainCategoryName();
}
//
$result = [
'@context' => 'http://schema.org',
'@type' => 'Product',
'productID' => $this->getGoodsId(),
'name' => $this->getGoodsName(),
'sku' => $this->getGoodsMainKataban(),
'mpn' => $this->getGoodsMainKataban(),
'category' => $category,
];
//
if ($aggregateRating = $this->getSchemaOrgAggregateRating()) {
//
$result['aggregateRating'] = $aggregateRating;
}
//
if ($review = $this->getSchemaOrgReviewList()) {
//
$result['review'] = $review;
}
//
if ($offers = $this->getSchemaOrgAggregateOffer()) {
//
$result['offers'] = $offers;
}
//
return $result;
});
}
public function getSchemaOrgAggregateOffer()
{
return self::compute($this->schemaOrgAggregateOffer, function () {
//
$result = [];
//
$goodsPrice = $this->getPrice();
$availability = $this->isStockAvailable() ? 'InStock' : 'OutOfStock';
//
$result = [
'@type' => 'AggregateOffer',
'availability' => "http://schema.org/{$availability}",
'price' => $goodsPrice['min_price_in_tax'],
'lowPrice' => $goodsPrice['min_price_in_tax'],
'highPrice' => $goodsPrice['max_price_in_tax'],
'priceCurrency' => 'JPY',
'url' => $this->getItemUrl(),
];
//
if ($priceValidUntil = $goodsPrice['max_cp_end_datetime']) {
$result['priceValidUntil'] = date('Y-m-d', strtotime($priceValidUntil));
}
//
return $result;
});
}
public function getSchemaOrgAggregateRating()
{
return self::compute($this->schemaOrgAggregateRating, function () {
//
$result = [];
//
if ($reviewList = $this->getReviewList($reviewCount)) {
$cr_points = array_map(function ($v) {
return $v["cr_points"];
}, $reviewList);
$arg = empty($cr_points) ? 0 : (array_sum($cr_points) / count($cr_points));
$ratingValue = (floor($arg * 10)) / 10;
//
$result = [
'@type' => 'AggregateRating',
'ratingValue' => $ratingValue,
'reviewCount' => $reviewCount,
];
}
//
return $result;
});
}
public function getSchemaOrgReviewList()
{
return self::compute($this->schemaOrgReviewList, function () {
//
$reviewList = $this->getReviewList();
//
$result = [];
//
foreach ($reviewList as $review) {
//
$result[] = [
'@type' => 'Review',
'datePublished' => date('Y-m-d', strtotime($review['app_datetime'])),
'reviewBody' => !empty($review['cr_staff_comment']) ? $review['cr_staff_comment'] : $review['cr_comment'],
'author' => [
'@type' => 'Person',
'name' => empty($review['cr_name']) ? '匿名希望' : $review['cr_name'],
],
'reviewRating' => [
'@type' => 'Rating',
'bestRating' => 5,
'ratingValue' => $review['cr_points'],
'worstRating' => 1,
],
];
}
//
return $result;
});
}
public function getReviewSummary()
{
return self::compute($this->reviewSummary, function () {
//
$result = [
'ratingValue' => 0,
'reviewCount' => 0,
'imgStars' => '',
];
$image_name = 0;
$arg = 0;
//
if ($reviewList = $this->getReviewList($reviewCount)) {
$cr_points = array_map(function ($v) {
return $v["cr_points"];
}, $reviewList);
$arg = empty($cr_points) ? 0 : (array_sum($cr_points) / count($cr_points));
$ratingValue = (floor($arg * 10)) / 10;
//
$image_name = (int)($arg * 2) / 2 * 10;
//
$result['ratingValue'] = $ratingValue;
$result['reviewCount'] = $reviewCount;
}
//
$result['imgStars'] = "<img class=\"history-average-img\" alt=\"お客様からの口コミレビュー評価の星の数{$arg}\" src=\"/images/review/star_m{$image_name}.gif\">";
//
return $result;
});
}
public function getReviewList(&$count = null, $limit = self::REVIEW_GET_MAX, $offset = 0)
{
return self::compute($this->reviewList, function () use ($limit, $offset, &$count) {
//
$id = $this->getGoodsId();
//
return self::getReviewListById($id, $limit, $offset, $count);
});
}
public static function getReviewListById($id, $limit = null, $offset = 0, &$count = null)
{
return CacheService::getCached(function () use ($id, $limit, $offset, &$count) {
$sql = (new SqlService())
->Table('customer_review_table')
->Set('cr_approval', 1)
->Set('cr_site_id', 0)
->Set('cr_main_category_id', 0)
->Set('cr_goods_id', $id)
->Order('app_datetime', 'DESC');
//
$count = call_user_func(function ($sql) {
return (int)$sql->Count();
}, clone $sql);
//
if (!empty($limit)) $sql
->Limit($offset, $limit);
//
$result = (array)$sql
->FindAll();
//
return $result;
});
}
public function getPrice()
{
return self::getPriceByGoodsId($this->getGoodsId());
}
/**
* TODO: 疑似バッチ
* @param int[]|int $goodsId
* @param $datetime
* @return mixed
* @throws \ReflectionException
*/
public static function getPriceByGoodsId($goodsId, $datetime = null)
{
//
if ($datetime === null) {
//
$datetime = date("Y-m-d H:i:s");
}
//
$hash = md5(serialize($goodsId));
$label = "goods-price-{$hash}-{$datetime}";
//
return CacheService::getCached(function () use ($goodsId, $datetime) {
//
$goodsIdList = [];
foreach ((array)$goodsId as $i => $_goodsId) {
$goodsIdList["goodsId{$i}"] = $_goodsId;
}
$goodsIdListPlaceHolder = implode(',', array_map(function ($key) {
return ":{$key}";
}, array_keys($goodsIdList)));
//
// TODO: 税率は動的に取得
$sql = "SELECT
goods_id
, MIN(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN (truncate((cp_price/1.10) + .5,0)) ELSE (gp_price2) END ) AS `min_price_ex_tax`
, MIN(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN (cp_price) ELSE (ROUND(gp_price2 * (1+ 10/100))) END) AS `min_price_in_tax`
, MAX(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN (truncate((cp_price/1.10) + .5,0)) ELSE (gp_price2) END ) AS `max_price_ex_tax`
, MAX(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN (cp_price) ELSE (ROUND(gp_price2 * (1+ 10/100))) END) AS `max_price_in_tax`
, MIN(`cp_start_datetime`) AS `min_cp_start_datetime`
, MAX(`cp_end_datetime`) AS `max_cp_end_datetime`
, (:datetime BETWEEN MIN(`cp_start_datetime`) AND MAX(`cp_end_datetime`)) AS is_campaign
FROM
goods_table
INNER JOIN
goods_price_table
ON
goods_id = gp_goods
AND
IfNull(gp_display, 0) != 99
LEFT JOIN
campaign_price_table
ON
gp_id = cp_gp
AND
cp_start_datetime <= :datetime
AND
cp_end_datetime >= :datetime
AND
cp_del_flg = 0
WHERE
goods_id IN ({$goodsIdListPlaceHolder})
GROUP BY
goods_id";
$params = array_merge([
'datetime' => $datetime,
], $goodsIdList);
//
$sql = (new SqlService())
// ->Select('goods_id, MIN(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN (truncate((cp_price/1.10) + .5,0)) ELSE (gp_price2) END ), MAX(CASE WHEN cp_price IS NOT NULL AND cp_price > 0 THEN (cp_price) ELSE (ROUND(gp_price2 * (1+ 10/100))) END)')
// ->Table('goods_table')
// ->Join('goods_price_table', 'T.goods_id = T1.gp_goods', 'INNER')
// ->Join('campaign_price_table', 'T.goods_id = T1.gp_goods AND cp_start_datetime <= :datetime AND cp_end_datetime >= :datetime AND cp_del_flg = 0', 'LEFT')
// ->Set('goods_id', $goodsId)
->Sql($sql)
->Params($params)
;
//
if (is_array($goodsId)) {
//
$result = $sql->FetchAll();
} else {
//
$result = $sql->Fetch();
}
//
return $result;
}, $label);
}
public function getStock()
{
return self::getStockById($this->getGoodsId(), true);
}
public function isStockAvailable()
{
return self::getStockById($this->getGoodsId());
}
/**
* @param int|NULL $goods_id
* @param bool $is_matrix
* @param int|NULL $jan_id
* @param int|NULL $gp_id
* @param int|NULL $gcl_id
* @param string|NULL $date
* @return mixed
* @throws \Exception
*/
public static function getStockById($goods_id = NULL, $is_matrix = false, $jan_id = NULL, $gp_id = NULL, $gcl_id = NULL, $date = NULL)
{
return CacheService::getCached(function () use ($goods_id, $is_matrix, $jan_id, $gp_id, $gcl_id, $date) {
//
$skuList = SkuExtended::getInstanceList($goods_id, $jan_id, $gcl_id, $gp_id, $date);
$stock_total_summary = 0;
$stockList = [];
foreach ($skuList as $sku) {
//
$gclId = $sku->getGclId();
$gpId = $sku->getGpId();
//
if (!isset($stockList[$gclId])) {
//
$stockList[$gclId] = [];
}
//
if (!isset($stockList[$gclId][$gpId])) {
//
$stockList[$gclId][$gpId] = [
'stock_total' => null,
'stock_sokujitsu' => null,
];
}
//
if (!$sku->isNoDisplay()) {
//
$stockTotal = $sku->getStockTotal();
//
$stockList[$gclId][$gpId] = [
'stock_total' => $stockTotal,
'stock_sokujitsu' => $sku->getStockSokujitsu(),
];
//
$stock_total_summary += (($stockTotal === '*') ? 1 : $stockTotal);
}
}
//
if ($is_matrix === false) {
//
if (!empty($jan_id) || (!empty($gcl_id) && !empty($gp_id))) {
// is_matrix = false ・・・ 指定されたSKUの分のみ出力
return $stockList[$gclId][$gpId];
} else {
// is_matrix = false ・・・ SKU指定が省略された場合、在庫の有/無を返す。
return $stock_total_summary > 0;
}
} else {
//is_matrix = true ・・・ 全SKUの多段配列でSKU毎に出力
return $stockList;
}
});
}
public function getAsGoodsSetPurchase($flattened = false)
{
return self::getAsGoodsSetPurchaseById($this->getGoodsId(), $flattened);
}
public static function getAsGoodsSetPurchaseById($goodsId, $flattened = false)
{
return CacheService::getCached(function () use ($goodsId, $flattened) {
//
$goodsSetPurchase = CacheService::getCached(function () use ($goodsId) {
return (new SqlService())
->Select(implode(', ', [
'T.gsp_type',
'T.gsp_name',
'T1.goods_id',
'T1.goods_main_kataban',
'T1.goods_name',
'T3.color_name',
'T3.color_rgb',
]))
->Table('goods_set_purchase_table')
->Join('goods_table', 'T1.goods_id = T.gsp_goods_child', 'INNER')
->Join('goods_color_table', 'T1.goods_id = T2.gcl_goods AND T.gsp_type > 0') // メイン品番のカラーは取得しない
->Join('color_table', 'T3.color_id = T2.gcl_color_id AND T.gsp_type > 0') // メイン品番のカラーは取得しない
->Set('gsp_goods_parent', $goodsId)
->OrderBy('T.gsp_type')
->FindAll()
;
});
//
if ($flattened) {
//
$result = [];
//
foreach ($goodsSetPurchase as $goods) {
//
if ($type = GoodsSetPurchase::TYPE_LIST[$goods['gsp_type']])
//
foreach ($goods as $key => $value) {
//
$result["{$type['name']}_{$key}"] = $value;
}
}
} else {
//
$result = $goodsSetPurchase;
}
//
return $result;
});
}
/**
* @return GoodsSetPurchaseExtended[]
*/
public function getChildrenAsGoodsSetPurchase()
{
return GoodsSetPurchaseExtended::getListByParentGoodsId($this->getGoodsId());
}
public static function getFeedGoodsByIdForYDN($goodsId, $quantity = 1)
{
//
$feedGoods = self::getFeedGoodsById($goodsId);
//
return array(
'item_id' => $feedGoods['goods_id'],
'category_id' => $feedGoods['categoryId'],
'price' => ((int)($feedGoods['sale_price'])),
'quantity' => $quantity,
);
}
public static function getFeedGoodsByIdForGDN($goodsId, $google_business_vertical = 'retail')
{
//
$feedGoods = self::getFeedGoodsById($goodsId);
//
$gdn = array(
'id' => $feedGoods['goods_id'],
);
if (!empty($google_business_vertical)) {
$gdn['google_business_vertical'] = $google_business_vertical;
}
return $gdn;
}
/**
* @param $goodsId
* @return string
* @link
*/
public static function getFeedGoodsById($goodsId)
{
//
$result = (new SqlService())
->Select("
T.goods_id
, T3.jan_shiire_no_list
, T2.price
, T2.sale_price
, T1.categoryId
, T1.categoryName
, T3.stock
, T3.lm_stock
, T3.ki_date
, T3.zero_period
, T4.rating
, T4.reviews
")
->Table('goods_table')
->Join('feed_goods_category', 'T.goods_id = T1.goods_id', 'INNER')
->Join('feed_goods_price', 'T.goods_id = T2.goods_id', 'INNER')
->Join('feed_goods_stock', 'T.goods_id = T3.goods_id', 'INNER')
->Join('feed_goods_review', 'T.goods_id = T4.goods_id', 'LEFT')
->Set('T.goods_id', $goodsId)
->Find()
;
//
return $result;
}
/**
* @return Item
*/
public function getItem()
{
return self::compute($this->item, function () {
return new Item($this);
});
}
/**
* @return TargetGenderLabel
*/
public function getTargetGenderLabel()
{
return self::compute($this->targetGenderLabel, function () {
try {
return TargetGenderLabel::getById($this->getGoodsTargetGender());
} catch(\Exception $e) {
return null;
}
});
}
/**
* @return CategoryListIconLabel
*/
public function getCategoryListIconLabel()
{
return self::compute($this->categoryListIconLabel, function () {
try {
return CategoryListIconLabel::getById($this->getGoodsCategoryListIconId());
} catch(\Exception $e) {
return null;
}
});
}
/**
* @return VendingStatusLabel
*/
public function getVendingStatusLabel()
{
return self::compute($this->vendingStatusLabel, function () {
try {
$status = $this->getGoodsVendingStatus();
if ($status === Goods::VENDING_STATUS_EXCLUDE_MANUFACTURER_STOCK) {
$status = Goods::VENDING_STATUS_VENDING;
}
return VendingStatusLabel::getById($status);
} catch(\Exception $e) {
return null;
}
});
}
/**
* @return ColorNumberLabel
*/
public function getColorNumberLabel()
{
return self::compute($this->colorNumberLabel, function () {
try {
return ColorNumberLabel::getById(count($this->getItem()->getColorList()));
} catch(\Exception $e) {
return null;
}
});
}
/**
* @return Label[]
*/
public function getLabelList()
{
return self::compute($this->labelList, function () {
return array_filter([
$this->getTargetGenderLabel(),
$this->getColorNumberLabel(),
$this->getCategoryListIconLabel(),
], function ($label) {
return $label !== null;
});
});
}
/**
* @return mixed
* @throws \Exception
*/
public function isSokujitsuHassouAvailable()
{
//
return self::compute($this->isSokujitsuHassouAvailable, function () {
//
return (new SokujitsuHassou())
->check($this->getGoodsId(), false) > SokujitsuHassou::FLG_NONE
;
});
}
}