Страницы поставщикам и покупателям переделаны + исправление доставки

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-05-11 06:47:04 +10:00
parent 5d9228ec1b
commit 7e5f39c8e9
37 changed files with 670 additions and 208 deletions

View File

@ -89,7 +89,7 @@ class CartController extends Controller
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? 'Комментарий к заказу';
$comm = $edge->comm ?? null;
$edge->comm = $text;
$edge->comm = empty($text) ? 'Комментарий к заказу' : $text;
if ($edge->save()) {
// Ребро обновлено
@ -101,7 +101,7 @@ class CartController extends Controller
++$amount;
// Запись в буфер ответа
$return['comm'] = $text;
$return['comm'] = $edge->comm;
}
}

View File

@ -5,11 +5,63 @@ declare(strict_types=1);
namespace app\controllers;
use yii;
use yii\filters\AccessControl;
use yii\web\Cookie;
use yii\web\Response;
use yii\web\Controller;
class OfferController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'actions' => ['index', 'accept']
],
[
'allow' => false,
'roles' => ['?'],
'denyCallback' => [$this, 'accessDenied']
]
]
]
];
}
public function accessDenied()
{
// Инициализация
$cookies = yii::$app->response->cookies;
// Запись cookie с редиректом, который выполнится после авторизации
$cookies->add(new Cookie([
'name' => 'offer',
'value' => yii::$app->request->pathInfo
]));
if (Yii::$app->request->isPost) {
// POST-запрос
// Настройка
Yii::$app->response->format = Response::FORMAT_JSON;
// Генерация ответа
Yii::$app->response->content = json_encode([
'redirect' => '/authentication',
'_csrf' => Yii::$app->request->getCsrfToken()
]);
} else if (Yii::$app->request->isGet) {
// GET-запрос
$this->redirect('/authentication');
}
}
public function actionIndex()
{
return $this->render('/offer/index');

View File

@ -8,6 +8,7 @@ use yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use yii\web\Cookie;
use app\models\Order;
use app\models\AccountEdgeOrder;

View File

@ -264,6 +264,7 @@ class ProductController extends Controller
// Инициализация
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
$product->wght = $text;
if ($product->save()) {

View File

@ -184,11 +184,18 @@ class ProfileController extends Controller
{
// Инициализация
$model_notifications = null;
$model_settings = Settings::readLast();
$panel = yii::$app->request->post('panel') ?? yii::$app->request->get('panel');
$sidebar = $this->renderPartial('sidebar');
if (!is_null($vars = yii::$app->request->post('Notification') ?? yii::$app->request->get('Notification'))) {
if (!$model_settings = Settings::readLast()) {
$model_settings = new Settings();
if(!$model_settings->save()) {
$this->redirect('/');
}
}
if ($vars = yii::$app->request->post('Notification') ?? yii::$app->request->get('Notification')) {
// Обнаружены входные параметры из раздела "Уведомления"
// Реинициализация с новыми параметрами
@ -196,7 +203,7 @@ class ProfileController extends Controller
// Запись уведомления и отправка (запись ребра до аккаунта)
$model_notifications->write();
} else if (!is_null($vars = yii::$app->request->post('Settings') ?? yii::$app->request->get('Settings'))) {
} else if ($vars = yii::$app->request->post('Settings') ?? yii::$app->request->get('Settings')) {
// Обнаружены входные параметры из раздела "Настройки"
if ($to = new Settings($vars)) {

View File

@ -15,6 +15,8 @@ use app\models\Search;
use app\models\connection\Dellin;
use Exception;
class SearchController extends Controller
{
/**
@ -148,7 +150,7 @@ class SearchController extends Controller
// Перебор продуктов
// Поиск поставок привязанных к продуктам
$row['supplies'] = Supply::searchByEdge(
$connections = Supply::searchByEdge(
from: 'product',
to: 'supply',
edge: 'supply_edge_product',
@ -160,30 +162,43 @@ class SearchController extends Controller
['supply_edge_product.type' => 'connect']
],
where: 'supply._id == supply_edge_product[0]._from',
select: 'supply_edge_product[0]'
select: '{supply, supply_edge_product}'
);
if (count($row['supplies']) === 11) {
if (count($connections) === 11) {
// Если в базе данных хранится много поставок
// Инициализация
$row['overload'] = true;
}
foreach ($row['supplies'] as &$edge) {
foreach ($connections as &$connection) {
// Перебор поставок
// Инициализация аккаунта
$edge['account'] = Account::searchBySupplyId($edge['_from']);
$connection['account'] = Account::searchBySupplyId($connection['supply_edge_product'][0]['_from']);
try {
// Инициализация доставки
$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']['max'] = $edge['delivery']['period_to'];
$edge['delivery']['price'] = $edge['delivery']['price'];
$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)
);
} catch (Exception $e) {
$connection['delivery']['error'] = true;
// var_dump(json_decode($e->getMessage(), true)['errors']); die;
}
// Инициализация цены (цена поставки + цена доставки + наша наценка)
$edge['prce'] = ($edge['prce'] ?? $edge['onec']['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($edge['delivery']['price'] ?? 0) + ($settings['increase'] ?? 0);
$connection['cost'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply_edge_product'][0]['onec']['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['price']['all'] ?? $connection['delivery']['price']['one'] ?? 0) + ($settings['increase'] ?? 0);
}
$row = $connections;
}
// Запись ответа

View File

@ -6,10 +6,16 @@ namespace app\controllers;
use yii\web\Controller;
use app\models\Request;
class SuppliersController extends Controller
{
public function actionIndex()
{
return $this->renderPartial('/suppliers/index');
}
public function actionRequest() {
return $this->renderPartial('/suppliers/request');
}
}

View File

@ -0,0 +1,20 @@
<?php
use mirzaev\yii2\arangodb\Migration;
class m210510_180939_create_request_collection extends Migration
{
public function up()
{
/**
* @param string Название коллекции
* @param array Тип коллекции (2 - документ, 3 - ребро)
*/
$this->createCollection('request', ['type' => 2]);
}
public function down()
{
$this->dropCollection('request');
}
}

View File

@ -177,7 +177,7 @@ abstract class Document extends ActiveRecord
if (is_array($this->$attribute)) {
foreach ($this->$attribute as $value) {
if (!(bool) preg_match('/^[0-9]*$/m', $value)) {
if (!(bool) preg_match('/^[0-9\.]*$/m', $value)) {
$this->addError($attribute, 'В массиве найдены запрещённые символы');
}
}

View File

@ -381,12 +381,11 @@ class Order extends Document implements DocumentInterface
} 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']['all'] ?? $connection['delivery']['price']['one'] ?? 0) + ($settings['increase'] ?? 0);
// Запись валюты
$connection['currency'] = $cost['Валюта'];
@ -465,7 +464,7 @@ class Order extends Document implements DocumentInterface
}
}
file_put_contents('supplies.txt', print_r($supplies, true));
// file_put_contents('supplies.txt', print_r($supplies, true));
if (count($supplies) > 0) {
// Поставки были записаны
@ -489,7 +488,7 @@ class Order extends Document implements DocumentInterface
return $supplies_buffer;
}
file_put_contents('AAAAAAAAAAAAAAAAAAA.txt', print_r(1, true));
// file_put_contents('AAAAAAAAAAAAAAAAAAA.txt', print_r(1, true));
return [];
}

View File

@ -54,8 +54,8 @@ class OrderEdgeSupply extends Edge
'comm'
],
'string',
'length' => [3, 256],
'message' => '{attribute} должен быть строкой от 3 до 256 символов'
'length' => [0, 300],
'message' => '{attribute} должен быть строкой от 0 до 300 символов'
]
]
);

View File

@ -196,8 +196,9 @@ class Product extends Document
[
'wght',
'integer',
'max' => 9999,
'message' => '{attribute} должен быть строкой от 0 до 6 символов'
'min' => 0,
'max' => 30000,
'message' => '{attribute} должен иметь значение от 0 до 30000'
]
]
);

View File

@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
namespace app\models;
use yii;
use yii\web\UploadedFile;
use yii\imagine\Image;
use app\models\traits\SearchByEdge;
use moonland\phpexcel\Excel;
use Exception;
/**
* Запрос (регистрация поставщика)
*
* Представляет собой набор данных от поставщика для регистрации
*/
class Request extends Document
{
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'request';
}
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
parent::attributes(),
[
'text',
'phon',
'mail',
'file'
]
);
}
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[
'text' => 'Обращение',
'phon' => 'Номер',
'mail' => 'Почта',
'file' => 'Юридические данные'
]
);
}
/**
* Правила
*
* @todo Правило для всех трёх габаритов
*/
public function rules(): array
{
return array_merge(
parent::rules(),
[
[
[
'file',
'mail'
],
'required',
'message' => 'Обязательные поля: {attribute}'
],
[
'file',
'file',
'skipOnEmpty' => false,
// 'extensions' => 'xlsx',
'checkExtensionByMimeType' => false,
'maxFiles' => 1,
'maxSize' => 1024 * 1024 * 30,
// 'wrongExtension' => 'Разрешены только документы в формате: ".xlsx"',
'message' => 'Проблема при чтении документа'
]
]
);
}
}

View File

@ -59,39 +59,40 @@ class Dellin extends Model
/**
* Рассчет доставки (расширенный)
*
* Рассчет нескольких товаров идет через простое перемножение результатов доставки одного товара
* В API всегда идет рассчет для одного товара, так было решено
*
* @param string $from Номер КЛАДР
* @param string $to Номер КЛАДР
* @param int $weight Вес (кг)
* @param int $x Ширина (м)
* @param int $y Высота (м)
* @param int $z Длинна (м)
* @param int $weight Вес (г)
* @param int $x Ширина (cм)
* @param int $y Высота (cм)
* @param int $z Длинна (cм)
* @param int $amount Количество
*
* @return string
*
* @todo Переработать "weight" (если посылок больше чем одна, то отправить вес самого тяжелого груза), хотя здесь же копии обрабатываются и вес у них один... Надо думать
* @todo Загружать помимо терминалов ещё и адреса, чтобы доделать доставку малогабаритных грузов
* Разрабраться с параметрами 0,54м * 0,39м * 0,39м (0.082134м) и 0.1 куб метр в чем разница
*/
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, $amount) {
// Всё готово к работе
// Рассчёт типа доставки
if (
$weight <= 10
&& (($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 <= 0.1
) {
// Доставка категории "small"
// Значения по умолчанию, если указан 0
$x === 0 and $x = 25;
$y === 0 and $y = 55;
$z === 0 and $z = 25;
$weight === 0 and $weight = 300;
$type = 'small';
} else {
// Доставка категории "auto"
// Конвертация из сантиметров в метры
$x /= 100;
$y /= 100;
$z /= 100;
$type = 'auto';
}
// Конвертация из граммов в килограммы
$weight /= 1000;
// Вычисление самой крупной стороны, так как ДеловыеЛинии имеют ограничения на все три поля и у длинны оно больше всех
if ($x > $z && $x > $y) {
@ -108,15 +109,36 @@ class Dellin extends Model
$width = $x;
$height = $z;
$length = $y;
} else if ($z > $x && $z > $y) {
} else {
// } else if ($z > $x && $z > $y) {
// "Z" больше всех
// Инициализация
$width = $x;
$height = $y;
$length = $z;
}
// Рассчёт типа доставки
// if (
// $weight <= 30 &&
// $x * $y * $z <= 0.082134 // &&
// // $x * $y * $z <= 0.1
if (
$weight <= 30
&& ($length <= 0.54 && $width <= 0.39 && $height <= 0.39)
&& $length * $width * $height <= 0.1
) {
// Доставка категории "small"
$type = 'small';
$variant = 'address';
} else {
echo 'Ошибка';
// Доставка категории "auto"
$type = 'auto';
$variant = 'terminal';
}
// Запрос
@ -130,12 +152,12 @@ class Dellin extends Model
],
'derival' => [
'produceDate' => date('Y-m-d', time() + ($settings['delivery_handle_time'] ?? 86400)),
'variant' => 'terminal',
'variant' => $variant,
'terminalID' => $from,
],
'arrival' => [
'variant' => 'terminal',
'variant' => $variant,
'terminalID' => $to
]
],
@ -145,7 +167,7 @@ class Dellin extends Model
]
],
'cargo' => [
'quantity' => $amount,
'quantity' => 1,
'width' => $width,
'height' => $height,
'length' => $length,
@ -167,6 +189,11 @@ class Dellin extends Model
if ($response['metadata']['status'] === 200) {
// Со стороны ДеловыеЛинии ошибок нет
$response['data']['price'] = [
'one' => $response['data']['price'],
'all' => $response['data']['price'] * $amount
];
return $response['data'];
}

View File

@ -60,25 +60,26 @@ AppAsset::register($this);
</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">
<main id="page_buyers" class="container pb-5 flex-grow-1 d-flex justify-content-center">
<article class="col my-auto p-3 px-0 rounded overflow-hidden">
<h1 class="py-3 mt-2 mb-5 text-center"><b>Что в нас ценят?</b></h1>
<div class="row mb-5 pb-3">
<div class="col-4">
<img src="" />
<h5 class="text-center"><b>Удобный сервис для заказа и отслеживания</b></h5>
<img class="px-5 img-fluid" src="/img/icons/track.png" title="Подробное отслеживание" />
<h5 class="text-center"><b>Подробное отслеживание</b></h5>
</div>
<div class="col-4">
<img src="" />
<h5 class="text-center"><b>Бесплатное экспедирование товаров в городах присутствия SkillParts</b></h5>
<img class="px-5 img-fluid" src="/img/icons/truck.png" title="Бесплатное экспедирование" />
<h5 class="text-center"><b>Бесплатное экспедирование</b></h5>
</div>
<div class="col-4">
<img src="" />
<h5 class="text-center"><b>Все поставщики России в одном месте</b></h5>
<img class="px-5 img-fluid" src="/img/icons/assortiment.png" title="Наличие всех поставщиков" />
<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>
<a class="mr-4 text-center text-white btn button_blue button_clean" href="/registration">Зарегистрироваться</a>
<a class="text-center text-white btn button_blue button_clean" href="/offer">Оферта</a>
</div>
</article>
</main>

View File

@ -47,7 +47,7 @@ use DateTime;
} else {
// Удалось рассчитать доставку
$delivery = date('d', DateTime::createFromFormat('Y-m-d', $connection['delivery']['orderDates']['arrivalToOspReceiver'])->getTimestamp() - time());
$delivery = (DateTime::createFromFormat('Y-m-d', $connection['delivery']['orderDates']['arrivalToOspReceiver'])->getTimestamp() - time()) / 60 / 60 / 24 + 1;
}
// Инициализация цены
@ -119,4 +119,5 @@ use DateTime;
</article>
</div>
<script src="/js/textarea.js" defer></script>
<script src="/js/cart.js" defer></script>

View File

@ -6,20 +6,21 @@
<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>1.1. Поставщик предлагает заключить договор купли-продажи потребителю, компании и предпринимателю (далее - покупатель) на описанных ниже условиях</p>
<p>1.2. Договор считается заключенным в момент заказа товара на сайте (skillparts.ru)</p>
<p>1.3. Стороны признают юридическую силу скан-копий подписанных документов, переписки, записей в протоколе работы программ, хранящихся на серверах Торговой площадки</p>
<p>1.4 Условия оферты могут быть изменены, дополнены, в этом случае поставщик высылает покупателю уведомление на согласование в личный кабинет или на почту</p>
<p>2. Термины и определения
Поставщик компания ООО «СтандартМашинери», либо филиал компании ООО «СтандартМашинери»
Торговая площадка ООО «СтнадартМашинери», предоставляющий программно-аппаратный комплекс организационных, информационных и технических решений, обеспечивающих взаимодействие поставщика и покупателя через электронные каналы связи.</p>
Торговая площадка ООО «СтандартМашинери», предоставляющий программно-аппаратный комплекс организационных, информационных и технических решений, обеспечивающих взаимодействие поставщика и покупателя через электронные каналы связи</p>
<p>3. Условия работы и оплата</p>
<p>3.1. Поставщик обязуется приобрести в собственность товар, заказанный покупателем на сайте, для последующей продажи покупателю, а потребитель обязуется оплатить заказанный Товар.</p>
<p>3.2. Цена, количество, наименование заказанного покупателем товара, определяются в момент отправки заказа поставщику.</p>
<p>3.3. Покупатель может оплатить заказ или пополнить баланс на сайте. Оплата произведённая на сайте, осуществляется на счёт торговой площадки и учитывается поставщиком как оплата заказа покупателем.</p>
<p>3.4. Условия возврата товара отражены и регулируются в личном кабинете покупателя.</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>
<p>4.1. Покупатель даёт своё согласие поставщику и торговой площадке осуществлять следующие действия с персональными данными: сбор, систематизацию, накопление, хранение, обновление, изменение, деперсонализацию, уничтожение</p>
</br>
<p> Торговая площадка
ООО «СтандартМашинери» ИНН: 2724241607</br>
@ -30,7 +31,7 @@
</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>
<a class="col-auto text-center text-white btn button_blue button_clean" href="/offer/accept">Принять</a>
</div>
</article>
</div>

View File

@ -167,22 +167,22 @@ 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">
<b>Вес:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_weight_edit('<?= $model['catn'] ?>', this);"><?= empty($model['wght']) ? '0' : $model['wght'] ?></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_weight_edit('<?= $model['catn'] ?>', this);"><?= empty($model['wght']) ? '0' : $model['wght'] ?></span><span class="mr-1">г</span>
</p>
</section>
<?php else : ?>
<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">
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1"><?= empty($model['wght']) ? '0' : $model['wght'] ?></span><small>кг</small>
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1"><?= empty($model['wght']) ? '0' : $model['wght'] ?></span><small>г</small>
</p>
</section>
<?php endif ?>

View File

@ -60,7 +60,8 @@ if (
<?= $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\')'
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_account\')',
'disabled' => count($delivery_to_terminal_list) <= 1
])->label('Терминал'); ?>
<small class="d-block mb-1">Выберите терминал <b><u>получателя</u></b> для <b>рассчёта доставки</b></small>
@ -91,7 +92,8 @@ if (
<?= $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\')'
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_company\')',
'disabled' => count($delivery_from_terminal_list) <= 1
])->label('Терминал'); ?>
<small class="d-block mb-1">Выберите терминал <b><u>отправителя</u></b> для <b>рассчёта доставки</b></small>

View File

@ -60,10 +60,16 @@ $panel ?? $panel = 'profile_panel_panel_input_notifications';
<small class="d-block mb-1"><b>Множественная отправка:</b> @all или перечислить через запятую</small>
<small class="d-block mb-3"><b>Тестирование:</b> @test или оставить поле пустым</small>
<?= $form->field($model_notifications, 'text', ['options' => ['class' => "mb-3"]])->textarea(); ?>
<?= $form->field($model_notifications, 'text', ['options' => ['class' => "mb-1"]])->textarea(["maxlength" => '300']); ?>
<?= Html::submitButton('Отправить', ['name' => 'submitNotification', 'onclick' => 'page_profile_panel_notification_create(this.parentElement);', 'class' => 'flex-grow-1 mr-2 btn button_white button_clean']) ?>
<?= Html::submitButton('Отправить как HTML', ['name' => 'submitNotification', 'onclick' => 'page_profile_panel_notification_create(this.parentElement, 1);', 'class' => 'flex-grow-1 mr-2 btn button_white button_clean']) ?>
<p class="mb-3 text-right">
<span id="notification-text-current">0</span>
<span> / </span>
<span id="notification-text-maximum">300</span>
</p>
<?= Html::submitButton('Отправить', ['name' => 'submitNotification', 'onclick' => 'page_profile_panel_notification_create(this.parentElement);', 'id' => 'notification-button-send', 'class' => 'flex-grow-1 mr-2 btn button_white button_clean']) ?>
<?= Html::submitButton('Отправить как HTML', ['name' => 'submitNotification', 'onclick' => 'page_profile_panel_notification_create(this.parentElement, 1);', 'id' => 'notification-button-send-html', 'class' => 'flex-grow-1 mr-2 btn button_white button_clean']) ?>
<?php ActiveForm::end(); ?>
</div>
@ -143,3 +149,32 @@ $panel ?? $panel = 'profile_panel_panel_input_notifications';
<script src="/js/profile.js" defer></script>
<script src="/js/profile_panel.js" defer></script>
<script src="/js/textarea.js" defer></script>
<script defer>
document.addEventListener('DOMContentLoaded', function() {
initTextarea(
'#notification-text',
'#notification-text-current',
'#notification-text-maximum',
function() {
let send = document.getElementById('notification-button-send');
let send_html = document.getElementById('notification-button-send-html');
send.removeAttribute('onchange');
send_html.removeAttribute('onchange');
send.disabled = true;
send_html.disabled = true;
},
function() {
let send = document.getElementById('notification-button-send');
let send_html = document.getElementById('notification-button-send-html');
send.setAttribute('onchange', 'page_profile_panel_notification_create(this.parentElement);');
send_html.setAttribute('onchange', 'page_profile_panel_notification_create(this.parentElement, 1);');
send.disabled = false;
send_html.disabled = false;
});
}, false);
</script>

View File

@ -31,7 +31,7 @@
<?php
// Инициализация
extract($row);
extract($row[0]);
$name ?? $name = 'Без названия';
// $dscr ?? $dscr = 'Описание';
$catg ?? $catg = 'Категория';
@ -60,18 +60,16 @@
$supplies_html = '';
?>
<?php foreach ($supplies as $supply) : ?>
<?php
// Инициализация артикула
$catn = $supply['catn'] ?? $supply['onec']['Артикул'];
// Инициализация цены
$price_raw = $supply['prce'];
$price = $price_raw . ' ' . $supply['onec']['Цены']['Цена']['Валюта'];
$price_raw = $cost;
$price = $price_raw . ' ' . $supply_edge_product[0]['onec']['Цены']['Цена']['Валюта'];
// Инициализация количества
$amount_raw = $amount = $supply['amnt'] ?? $supply['onec']['Количество'];
$amount_raw = $amount = $supply['amnt'] ?? $supply_edge_product[0]['onec']['Количество'];
if (empty($amount_raw) || $amount_raw < 1) {
// Уже не используется
$amount = 'Под заказ';
@ -79,11 +77,19 @@
$amount .= ' шт';
}
// Инициализация доставки
$delivery = $supply['delivery']['max'];
// Инициализация доставки// Инициализация доставки
if (isset($delivery['error'])) {
// Не удалось рассчитать доставку
$delivery = '?';
} else {
// Удалось рассчитать доставку
$delivery = (DateTime::createFromFormat('Y-m-d', $delivery['orderDates']['arrivalToOspReceiver'])->getTimestamp() - time()) / 60 / 60 / 24 + 1;
}
// Инициализация индекса аккаунта
$index = $supply['account']['indx'] ?? 'Неизвестен';
$index = $account['indx'] ?? 'Неизвестен';
if ($amount_raw < 1 || $price_raw < 1) {
// Нет в наличии или цена 0 рублей
@ -122,8 +128,6 @@
}
?>
<?php endforeach ?>
<div class="col pb-2">
<div class="row p-2 rounded">
<img class="ml-0 h-100 img-fluid rounded" src="<?= $covr ?>" />

View File

@ -38,7 +38,7 @@ if (isset($history) && $history) {
foreach ($response as $row) {
// Перебор найденных данных
$catn = $row['catn'];
$catn = $row[0]['supply']['catn'];
echo <<<HTML
<a class="dropdown-item button_white text-dark" href="/product/$catn">$catn</a>

View File

@ -63,28 +63,32 @@ AppAsset::register($this);
</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">
<main id="page_suppliers" class="container pb-5 flex-grow-1 d-flex justify-content-center">
<article class="col my-auto p-3 px-0 rounded overflow-hidden">
<h1 class="py-3 mt-2 mb-5 text-center"><b>Преимущества наших партнёров</b></h1>
<div class="row mb-5 px-3 pb-3">
<div class="col-4">
<img src="" />
<h5 class="text-center"><b>Дополнительный инструмент продаж для вашего бизнеса</b></h5>
<img class="px-5 img-fluid" src="/img/icons/brain.png" title="Современный инструмент"/>
<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>
<img class="px-5 img-fluid" src="/img/icons/map.png" title="Расширение географии"/>
<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>
<img class="px-5 img-fluid" src="/img/icons/shield.png" title="Безопасный расчёт"/>
<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 class="d-flex flex-column mr-4 text-center">
<a class="mb-1 text-center text-whitw btn button_blue button_clean" href="/suppliers/request">Присоединиться</a>
<small>Ответ в течение суток</small>
</div>
<a class="text-center text-white btn button_blue button_offer_supplier button_clean" role="button" onclick="return false;">Оферта</a>
</div>
</article>
</main>

View File

@ -0,0 +1,134 @@
<?php
declare(strict_types=1);
use yii\helpers\Html;
use yii;
use yii\bootstrap\ActiveForm;
use app\assets\AppAsset;
use app\models\Request;
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>
</header>
<main id="page_suppliers" class="container pb-5 flex-grow-1 d-flex justify-content-center">
<article class="col my-auto p-3 px-5 rounded overflow-hidden">
<h3 class="py-3 mt-2 mb-3 text-center"><b>Заявка на подключение</b></h3>
<?php $form = ActiveForm::begin([
'id' => 'form_suppliers_request',
'action' => false,
'fieldConfig' => [
'template' => '{label}{input}',
],
// 'options' => [
// 'onsubmit' => 'return false;'
// ]
]);
// Инициализация
$model_request ?? $model_request = new Request();
?>
<div class="row mb-3">
<?= $form->field($model_request, 'phon', ['options' => ['class' => "mb-1 col-3"]])->input('tel', ['aria-invalid' => false, 'aria-required' => true, 'pattern' => '7[0-9]{3}[0-9]{3}[0-9]{2}[0-9]{2}', 'placeholder' => '79091112233', 'title' => '79091112233']); ?>
<?= $form->field($model_request, 'mail', ['options' => ['class' => "mb-1 col-4"]])->input('email', ['placeholder' => 'company@mail.ru']); ?>
<?= $form->field($model_request, 'file', ['options' => ['class' => "mb-1 col-5 d-flex flex-column justify-content-center"]])->fileInput(['multiple' => true, 'class' => 'my-auto px-0']) ?>
</div>
<?= $form->field($model_request, 'text', ['options' => ['class' => "mb-1"]])->textarea(['rows' => '5', 'maxlength' => '300']) ?>
<p class="mb-3 text-right">
<span id="request-text-current">0</span>
<span> / </span>
<span id="request-text-maximum">300</span>
</p>
<div class="row">
<?= Html::submitButton('Отправить', ['name' => 'submitRequest', 'id' => 'request-button-send', 'class' => 'col-auto mx-auto btn button_white button_clean']) ?>
</div>
<?php ActiveForm::end(); ?>
</article>
</main>
<script src="/js/textarea.js" defer></script>
<script defer>
document.addEventListener('DOMContentLoaded', function() {
initTextarea(
'#request-text',
'#request-text-current',
'#request-text-maximum',
function() {
let send = document.getElementById('request-button-send');
send.disabled = true;
},
function() {
let send = document.getElementById('suppliers-button-send');
send.disabled = false;
});
}, false);
</script>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

View File

@ -13,17 +13,3 @@ main {
#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

@ -1,17 +1,3 @@
#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

@ -16,10 +16,6 @@ main {
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);
#page_suppliers article>div .button_offer_supplier {
height: min-content;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -193,10 +193,58 @@ function cart_cost_calculate() {
*/
function cart_list_comment_edit(catn, element) {
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
element.innerHTML = '<textarea class="form-control" cols="50" rows="5" onchange = "return cart_list_comment_save(\'' + catn + '\', this.parentElement)">' + element.innerText + '</textarea>';
// Инициализация textarea
element.innerHTML = '<textarea id="' + element.id + '-textarea" class="mb-1 form-control" cols="50" rows="5" maxlength="300" onchange="return cart_list_comment_save(\'' + catn + '\', this.parentElement)">' + element.innerText + '</textarea>';
element.removeAttribute('onclick');
// Инициализация счетчика
let counter = document.createElement('p');
counter.setAttribute('id', element.id + '-textarea-counter');
counter.setAttribute('class', "text-right");
// Инициализация значения текущего количества символов
let counter_current = document.createElement('span');
counter_current.setAttribute('id', element.id + '-textarea-counter-current');
counter_current.innerText = document.getElementById(element.id + '-textarea').value.length;
// Инициализация разделителя между текущим и максимальным значениями
let counter_delimiter = document.createElement('span');
counter_delimiter.innerText = ' / ';
// Инициализация значения максиального количества символов
let counter_maximum = document.createElement('span');
counter_maximum.setAttribute('id', element.id + '-textarea-counter-maximum');
counter_maximum.innerText = 300;
// Формирование счетчика
counter.append(counter_current);
counter.append(counter_delimiter);
counter.append(counter_maximum);
// Запись счетчика после textarea
element.after(counter);
// Инициализация счетчика
initTextarea(
'#' + element.id + '-textarea',
'#' + counter_current.id,
'#' + counter_maximum.id,
function () {
let textarea = document.getElementById(element.id + '-textarea');
textarea.removeAttribute('onchange');
},
function () {
let textarea = document.getElementById(element.id + '-textarea');
textarea.setAttribute('onchange', 'return cart_list_comment_save(\'' + catn + '\', this.parentElement)');
});
return false;
}
@ -209,11 +257,19 @@ function cart_list_comment_save(catn, element) {
let text = element.children[0].value;
// Обновление заголовка (предзагрузка)
if (text.trim() == '') {
element.innerHTML = 'Комментарий к заказу';
} else {
element.innerHTML = text;
}
// Деинициализация счетчика
document.getElementById(element.id + '-textarea-counter').remove();
// Запись аттрибута (предзагрузка)
element.setAttribute('onclick', 'return cart_list_comment_edit(\'' + catn + '\', this);');
$.ajax({
url: '/cart/' + catn + '/edit/comm',
type: 'post',
@ -224,7 +280,7 @@ function cart_list_comment_save(catn, element) {
},
success: function (data, status) {
// Заголовок
if (data.comm !== undefined && element !== null && element !== undefined) {
if (data.comm !== undefined) {
// Обновление заголовка
element.innerHTML = data.comm;

View File

@ -174,23 +174,3 @@ function page_profile_response(data, status) {
$('meta[name=csrf-token]').prop("content", data._csrf);
}
}
// Сокрытие первого элемента <option> в списке
function initDropdownImportSectionsOem() {
let dropdown = document.getElementById('account-opts-import_sections_oem');
if (dropdown !== null && dropdown.length > 1) {
dropdown.children[0].hidden = true;
}
}
// Сокрытие первого элемента <option> в списке
function initDropdownAccountSectionsCity() {
let dropdown = document.getElementById('account-opts-account_sections_city');
if (dropdown !== null && dropdown.length > 1) {
dropdown.children[0].hidden = true;
}
}
initDropdownImportSectionsOem();
initDropdownAccountSectionsCity();

View File

@ -0,0 +1,12 @@
// Сокрытие первого элемента <option> в списке
function initDropdown(id) {
let dropdown = document.getElementById(id);
if (dropdown !== null && dropdown.length > 1) {
dropdown.children[0].hidden = true;
}
}
initDropdown('account-opts-import_sections_oem');
initDropdown('account-opts-delivery_from_terminal');
initDropdown('account-opts-delivery_to_terminal');

View File

@ -0,0 +1,40 @@
function initTextarea(textarea_id, counter_current_id, counter_maximum_id, disable_callable, enable_callable) {
$(textarea_id).on('change keyup paste', function () {
characterCount = $(this).val().length;
current = $(counter_current_id);
maximum = $(counter_maximum_id);
current.text(characterCount);
if (characterCount < 70) {
current.css('color', '#343a40');
}
if (characterCount > 160 && characterCount < 179) {
current.css('color', '#600000');
}
if (characterCount > 180 && characterCount < 209) {
current.css('color', '#700000');
}
if (characterCount > 210 && characterCount < 249) {
current.css('color', '#c00');
}
if (characterCount > 250 && characterCount < 299) {
current.css('color', '#d00');
}
if (characterCount > 300) {
disable_callable();
if (characterCount < 999) {
current.css('color', '#e00');
maximum.css('color', '#e00');
current.css('color', '#e00');
} else {
maximum.css('color', 'rgb(210, 0, 0)');
}
} else {
maximum.css('color', '#343a40');
enable_callable();
}
});
}