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

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\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'
));

View File

@ -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'];

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

View File

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

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

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

View File

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

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\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());
}
}

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

View File

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

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">
<!-- Габариты -->
<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>

View File

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

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