vendor/lm/engine-zaiko/src/Entity/SkuExtended.php line 19

Open in your IDE?
  1. <?php
  2. namespace Lm\Engine\Zaiko\Entity;
  3. use Lm\Engine\Zaiko\Yoyaku;
  4. use Lm\Engine\Zaiko\Zaiko;
  5. use Lm\Entity\Sku;
  6. use Lm\Service\Cache\CacheService;
  7. use Lm\Service\Db\SqlService;
  8. use Lm\Util\Date;
  9. use Lm\Util\Str;
  10. class SkuExtended extends Sku
  11. {
  12.     /**
  13.      * @return false|string[]
  14.      */
  15.     public function getShiiresakiSoukoHanteiAsArray()
  16.     {
  17.         return Str::csvToArray($this->getShiiresakiSoukoHantei());
  18.     }
  19.     /**
  20.      * @return false|string[]
  21.      */
  22.     public function getChokusouIncludeHinbanListAsArray()
  23.     {
  24.         return Str::csvToArray($this->getChokusouIncludeHinbanList());
  25.     }
  26.     /**
  27.      * @return false|string[]
  28.      */
  29.     public function getChokusouExcludeHinbanListAsArray()
  30.     {
  31.         return Str::csvToArray($this->getChokusouExcludeHinbanList());
  32.     }
  33.     /**
  34.      * @return false|string[]
  35.      */
  36.     public function getBichikuIncludeHinbanListAsArray()
  37.     {
  38.         return Str::csvToArray($this->getBichikuIncludeHinbanList());
  39.     }
  40.     /**
  41.      * @return int
  42.      */
  43.     public function getStockAvailability()
  44.     {
  45.         return self::compute($this->stockAvailability, function () {
  46.             //
  47.             if ($this->getStockTotal() === null) {
  48.                 //
  49.                 return Sku::STOCK_AVL_UNKNOWN;
  50.             } else if ($this->getStockTotal() === 0) {
  51.                 //
  52.                 return Sku::STOCK_AVL_OUT_OF_STOCK;
  53.             } else if ($this->getStockTotal() <= Zaiko::LOW_STOCK_LESS_THAN) {
  54.                 //
  55.                 return Sku::STOCK_AVL_LOW_STOCK;
  56.             } else {
  57.                 //
  58.                 return Sku::STOCK_AVL_IN_STOCK;
  59.             }
  60.         });
  61.     }
  62.     /**
  63.      * @return int
  64.      * @throws \Exception
  65.      */
  66.     public function getBackOrder()
  67.     {
  68.         return self::compute($this->backOrder, function () {
  69.             //
  70.             if ($nyukaDate $this->getBichikuNyukaDate() ?: $this->getNyukaDate()) {
  71.                 //
  72.                 if (Yoyaku::calculateIsYoyakuAvailable($nyukaDate)) {
  73.                     //
  74.                     return Sku::BACK_ORDER_RESERVATION;
  75.                 } else {
  76.                     //
  77.                     return Sku::BACK_ORDER_WAITING;
  78.                 }
  79.             } else {
  80.                 //
  81.                 return Sku::BACK_ORDER_UNAVAILABLE;
  82.             }
  83.         });
  84.     }
  85.     /**
  86.      * @return bool
  87.      */
  88.     public function isChokusouAvailable()
  89.     {
  90.         //
  91.         $result false;
  92.         //
  93.         if ($this->getIsDirectDeliveryConfigExists() == 1) {
  94.             // 直送設定あり
  95.             $makerHinban $this->getMakerHinban();
  96.             $lmHinban $this->getLmHinban();
  97.             $makerHinbanCharcters preg_replace('/[^a-zA-Z]/'''$makerHinban);
  98.             $shiiresakiSoukoCharactersList $this->getShiiresakiSoukoHanteiAsArray();
  99.             $chokusouIncludeHinbanList $this->getChokusouIncludeHinbanListAsArray();
  100.             $chokusouExcludeHinbanList $this->getChokusouExcludeHinbanListAsArray();
  101.             //
  102.             if (in_array($lmHinban$chokusouExcludeHinbanList)) {
  103.                 // 除外品番
  104.                 // 無条件で 直送不可 とする
  105.                 $result false;
  106.             } else if (empty($chokusouIncludeHinbanList) || in_array($lmHinban$chokusouIncludeHinbanList)) {
  107.                 // メーカー直送品番(対象商品をLM品番で入力)
  108.                 $result true;
  109.             } else if (empty($shiiresakiSoukoCharactersList) || in_array($makerHinbanCharcters$shiiresakiSoukoCharactersList)) {
  110.                 // メーカー直送品番(該当アルファベット)
  111.                 $result true;
  112.             }
  113.         }
  114.         //
  115.         return $result;
  116.     }
  117.     /**
  118.      * @return bool
  119.      */
  120.     public function isNoDisplay()
  121.     {
  122.         return $this->getNoDisp() === 1;
  123.     }
  124.     public static function getInstanceList($goodsId$janId null$gclId null$gpId null$datetime null)
  125.     {
  126.         //
  127.         return CacheService::getCached(function () use ($goodsId$janId$gclId$gpId$datetime) {
  128.             //
  129.             if (empty($datetime)) {
  130.                 // 日時の指定が省略された場合、当日の00:00:00が指定されたものとする
  131.                 $datetime date(self::DATE_FORMAT_DEFAULT." 00:00:00");
  132.             } else {
  133.                 //
  134.                 $datetime Date::getAsDateTime($datetime)->format(self::DATE_TIME_FORMAT_DEFAULT);
  135.             }
  136.             // セット品番の対応
  137.             // TODO: 異なるメーカーを含むセット品番の対応
  138.             $goodsSetPurchaseFlg false;
  139.             $childGoodsList = [];
  140.             if (!empty($goodsId)) {
  141.                 //
  142.                 if ($goods self::getGoodsInfoByGoodsId($goodsId)) {
  143.                     // セット品番か否か
  144.                     // // goodsSetPurchaseFlg = ($goods['goods_set_purchase_flg'] == 1);
  145.                     // // childGoodsList = array_values(array_filter(explode(',', $goods['child_goods_list']), function ($item) {
  146.                     // //     return trim($item) !== '';
  147.                     // // ));
  148.                 } else {
  149.                     //
  150.                     throw new \Exception("指定された商品が見つかりません");
  151.                 }
  152.             }
  153.             //
  154.             if (!empty($childGoodsList)) {
  155.                 //
  156.                 $_skuList self::getGoodsStockInfoByGoodsIdList($childGoodsList$datetime);
  157.             } elseif (!empty($gclId) && !empty($gpId)) {
  158.                 //
  159.                 $_skuList self::getGoodsStockInfoBySkuIdentity($gclId$gpId$datetime);
  160.             } elseif (!empty($janId)) {
  161.                 //
  162.                 $_skuList self::getGoodsStockInfoByJanId($janId$datetime);
  163.             } elseif (!empty($goodsId)) {
  164.                 //
  165.                 $_skuList self::getGoodsStockInfoByGoodsId($goodsId$datetime);
  166.             } else {
  167.                 //
  168.                 throw new \Exception('$goods_id, $jan_id, $gp_id & $gcl_id のいずれかを指定する必要があります');
  169.             }
  170.             //
  171.             $skuList array_map(function ($_sku) {
  172.                 //
  173.                 return new SkuExtended($_sku);
  174.             }, $_skuList);
  175.             //
  176.             return $skuList;
  177.         });
  178.     }
  179.     /**
  180.      * @param $goodsId
  181.      * @param $janId
  182.      * @param $gclId
  183.      * @param $gpId
  184.      * @param $datetime
  185.      * @return mixed
  186.      * @throws \Exception
  187.      */
  188.     public static function getInstance($goodsId$janId null$gclId null$gpId null$datetime null)
  189.     {
  190.         return CacheService::getCached(function () use ($goodsId$janId$gclId$gpId$datetime) {
  191.             //
  192.             $skuList = static::getInstanceList($goodsId$janId$gclId$gpId$datetime);
  193.             //
  194.             if (($skuList array_filter($skuList, function ($sku) use ($janId$gclId$gpId) {
  195.                 /**
  196.                  * @var SkuExtended $sku
  197.                  */
  198.                 if (!empty($janId)) {
  199.                     //
  200.                     return $sku->getJanId() === $janId;
  201.                 } else if (!empty($gclId) && !empty($gpId)) {
  202.                     //
  203.                     return ($sku->getGclId() === (int)$gclId) && ($sku->getGpId() === (int)$gpId);
  204.                 }
  205.             })) && !empty($skuList[0])) {
  206.                 //
  207.                 return $skuList[0];
  208.             } else {
  209.                 //
  210.                 throw new \Exception('SKU情報が見つかりませんでした');
  211.             }
  212.         });
  213.     }
  214.     /**
  215.      * @param string $datetime
  216.      * @param array $bind
  217.      * @param string|null $criteria
  218.      * @return array|null
  219.      */
  220.     protected static function getGoodsStockInfo($datetime, array $bind = [], $criteria '')
  221.     {
  222.         //
  223.         $bind += [
  224.             'datetime' => $datetime,
  225.             'yoyaku_available_since_days_ago' => Yoyaku::YOYAKU_AVAILABLE_SINCE_DAYS_AGO,
  226.         ];
  227.         //
  228.         $sql "SELECT
  229.                     goods_id
  230.                 ,    shiiresaki_id
  231.                 ,    jan_id
  232.                 ,    gcl_id
  233.                 ,    gcl_display
  234.                 ,    gcl_display_status
  235.                 ,    gp_id
  236.                 ,    gp_display
  237.                 ,    gp_kataban AS `lmHinban`
  238.                 ,    jan_shiire_no AS `makerHinban`
  239.                 ,    jan_nodisplay AS `noDisp`
  240.                 ,    jan_shiire_color
  241.                 ,    color_id
  242.                 ,    color_name
  243.                 ,    size_id
  244.                 ,    size_name
  245.                 ,    shiiresaki_souko_hantei
  246.                 ,    DATE_FORMAT(shiiresaki_shimekiri_time, '%H:%i') AS `timeLimit`
  247.                 ,    goods_set_purchase_flg
  248.                 ,    (dd_id IS NOT NULL) AS `isDirectDeliveryConfigExists`
  249.                 ,    dd_hinban_chokusou AS `chokusouIncludeHinbanList`
  250.                 ,    dd_hinban_exclude AS `chokusouExcludeHinbanList`
  251.                 ,    dd_hinban_bichiku AS `bichikuIncludeHinbanList`
  252.                 ,    `nyuka_date`
  253.                 ,    IfNull(`nyuka_date`, '9999-99-99 23:59:59') BETWEEN :datetime AND :datetime + INTERVAL :yoyaku_available_since_days_ago DAY AS `is_yoyaku_available`
  254.                 ,    CASE WHEN stock_total > 0 THEN DATE_FORMAT(`bichiku_nyuka_date`, '%Y-%m-%d') ELSE NULL END AS `bichiku_nyuka_date`
  255.                 ,    `is_bichiku_ready`
  256.                 ,    `is_bichiku_yoyaku_available`
  257.                 ,    COALESCE(`stock_total`, '*') AS `stock_total`
  258.                 ,    `stock_other`
  259.                 ,    COALESCE(NullIf(`stock_bichiku` * `is_bichiku_ready`, 0), NullIf(`stock_chokusou`, 0), 0) AS `stock_sokujitsu`
  260.                 ,    `stock_chokusou`
  261.                 ,    `stock_bichiku`
  262.                 ,    ki_comment AS `nyuka_date_comment`
  263.                 ,    cp_price AS `cp_price_in_tax`
  264.                 ,    gp_price2 AS `gp_price_ex_tax`
  265.                 ,    gp_teika AS `gp_teika_in_tax`
  266.                 FROM (
  267.                     SELECT
  268.                         *
  269.                     ,    CASE
  270.                             WHEN
  271.                                 `stock_total_sub` > 0
  272.                             THEN
  273.                                 null
  274.                             ELSE
  275.                                 STR_TO_DATE(`_nyuka_date`, '%Y-%m-%d')
  276.                         END AS `nyuka_date`
  277.                     FROM (
  278.                         SELECT
  279.                             *
  280.                         ,    NullIf(LEAST(IfNull(ki_date, '9999-99-99 23:59:59'), IfNull(zero_period, '9999-99-99 23:59:59')), '9999-99-99 23:59:59') AS `_nyuka_date`
  281.                         FROM
  282.                             goods_table AS `goods`
  283.                         INNER JOIN
  284.                             shiiresaki_table AS `shiiresaki`
  285.                         ON
  286.                             shiiresaki_id = goods_shiiresaki
  287.                         LEFT JOIN
  288.                             direct_delivery_table AS `direct_delivery`
  289.                         ON
  290.                             shiiresaki_id = dd_shiiresaki
  291.                         INNER JOIN
  292.                             goods_color_table AS `gcl`
  293.                         ON
  294.                             goods_id = gcl_goods
  295.                         INNER JOIN
  296.                             color_table AS `color`
  297.                         ON
  298.                             color_id = gcl_color_id
  299.                         INNER JOIN
  300.                             goods_price_table AS `gp`
  301.                         ON
  302.                             goods_id = gp_goods
  303.                         INNER JOIN
  304.                             size_table AS `size`
  305.                         ON
  306.                             size_id = gp_size_id
  307.                         INNER JOIN (
  308.                             SELECT
  309.                                 `jan`.*
  310.                             ,    (
  311.                                     jan_stock
  312.                                 +    IfNull(jan_stock2, 0)
  313.                                 +    IfNull(`stock_bichiku`, 0)
  314.                                 +    IfNull(jan_stock4, 0)
  315.                                 +    IfNull(jan_stock5, 0)
  316.                                 +    IfNull(jan_stock6, 0)
  317.                                 +    IfNull(jan_stock7, 0)
  318.                                 +    IfNull(jan_stock8, 0)
  319.                                 +    IfNull(jan_stock9, 0)
  320.                                 ) AS `stock_total`
  321.                             ,    (
  322.                                     IfNull(jan_stock4, 0)
  323.                                 +    IfNull(jan_stock5, 0)
  324.                                 +    IfNull(jan_stock6, 0)
  325.                                 +    IfNull(jan_stock7, 0)
  326.                                 +    IfNull(jan_stock8, 0)
  327.                                 +    IfNull(`stock_bichiku`, 0)
  328.                                 ) AS `stock_other`
  329.                             ,    (
  330.                                     IfNull(`stock_bichiku`, 0)
  331.                                 +    IfNull(jan_stock5, 0)
  332.                                 +    IfNull(jan_stock6, 0)
  333.                                 +    IfNull(jan_stock7, 0)
  334.                                 +    IfNull(jan_stock8, 0)
  335.                                 +    IfNull(jan_stock9, 0)
  336.                                 ) AS `stock_total_sub`
  337.                             ,    (`stock_bichiku` * `is_bichiku_ready`) AS `stock_bichiku_available`
  338.                             ,    (`stock_bichiku` * `is_bichiku_yoyaku_available`) AS `stock_bichiku_yoyaku_available`
  339.                             FROM (
  340.                                 SELECT
  341.                                     `jan`.*
  342.                                 ,    NullIf(IfNull(jan_stock3, 0) * `is_jan_stock3_nyuka_date_not_out_date` * (`is_bichiku_ready` || `is_bichiku_yoyaku_available`), 0) AS `stock_bichiku`
  343.                                 FROM (
  344.                                     SELECT
  345.                                         `jan`.*
  346.                                     ,    CASE WHEN jan_stock != 0 THEN (IfNull(`bichiku_nyuka_date`, '9999-99-99 23:59:59') BETWEEN :datetime AND :datetime + INTERVAL :yoyaku_available_since_days_ago DAY) ELSE bichiku_nyuka_date IS NOT NULL END AS `is_bichiku_yoyaku_available`
  347.                                     FROM (
  348.                                         SELECT
  349.                                             `jan`.*
  350.                                         ,    (IfNull(jan_stock, 0) + IfNull(jan_stock5, 0) + IfNull(jan_stock7, 0)) AS `stock_chokusou`
  351.                                         ,    DATE_FORMAT(jan_stock3_nyuka_date + INTERVAL 1 DAY,'%Y-%m-%d %h:%i:%s') AS `bichiku_nyuka_date`
  352.                                         ,    IfNull(jan_stock, 0) = 0 OR (jan_stock3_nyuka_date IS  NULL OR (IfNull(DATE_FORMAT(jan_stock3_nyuka_date + INTERVAL 1 DAY, '%Y-%m-%d'), '0000-00-00') >= DATE_FORMAT(:datetime, '%Y-%m-%d'))) AS `is_jan_stock3_nyuka_date_not_out_date`
  353.                                         ,    (jan_stock3 IS NOT NULL AND (IfNull(DATE_FORMAT(jan_stock3_nyuka_date, '%Y-%m-%d'), '0000-00-00 00:00:00') < DATE_FORMAT(:datetime, '%Y-%m-%d'))) AS `is_bichiku_ready`
  354.                                         FROM
  355.                                             goods_table AS `goods`
  356.                                         INNER JOIN
  357.                                             goods_color_table AS `gcl`
  358.                                         ON
  359.                                             goods_id = gcl_goods
  360.                                         INNER JOIN
  361.                                             color_table AS `color`
  362.                                         ON
  363.                                             color_id = gcl_color_id
  364.                                         INNER JOIN
  365.                                             goods_price_table AS `gp`
  366.                                         ON
  367.                                             goods_id = gp_goods
  368.                                         INNER JOIN
  369.                                             size_table AS `size`
  370.                                         ON
  371.                                             size_id = gp_size_id
  372.                                         INNER JOIN
  373.                                             jancode_table AS `jan`
  374.                                         ON
  375.                                             goods_id = jan_goods
  376.                                         AND
  377.                                             gcl_id = jan_color
  378.                                         AND
  379.                                             gp_id = jan_price
  380.                                         WHERE
  381.                                             jan_ddate IS NULL
  382.                                         {$criteria}
  383.                                     ) AS `jan`
  384.                                 ) AS `jan`
  385.                             ) AS `jan`
  386.                         ) AS `jan`
  387.                         ON
  388.                             goods_id = jan_goods
  389.                         AND
  390.                             gcl_id = jan_color
  391.                         AND
  392.                             gp_id = jan_price
  393.                         LEFT JOIN
  394.                             keppin_item_table AS `ki`
  395.                         ON
  396.                             goods_id = ki_goods
  397.                         AND
  398.                             gcl_id = ki_gcl
  399.                         AND
  400.                             gp_id = ki_gp
  401.                         AND
  402.                             ki_date > :datetime
  403.                         LEFT JOIN
  404.                             zero_stock_table AS `zero`
  405.                         ON
  406.                             goods_id = zero_goods
  407.                         AND
  408.                             gcl_id = zero_gcl
  409.                         AND
  410.                             gp_id = zero_gp
  411.                         AND
  412.                             zero_period > :datetime
  413.                         WHERE
  414.                             goods_ddate IS NULL
  415.                         {$criteria}
  416.                     ) AS `stock`
  417.                 ) AS `stock`
  418.             LEFT JOIN
  419.                 campaign_price_table
  420.             ON
  421.                 gp_id = cp_gp
  422.             AND
  423.                 cp_start_datetime <= :datetime
  424.             AND
  425.                 cp_end_datetime >= :datetime
  426.             AND
  427.                 cp_del_flg = 0
  428.             ORDER BY
  429.                 goods_id
  430.             ,    gcl_display
  431.             ,    color_display
  432.             ,    gcl_id
  433.             ,    gp_display
  434.             ,    size_display
  435.             ,    gp_id";
  436.         //
  437.         $result = (new SqlService())
  438.             ->Sql($sql)
  439.             ->Params($bind)
  440.             ->FetchAll() ?: []
  441.         ;
  442.         //
  443.         return $result;
  444.     }
  445.     /**
  446.      * @param int $goodsId
  447.      * @param string $datetime
  448.      * @return array|false
  449.      */
  450.     protected static function getGoodsStockInfoByGoodsId($goodsId$datetime)
  451.     {
  452.         return CacheService::getCached(function () use ($goodsId$datetime) {
  453.             //
  454.             $bind = [
  455.                 'goods_id' => $goodsId,
  456.             ];
  457.             //
  458.             $criteria "AND
  459.                         goods_id = :goods_id";
  460.             //
  461.             $result self::getGoodsStockInfo($datetime$bind$criteria);
  462.             //
  463.             return $result;
  464.         });
  465.     }
  466.     /**
  467.      * @param array $goodsIdList
  468.      * @param string $datetime
  469.      * @return array|false
  470.      */
  471.     protected static function getGoodsStockInfoByGoodsIdList(array $goodsIdList$datetime)
  472.     {
  473.         return CacheService::getCached(function () use ($goodsIdList$datetime) {
  474.             //
  475.             $bind = [];
  476.             foreach ($goodsIdList as $i => $goodsId) {
  477.                 $bind["goodsId{$i}"] = $goodsId;
  478.             }
  479.             $placeHolderGoodsIdIn implode(','array_map(function ($item) {
  480.                 return ":{$item}";
  481.             }, array_keys($bind)));
  482.             //
  483.             $criteria "AND
  484.                         goods_id IN ({$placeHolderGoodsIdIn})";
  485.             //
  486.             $result self::getGoodsStockInfo($datetime$bind$criteria);
  487.             //
  488.             return $result;
  489.         });
  490.     }
  491.     /**
  492.      * @param int $janId
  493.      * @param string $datetime
  494.      * @return array|false
  495.      */
  496.     protected static function getGoodsStockInfoByJanId($janId$datetime)
  497.     {
  498.         return CacheService::getCached(function () use ($janId$datetime) {
  499.             //
  500.             $placeholders array_map(function ($key) {
  501.                 //
  502.                 return "jan_id_{$key}";
  503.             }, array_keys((array)$janId));
  504.             //
  505.             $bind array_combine($placeholders, (array)$janId);
  506.             $placeholdersIn implode(','array_map(function ($placeholder) {
  507.                 //
  508.                 return ":{$placeholder}";
  509.             }, $placeholders));
  510.             //
  511.             $criteria "AND
  512.                             jan_id IN ({$placeholdersIn})";
  513.             //
  514.             $result self::getGoodsStockInfo($datetime$bind$criteria);
  515.             //
  516.             return $result;
  517.         });
  518.     }
  519.     /**
  520.      * @param int $gclId
  521.      * @param int $gpId
  522.      * @param string $datetime
  523.      * @return array|false
  524.      */
  525.     protected static function getGoodsStockInfoBySkuIdentity($gclId$gpId$datetime)
  526.     {
  527.         return CacheService::getCached(function () use ($gclId$gpId$datetime) {
  528.             //
  529.             $bind = [
  530.                 'gcl_id' => $gclId,
  531.                 'gp_id' => $gpId,
  532.             ];
  533.             //
  534.             $criteria "AND
  535.                             gcl_id = :gcl_id
  536.                         AND
  537.                             gp_id = :gp_id";
  538.             //
  539.             $result self::getGoodsStockInfo($datetime$bind$criteria);
  540.             //
  541.             return $result;
  542.         });
  543.     }
  544.     /**
  545.      * @param int $goodsId
  546.      * @return mixed
  547.      */
  548.     protected static function getGoodsInfoByGoodsId($goodsId)
  549.     {
  550.         return CacheService::getCached(function () use ($goodsId) {
  551.             //
  552.             $sql "SELECT
  553.                     `parent`.goods_id
  554.                 ,    `parent`.goods_set_purchase_flg
  555.                 ,    GROUP_CONCAT(DISTINCT `child`.goods_id ORDER BY gsp_type SEPARATOR ',') AS `child_goods_list`
  556.                 FROM
  557.                     goods_table AS `parent`
  558.                 LEFT JOIN
  559.                     goods_set_purchase_table
  560.                 ON
  561.                     `parent`.goods_id = gsp_goods_parent
  562.                 LEFT JOIN
  563.                     goods_table AS `child`
  564.                 ON
  565.                     `child`.goods_id = gsp_goods_child
  566.                 WHERE
  567.                     `parent`.goods_id = :goods_id
  568.                 GROUP BY
  569.                     `parent`.goods_id";
  570.             //
  571.             $bind = [
  572.                 'goods_id' => $goodsId,
  573.             ];
  574.             //
  575.             $result = (new SqlService())
  576.                 ->Sql($sql)
  577.                 ->Params($bind)
  578.                 ->fetch()
  579.             ;
  580.             //
  581.             return $result;
  582.         });
  583.     }
  584. }