Beispiel #1
0
 /**
  * 2016-03-27
  * https://mage2.pro/t/1031
  * The methods
  * @see \Magento\Sales\Model\Order\Payment\Operations\AbstractOperation::getInvoiceForTransactionId()
  * and @see \Magento\Sales\Model\Order\Payment::_getInvoiceForTransactionId()
  * duplicate almost the same code
  * @param IO|O $order
  * @param int $transactionId.
  * @return Invoice|null
  */
 public static function getInvoiceForTransactionId(IO $order, $transactionId)
 {
     /** @var Payment $i */
     $i = df_om()->create(__CLASS__);
     $i->setOrder($order);
     return $i->_getInvoiceForTransactionId($transactionId);
 }
Beispiel #2
0
 /**
  * 2016-07-27
  * Цель плагина — добавление возможности отключения необходимости платёжного адреса.
  * Это будет использоваться моими платёжными модулями.
  * Помимо этого плагина для данной функциональности нужны ещё 2:
  * @see \Df\Customer\Plugin\Model\Address\AbstractAddress
  * @see \Df\Sales\Plugin\Model\Order\Address\Validator
  *
  * @see \Magento\Customer\Model\ResourceModel\AddressRepository::save()
  * @param Sb $sb
  * @param \Closure $proceed
  * @param AI|CDA $address
  * @return AI
  * @throws InputException
  */
 public function aroundSave(Sb $sb, \Closure $proceed, AI $address)
 {
     /** @var AI $result */
     /**
      * 2016-07-27
      * Адрес приобретает тип, только когда используется при оформлении заказа.
      * Пока же адрес просто принадлежит покупателю
      * @see \Magento\Customer\Model\Data\Address
      * @see \Magento\Customer\Api\Data\AddressInterface
      * а не используется в контексте оформления заказа, то такой адрес ещё типа не имеет,
      * и в будущем, в зависимости от контекста,
      * может использоваться и как адрес доставки, и как платёжный адрес.
      *
      * По этой причине мы не вызываем здесь @see df_address_is_billing()
      * В то же время, мы попадаем сюда при оформлении заказа,
      * поэтому мы не можем проводить валидацию адреса,
      * если необходимость платёжного адреса отключена администратором.
      * Поэтому ветка S::disabled() нужна.
      */
     if (!S::disabled()) {
         $result = $proceed($address);
     } else {
         /** @var Customer $customer */
         $customer = df_customer_get($address->getCustomerId());
         /** @var Address $addressM */
         $addressM = null;
         if ($address->getId()) {
             $addressM = df_address_registry()->retrieve($address->getId());
         }
         if ($addressM) {
             $addressM->updateData($address);
         } else {
             $addressM = df_om()->create(Address::class);
             $addressM->updateData($address);
             $addressM->setCustomer($customer);
         }
         // 2016-07-27
         // Вот здесь в ядре валидация, а мы её пропускаем.
         $addressM->save();
         // Clean up the customer registry since the Address save has side effect on customer:
         // \Magento\Customer\Model\ResourceModel\Address::_afterSave
         df_customer_registry()->remove($address->getCustomerId());
         df_address_registry()->push($addressM);
         $customer->getAddressesCollection()->clear();
         $result = $addressM->getDataModel();
     }
     return $result;
 }
Beispiel #3
0
/**
 * 2016-03-26
 * @param string|M $model
 * Идентификатор необязательно является целым числом,
 * потому что объект может загружаться по нестандартному ключу
 * (с указанием этого ключа параметром $field).
 * Так же, и первичный ключ может не быть целым числом (например, при загрузке валют).
 * @param string|int $id
 * @param bool $throwOnAbsence [optional]
 * @param string|null $field [optional]
 * @return M|null
 */
function df_load($model, $id, $throwOnAbsence = true, $field = null)
{
    df_assert($id);
    if (!is_null($field)) {
        df_param_string($field, 3);
    }
    /** @var M|null $result */
    $result = is_string($model) ? df_om()->create($model) : $model;
    df_assert($result instanceof M);
    $result->load($id, $field);
    if (!$result->getId()) {
        if (!$throwOnAbsence) {
            $result = null;
        } else {
            df_error('A model of class «%s» with ID «%s» is absent.', get_class($result), $id);
        }
    }
    return $result;
}
Beispiel #4
0
/**
 * @param string $type
 * @return mixed
 */
function df_o($type)
{
    return dfcf(function ($type) {
        return df_om()->get($type);
    }, func_get_args());
}
Beispiel #5
0
/**
 * 2016-03-26
 * @return Transaction
 */
function df_db_transaction()
{
    return df_om()->create(Transaction::class);
}
Beispiel #6
0
/**   
 * 2016-09-08
 * 2016-03-27
 * «How is an online refunding implemented?» https://mage2.pro/t/959
 * Сначала хотел cделать по аналогии с @see \Magento\Paypal\Model\Ipn::_registerPaymentRefund()
 * https://github.com/magento/magento2/blob/9546277/app/code/Magento/Paypal/Model/Ipn.php#L467-L501
 * Однако используемый там метод @see \Magento\Sales\Model\Order\Payment::registerRefundNotification()
 * нерабочий: «Invalid method Magento\Sales\Model\Order\Creditmemo::register»
 * https://mage2.pro/t/1029
 * Поэтому делаю по аналогии с @see \Magento\Sales\Controller\Adminhtml\Order\Creditmemo\Save::execute()
 *
 * @param P $p
 * @param I $i
 * @param string|int|float|null $amount [optional]
 * @return int
 */
function dfp_refund(P $p, I $i, $amount = null)
{
    /** @var M $m */
    $m = $p->getMethodInstance();
    /** @var O $o */
    $o = $m->o();
    /** @var CML $cml */
    $cml = df_o(CML::class);
    $cml->setOrderId($o->getId());
    $cml->setInvoiceId($i->getId());
    if ($amount) {
        /**
         * 2016-09-08
         * Обработка частичного возврата.
         * Делаем по аналогии с @see \Dfe\TwoCheckout\Handler\RefundIssued::cm()
         *
         * Произвожу расчёты в базовой валюте, чтобы не мешали курсовые колебания,
         * которые могли произойти в период между платежом и возвратом.
         */
        /** @var float $refundAmountB */
        $refundAmountB = $m->cToBase($m->amountParse($amount));
        /** @var float $invoiceAmountB */
        $invoiceAmountB = $i->getBaseGrandTotal();
        /** @var float $diffB */
        $diffB = $invoiceAmountB - $refundAmountB;
        if (!df_is0($diffB)) {
            /**
             * 2016-05-23
             * https://mage2.pro/tags/credit-memo-adjustment
             *
             * Стек вызова:
             * 1) @used-by \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader::load()
             * https://github.com/magento/magento2/blob/b366da/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php#L186
             * 2) @used-by \Magento\Sales\Model\Order\CreditmemoFactory::createByInvoice()
             * https://github.com/magento/magento2/blob/b366da/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php#L155
             * 3) @used-by \Magento\Sales\Model\Order\CreditmemoFactory::initData()
             * https://github.com/magento/magento2/blob/b366da/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php#L244-L246
             */
            $cml->setCreditmemo(['adjustment_negative' => df_currency_convert($diffB, df_currency_base($o), $o->getOrderCurrency())]);
        }
    }
    /** @var CM $cm */
    $cm = $cml->load();
    df_assert($cm);
    /**
     * 2016-03-28
     * Важно! Иначе order загрузит payment автоматически вместо нашего,
     * и флаг @see \Dfe\Stripe\Method::WEBHOOK_CASE будет утерян
     */
    $cm->getOrder()->setData(O::PAYMENT, $p);
    /** @var ICMS|CMS $cms */
    $cms = df_om()->create(ICMS::class);
    $cms->refund($cm, false);
    /**
     * 2016-03-28
     * @todo Надо отослать покупателю письмо-оповещение о возврате оплаты.
     * 2016-05-15
     * Что интересно, при возврате из административной части Magento 2
     * покупатель тоже не получает уведомление.
     */
    return $cm->getId();
}
Beispiel #7
0
 /**
  * 2015-10-12
  * Регистрация нового клиента.
  * @param MC $customer
  * @return void
  */
 private function register(MC $customer)
 {
     /**
      * 2015-10-12
      * https://github.com/magento/magento2/issues/2087
      * Приходится присваивать магазин в 2 шага...
      */
     /** @var \Magento\Store\Api\Data\StoreInterface|\Magento\Store\Model\Store $store */
     $store = df_store_m()->getStore();
     $customer->setStore($store);
     $customer->setGroupId(df_customer_group_m()->getDefaultGroup($store->getId())->getId());
     $customer->addData($this->customerData());
     $customer->save();
     /**
      * 2016-06-05
      * Не всегда имеет смысл автоматически создавать адрес.
      * В частности, для Amazon решил этого не делать,
      * потому что автоматический адрес создаётся на основании геолокации, что не точно,
      * а в случае с Amazon мы гарантированно можем получить точный адрес из профиля Amazon,
      * поэтому нам нет никакого смысла забивать систему неточным автоматическим адресом.
      * @see \Dfe\AmazonLogin\Controller\Index\Index::needCreateAddress()
      */
     if ($this->needCreateAddress()) {
         /** @var Address $address */
         $address = df_om()->create(Address::class);
         $address->setCustomer($customer);
         $address->addData(df_clean($this->addressData() + ['firstname' => $this->c()->nameFirst(), 'lastname' => $this->c()->nameLast(), 'middlename' => $this->c()->nameMiddle(), 'city' => df_visitor()->city(), 'country_id' => df_visitor()->iso2(), 'is_default_billing' => 1, 'is_default_shipping' => 1, 'postcode' => df_visitor()->postCode() ?: (df_is_postcode_required(df_visitor()->iso2()) ? '000000' : null), 'region' => df_visitor()->regionName(), 'region_id' => null, 'save_in_address_book' => 1, 'street' => '---', 'telephone' => '000000']));
         $address->save();
     }
     df_dispatch('customer_register_success', ['account_controller' => $this, 'customer' => $customer]);
 }