src/Eccube/Service/PurchaseFlow/Processor/AgencyCommissionProcessor.php line 56

Open in your IDE?
  1. <?php
  2. namespace Eccube\Service\PurchaseFlow\Processor;
  3. use Eccube\Annotation\OrderFlow;
  4. use Eccube\Entity\ItemHolderInterface;
  5. use Eccube\Service\PurchaseFlow\PurchaseContext;
  6. use Eccube\Service\PurchaseFlow\PurchaseProcessor;
  7. use Eccube\Entity\Order;
  8. use Plugin\CouponPro42\Entity\Master\CouponKind;
  9. use Eccube\Repository\TaxRuleRepository;
  10. use Symfony\Component\DependencyInjection\ContainerInterface;
  11. use Eccube\Service\TaxRuleService;
  12. /**
  13.  * @OrderFlow
  14.  */
  15. class AgencyCommissionProcessor implements PurchaseProcessor
  16. {
  17.     protected $taxRuleRepository;
  18.     /**
  19.      * @var TaxRuleService
  20.      */
  21.     private $taxRuleService;
  22.     /**
  23.      * @var ContainerInterface
  24.      */
  25.     protected $container;
  26.     public function __construct(
  27.         ContainerInterface $container,
  28.         TaxRuleRepository $taxRuleRepository,
  29.         TaxRuleService $taxRuleService
  30.     ) {
  31.         $this->container $container;
  32.         $this->taxRuleService $taxRuleService;
  33.         $this->taxRuleRepository $taxRuleRepository;
  34.     }
  35.     public function prepare(ItemHolderInterface $itemHolderPurchaseContext $context)
  36.     {
  37.         // このメソッドは今回使用しない
  38.         error_log('prepare');
  39.     }
  40.     public function commit(ItemHolderInterface $itemHolderPurchaseContext $context)
  41.     {
  42.         if (!$itemHolder instanceof Order) {
  43.             return;
  44.         }
  45.         // 代理店手数料の計算と設定を行う
  46.         $this->calculateAgencyCommission($itemHolder);
  47.     }
  48.     public function rollback(ItemHolderInterface $itemHolderPurchaseContext $context)
  49.     {
  50.         // ロールバック処理が必要な場合に実装
  51.         error_log('rollback');
  52.     }
  53.     //代理店手数料の計算
  54.     private function calculateAgencyCommission(Order $Order)
  55.     {
  56.         // OrderItemを取得
  57.         $OrderItems $Order->getOrderItems();
  58.         // 代理店手数料の計算と設定を行う
  59.         // デバック用 ログにクーポンタイプを記録
  60.         // OrderItemからOrderItemTypeエンティティを取得
  61.         // foreach ($OrderItems as $OrderItem) {
  62.         //     $itemType = $OrderItem->getOrderItemType();
  63.         //     error_log("一つのループ");
  64.         //     error_log($itemType);
  65.         //     $orderDiscountTotal = $Order->getDiscount();
  66.         //     error_log($orderDiscountTotal);
  67.         //     // クーポンによる値引き商品を特定
  68.         //     if ($OrderItem->getPrice() < 0) {
  69.         //         error_log("値引き項目");
  70.         //     }
  71.         // }
  72.         //===========================
  73.         //カスタマイズ 代理店手数料の計算
  74.         //===========================
  75.         //受注作成時に代理店手数料金を計算して、データベースへ保存する
  76.         //代理店手数料の計算方法:商品価格*代理店手数料率(%)
  77.         //1.値引きクーポンがあった場合(クーポンタイプ1):代理店手数料率(%)が最も低い商品に対して値引きをした上で、代理店手数料を計算
  78.         //2.送料無料クーポンがあった場合(クーポンタイプ3):値引き額は考慮せずに代理店手数料を計算
  79.         //3.割引クーポンがあった場合(クーポンタイプ2):注文の代理店手数料の合計値に対して割引率を適用
  80.         //4(なし).定期受注の回数値引きがあった場合:対象の値引き商品に対して、回数値引きを適用した金額の代理店手数料金額を計算
  81.         //5(なし).定期受注の回数値引きがあり、さらにその商品が代理店手数料率が高くクーポンによる値引きがあった場合:対象の商品に対して、回数値引きを適用した金額を設定し、その金額の代理店手数料を計算
  82.         //※クーポン価格>対象商品価格の場合は、残価分が0になるまで次ループで処理
  83.         //--------------
  84.         //ここで購入者が会員だった場合、会員データベースのagency_codeの値を取得して、値がnullではなかった場合にその情報をorderデータベースのagency_order_codeカラムへ保存する
  85.         // OrderオブジェクトからCustomerオブジェクトを取得
  86.         $Customer $Order->getCustomer();
  87.         // 会員データベースからagency_codeを取得
  88.         if ($Customer && $Customer->getId() && $Customer->getAgencyCode()) {
  89.             // 商品の総個数を計算するための変数を初期化
  90.             $totalProductQuantity 0;
  91.             // 値引き額を初期化
  92.             // $discountAmount = 0;
  93.             // 代理店手数料率の初期化
  94.             $agencyCommissionRate 0;
  95.             //================
  96.             //税設定の取得
  97.             //================
  98.             // TaxRuleRepositoryのインスタンスを取得
  99.             $taxRuleRepository $this->container->get(TaxRuleRepository::class);
  100.             // 現在有効な税率設定を取得
  101.             $currentTaxRule $taxRuleRepository->getByRule();
  102.             // 税率を取得
  103.             $taxRate $currentTaxRule->getTaxRate();
  104.             // 現在有効な税率設定を取得
  105.             $taxRoundingType $currentTaxRule->getRoundingType()->getId();
  106.             //調整値
  107.             $taxAdjust $currentTaxRule->getTaxAdjust();
  108.             // 代理店手数料合計値の初期化
  109.             $totalAgencyCommission 0;
  110.             //=================
  111.             //クーポンフラグの初期化
  112.             //=================
  113.             $flgDiscountCoupon false//値引きクーポンフラグ
  114.             $flgRebateCoupon false//割引クーポンフラグ
  115.             $flgPostageCoupon false//送料無料クーポンフラグ
  116.             //=================
  117.             //クーポン値引情報の初期化
  118.             //=================
  119.             $amountDiscountCoupon 0//クーポン値引金額
  120.             //=================
  121.             //クーポン値引金額の残高
  122.             //=================
  123.             $amountDiscountCouponBalance 0;
  124.             //=================
  125.             //定期購入回数割引情報の初期化
  126.             //================
  127.             $discountDetails = [];
  128.             //デバッグ用
  129.             // error_log('代理店手数料のループ');
  130.             //=====================================
  131.             //代理店手数料率に応じて商品の配列の並び替えを実行
  132.             //=====================================
  133.             // 商品かつ代理店手数料が設定されている商品の配列
  134.             $agencyCommissionRates = [];
  135.             foreach ($OrderItems as $OrderItem) {
  136.                 // 商品情報の取得
  137.                 $ProductClass $OrderItem->getProductClass();
  138.                 if ($ProductClass) {
  139.                     // 商品に設定された代理店手数料率(%)を取得
  140.                     $agencyCommissionRate $ProductClass->getAgencyCommission();
  141.                     // 代理店手数料が取得できた場合のみ配列に格納
  142.                     if ($agencyCommissionRate !== null) {
  143.                         $agencyCommissionRates[] = ['orderItem' => $OrderItem'rate' => $agencyCommissionRate];
  144.                     }
  145.                     // 手数料が取得できなかった場合配列に入れない
  146.                     // 0%があった場合の例外処理
  147.                     else {
  148.                         // $agencyCommissionRates[] = ['orderItem' => $OrderItem, 'rate' => 0];
  149.                     }
  150.                 }
  151.                 // regularOrderDetails フィールドから定期割引詳細を取得
  152.                 $regularOrderDetails $OrderItem->getRegularOrderDetails();
  153.                 // 各商品に対する定期割引情報が含まれている場合
  154.                 if ($regularOrderDetails) {
  155.                     error_log('各商品に対する定期割引情報が含まれている場合');
  156.                     foreach ($regularOrderDetails as $detail) {
  157.                         // 商品IDと割引価格を $discountDetails 配列に格納
  158.                         $discountDetails[$detail['productId']] = $detail['discountPrice'];
  159.                         error_log('定期割引' $discountDetails[$detail['productId']]);
  160.                     }
  161.                 }
  162.             }
  163.             // 代理店手数料率でソート
  164.             usort($agencyCommissionRates, function ($a$b) {
  165.                 return $a['rate'] <=> $b['rate'];
  166.             });
  167.             // ソートされたOrderItemsを取得
  168.             $sortedOrderItems array_map(function ($item) {
  169.                 return $item['orderItem'];
  170.             }, $agencyCommissionRates);
  171.             //適用されているクーポンタイプの取得
  172.             foreach ($OrderItems as $OrderItem) {
  173.                 //==============================
  174.                 //商品に設定されたクーポンタイプの取得
  175.                 //1:値引
  176.                 //2:割引
  177.                 //3:送料無料
  178.                 //==============================
  179.                 //クーポンタイプと値引き額の取得
  180.                 $OrderItemCouponKind $OrderItem->getCouponKind();
  181.                 if ($OrderItemCouponKind) {
  182.                     //値引きクーポンの場合
  183.                     if ($OrderItemCouponKind == CouponKind::DISCOUNT_PRICE) {
  184.                         $flgDiscountCoupon true//値引きクーポンフラグ
  185.                         error_log('値引きクーポンフラグ 適用');
  186.                         //割引クーポンの場合
  187.                     } else if ($OrderItemCouponKind == CouponKind::DISCOUNT_RATE) {
  188.                         $flgRebateCoupon true//割引クーポンフラグ
  189.                         error_log('割引クーポンフラグ 適用');
  190.                     }
  191.                     //送料無料クーポンの場合
  192.                     else if ($OrderItemCouponKind == CouponKind::FREE_DELIVERY_FEE) {
  193.                         $flgPostageCoupon true//送料無料クーポンフラグ
  194.                         error_log('送料クーポンフラグ 適用');
  195.                     }
  196.                     //値引額の取得
  197.                     $amountDiscountCoupon $OrderItem->getPrice();
  198.                     //クーポン残価の更新
  199.                     $amountDiscountCouponBalance $amountDiscountCoupon * -1;
  200.                 }
  201.             }
  202.             //代理店手数料率でソートされた商品の配列をループ
  203.             foreach ($sortedOrderItems as $OrderItem) {
  204.                 // 商品個数分だけループ
  205.                 for ($i 0$i $OrderItem->getQuantity(); $i++) {
  206.                     //商品名の取得
  207.                     $OrderItemName $OrderItem->getProductName();
  208.                     error_log($OrderItemName 'の代理店手数料計算処理を開始');
  209.                     //商品情報の取得
  210.                     $ProductClass $OrderItem->getProductClass();
  211.                     // 商品IDの取得
  212.                     $ProductId $OrderItem->getProductClass()->getProduct()->getId();
  213.                     error_log($ProductId ' 商品ID (Type: ' gettype($ProductId) . ')');
  214.                     // 割引詳細から該当商品の割引額を取得
  215.                     $regularDiscountAmount array_key_exists($ProductId$discountDetails) ? $discountDetails[$ProductId] : 0;
  216.                     error_log('定期割引取得結果' $regularDiscountAmount);
  217.                     error_log('ID' $ProductId);
  218.                     // discountDetailsの中身をエラーログに出力
  219.                     error_log('Discount Details: ' print_r($discountDetailstrue));
  220.                     //商品以外の場合スキップ
  221.                     if (!$ProductClass || $OrderItem->getPrice() < 0) {
  222.                         error_log($OrderItemName 'は商品以外なのでスキップ');
  223.                         continue;
  224.                     }
  225.                     // error_log('定期商品の値引き合計値: ' . $regularDiscountAmount);
  226.                     //商品の金額(税込)
  227.                     $OrderItemPrice $OrderItem->getPrice();
  228.                     // 丸め規則はデフォルトの課税規則に従う
  229.                     $OrderItemPrice $OrderItemPrice $this->taxRuleService->calcTax(
  230.                         $OrderItemPrice,
  231.                         $taxRate,
  232.                         $taxRoundingType,
  233.                         $taxAdjust
  234.                     );
  235.                     // error_log($OrderItemPrice . 'が商品の金額');
  236.                     //商品に設定された代理店手数料率(%)を取得
  237.                     $agencyCommissionRate $ProductClass->getAgencyCommission();
  238.                     // error_log($agencyCommissionRate . 'が代理店手数料率');
  239.                     //商品の税込サブトータル = 商品金額
  240.                     $subtotalWithTax $OrderItemPrice;
  241.                     // error_log($subtotal . '商品の税抜サブトータル');
  242.                     //商品の税込サブトータル
  243.                     // error_log($subtotalWithTax . '商品の税込サブトータル');
  244.                     //クーポンがある場合
  245.                     if ($flgDiscountCoupon || $flgPostageCoupon || $flgRebateCoupon) {
  246.                         // error_log('値引きクーポンの処理');
  247.                         //クーポン残価が正の場合
  248.                         if ($amountDiscountCouponBalance 0) {
  249.                             //クーポン残価がサブトータルより高い場合
  250.                             if ($amountDiscountCouponBalance $subtotalWithTax) {
  251.                                 //代理店手数料を反映させる金額は0
  252.                                 $subtotalWithTaxAndDiscount 0;
  253.                             }
  254.                             //クーポン残価がサブトータルより低い場合
  255.                             else {
  256.                                 // 代理店手数料を反映させる金額(サブトータル(税込) - 値引クーポンの残価 - 定期受注割引)を計算
  257.                                 $subtotalWithTaxAndDiscount $subtotalWithTax $amountDiscountCouponBalance $regularDiscountAmount;
  258.                                 //理店手数料を反映させる金額が負の場合は0
  259.                                 if ($subtotalWithTaxAndDiscount 0) {
  260.                                     $subtotalWithTaxAndDiscount 0;
  261.                                 }
  262.                             }
  263.                             //クーポン残価の更新
  264.                             $amountDiscountCouponBalance $amountDiscountCouponBalance $subtotalWithTax $regularDiscountAmount;
  265.                             // error_log($subtotalWithTax . '値引きクーポン対象の商品');
  266.                             // error_log('値引きクーポンの処理');
  267.                             // error_log('代理店手数料反映金額:'.$subtotalWithTaxAndDiscount);
  268.                             // error_log('代理店手数料反映金額計算:'.$subtotalWithTax.'-'.$amountDiscountCoupon.'-'.$regularDiscountAmount);
  269.                         } else {
  270.                             // error_log('値引きクーポン対象外の商品');
  271.                             // 代理店手数料を反映させる金額(サブトータル(税込) - 定期受注割引)を計算
  272.                             $subtotalWithTaxAndDiscount $subtotalWithTax $regularDiscountAmount;
  273.                             // error_log('代理店手数料反映金額:'.$subtotalWithTaxAndDiscount);
  274.                         }
  275.                     }
  276.                     //クーポンがない場合 
  277.                     else {
  278.                         // 代理店手数料を反映させる金額(サブトータル(税込)- 定期受注割引)を計算
  279.                         $subtotalWithTaxAndDiscount $subtotalWithTax $regularDiscountAmount;
  280.                     }
  281.                     error_log('代理店手数料反映金額:' $subtotalWithTaxAndDiscount);
  282.                     error_log('商品金額(端数処理前):' $OrderItem->getPrice());
  283.                     error_log('商品金額:' $OrderItemPrice);
  284.                     error_log('小計(税込):' $subtotalWithTax);
  285.                     error_log('純粋な手数料金額:' $subtotalWithTax * ($agencyCommissionRate 100.0));
  286.                     error_log('割引金額:' $regularDiscountAmount);
  287.                     //代理店手数料を計算
  288.                     if ($agencyCommissionRate 0) {
  289.                         $commissionAmount $subtotalWithTaxAndDiscount * ($agencyCommissionRate 100.0);
  290.                     } else {
  291.                         $commissionAmount 0;
  292.                     }
  293.                     // error_log('代理店手数料:'.$commissionAmount);
  294.                     // 代理店手数料に端数処理を適用(切り捨て)
  295.                     error_log('手数料結果端数処理前:' $commissionAmount);
  296.                     $commissionAmountRounded $this->applyRounding($commissionAmount2);
  297.                     error_log('手数料結果:' $commissionAmountRounded);
  298.                     // error_log('端数処理した代理店手数料:'.$commissionAmountRounded);
  299.                     // 代理店手数料の合計に加算
  300.                     $totalAgencyCommission += $commissionAmountRounded;
  301.                     // 各商品の個数を合計
  302.                     $totalProductQuantity += $OrderItem->getQuantity();
  303.                 }
  304.             }
  305.             // 受注に代理店手数料を設定
  306.             // 登録処理OK
  307.             $Order->setAgencyCommissionAmount($totalAgencyCommission);
  308.             // error_log('代理店手数料合計金額:'.$commissionAmountRounded);
  309.             // 商品の総個数を設定
  310.             $Order->setProductQuantity($totalProductQuantity);
  311.             // agency_codeがnullではない場合、その値をagency_order_codeに設定
  312.             $Order->setAgencyOrderCode($Customer->getAgencyCode());
  313.         } else {
  314.             // 会員でない、またはagency_codeがnullの場合、代理店手数料を0に設定
  315.             $totalAgencyCommission 0;
  316.             $Order->setAgencyCommissionAmount($totalAgencyCommission);
  317.         }
  318.     }
  319.     //========================
  320.     //税計算
  321.     //1:四捨五入
  322.     //2:切り捨て
  323.     //3:切り上げ
  324.     //========================
  325.     protected function applyRounding($amount$roundingType)
  326.     {
  327.         switch ($roundingType) {
  328.             case 1// 四捨五入
  329.                 return (int)round($amount);
  330.             case 2// 切り捨て
  331.                 return (int)floor($amount);
  332.             case 3// 切り上げ
  333.                 return (int)ceil($amount);
  334.             default:
  335.                 // デフォルト処理
  336.                 return (int)round($amount);
  337.         }
  338.     }
  339. }