Оферта, доставка, ограничения, страницы покупателям
This commit is contained in:
parent
3ea7a9e1eb
commit
03b52d071d
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use yii\web\Controller;
|
||||
|
||||
class BuyersController extends Controller
|
||||
{
|
||||
public function actionIndex()
|
||||
{
|
||||
return $this->renderPartial('/buyers/index');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use yii;
|
||||
|
||||
use yii\web\Controller;
|
||||
|
||||
class OfferController extends Controller
|
||||
{
|
||||
public function actionIndex()
|
||||
{
|
||||
return $this->render('/offer/index');
|
||||
}
|
||||
|
||||
public function actionAccept() {
|
||||
yii::$app->user->identity->acpt = true;
|
||||
|
||||
if (yii::$app->user->identity->save()) {
|
||||
// Удалось записать данные
|
||||
|
||||
yii::$app->response->redirect('/');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use yii\web\Controller;
|
||||
|
||||
class PartnersController extends Controller
|
||||
{
|
||||
public function actionIndex()
|
||||
{
|
||||
return $this->render('/partners/index');
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ use app\models\Search;
|
|||
use app\models\Notification;
|
||||
use app\models\Settings;
|
||||
use app\models\SettingsEdgeSettings;
|
||||
use app\models\connection\Dellin;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
|
@ -76,7 +75,7 @@ class ProfileController extends Controller
|
|||
// Генерация ответа
|
||||
Yii::$app->response->content = json_encode([
|
||||
'main' => $this->renderPartial('/account/index'),
|
||||
'redirect' => '/authentication',
|
||||
'redirect' => '/profile',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
]);
|
||||
} else if (Yii::$app->request->isGet) {
|
||||
|
@ -118,15 +117,37 @@ class ProfileController extends Controller
|
|||
}
|
||||
|
||||
// Инициализация
|
||||
$delivery_from_city_list = $model->genListCitiesFrom();
|
||||
$delivery_to_city_list = $model->genListCitiesTo();
|
||||
$delivery_from_terminal_list = $model->genListTerminalsFrom();
|
||||
$delivery_to_terminal_list = $model->genListTerminalsTo();
|
||||
$import_oem_list = $model->genListOem(Supply::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]'));
|
||||
$array_unshift_in_start = function (array &$array, string|int $key, mixed $value)
|
||||
{
|
||||
$array = array_reverse($array, true);
|
||||
$array[$key] = $value;
|
||||
return $array = array_reverse($array, true);
|
||||
};
|
||||
$array_write_default_value = function (array &$array, string $key = 'Выберите', string $value = 'Выберите') use ($array_unshift_in_start) {
|
||||
if (isset($array[$key])) {
|
||||
// Смещение или ассоциация найдена
|
||||
|
||||
// Деинициализация
|
||||
unset($array[$key]);
|
||||
|
||||
// Инициализация
|
||||
$array_unshift_in_start($array, $key, $value);
|
||||
}
|
||||
};
|
||||
|
||||
// Сортировка по алфавиту
|
||||
asort($delivery_from_city_list);
|
||||
asort($delivery_to_city_list);
|
||||
asort($delivery_from_terminal_list);
|
||||
asort($delivery_to_terminal_list);
|
||||
asort($import_oem_list);
|
||||
|
||||
// Перемещение в начало массива значения "Выберите"
|
||||
$array_write_default_value($delivery_from_terminal_list);
|
||||
$array_write_default_value($delivery_to_terminal_list);
|
||||
$array_write_default_value($import_oem_list);
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
|
@ -136,8 +157,8 @@ class ProfileController extends Controller
|
|||
'main' => $this->renderPartial('index', compact(
|
||||
'model',
|
||||
'sidebar',
|
||||
'delivery_from_city_list',
|
||||
'delivery_to_city_list',
|
||||
'delivery_from_terminal_list',
|
||||
'delivery_to_terminal_list',
|
||||
'import_oem_list',
|
||||
'panel'
|
||||
)),
|
||||
|
@ -149,8 +170,8 @@ class ProfileController extends Controller
|
|||
return $this->render('index', compact(
|
||||
'model',
|
||||
'sidebar',
|
||||
'delivery_from_city_list',
|
||||
'delivery_to_city_list',
|
||||
'delivery_from_terminal_list',
|
||||
'delivery_to_terminal_list',
|
||||
'import_oem_list',
|
||||
'panel'
|
||||
));
|
||||
|
|
|
@ -8,6 +8,7 @@ use yii;
|
|||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
|
||||
use app\models\Account;
|
||||
use app\models\Product;
|
||||
use app\models\Supply;
|
||||
use app\models\Search;
|
||||
|
@ -173,7 +174,7 @@ class SearchController extends Controller
|
|||
// Перебор поставок
|
||||
|
||||
// Инициализация аккаунта
|
||||
$edge['account'] = Supply::searchAccountById($edge['_from']);
|
||||
$edge['account'] = Account::searchBySupplyId($edge['_from']);
|
||||
|
||||
// Инициализация доставки
|
||||
$edge['delivery'] = Dellin::calcDelivery($edge['account']['opts']['delivery_from_city'] ?? $settings['delivery_from_city_default'] ?? '2700000100000000000000000', yii::$app->user->identity->opts['delivery_to_city'] ?? $settings['delivery_to_city_default'] ?? '2700000100000000000000000')['terminals_standard'];
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use yii\web\Controller;
|
||||
|
||||
class SuppliersController extends Controller
|
||||
{
|
||||
public function actionIndex()
|
||||
{
|
||||
return $this->renderPartial('/suppliers/index');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210502_102203_create_terminal_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
/**
|
||||
* @param string Название коллекции
|
||||
* @param array Тип коллекции (2 - документ, 3 - ребро)
|
||||
*/
|
||||
$this->createCollection('terminal', ['type' => 2]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('terminal');
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210412_171912_create_city_controller extends Migration
|
||||
class m210502_102358_create_dellin_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
|
@ -10,11 +10,11 @@ class m210412_171912_create_city_controller extends Migration
|
|||
* @param string Название коллекции
|
||||
* @param array Тип коллекции (2 - документ, 3 - ребро)
|
||||
*/
|
||||
$this->createCollection('city', ['type' => 2]);
|
||||
$this->createCollection('dellin', ['type' => 2]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('city');
|
||||
$this->dropCollection('dellin');
|
||||
}
|
||||
}
|
|
@ -9,7 +9,8 @@ use yii\web\IdentityInterface;
|
|||
|
||||
use carono\exchange1c\interfaces\PartnerInterface;
|
||||
|
||||
use app\models\connection\Dellin;
|
||||
use app\models\Dellin;
|
||||
use app\models\traits\SearchByEdge;
|
||||
|
||||
/**
|
||||
* Аккаунт
|
||||
|
@ -18,6 +19,8 @@ use app\models\connection\Dellin;
|
|||
*/
|
||||
class Account extends Document implements IdentityInterface, PartnerInterface
|
||||
{
|
||||
use SearchByEdge;
|
||||
|
||||
/**
|
||||
* Имя коллекции
|
||||
*/
|
||||
|
@ -46,7 +49,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
'onec',
|
||||
'opts',
|
||||
'agnt',
|
||||
'type'
|
||||
'type',
|
||||
'acpt'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -71,7 +75,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
'onec' => 'Данные 1C',
|
||||
'opts' => 'Параметры',
|
||||
'agnt' => 'Агент (поставщик)',
|
||||
'type' => 'Тип аккаунта'
|
||||
'type' => 'Тип аккаунта',
|
||||
'acpt' => 'Согласие с офертой'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -314,63 +319,68 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Генерация списка городов из ДеловыеЛинии для отправителя
|
||||
* Генерация списка терминалов из ДеловыеЛинии для отправителя
|
||||
*
|
||||
* Актуальное (выбранное, активное) значение записывается первым
|
||||
*
|
||||
* @param array Необработанный список городов
|
||||
* @param array Необработанный список терминалов
|
||||
*/
|
||||
public function genListCitiesFrom(): array
|
||||
public function genListTerminalsFrom(): array
|
||||
{
|
||||
// Инициализация
|
||||
$list = [];
|
||||
|
||||
$cities = City::readAll();
|
||||
$cities = Dellin::readAll();
|
||||
|
||||
foreach ($cities as $city) {
|
||||
// Перебор городов
|
||||
|
||||
if (in_array($city->name, $list, true)) {
|
||||
// Если встретился дубликат (исполняется очень часто)
|
||||
foreach ($city->data['terminals']['terminal'] as $termial) {
|
||||
// Перебор терминалов
|
||||
|
||||
continue;
|
||||
if (in_array('id_'.$termial['id'], $list, true)) {
|
||||
// Если встретился дубликат (исполняется очень часто)
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Запись
|
||||
empty($termial['id']) or $list['id_'.$termial['id']] = $city->data['name'] . ' (' . $termial['address'] . ')';
|
||||
}
|
||||
|
||||
// Запись
|
||||
empty($city->name) or $list[$city->code] = $city->name;
|
||||
}
|
||||
|
||||
return $this->syncListWithSettings($list, 'delivery_from_city');
|
||||
return $this->syncListWithSettings($list, 'delivery_from_terminal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация списка городов из ДеловыеЛинии для получателя
|
||||
* Генерация списка терминалов из ДеловыеЛинии для получателя
|
||||
*
|
||||
* Актуальное (выбранное, активное) значение записывается первым
|
||||
*
|
||||
* @param array Необработанный список городов
|
||||
* @param array Необработанный список терминалов
|
||||
*/
|
||||
public function genListCitiesTo(): array
|
||||
public function genListTerminalsTo(): array
|
||||
{
|
||||
// Инициализация
|
||||
$list = [];
|
||||
|
||||
$cities = City::readAll();
|
||||
$terminals = Terminal::readAll();
|
||||
|
||||
foreach ($cities as $city) {
|
||||
foreach ($terminals as $terminal) {
|
||||
// Перебор городов
|
||||
|
||||
if (in_array($city->name, $list, true)) {
|
||||
if (in_array('id_' . $terminal->dell, $list, true)) {
|
||||
// Если встретился дубликат (исполняется очень часто)
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Запись
|
||||
empty($city->name) or $list[$city->code] = $city->name;
|
||||
empty($terminal->cntr) && empty($terminal->city) && empty($terminal->strt) && empty($terminal->hous)
|
||||
or $list['id_' . $terminal->dell] = "$terminal->city ($terminal->strt, $terminal->hous, $terminal->offs)";
|
||||
}
|
||||
|
||||
return $this->syncListWithSettings($list, 'delivery_to_city');
|
||||
return $this->syncListWithSettings($list, 'delivery_to_terminal');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,7 +418,7 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
// Параметр $var не найден в настройках аккаунта
|
||||
|
||||
// Сохранение параметра из данных аккаунта в начале массива
|
||||
$list = array_merge(['Выберите'], $list);
|
||||
$list = array_merge(['Выберите' => 'Выберите'], $list);
|
||||
}
|
||||
|
||||
return $list;
|
||||
|
@ -474,4 +484,33 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Найти по идентификатору поставки
|
||||
*
|
||||
* @param string|null $_id Идентификатор поставки
|
||||
*
|
||||
* @return self|null Аккаунт владельца
|
||||
*/
|
||||
public static function searchBySupplyId(string $_id): ?array
|
||||
{
|
||||
return static::searchByEdge(
|
||||
from: 'supply',
|
||||
to: 'account',
|
||||
edge: 'account_edge_supply',
|
||||
direction: 'OUTBOUND',
|
||||
subquery_where: [
|
||||
[
|
||||
'account_edge_supply._from == account._id'
|
||||
],
|
||||
[
|
||||
'account_edge_supply._to == "' . $_id . '"'
|
||||
]
|
||||
],
|
||||
subquery_select: 'account',
|
||||
where: 'account_edge_supply[0]._id != null',
|
||||
limit: 1,
|
||||
select: 'account_edge_supply[0]'
|
||||
)[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class City extends Document
|
||||
{
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'city';
|
||||
}
|
||||
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'indx',
|
||||
'name',
|
||||
'code',
|
||||
'term'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
'indx',
|
||||
'string'
|
||||
],
|
||||
[
|
||||
[
|
||||
'indx',
|
||||
'name',
|
||||
'code',
|
||||
'term'
|
||||
],
|
||||
'required',
|
||||
'message' => 'Заполните поле: {attribute}'
|
||||
],
|
||||
[
|
||||
[
|
||||
'name',
|
||||
'code'
|
||||
],
|
||||
'string'
|
||||
],
|
||||
[
|
||||
'term',
|
||||
'boolean'
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'indx' => 'Идентификатор в ДеловыеЛинии',
|
||||
'name' => 'Название',
|
||||
'code' => 'Код КЛАДР',
|
||||
'term' => 'Указатель наличия терминала в городе'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск по идентификатору в ДеловыеЛинии
|
||||
*/
|
||||
public static function searchByDellinId(string $indx): ?static
|
||||
{
|
||||
return static::findOne(['indx' => $indx]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class Dellin extends Document
|
||||
{
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'dellin';
|
||||
}
|
||||
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'data'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'data' => 'Данные ДеловыеЛинии',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск по идентификатору города
|
||||
*/
|
||||
public static function searchByCityId(string $id): ?static
|
||||
{
|
||||
return static::findOne(['data["id"]' => $id]);
|
||||
}
|
||||
}
|
|
@ -361,10 +361,29 @@ class Order extends Document implements DocumentInterface
|
|||
}
|
||||
|
||||
// Поиск ребра до аккаунта
|
||||
$connection['account'] = Supply::searchAccountById($connection['supply']['_id']);
|
||||
$connection['account'] = Account::searchBySupplyId($connection['supply']['_id']);
|
||||
|
||||
// Инициализация доставки
|
||||
$connection['delivery'] = Dellin::calcDelivery($connection['account']['opts']['delivery_from_city'] ?? $settings['delivery_from_city_default'] ?? '2700000100000000000000000', yii::$app->user->identity->opts['delivery_to_city'] ?? $settings['delivery_to_city_default'] ?? '2700000100000000000000000')['terminals_standard'];
|
||||
// Поиск привязанного товара
|
||||
$connection['product'] = Product::searchBySupplyId($connection['supply']['_id']);
|
||||
|
||||
try
|
||||
{
|
||||
// Инициализация доставки
|
||||
$connection['delivery'] = Dellin::calcDeliveryAdvanced(
|
||||
explode('_', $connection['account']['opts']['delivery_from_terminal'])[1],
|
||||
explode('_', yii::$app->user->identity->opts['delivery_to_terminal'])[1],
|
||||
(int) ($connection['product']['wght'] ?? 0),
|
||||
(int) ($connection['product']['dmns']['x'] ?? 0),
|
||||
(int) ($connection['product']['dmns']['y'] ?? 0),
|
||||
(int) ($connection['product']['dmns']['z'] ?? 0),
|
||||
count($connection['order_edge_supply'])
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
$connection['delivery']['error'] = true;
|
||||
|
||||
|
||||
// var_dump(json_decode($e->getMessage(), true)['errors']); die;
|
||||
}
|
||||
|
||||
// Запись цены (цена поставки + цена доставки + наша наценка)
|
||||
$connection['cost'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['price'] ?? 0) + ($settings['increase'] ?? 0);
|
||||
|
|
|
@ -41,6 +41,26 @@ class OrderEdgeSupply extends Edge
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Правила
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
[
|
||||
'comm'
|
||||
],
|
||||
'string',
|
||||
'length' => [3, 256],
|
||||
'message' => '{attribute} должен быть строкой от 3 до 256 символов'
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск поставки по артикулу
|
||||
*
|
||||
|
|
|
@ -112,6 +112,8 @@ class Product extends Document
|
|||
|
||||
/**
|
||||
* Правила
|
||||
*
|
||||
* @todo Правило для всех трёх габаритов
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
|
@ -175,6 +177,27 @@ class Product extends Document
|
|||
'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"',
|
||||
'message' => 'Проблема при загрузке изображения',
|
||||
'on' => self::SCENARIO_IMPORT_IMAGE
|
||||
],
|
||||
[
|
||||
[
|
||||
'name',
|
||||
'prod'
|
||||
],
|
||||
'string',
|
||||
'length' => [3, 80],
|
||||
'message' => '{attribute} должен быть строкой от 3 до 80 символов'
|
||||
],
|
||||
[
|
||||
'dscr',
|
||||
'string',
|
||||
'length' => [3, 256],
|
||||
'message' => '{attribute} должен быть строкой от 3 до 256 символов'
|
||||
],
|
||||
[
|
||||
'wght',
|
||||
'integer',
|
||||
'max' => 9999,
|
||||
'message' => '{attribute} должен быть строкой от 0 до 6 символов'
|
||||
]
|
||||
]
|
||||
);
|
||||
|
@ -468,4 +491,33 @@ class Product extends Document
|
|||
// Отправка
|
||||
return (bool) $model->write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Найти по идентификатору поставки
|
||||
*
|
||||
* @param string|null $_id Идентификатор поставки
|
||||
*
|
||||
* @return self|null Привязанный продукт
|
||||
*/
|
||||
public static function searchBySupplyId(string $_id): ?array
|
||||
{
|
||||
return static::searchByEdge(
|
||||
from: 'supply',
|
||||
to: 'product',
|
||||
edge: 'supply_edge_product',
|
||||
direction: 'INBOUND',
|
||||
subquery_where: [
|
||||
[
|
||||
'supply_edge_product._from == "' . $_id . '"'
|
||||
],
|
||||
[
|
||||
'supply_edge_product._to == product._id'
|
||||
]
|
||||
],
|
||||
subquery_select: 'product',
|
||||
where: 'supply_edge_product[0]._id != null',
|
||||
limit: 1,
|
||||
select: 'supply_edge_product[0]'
|
||||
)[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -601,33 +601,4 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
|||
{
|
||||
return static::searchAccountById($this->readId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Найти аккаунт владельца
|
||||
*
|
||||
* @param string|null $_id Идентификатор
|
||||
*
|
||||
* @return Account|null Аккаунт владельца
|
||||
*/
|
||||
public static function searchAccountById(string $_id): ?array
|
||||
{
|
||||
return static::searchByEdge(
|
||||
from: 'account',
|
||||
to: 'supply',
|
||||
edge: 'account_edge_supply',
|
||||
direction: 'INBOUND',
|
||||
subquery_where: [
|
||||
[
|
||||
'account_edge_supply._from == account._id'
|
||||
],
|
||||
[
|
||||
'account_edge_supply._to == "' . $_id . '"'
|
||||
]
|
||||
],
|
||||
subquery_select: 'account',
|
||||
where: 'account_edge_supply[0]._id != null',
|
||||
limit: 1,
|
||||
select: 'account_edge_supply[0]'
|
||||
)[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
/**
|
||||
* Терминалы выдачи
|
||||
*/
|
||||
class Terminal extends Document
|
||||
{
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'terminal';
|
||||
}
|
||||
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'name',
|
||||
'cntr',
|
||||
'city',
|
||||
'strt',
|
||||
'hous',
|
||||
'offs',
|
||||
'dell',
|
||||
'hndl'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
[
|
||||
'name',
|
||||
'cntr',
|
||||
'city',
|
||||
'strt',
|
||||
'hous',
|
||||
'offs',
|
||||
'dell'
|
||||
],
|
||||
'string'
|
||||
],
|
||||
[
|
||||
'hndl',
|
||||
'int'
|
||||
],
|
||||
[
|
||||
[
|
||||
'name',
|
||||
'cntr',
|
||||
'city',
|
||||
'strt',
|
||||
'hous',
|
||||
'dell',
|
||||
'hndl'
|
||||
],
|
||||
'required',
|
||||
'message' => 'Заполните поле: {attribute}'
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'name' => 'Название',
|
||||
'cntr' => 'Страна',
|
||||
'city' => 'Город',
|
||||
'strt' => 'Улица',
|
||||
'hous' => 'Дом',
|
||||
'offs' => 'Офис',
|
||||
'dell' => 'Терминал ДеловыеЛинии для рассчётов доставки',
|
||||
'hndl' => 'Количество дней для обработки после получения от ДеловыеЛинии'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,9 +7,10 @@ namespace app\models\connection;
|
|||
use yii;
|
||||
use yii\base\Model;
|
||||
|
||||
use app\models\City;
|
||||
use app\models\Dellin as DellinModel;
|
||||
|
||||
use GuzzleHttp\Client as Guzzle;
|
||||
use GuzzleHttp\Exception\ClientException as GuzzleException;
|
||||
|
||||
use Exception;
|
||||
use phpDocumentor\Reflection\Types\Nullable;
|
||||
|
@ -61,15 +62,18 @@ class Dellin extends Model
|
|||
* @param string $from Номер КЛАДР
|
||||
* @param string $to Номер КЛАДР
|
||||
* @param int $weight Вес (кг)
|
||||
* @param int $x Ширина (см)
|
||||
* @param int $y Высота (см)
|
||||
* @param int $z Длинна (см)
|
||||
* @param int $x Ширина (м)
|
||||
* @param int $y Высота (м)
|
||||
* @param int $z Длинна (м)
|
||||
* @param int $amount Количество
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @todo Переработать "weight" (если посылок больше чем одна, то отправить вес самого тяжелого груза), хотя здесь же копии обрабатываются и вес у них один... Надо думать
|
||||
*/
|
||||
public static function calcDeliveryAdvanced(string $from, string $to, int $weight, int $x, int $y, int $z): array
|
||||
public static function calcDeliveryAdvanced(string $from, string $to, int $weight, int $x, int $y, int $z, int $amount = 1): array
|
||||
{
|
||||
return self::handle(function () use ($from, $to, $weight, $x, $y, $z) {
|
||||
return self::handle(function () use ($from, $to, $weight, $x, $y, $z, $amount) {
|
||||
// Всё готово к работе
|
||||
|
||||
// Рассчёт типа доставки
|
||||
|
@ -78,7 +82,7 @@ class Dellin extends Model
|
|||
&& (($x <= 5.4 && $y <= 3.9 && $z <= 3.9)
|
||||
|| ($x <= 3.9 && $y <= 5.4 && $z <= 3.9)
|
||||
|| ($x <= 3.9 && $y <= 3.9 && $z <= 5.4))
|
||||
&& $x * $y * $z <= 1000000
|
||||
&& $x * $y * $z <= 0.1
|
||||
) {
|
||||
// Доставка категории "small"
|
||||
|
||||
|
@ -89,8 +93,34 @@ class Dellin extends Model
|
|||
$type = 'auto';
|
||||
}
|
||||
|
||||
// Вычисление самой крупной стороны, так как ДеловыеЛинии имеют ограничения на все три поля и у длинны оно больше всех
|
||||
if ($x > $z && $x > $y) {
|
||||
// "X" больше всех
|
||||
|
||||
// Инициализация
|
||||
$width = $z;
|
||||
$height = $y;
|
||||
$length = $x;
|
||||
} else if ($y > $x && $y > $z) {
|
||||
// "Y" больше всех
|
||||
|
||||
// Инициализация
|
||||
$width = $x;
|
||||
$height = $z;
|
||||
$length = $y;
|
||||
} else if ($z > $x && $z > $y) {
|
||||
// "Z" больше всех
|
||||
|
||||
// Инициализация
|
||||
$width = $x;
|
||||
$height = $y;
|
||||
$length = $z;
|
||||
} else {
|
||||
echo 'Ошибка';
|
||||
}
|
||||
|
||||
// Запрос
|
||||
$request = self::$browser->post('/v1/micro_calc.json', [
|
||||
$request = self::$browser->post('/v2/calculator.json', [
|
||||
'json' => [
|
||||
'appkey' => yii::$app->params['dellin']['key'],
|
||||
'sessionID' => self::$session,
|
||||
|
@ -98,9 +128,32 @@ class Dellin extends Model
|
|||
'deliveryType' => [
|
||||
'type' => $type
|
||||
],
|
||||
'derival' => [
|
||||
'produceDate' => date('Y-m-d', time() + ($settings['delivery_handle_time'] ?? 86400)),
|
||||
'variant' => 'terminal',
|
||||
'terminalID' => $from,
|
||||
|
||||
],
|
||||
'arrival' => [
|
||||
'variant' => 'terminal',
|
||||
'terminalID' => $to
|
||||
]
|
||||
],
|
||||
'members' => [
|
||||
'requester' => [
|
||||
'role' => 'sender'
|
||||
]
|
||||
],
|
||||
'cargo' => [
|
||||
'quantity' => $amount,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'length' => $length,
|
||||
'weight' => $weight,
|
||||
'totalVolume' => $x * $y * $z,
|
||||
'totalWeight' => $weight,
|
||||
'oversizedWeight' => $weight,
|
||||
'oversizedVolume' => $x * $y * $z
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
@ -177,129 +230,129 @@ class Dellin extends Model
|
|||
*
|
||||
* @return array|null Сохранённые города
|
||||
*/
|
||||
public static function importCities(): ?int
|
||||
{
|
||||
return self::handle(function () {
|
||||
// Всё готово к работе
|
||||
// public static function importCities(): ?int
|
||||
// {
|
||||
// return self::handle(function () {
|
||||
// // Всё готово к работе
|
||||
|
||||
// Запрос ссылки на файл с городами, возвращает ['hash' => string, 'url' => string]
|
||||
$request = self::$browser->post('/v1/public/cities.json', [
|
||||
'json' => [
|
||||
'appkey' => yii::$app->params['dellin']['key'],
|
||||
]
|
||||
]);
|
||||
// // Запрос ссылки на файл с городами, возвращает ['hash' => string, 'url' => string]
|
||||
// $request = self::$browser->post('/v1/public/cities.json', [
|
||||
// 'json' => [
|
||||
// 'appkey' => yii::$app->params['dellin']['key'],
|
||||
// ]
|
||||
// ]);
|
||||
|
||||
if ($request->getStatusCode() === 200) {
|
||||
// Запрос прошел успешно
|
||||
// if ($request->getStatusCode() === 200) {
|
||||
// // Запрос прошел успешно
|
||||
|
||||
// Инициализация
|
||||
$response = json_decode((string) $request->getBody(), true);
|
||||
$hash_target = $response['hash'];
|
||||
$dir = YII_PATH_PUBLIC . '/../assets/import/' . date('Y-m-d', time()) . '/dellin/cities/' . (yii::$app->user->identity->_key ?? 'system') . '/';
|
||||
// // Инициализация
|
||||
// $response = json_decode((string) $request->getBody(), true);
|
||||
// $hash_target = $response['hash'];
|
||||
// $dir = YII_PATH_PUBLIC . '/../assets/import/' . date('Y-m-d', time()) . '/dellin/cities/' . (yii::$app->user->identity->_key ?? 'system') . '/';
|
||||
|
||||
if (!file_exists($dir)) {
|
||||
// Директории не существует
|
||||
// if (!file_exists($dir)) {
|
||||
// // Директории не существует
|
||||
|
||||
mkdir($dir, 0775, true);
|
||||
}
|
||||
// mkdir($dir, 0775, true);
|
||||
// }
|
||||
|
||||
$request = self::$browser->get($response['url'], [
|
||||
'sink' => $file = $dir . time() . '.csv'
|
||||
]);
|
||||
// $request = self::$browser->get($response['url'], [
|
||||
// 'sink' => $file = $dir . time() . '.csv'
|
||||
// ]);
|
||||
|
||||
// Проверка хеша (оказалось это хеш запроса, бесполезный)
|
||||
// if ($hash_target === $hash_received = md5_file($file)) {
|
||||
// Удалось пройти проверку на хеши файлов
|
||||
// // Проверка хеша (оказалось это хеш запроса, бесполезный)
|
||||
// // if ($hash_target === $hash_received = md5_file($file)) {
|
||||
// // Удалось пройти проверку на хеши файлов
|
||||
|
||||
// Инициализация (чтение файла)
|
||||
$file = fopen($file, "r");
|
||||
$first_raw_block = true;
|
||||
// // Инициализация (чтение файла)
|
||||
// $file = fopen($file, "r");
|
||||
// $first_raw_block = true;
|
||||
|
||||
while ($row = fgets($file, 4096)) {
|
||||
// Перебор строк
|
||||
// while ($row = fgets($file, 4096)) {
|
||||
// // Перебор строк
|
||||
|
||||
if ($first_raw_block) {
|
||||
// Сработала защита от чтения первой строки файла (указываются названия колонок)
|
||||
// if ($first_raw_block) {
|
||||
// // Сработала защита от чтения первой строки файла (указываются названия колонок)
|
||||
|
||||
// Отключение
|
||||
$first_raw_block = false;
|
||||
// // Отключение
|
||||
// $first_raw_block = false;
|
||||
|
||||
// Пропуск цикла
|
||||
continue;
|
||||
}
|
||||
// // Пропуск цикла
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// Инициализация
|
||||
$data = explode(',', $row, 4);
|
||||
$amount = 0;
|
||||
// // Инициализация
|
||||
// $data = explode(',', $row, 4);
|
||||
// $amount = 0;
|
||||
|
||||
// Очистка
|
||||
array_walk($data, fn (&$value) => $value = trim($value, '"'));
|
||||
// // Очистка
|
||||
// array_walk($data, fn (&$value) => $value = trim($value, '"'));
|
||||
|
||||
if ($city = City::searchByDellinId($data[0])) {
|
||||
// Удалось найти город в базе данных
|
||||
// if ($city = City::searchByDellinId($data[0])) {
|
||||
// // Удалось найти город в базе данных
|
||||
|
||||
$after_import_log = function () use ($city): void {
|
||||
// Запись в журнал
|
||||
$city->journal('update');
|
||||
// $after_import_log = function () use ($city): void {
|
||||
// // Запись в журнал
|
||||
// $city->journal('update');
|
||||
|
||||
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||
// Вызов из терминала
|
||||
// if (yii::$app->getRequest()->isConsoleRequest) {
|
||||
// // Вызов из терминала
|
||||
|
||||
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// Не удалось найти город в базе данных
|
||||
// echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
|
||||
// }
|
||||
// };
|
||||
// } else {
|
||||
// // Не удалось найти город в базе данных
|
||||
|
||||
$city = new City();
|
||||
// $city = new City();
|
||||
|
||||
$after_import_log = function () use ($city): void {
|
||||
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||
// Вызов из терминала
|
||||
// $after_import_log = function () use ($city): void {
|
||||
// if (yii::$app->getRequest()->isConsoleRequest) {
|
||||
// // Вызов из терминала
|
||||
|
||||
echo 'Удалось записать город: ' . $city->name . PHP_EOL;
|
||||
}
|
||||
};
|
||||
}
|
||||
// echo 'Удалось записать город: ' . $city->name . PHP_EOL;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
// Запись
|
||||
$city->indx = $data[0];
|
||||
$city->name = $data[1];
|
||||
$city->code = $data[2];
|
||||
$city->term = (bool) $data[3];
|
||||
// // Запись
|
||||
// $city->indx = $data[0];
|
||||
// $city->name = $data[1];
|
||||
// $city->code = $data[2];
|
||||
// $city->term = (bool) $data[3];
|
||||
|
||||
// Отправка в базу данных
|
||||
if ($city->save()) {
|
||||
// Удалось сохранить в базе данных
|
||||
// // Отправка в базу данных
|
||||
// if ($city->save()) {
|
||||
// // Удалось сохранить в базе данных
|
||||
|
||||
// Запись в журнал
|
||||
$after_import_log();
|
||||
// // Запись в журнал
|
||||
// $after_import_log();
|
||||
|
||||
// Постинкрементация счётчика
|
||||
$amount++;
|
||||
// // Постинкрементация счётчика
|
||||
// $amount++;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
// Не удалось сохранить в базе данных
|
||||
// continue;
|
||||
// } else {
|
||||
// // Не удалось сохранить в базе данных
|
||||
|
||||
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
|
||||
}
|
||||
}
|
||||
// throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Деинициализация
|
||||
fclose($file);
|
||||
// // Деинициализация
|
||||
// fclose($file);
|
||||
|
||||
return $amount;
|
||||
// } else {
|
||||
// // Не удалось пройти проверку на соответствие хешей файлов
|
||||
// return $amount;
|
||||
// // } else {
|
||||
// // // Не удалось пройти проверку на соответствие хешей файлов
|
||||
|
||||
// throw new Exception('Хеши файлов не совпадают. Должен быть: "' . $hash_target . '", получен: "' . $hash_received . '"', 500);
|
||||
// }
|
||||
}
|
||||
// // throw new Exception('Хеши файлов не совпадают. Должен быть: "' . $hash_target . '", получен: "' . $hash_received . '"', 500);
|
||||
// // }
|
||||
// }
|
||||
|
||||
throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', 500);
|
||||
});
|
||||
}
|
||||
// throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', 500);
|
||||
// });
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
|
@ -325,6 +378,7 @@ class Dellin extends Model
|
|||
// Инициализация
|
||||
$response = json_decode((string) $request->getBody(), true);
|
||||
$dir = YII_PATH_PUBLIC . '/../assets/import/' . date('Y-m-d', time()) . '/dellin/terminals/' . (yii::$app->user->identity->_key ?? 'system') . '/';
|
||||
$amount = 0;
|
||||
|
||||
if (!file_exists($dir)) {
|
||||
// Директории не существует
|
||||
|
@ -336,68 +390,44 @@ class Dellin extends Model
|
|||
'sink' => $file = $dir . time() . '.json'
|
||||
]);
|
||||
|
||||
die;
|
||||
// Инициализация
|
||||
$terminals = json_decode(fread(fopen($file, "r"), filesize($file)), true);
|
||||
|
||||
foreach ($terminals['city'] as $terminal) {
|
||||
// Перебор городов
|
||||
|
||||
// Инициализация (чтение файла)
|
||||
$file = fopen($file, "r");
|
||||
$first_raw_block = true;
|
||||
|
||||
while ($row = fgets($file, 4096)) {
|
||||
// Перебор строк
|
||||
|
||||
if ($first_raw_block) {
|
||||
// Сработала защита от чтения первой строки файла (указываются названия колонок)
|
||||
|
||||
// Отключение
|
||||
$first_raw_block = false;
|
||||
|
||||
// Пропуск цикла
|
||||
continue;
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
$data = explode(',', $row, 4);
|
||||
$amount = 0;
|
||||
|
||||
// Очистка
|
||||
array_walk($data, fn (&$value) => $value = trim($value, '"'));
|
||||
|
||||
if ($city = Terminal::searchByDellinId($data[0])) {
|
||||
if ($model = DellinModel::searchByCityId($terminal['id'])) {
|
||||
// Удалось найти город в базе данных
|
||||
|
||||
$after_import_log = function () use ($city): void {
|
||||
$after_import_log = function () use ($model): void {
|
||||
// Запись в журнал
|
||||
$city->journal('update');
|
||||
$model->journal('update');
|
||||
|
||||
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||
// Вызов из терминала
|
||||
|
||||
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
|
||||
echo 'Удалось перезаписать терминалы города: ' . ($model->data['name'] ?? 'Неизвестно') . PHP_EOL;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// Не удалось найти город в базе данных
|
||||
|
||||
$terminal = new Terminal();
|
||||
$model = new DellinModel();
|
||||
|
||||
$after_import_log = function () use ($terminal): void {
|
||||
$after_import_log = function () use ($model): void {
|
||||
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||
// Вызов из терминала
|
||||
|
||||
echo 'Удалось записать город: ' . $terminal->name . PHP_EOL;
|
||||
echo 'Удалось записать терминалы города: ' . ($model->data['name'] ?? 'Неизвестно') . PHP_EOL;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Запись
|
||||
$terminal->indx = $data[0];
|
||||
$terminal->name = $data[1];
|
||||
$terminal->code = $data[2];
|
||||
$terminal->term = (bool) $data[3];
|
||||
$model->data = $terminal;
|
||||
|
||||
// Отправка в базу данных
|
||||
if ($terminal->save()) {
|
||||
if ($model->save()) {
|
||||
// Удалось сохранить в базе данных
|
||||
|
||||
// Запись в журнал
|
||||
|
@ -410,13 +440,10 @@ class Dellin extends Model
|
|||
} else {
|
||||
// Не удалось сохранить в базе данных
|
||||
|
||||
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
|
||||
throw new Exception('Не удалось сохранить терминалы города "' . ($model->data['name'] ?? 'Неизвестно') . '" в базу данных', 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Деинициализация
|
||||
fclose($file);
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
|
@ -483,9 +510,10 @@ class Dellin extends Model
|
|||
} else {
|
||||
throw new Exception('Браузер не инициализирован', 500);
|
||||
}
|
||||
} catch (GuzzleException $e) {
|
||||
throw new Exception($e->getResponse()->getBody()->getContents() ?? 'Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage(), 500, $e->getPrevious());
|
||||
// throw new Exception('Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
|
||||
throw new Exception($e->getMessage() ?? 'Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
use app\assets\AppAsset;
|
||||
|
||||
AppAsset::register($this);
|
||||
|
||||
?>
|
||||
|
||||
<?php $this->beginPage() ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?= yii::$app->language ?>">
|
||||
|
||||
<head>
|
||||
<meta charset="<?= yii::$app->charset ?>">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/css/pages/buyers.css" rel="stylesheet">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/favicons/android-icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicons/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/ms-icon-144x144.png">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
|
||||
<?php $this->registerCsrfMetaTags() ?>
|
||||
|
||||
<title><?= Html::encode($this->title ?? 'Покупателям | SkillParts') ?></title>
|
||||
|
||||
<?php $this->head() ?>
|
||||
</head>
|
||||
|
||||
<body class="d-flex flex-column">
|
||||
<?php $this->beginBody() ?>
|
||||
|
||||
<header class="container pt-2 mt-1 mb-2 mb-sm-4">
|
||||
<div class="row row h-100">
|
||||
<div id="logo" class="col-3 col-md-4 h-100">
|
||||
<a class="py-2 h-100 d-inline-flex" title="SkillParts" href="/">
|
||||
<img class="img-fluid" src="/img/logos/skillparts.svg" alt="SkillParts">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="page_buyers" class="container pb-5 flex-grow-1 d-flex">
|
||||
<article class="my-auto p-3 rounded overflow-hidden">
|
||||
<h1 class="py-3 mt-2 mb-5 text-center"><b>Что ценят покупатели SkillParts?</b></h1>
|
||||
<div class="row mb-4 px-3 pb-3">
|
||||
<div class="col-4">
|
||||
<img src="" />
|
||||
<h5 class="text-center"><b>Удобный сервис для заказа и отслеживания</b></h5>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img src="" />
|
||||
<h5 class="text-center"><b>Бесплатное экспедирование товаров в городах присутствия SkillParts</b></h5>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img src="" />
|
||||
<h5 class="text-center"><b>Все поставщики России в одном месте</b></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-3 pb-3 justify-content-center">
|
||||
<a class="col-auto text-center text-dark btn button_become_buyer button_clean" href="/registration">Стать покупателем</a>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<?php $this->endBody() ?>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
<?php $this->endPage() ?>
|
|
@ -4,6 +4,8 @@ use yii;
|
|||
|
||||
use app\models\connection\Dellin;
|
||||
|
||||
use DateTime;
|
||||
|
||||
?>
|
||||
|
||||
<link href="/css/pages/cart.css" rel="stylesheet">
|
||||
|
@ -38,7 +40,15 @@ use app\models\connection\Dellin;
|
|||
// Перебор поставок
|
||||
|
||||
// Инициализация доставки
|
||||
$delivery = $connection['delivery']['period_to'];
|
||||
if (isset($connection['delivery']['error'])) {
|
||||
// Не удалось рассчитать доставку
|
||||
|
||||
$delivery = '?';
|
||||
} else {
|
||||
// Удалось рассчитать доставку
|
||||
|
||||
$delivery = date('d', DateTime::createFromFormat('Y-m-d', $connection['delivery']['orderDates']['arrivalToOspReceiver'])->getTimestamp() - time());
|
||||
}
|
||||
|
||||
// Инициализация цены
|
||||
$cost = $connection['cost'] . ' ' . $connection['currency'];
|
||||
|
@ -63,7 +73,7 @@ use app\models\connection\Dellin;
|
|||
<input id="cart_list_amnt_{$connection['supply']['catn']}" class="form-control text-center" type="text" value="{$connection['amount']}" onchange="return cart_list_amount_update('{$connection['supply']['catn']}', this)" aria-invalid="false">
|
||||
</div>
|
||||
<div class="col-2 my-auto text-right">
|
||||
$delivery дней
|
||||
$delivery дн
|
||||
</div>
|
||||
<div class="col-2 my-auto mr-3 text-right">
|
||||
$cost
|
||||
|
|
|
@ -13,10 +13,10 @@ AppAsset::register($this);
|
|||
<?php $this->beginPage() ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?= Yii::$app->language ?>">
|
||||
<html lang="<?= yii::$app->language ?>">
|
||||
|
||||
<head>
|
||||
<meta charset="<?= Yii::$app->charset ?>">
|
||||
<meta charset="<?= yii::$app->charset ?>">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
|
@ -129,9 +129,9 @@ AppAsset::register($this);
|
|||
</div>
|
||||
<div class="col-md-auto mr-md-5 partnership">
|
||||
<h5 class="row mb-2"><b>Партнёрство</b></h5>
|
||||
<small class="row mb-1"><a>Оптовым покупателям</a></small>
|
||||
<small class="row mb-1"><a>Поставщикам</a></small>
|
||||
<small class="row mb-1"><a>Партнерская сеть</a></small>
|
||||
<small class="row mb-1"><a class="text-dark" href="/buyers">Покупателям</a></small>
|
||||
<small class="row mb-1"><a class="text-dark" href="/suppliers">Поставщикам</a></small>
|
||||
<small class="row mb-1"><a class="text-dark" href="/partners">Сеть филиалов</a></small>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
@ -141,4 +141,4 @@ AppAsset::register($this);
|
|||
|
||||
</html>
|
||||
|
||||
<?php $this->endPage() ?>
|
||||
<?php $this->endPage() ?>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<link href="/css/pages/offer.css" rel="stylesheet">
|
||||
|
||||
<div id="page_offer" class="container mb-auto py-3">
|
||||
<article class="p-5 rounded overflow-hidden">
|
||||
<div class="row mb-5">
|
||||
<div class="col">
|
||||
<h4 class="mb-4 text-center"><b>Оферта покупателям</b></h4>
|
||||
<p>1. Общие условия</p>
|
||||
<p>1.1. Поставщик предлагает заключить договор купли-продажи потребителю, компании и предпринимателю (далее- покупатель) на описанных ниже условиях.</p>
|
||||
<p>1.2. Договор считается заключенным в момент заказа товара на сайте (www.SkillParts.ru).</p>
|
||||
<p>1.3. Стороны признают юридическую силу скан-копий подписанных документов, переписки, записей в протоколе работы программ, хранящихся на серверах Торговой площадки.</p>
|
||||
<p>2. Термины и определения
|
||||
Поставщик — компания ООО «СтандартМашинери», либо филиал компании ООО «СтандартМашинери»
|
||||
Торговая площадка — ООО «СтнадартМашинери», предоставляющий программно-аппаратный комплекс организационных, информационных и технических решений, обеспечивающих взаимодействие поставщика и покупателя через электронные каналы связи.</p>
|
||||
<p>3. Условия работы и оплата</p>
|
||||
<p>3.1. Поставщик обязуется приобрести в собственность товар, заказанный покупателем на сайте, для последующей продажи покупателю, а потребитель обязуется оплатить заказанный Товар.</p>
|
||||
<p>3.2. Цена, количество, наименование заказанного покупателем товара, определяются в момент отправки заказа поставщику.</p>
|
||||
<p>3.3. Покупатель может оплатить заказ или пополнить баланс на сайте. Оплата произведённая на сайте, осуществляется на счёт торговой площадки и учитывается поставщиком как оплата заказа покупателем.</p>
|
||||
<p>3.4. Условия возврата товара отражены и регулируются в личном кабинете покупателя.</p>
|
||||
<p>3.5. Покупатель направляет претензии по исполнению заказа поставщику. В случае неудовлетворения требований, покупатель может информировать торговую площадку на адрес электронной почты info@skillparts.ru</p>
|
||||
<p>4. Предоставление информации</p>
|
||||
<p>4.1. Покупатель даёт своё согласие поставщику и торговой площадке осуществлять следующие действия с персональными данными: сбор, систематизацию, накопление, хранение, обновление, изменение, деперсонализацию, уничтожение.</p>
|
||||
</br>
|
||||
<p> Торговая площадка
|
||||
ООО «СтандартМашинери» ИНН: 2724241607</br>
|
||||
Юридический адрес: 680014, Хабаровский край, г. Хабаровск, ул. Промышленная 3, офис 105</br>
|
||||
АО «Тинькофф Банк», р/с 40702810610000696279, БИК: 044525974</br>
|
||||
Почта: info@skillparts.ru</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-0 justify-content-center">
|
||||
<a class="col-auto text-center text-dark btn button_accept_offer button_clean" href="/offer/accept">Принять</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
|
@ -0,0 +1,11 @@
|
|||
<link href="/css/pages/partners.css" rel="stylesheet">
|
||||
|
||||
<div id="page_partners" class="container mb-auto py-3">
|
||||
<article class="py-3 rounded">
|
||||
<div class="rounded overflow-hidden">
|
||||
<iframe width="100%" height="400" src="https://maps.google.com/maps?width=800&height=300&hl=ru&q=%D0%A5%D0%B0%D0%B1%D0%B0%D1%80%D0%BE%D0%B2%D1%81%D0%BA%20%D0%9F%D1%80%D0%BE%D0%BC%D1%8B%D1%88%D0%BB%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F%203+(SkillParts)&ie=UTF8&t=&z=13&iwloc=B&output=embed" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>
|
||||
<div class="p-4">
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
|
@ -167,7 +167,7 @@ use app\models\Product;
|
|||
<section id="prod_<?= $model['catn'] ?>_info" class="col">
|
||||
<!-- Габариты -->
|
||||
<p class="form-control-sm p-0 h-auto">
|
||||
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'x');"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'y');"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'z');"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span><span class="mr-1">см</span>
|
||||
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'x');"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span><span class="mr-1">м</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'y');"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span><span class="mr-1">м</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'z');"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span><span class="mr-1">м</span>
|
||||
</p>
|
||||
<!-- Вес -->
|
||||
<p class="form-control-sm p-0 h-auto">
|
||||
|
@ -178,7 +178,7 @@ use app\models\Product;
|
|||
<section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
|
||||
<!-- Габариты -->
|
||||
<p class="form-control-sm p-0 h-auto">
|
||||
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span><span class="mr-1">см</span>
|
||||
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span><span class="mr-1">м</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span><span class="mr-1">м</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span><span class="mr-1">м</span>
|
||||
</p>
|
||||
<!-- Вес -->
|
||||
<p class="form-control-sm p-0 h-auto">
|
||||
|
@ -228,21 +228,6 @@ use app\models\Product;
|
|||
$model = new Product();
|
||||
?>
|
||||
|
||||
<div class="col-6 px-0 mr-4 btn-group">
|
||||
<?= Html::submitButton('В корзину', ['name' => 'cartWrite', 'onclick' => 'product_cart_write(this.parentElement);', 'class' => 'col-10 btn button_blue button_clean py-2 px-5']) ?>
|
||||
<?= $form->field($model, 'amount', ['options' => ['class' => 'col h-100 m-0 form-group']])->textInput(['value' => '1', 'class' => 'form-control h-100 rounded-0 text-center button_clean']); ?>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="mt-0">
|
||||
<strong>Хабаровск: </strong>
|
||||
в наличии
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Доставим: завтра
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -55,15 +55,15 @@ if (
|
|||
|
||||
// Инициализация
|
||||
$model ?? $model = yii::$app->user->identity;
|
||||
$delivery_to_city_list or $delivery_to_city_list = ['Нет данных'];
|
||||
$delivery_to_terminal_list or $delivery_to_terminal_list = ['Нет данных'];
|
||||
?>
|
||||
|
||||
<?= $form->field($model, 'opts[delivery_to_city]', ['options' => ['class' => "mb-1"]])
|
||||
->dropDownList($delivery_to_city_list, [
|
||||
<?= $form->field($model, 'opts[delivery_to_terminal]', ['options' => ['class' => "mb-1"]])
|
||||
->dropDownList($delivery_to_terminal_list, [
|
||||
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_account\')'
|
||||
])->label('Город'); ?>
|
||||
])->label('Терминал'); ?>
|
||||
|
||||
<small class="d-block mb-1">Выберите город <b><u>получателя</u></b> для <b>рассчёта доставки</b></small>
|
||||
<small class="d-block mb-1">Выберите терминал <b><u>получателя</u></b> для <b>рассчёта доставки</b></small>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
|
@ -86,15 +86,15 @@ if (
|
|||
|
||||
// Инициализация
|
||||
$model ?? $model = yii::$app->user->identity;
|
||||
$delivery_from_city_list or $delivery_from_city_list = ['Нет данных'];
|
||||
$delivery_from_terminal_list or $delivery_from_terminal_list = ['Нет данных'];
|
||||
?>
|
||||
|
||||
<?= $form->field($model, 'opts[delivery_from_city]', ['options' => ['class' => "mb-1"]])
|
||||
->dropDownList($delivery_from_city_list, [
|
||||
<?= $form->field($model, 'opts[delivery_from_terminal]', ['options' => ['class' => "mb-1"]])
|
||||
->dropDownList($delivery_from_terminal_list, [
|
||||
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_company\')'
|
||||
])->label('Город'); ?>
|
||||
])->label('Терминал'); ?>
|
||||
|
||||
<small class="d-block mb-1">Выберите город <b><u>отправителя</u></b> для <b>рассчёта доставки</b></small>
|
||||
<small class="d-block mb-1">Выберите терминал <b><u>отправителя</u></b> для <b>рассчёта доставки</b></small>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
use app\assets\AppAsset;
|
||||
|
||||
AppAsset::register($this);
|
||||
|
||||
?>
|
||||
|
||||
<?php $this->beginPage() ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?= yii::$app->language ?>">
|
||||
|
||||
<head>
|
||||
<meta charset="<?= yii::$app->charset ?>">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/css/pages/suppliers.css" rel="stylesheet">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/favicons/android-icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicons/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/ms-icon-144x144.png">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
|
||||
<?php $this->registerCsrfMetaTags() ?>
|
||||
|
||||
<title><?= Html::encode($this->title ?? 'Поставщикам | SkillParts') ?></title>
|
||||
|
||||
<?php $this->head() ?>
|
||||
</head>
|
||||
|
||||
<body class="d-flex flex-column">
|
||||
<?php $this->beginBody() ?>
|
||||
|
||||
<header class="container pt-2 mt-1 mb-2 mb-sm-4">
|
||||
<div class="row row h-100">
|
||||
<div id="logo" class="col-3 col-md-4 h-100">
|
||||
<a class="py-2 h-100 d-inline-flex" title="SkillParts" href="/">
|
||||
<img class="img-fluid" src="/img/logos/skillparts.svg" alt="SkillParts">
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-3 mt-auto ml-auto d-flex justify-content-end">
|
||||
<a class="py-2 h-100 d-inline-flex text-dark" href="/authentication">Вход в кабинет поставщика</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="page_suppliers" class="container pb-5 flex-grow-1 d-flex">
|
||||
<article class="my-auto p-3 rounded overflow-hidden">
|
||||
<h1 class="py-3 mt-2 mb-5 text-center"><b>Продавайте свои товары на</br>площадке SkillParts по всей России</b></h1>
|
||||
<div class="row mb-4 px-3 pb-3">
|
||||
<div class="col-4">
|
||||
<img src="" />
|
||||
<h5 class="text-center"><b>Дополнительный инструмент продаж для вашего бизнеса</b></h5>
|
||||
<p class="text-center"><small>Не требует размещения штата сотрудников</small></p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img src="" />
|
||||
<h5 class="text-center"><b>Расширяйте географию продаж</b></h5>
|
||||
<p class="text-center"><small>Тысячи клиентов по всей России</small></p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img src="" />
|
||||
<h5 class="text-center"><b>Своевременные взаиморасчеты</b></h5>
|
||||
<p class="text-center"><small>В течение 5-7 банковских дней</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-3 pb-3 justify-content-center">
|
||||
<a class="col-auto text-center text-dark btn button_become_supplier button_clean" role="button" onclick="return false;">Стать поставщиком</a>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<?php $this->endBody() ?>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
<?php $this->endPage() ?>
|
|
@ -0,0 +1,29 @@
|
|||
main {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
#page_buyers article {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#page_buyers article>div h5 {
|
||||
color: #011b5c;
|
||||
}
|
||||
|
||||
#page_buyers article>div p {
|
||||
color: #617fca;
|
||||
}
|
||||
|
||||
#page_buyers article>div .button_become_buyer {
|
||||
border: 3px solid;
|
||||
border-radius: 0;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
#page_buyers article>div .button_become_buyer:hover {
|
||||
background-color: rgb(250, 249, 253);
|
||||
}
|
||||
|
||||
#page_buyers article>div .button_become_buyer:active {
|
||||
background-color: rgb(229, 225, 243);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#page_offer article {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#page_offer article>div .button_accept_offer {
|
||||
border: 3px solid;
|
||||
border-radius: 0;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
#page_offer article>div .button_accept_offer:hover {
|
||||
background-color: rgb(250, 249, 253);
|
||||
}
|
||||
|
||||
#page_offer article>div .button_accept_offer:active {
|
||||
background-color: rgb(229, 225, 243);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
main {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
#page_suppliers article {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#page_suppliers article>div h5 {
|
||||
color: #011b5c;
|
||||
}
|
||||
|
||||
#page_suppliers article>div .button_become_supplier {
|
||||
border: 3px solid;
|
||||
border-radius: 0;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
#page_suppliers article>div .button_become_supplier:hover {
|
||||
background-color: rgb(250, 249, 253);
|
||||
}
|
||||
|
||||
#page_suppliers article>div .button_become_supplier:active {
|
||||
background-color: rgb(229, 225, 243);
|
||||
}
|
Reference in New Issue