Оферта, доставка, ограничения, страницы покупателям

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-05-04 07:59:37 +10:00
parent 3ea7a9e1eb
commit 03b52d071d
29 changed files with 920 additions and 328 deletions

View File

@ -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');
}
}

View File

@ -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('/');
}
}
}

View File

@ -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');
}
}

View File

@ -17,7 +17,6 @@ use app\models\Search;
use app\models\Notification; use app\models\Notification;
use app\models\Settings; use app\models\Settings;
use app\models\SettingsEdgeSettings; use app\models\SettingsEdgeSettings;
use app\models\connection\Dellin;
class ProfileController extends Controller class ProfileController extends Controller
{ {
@ -76,7 +75,7 @@ class ProfileController extends Controller
// Генерация ответа // Генерация ответа
Yii::$app->response->content = json_encode([ Yii::$app->response->content = json_encode([
'main' => $this->renderPartial('/account/index'), 'main' => $this->renderPartial('/account/index'),
'redirect' => '/authentication', 'redirect' => '/profile',
'_csrf' => Yii::$app->request->getCsrfToken() '_csrf' => Yii::$app->request->getCsrfToken()
]); ]);
} else if (Yii::$app->request->isGet) { } else if (Yii::$app->request->isGet) {
@ -118,15 +117,37 @@ class ProfileController extends Controller
} }
// Инициализация // Инициализация
$delivery_from_city_list = $model->genListCitiesFrom(); $delivery_from_terminal_list = $model->genListTerminalsFrom();
$delivery_to_city_list = $model->genListCitiesTo(); $delivery_to_terminal_list = $model->genListTerminalsTo();
$import_oem_list = $model->genListOem(Supply::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]')); $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_from_terminal_list);
asort($delivery_to_city_list); asort($delivery_to_terminal_list);
asort($import_oem_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) { if (yii::$app->request->isPost) {
// POST-запрос // POST-запрос
@ -136,8 +157,8 @@ class ProfileController extends Controller
'main' => $this->renderPartial('index', compact( 'main' => $this->renderPartial('index', compact(
'model', 'model',
'sidebar', 'sidebar',
'delivery_from_city_list', 'delivery_from_terminal_list',
'delivery_to_city_list', 'delivery_to_terminal_list',
'import_oem_list', 'import_oem_list',
'panel' 'panel'
)), )),
@ -149,8 +170,8 @@ class ProfileController extends Controller
return $this->render('index', compact( return $this->render('index', compact(
'model', 'model',
'sidebar', 'sidebar',
'delivery_from_city_list', 'delivery_from_terminal_list',
'delivery_to_city_list', 'delivery_to_terminal_list',
'import_oem_list', 'import_oem_list',
'panel' 'panel'
)); ));

View File

@ -8,6 +8,7 @@ use yii;
use yii\web\Controller; use yii\web\Controller;
use yii\web\Response; use yii\web\Response;
use app\models\Account;
use app\models\Product; use app\models\Product;
use app\models\Supply; use app\models\Supply;
use app\models\Search; 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']; $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'];

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -2,7 +2,7 @@
use mirzaev\yii2\arangodb\Migration; use mirzaev\yii2\arangodb\Migration;
class m210412_171912_create_city_controller extends Migration class m210502_102358_create_dellin_collection extends Migration
{ {
public function up() public function up()
{ {
@ -10,11 +10,11 @@ class m210412_171912_create_city_controller extends Migration
* @param string Название коллекции * @param string Название коллекции
* @param array Тип коллекции (2 - документ, 3 - ребро) * @param array Тип коллекции (2 - документ, 3 - ребро)
*/ */
$this->createCollection('city', ['type' => 2]); $this->createCollection('dellin', ['type' => 2]);
} }
public function down() public function down()
{ {
$this->dropCollection('city'); $this->dropCollection('dellin');
} }
} }

View File

@ -9,7 +9,8 @@ use yii\web\IdentityInterface;
use carono\exchange1c\interfaces\PartnerInterface; 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 class Account extends Document implements IdentityInterface, PartnerInterface
{ {
use SearchByEdge;
/** /**
* Имя коллекции * Имя коллекции
*/ */
@ -46,7 +49,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
'onec', 'onec',
'opts', 'opts',
'agnt', 'agnt',
'type' 'type',
'acpt'
] ]
); );
} }
@ -71,7 +75,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
'onec' => 'Данные 1C', 'onec' => 'Данные 1C',
'opts' => 'Параметры', 'opts' => 'Параметры',
'agnt' => 'Агент (поставщик)', '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 = []; $list = [];
$cities = City::readAll(); $cities = Dellin::readAll();
foreach ($cities as $city) { 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 = []; $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; 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 не найден в настройках аккаунта // Параметр $var не найден в настройках аккаунта
// Сохранение параметра из данных аккаунта в начале массива // Сохранение параметра из данных аккаунта в начале массива
$list = array_merge(['Выберите'], $list); $list = array_merge(['Выберите' => 'Выберите'], $list);
} }
return $list; return $list;
@ -474,4 +484,33 @@ class Account extends Document implements IdentityInterface, PartnerInterface
return $amount; 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];
}
} }

View File

@ -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]);
}
}

View File

@ -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]);
}
}

View File

@ -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); $connection['cost'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['price'] ?? 0) + ($settings['increase'] ?? 0);

View File

@ -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 символов'
]
]
);
}
/** /**
* Поиск поставки по артикулу * Поиск поставки по артикулу
* *

View File

@ -112,6 +112,8 @@ class Product extends Document
/** /**
* Правила * Правила
*
* @todo Правило для всех трёх габаритов
*/ */
public function rules(): array public function rules(): array
{ {
@ -175,6 +177,27 @@ class Product extends Document
'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"', 'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"',
'message' => 'Проблема при загрузке изображения', 'message' => 'Проблема при загрузке изображения',
'on' => self::SCENARIO_IMPORT_IMAGE '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(); 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];
}
} }

View File

@ -601,33 +601,4 @@ class Supply extends Product implements ProductInterface, OfferInterface
{ {
return static::searchAccountById($this->readId()); 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];
}
} }

View File

@ -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' => 'Количество дней для обработки после получения от ДеловыеЛинии'
]
);
}
}

View File

@ -7,9 +7,10 @@ namespace app\models\connection;
use yii; use yii;
use yii\base\Model; use yii\base\Model;
use app\models\City; use app\models\Dellin as DellinModel;
use GuzzleHttp\Client as Guzzle; use GuzzleHttp\Client as Guzzle;
use GuzzleHttp\Exception\ClientException as GuzzleException;
use Exception; use Exception;
use phpDocumentor\Reflection\Types\Nullable; use phpDocumentor\Reflection\Types\Nullable;
@ -61,15 +62,18 @@ class Dellin extends Model
* @param string $from Номер КЛАДР * @param string $from Номер КЛАДР
* @param string $to Номер КЛАДР * @param string $to Номер КЛАДР
* @param int $weight Вес (кг) * @param int $weight Вес (кг)
* @param int $x Ширина (см) * @param int $x Ширина (м)
* @param int $y Высота (см) * @param int $y Высота (м)
* @param int $z Длинна (см) * @param int $z Длинна (м)
* @param int $amount Количество
* *
* @return string * @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 <= 5.4 && $y <= 3.9 && $z <= 3.9)
|| ($x <= 3.9 && $y <= 5.4 && $z <= 3.9) || ($x <= 3.9 && $y <= 5.4 && $z <= 3.9)
|| ($x <= 3.9 && $y <= 3.9 && $z <= 5.4)) || ($x <= 3.9 && $y <= 3.9 && $z <= 5.4))
&& $x * $y * $z <= 1000000 && $x * $y * $z <= 0.1
) { ) {
// Доставка категории "small" // Доставка категории "small"
@ -89,8 +93,34 @@ class Dellin extends Model
$type = 'auto'; $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' => [ 'json' => [
'appkey' => yii::$app->params['dellin']['key'], 'appkey' => yii::$app->params['dellin']['key'],
'sessionID' => self::$session, 'sessionID' => self::$session,
@ -98,9 +128,32 @@ class Dellin extends Model
'deliveryType' => [ 'deliveryType' => [
'type' => $type 'type' => $type
], ],
'derival' => [
'produceDate' => date('Y-m-d', time() + ($settings['delivery_handle_time'] ?? 86400)),
'variant' => 'terminal',
'terminalID' => $from,
],
'arrival' => [ 'arrival' => [
'variant' => 'terminal', '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 Сохранённые города * @return array|null Сохранённые города
*/ */
public static function importCities(): ?int // public static function importCities(): ?int
{ // {
return self::handle(function () { // return self::handle(function () {
// Всё готово к работе // // Всё готово к работе
// Запрос ссылки на файл с городами, возвращает ['hash' => string, 'url' => string] // // Запрос ссылки на файл с городами, возвращает ['hash' => string, 'url' => string]
$request = self::$browser->post('/v1/public/cities.json', [ // $request = self::$browser->post('/v1/public/cities.json', [
'json' => [ // 'json' => [
'appkey' => yii::$app->params['dellin']['key'], // 'appkey' => yii::$app->params['dellin']['key'],
] // ]
]); // ]);
if ($request->getStatusCode() === 200) { // if ($request->getStatusCode() === 200) {
// Запрос прошел успешно // // Запрос прошел успешно
// Инициализация // // Инициализация
$response = json_decode((string) $request->getBody(), true); // $response = json_decode((string) $request->getBody(), true);
$hash_target = $response['hash']; // $hash_target = $response['hash'];
$dir = YII_PATH_PUBLIC . '/../assets/import/' . date('Y-m-d', time()) . '/dellin/cities/' . (yii::$app->user->identity->_key ?? 'system') . '/'; // $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'], [ // $request = self::$browser->get($response['url'], [
'sink' => $file = $dir . time() . '.csv' // '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"); // $file = fopen($file, "r");
$first_raw_block = true; // $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); // $data = explode(',', $row, 4);
$amount = 0; // $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 { // $after_import_log = function () use ($city): void {
// Запись в журнал // // Запись в журнал
$city->journal('update'); // $city->journal('update');
if (yii::$app->getRequest()->isConsoleRequest) { // if (yii::$app->getRequest()->isConsoleRequest) {
// Вызов из терминала // // Вызов из терминала
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL; // echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
} // }
}; // };
} else { // } else {
// Не удалось найти город в базе данных // // Не удалось найти город в базе данных
$city = new City(); // $city = new City();
$after_import_log = function () use ($city): void { // $after_import_log = function () use ($city): void {
if (yii::$app->getRequest()->isConsoleRequest) { // if (yii::$app->getRequest()->isConsoleRequest) {
// Вызов из терминала // // Вызов из терминала
echo 'Удалось записать город: ' . $city->name . PHP_EOL; // echo 'Удалось записать город: ' . $city->name . PHP_EOL;
} // }
}; // };
} // }
// Запись // // Запись
$city->indx = $data[0]; // $city->indx = $data[0];
$city->name = $data[1]; // $city->name = $data[1];
$city->code = $data[2]; // $city->code = $data[2];
$city->term = (bool) $data[3]; // $city->term = (bool) $data[3];
// Отправка в базу данных // // Отправка в базу данных
if ($city->save()) { // if ($city->save()) {
// Удалось сохранить в базе данных // // Удалось сохранить в базе данных
// Запись в журнал // // Запись в журнал
$after_import_log(); // $after_import_log();
// Постинкрементация счётчика // // Постинкрементация счётчика
$amount++; // $amount++;
continue; // continue;
} else { // } else {
// Не удалось сохранить в базе данных // // Не удалось сохранить в базе данных
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500); // throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
} // }
} // }
// Деинициализация // // Деинициализация
fclose($file); // fclose($file);
return $amount; // return $amount;
// } else { // // } 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); $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') . '/'; $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)) { if (!file_exists($dir)) {
// Директории не существует // Директории не существует
@ -336,68 +390,44 @@ class Dellin extends Model
'sink' => $file = $dir . time() . '.json' 'sink' => $file = $dir . time() . '.json'
]); ]);
die; // Инициализация
$terminals = json_decode(fread(fopen($file, "r"), filesize($file)), true);
foreach ($terminals['city'] as $terminal) {
// Перебор городов
// Инициализация (чтение файла) if ($model = DellinModel::searchByCityId($terminal['id'])) {
$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])) {
// Удалось найти город в базе данных // Удалось найти город в базе данных
$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) { if (yii::$app->getRequest()->isConsoleRequest) {
// Вызов из терминала // Вызов из терминала
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL; echo 'Удалось перезаписать терминалы города: ' . ($model->data['name'] ?? 'Неизвестно') . PHP_EOL;
} }
}; };
} else { } 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) { if (yii::$app->getRequest()->isConsoleRequest) {
// Вызов из терминала // Вызов из терминала
echo 'Удалось записать город: ' . $terminal->name . PHP_EOL; echo 'Удалось записать терминалы города: ' . ($model->data['name'] ?? 'Неизвестно') . PHP_EOL;
} }
}; };
} }
// Запись // Запись
$terminal->indx = $data[0]; $model->data = $terminal;
$terminal->name = $data[1];
$terminal->code = $data[2];
$terminal->term = (bool) $data[3];
// Отправка в базу данных // Отправка в базу данных
if ($terminal->save()) { if ($model->save()) {
// Удалось сохранить в базе данных // Удалось сохранить в базе данных
// Запись в журнал // Запись в журнал
@ -410,13 +440,10 @@ class Dellin extends Model
} else { } else {
// Не удалось сохранить в базе данных // Не удалось сохранить в базе данных
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500); throw new Exception('Не удалось сохранить терминалы города "' . ($model->data['name'] ?? 'Неизвестно') . '" в базу данных', 500);
} }
} }
// Деинициализация
fclose($file);
return $amount; return $amount;
} }
@ -483,9 +510,10 @@ class Dellin extends Model
} else { } else {
throw new Exception('Браузер не инициализирован', 500); throw new Exception('Браузер не инициализирован', 500);
} }
} catch (GuzzleException $e) {
throw new Exception($e->getResponse()->getBody()->getContents() ?? 'Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
} catch (Exception $e) { } catch (Exception $e) {
throw new Exception($e->getMessage(), 500, $e->getPrevious()); throw new Exception($e->getMessage() ?? 'Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
// throw new Exception('Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
} }
} }

View File

@ -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() ?>

View File

@ -4,6 +4,8 @@ use yii;
use app\models\connection\Dellin; use app\models\connection\Dellin;
use DateTime;
?> ?>
<link href="/css/pages/cart.css" rel="stylesheet"> <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']; $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"> <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>
<div class="col-2 my-auto text-right"> <div class="col-2 my-auto text-right">
$delivery дней $delivery дн
</div> </div>
<div class="col-2 my-auto mr-3 text-right"> <div class="col-2 my-auto mr-3 text-right">
$cost $cost

View File

@ -13,10 +13,10 @@ AppAsset::register($this);
<?php $this->beginPage() ?> <?php $this->beginPage() ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>"> <html lang="<?= yii::$app->language ?>">
<head> <head>
<meta charset="<?= Yii::$app->charset ?>"> <meta charset="<?= yii::$app->charset ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
@ -129,9 +129,9 @@ AppAsset::register($this);
</div> </div>
<div class="col-md-auto mr-md-5 partnership"> <div class="col-md-auto mr-md-5 partnership">
<h5 class="row mb-2"><b>Партнёрство</b></h5> <h5 class="row mb-2"><b>Партнёрство</b></h5>
<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>Поставщикам</a></small> <small class="row mb-1"><a class="text-dark" href="/suppliers">Поставщикам</a></small>
<small class="row mb-1"><a>Партнерская сеть</a></small> <small class="row mb-1"><a class="text-dark" href="/partners">Сеть филиалов</a></small>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -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>

View File

@ -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&amp;height=300&amp;hl=ru&amp;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)&amp;ie=UTF8&amp;t=&amp;z=13&amp;iwloc=B&amp;output=embed" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>
<div class="p-4">
</div>
</div>
</article>
</div>

View File

@ -167,7 +167,7 @@ use app\models\Product;
<section id="prod_<?= $model['catn'] ?>_info" class="col"> <section id="prod_<?= $model['catn'] ?>_info" class="col">
<!-- Габариты --> <!-- Габариты -->
<p class="form-control-sm p-0 h-auto"> <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>
<!-- Вес --> <!-- Вес -->
<p class="form-control-sm p-0 h-auto"> <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"> <section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
<!-- Габариты --> <!-- Габариты -->
<p class="form-control-sm p-0 h-auto"> <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>
<!-- Вес --> <!-- Вес -->
<p class="form-control-sm p-0 h-auto"> <p class="form-control-sm p-0 h-auto">
@ -228,21 +228,6 @@ use app\models\Product;
$model = new 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(); ?> <?php ActiveForm::end(); ?>
</div> </div>
</div> </div>

View File

@ -55,15 +55,15 @@ if (
// Инициализация // Инициализация
$model ?? $model = yii::$app->user->identity; $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"]]) <?= $form->field($model, 'opts[delivery_to_terminal]', ['options' => ['class' => "mb-1"]])
->dropDownList($delivery_to_city_list, [ ->dropDownList($delivery_to_terminal_list, [
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_account\')' '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(); ?> <?php ActiveForm::end(); ?>
</div> </div>
@ -86,15 +86,15 @@ if (
// Инициализация // Инициализация
$model ?? $model = yii::$app->user->identity; $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"]]) <?= $form->field($model, 'opts[delivery_from_terminal]', ['options' => ['class' => "mb-1"]])
->dropDownList($delivery_from_city_list, [ ->dropDownList($delivery_from_terminal_list, [
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_company\')' '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(); ?> <?php ActiveForm::end(); ?>
</div> </div>

View File

@ -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() ?>

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}