Jak by jste zrefaktorovali tento model pro objednávky

Dan Hundrt
Člen | 74
+
0
-

Zdravím,

rád bych se Vás zeptal, zdali nemáte návrh na zrefaktorování komponenty níže. V kostce jde o třídu, která pracuje s objednávkami – tahá objednávky, ukládá samotnou objednávku, odběratele, platební metody, typu doručení, případně fakturační údaje.

Nelíbí se ukecanost samotných metod (findAll()), názvy si myslím že ok.

Děkuji

<?php

declare(strict_types=1);

namespace App\Model;

use DateTime;
use Nette\Database\Context;
use Nette\Database\Table\ActiveRow;

class OrderModel
{
  /** Order status */
  private const STATUS_NEW = 0;
  private const STATUS_PAYED = 1;

  /** @var Context */
  public $database;

  /** @var BasketModel */
  private $basketModel;

  /** @var HistoryModel */
  private $historyModel;

  /** @var SubscriberModel */
  private $subscriberModel;

  /** @var DeliveryModel */
  private $deliveryModel;

  /** @var PayModel */
  private $payModel;

  public function __construct(
    BasketModel $basketModel,
    Context $database,
    HistoryModel $historyModel,
    SubscriberModel $subscriberModel,
    DeliveryModel $deliveryModel,
    PayModel $payModel)
  {
    $this->basketModel = $basketModel;
    $this->database = $database;
    $this->historyModel = $historyModel;
    $this->deliveryModel = $deliveryModel;
    $this->payModel = $payModel;
    $this->subscriberModel = $subscriberModel;
  }

  /**
   * @inheritdoc Get all order
   * @return array
   */
  public function findAll(): array
  {
    $data = $this->database->table('order')->order('id DESC');

    $result = [];
    foreach ($data->fetchAll() as $item) {
      $sum = 0;
      foreach ($item->related('order_products') as $product) {
        $sum += $product->offsetGet('price') * $product->offsetGet('stock');
      }

      $delivery = $item->ref('delivery_id')->offsetGet('price');
      $pay = $item->ref('pay_id')->offsetGet('price');

      $getStatus = $item->related('history_order')->order('id', 'DESC')->fetch();

      $result[] = [
        'order'       => $item->toArray(),
        'subscribers' => $item->ref('subscribers')->toArray(),
        'status'      => $this->historyModel->getActiveStatus($getStatus['type'] ?: 1),
        'price'       => $sum + $pay + $delivery,
      ];
    }

    return $result;
  }

  /**
   * @param int $number
   * @return ActiveRow
   */
  public function findByNumber(int $number): ActiveRow
  {
    return $this->database->table('order')->where(['number' => $number])->fetch();
  }

  /**
   * @inheritdoc Get detail order with all data
   * @param int $id
   * @return array
   */
  public function find(int $id): array
  {
    $data = $this->database->table('order')->get($id);

    $sum = 0;
    foreach ($data->related('order_products') as $product) {
      $sum += $product->offsetGet('price') * $product->offsetGet('stock');
    }

    $price = $data->ref('pay_id')->offsetGet('price') + $data->ref('delivery_id')->offsetGet('price');

    return [
      'order'              => $data,
      'subscriber'         => $data->ref('subscribers'),
      'subscriberCompany'  => $data->ref('subscribers')->ref('company_id'),
      'subscriberDelivery' => $data->ref('subscribers')->ref('delivery_id'),
      'delivery'           => $data->ref('delivery_id'),
      'pay'                => $data->ref('pay_id'),
      'products'           => $data->related('order_products')->fetchAll(),
      'totalPrice'         => $sum + $price,
      'status'             => $data->related('history_order'),
    ];
  }

  /**
   * @inheritdoc Get
   * @param string $hash
   * @return mixed
   */
  public function findByHash(string $hash)
  {
    return $this->database->table('order')->where(['hash' => $hash])->fetch();
  }

  /**
   * @param $data
   * @param string $hash
   * @param int $number
   * @return bool
   * @throws \Exception
   */
  public function save($data, string $hash, int $number)
  {
    if ($this->saveSubscriber($data, $hash, $number)) {
      return $this->basketModel->delete();
    }
  }


  /**
   * @param $value
   * @param string $hash
   * @param int $number
   * @return bool|int|ActiveRow
   * @throws \Exception
   */
  public function saveSubscriber($value, string $hash, int $number)
  {
    $subscribersId = $this->database->table('subscribers')->insert([
      'date'        => new DateTime(),
      'name'        => $value['name'],
      'surname'     => $value['surname'],
      'email'       => $value['email'],
      'phone'       => str_replace(' ', '', $value['phone']),
      'delivery_id' => $this->subscriberModel->saveDelivery($value)->offsetGet('id'),
      'company_id'  => $this->subscriberModel->saveCompany($value)
    ])->offsetGet('id');

    $delivery = $this->deliveryModel->copyDeliveryToOrder($value['delivery'])->offsetGet('id');
    $pay = $this->payModel->copyPayToOrder($value['pay'])->offsetGet('id');

    return $this->saveOrderInterbankTable($subscribersId, $delivery, $pay, $hash, $number);
  }


  /**
   * @inheritdoc Insert data to interbank table (order)
   * @param int $id
   * @param int $delivery
   * @param int $pay
   * @param int $number
   * @param string $hash
   * @return bool|int|ActiveRow
   * @throws \Exception
   */
  public function saveOrderInterbankTable(int $id, ?int $delivery, ?int $pay, string $hash, int $number)
  {
    return $this->saveProducts($this->database->table('order')->insert([
      'subscribers_id' => $id,
      'delivery_id'    => $delivery,
      'pay_id'         => $pay,
      'status'         => self::STATUS_NEW,
      'number'         => $number,
      'hash'           => $hash
    ])->offsetGet('id'));
  }

  /**
   * @inheritdoc Save product to table
   * @param $id
   * @return ActiveRow
   * @throws \Exception
   */
  public function saveProducts($id): ActiveRow
  {
    $basket = $this->basketModel->getUserBasket();
    $data = $this->database->table('basket_product')->where(['basket_id' => $basket['id']])->fetchAll();

    $result = [];
    foreach ($data as $product) {
      $cart = $product->toArray();
      $product = $product->ref('product')->toArray();

      $result[] = [
        'stock'      => $cart['count'],
        'price'      => $product['price'],
        'title'      => $product['title'],
        'product_id' => $product['id'],
        'date'       => new DateTime(),
        'order_id'   => $id,
      ];
    }

    return $this->database->table('order_products')->insert($result);
  }

  /**
   * @inheritdoc Set status order
   * @param int $status
   * @param int $number
   * @return int
   */
  public function setStatus(int $status, int $number): int
  {
    return $this->database->table('order')->where(['number' => $number])->update(['status' => $status]);
  }

  /**
   * @inheritdoc Find only order
   * @return array
   */
  public function findOnlyOrders(): array
  {
    return $this->database->table('order')->fetchAll();
  }
}
CZechBoY
Člen | 3608
+
0
-

Já bych každou public metodu vyhodil do samostatný třídy. Pokud chceš mít vše na jednom místě tak bych pak z tohohle udělal fasádu, která by jen v každé metodě volala jednotlivé služby.

David Matějka
Moderator | 6445
+
0
-

proc pouzivas $product->offsetGet('price') a ne $product['price'] resp. $product->price?

a jako prvni krok bych vytvoril nejaka DTO pro ta data. takhle vracis array of array, takze nefunguje staticka analyza, napovidani atd.