diff --git a/mirzaev/skillparts/system/config/web.php.example b/mirzaev/skillparts/system/config/web.php.example index 2d23fc2..0628606 100644 --- a/mirzaev/skillparts/system/config/web.php.example +++ b/mirzaev/skillparts/system/config/web.php.example @@ -77,8 +77,11 @@ $config = [ 'controller' => 'main' ], 'product/' => 'product/index', - '///' => '
/-', - 'orders' => 'order/index' + '///' => '
/-', + 'orders' => 'order/index', + 'orders/<_key:[^/]+>/' => 'order/', + 'orders/supply/<_key:[^/]+>/' => 'order/supply-', + 'orders/supply/<_key:[^/]+>//' => 'order/supply--' ], ], diff --git a/mirzaev/skillparts/system/controllers/OrderController.php b/mirzaev/skillparts/system/controllers/OrderController.php index 324d87e..e431ac6 100644 --- a/mirzaev/skillparts/system/controllers/OrderController.php +++ b/mirzaev/skillparts/system/controllers/OrderController.php @@ -11,9 +11,16 @@ use yii\web\Response; use yii\web\Cookie; use app\models\Order; +use app\models\Account; +use app\models\Product; +use app\models\OrderEdgeSupply; use app\models\AccountEdgeOrder; +use app\models\connection\Dellin; use app\models\Notification; +use app\models\SupplyEdgeProduct; + use Codeception\PHPUnit\ResultPrinter\HTML; + use Exception; class OrderController extends Controller @@ -27,7 +34,7 @@ class OrderController extends Controller [ 'allow' => true, 'roles' => ['@'], - 'actions' => ['index', 'write', 'delete', 'amount-update', 'pay'] + 'actions' => ['index', 'accept', 'read', 'write', 'delete', 'amount-update', 'pay', 'supply-read', 'supply-write-stts'] ], [ 'allow' => false, @@ -78,6 +85,7 @@ class OrderController extends Controller if (yii::$app->request->isPost) { // POST-запрос + // Настройка yii::$app->response->format = Response::FORMAT_JSON; return [ @@ -91,6 +99,47 @@ class OrderController extends Controller return $this->render('/orders/index', compact('orders', 'moderator_orders')); } + /** + * Подтверждение заказа + * + * @param int $_key Ключ записи в коллекции order + * + * @return string|array|null + */ + public function actionAccept(int $_key): string|array|null + { + // Инициализация + $buffer = []; + $account_edge_order = AccountEdgeOrder::searchByOrder(Order::collectionName() . '/' . $_key, limit: 1)[0]; + + // Запись в буфер записи в базу данных + $account_edge_order->type = 'accepted'; + + // Отправка изменений в базу данных + if ($account_edge_order->save()) { + // Удалось сохранить изменения + + // Инициализация + $orders = Order::search(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}'); + $moderator_orders = self::genOrdersForModeration(); + + // Запись в буфер вывода + $buffer['main'] = $this->renderPartial('/orders/index', compact('orders', 'moderator_orders')); + } else { + // Не удалось сохранить изменения + + yii::$app->response->statusCode = 500; + } + + // Запись обязательных параметров + $buffer['_csrf'] = yii::$app->request->getCsrfToken(); + + // Настройка ответа + yii::$app->response->format = Response::FORMAT_JSON; + + return $buffer; + } + /** * Запись */ @@ -355,7 +404,8 @@ class OrderController extends Controller * * @return array ['order' => array, 'order_edge_account' => array, 'supplies' => array] */ - protected static function genOrdersForModeration(int $page = 1): array { + protected static function genOrdersForModeration(int $page = 1): array + { $orders = Order::search(account: '@all', type: 'requested', limit: 10, page: 1, select: '{account_edge_order, order}'); foreach ($orders as &$order) { @@ -366,4 +416,101 @@ class OrderController extends Controller return $orders; } + + /** + * Чтение инстанции поставки в заказе (order_edge_supply) + * + * @param int $_key Ключ записи в коллекции order_edge_supply + * + * @return string|array|null + */ + public function actionSupplyRead(int $_key): string|array|null + { + // Инициализация + $buffer = []; + + if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $_key)) { + // Удалось найти инстанцию поставки + + // Инициализация ребра: ПОСТАВКА -> ТОВАР + $supply_edge_product = SupplyEdgeProduct::searchBySupplyId($order_edge_supply->_to); + + // // Поиск ребра до аккаунта + // $account = Account::searchBySupplyId($order_edge_supply->_to); + + // // Поиск привязанного товара + // $product = Product::searchBySupplyId($order_edge_supply->_to); + + // try { + // // Инициализация доставки + // $delivery = Dellin::calcDeliveryAdvanced( + // explode('_', $account['opts']['delivery_from_terminal'])[1], + // explode('_', yii::$app->user->identity->opts['delivery_to_terminal'])[1], + // (int) ($product['wght'] ?? 0), + // (int) ($product['dmns']['x'] ?? 0), + // (int) ($product['dmns']['y'] ?? 0), + // (int) ($product['dmns']['z'] ?? 0) + // ); + // } catch (Exception $e) { + // // var_dump(json_decode($e->getMessage(), true)['errors']); die; + // } + + // Запись параметров + $buffer['cost'] = $order_edge_supply->cost ?? $order_edge_supply->cost = $supply_edge_product[0]['onec']['Цены']['Цена']['ЦенаЗаЕдиницу']; + $buffer['time'] = $order_edge_supply->time ?? 0; + // $buffer['time'] = $order_edge_supply->time ?? $delivery ?? 0; + $buffer['comm'] = $order_edge_supply->comm ?? $order_edge_supply->comm = 'Комментарий к заказу'; + $buffer['stts'] = $order_edge_supply->stts ?? $order_edge_supply->stts = 0; + + $order_edge_supply->save(); + } + + // Запись обязательных параметров + $buffer['_csrf'] = yii::$app->request->getCsrfToken(); + + // Настройка ответа + yii::$app->response->format = Response::FORMAT_JSON; + + return $buffer; + } + + /** + * Чтение инстанции поставки в заказе (order_edge_supply) + * + * @param int $_key Ключ записи в коллекции order_edge_supply + * + * @return string|array|null + */ + public function actionSupplyWriteStts(int $_key): string|array|null + { + // Инициализация + $stts = yii::$app->request->post('stts') ?? yii::$app->request->get('stts'); + $buffer = []; + + if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $_key)) { + // Удалось найти инстанцию поставки + + // Запись в буфер вывода и буфер записи в базу данных + $buffer['stts'] = $order_edge_supply->stts = $stts; + + // Отправка в базу данных + if ($order_edge_supply->save()) { + // Удалось сохранить изменения + + + } else { + // Не удалось сохранить изменения + + yii::$app->response->statusCode = 500; + } + } + + // Запись обязательных параметров + $buffer['_csrf'] = yii::$app->request->getCsrfToken(); + + // Настройка ответа + yii::$app->response->format = Response::FORMAT_JSON; + + return $buffer; + } } diff --git a/mirzaev/skillparts/system/models/AccountEdgeOrder.php b/mirzaev/skillparts/system/models/AccountEdgeOrder.php index ef138d5..8840e58 100644 --- a/mirzaev/skillparts/system/models/AccountEdgeOrder.php +++ b/mirzaev/skillparts/system/models/AccountEdgeOrder.php @@ -10,4 +10,17 @@ class AccountEdgeOrder extends Edge { return 'account_edge_order'; } + + /** + * Поиск по идентификатору заказа + * + * @param string $order_id Идентификатор записи заказа в базе данных + * @param int $limit Ограничение + * + * @return array|null + */ + public static function searchByOrder(string $order_id, int $limit = 1): ?array + { + return self::find()->where(['_to' => $order_id])->limit($limit)->all(); + } } diff --git a/mirzaev/skillparts/system/models/OrderEdgeSupply.php b/mirzaev/skillparts/system/models/OrderEdgeSupply.php index ffc174c..b0c896c 100644 --- a/mirzaev/skillparts/system/models/OrderEdgeSupply.php +++ b/mirzaev/skillparts/system/models/OrderEdgeSupply.php @@ -23,7 +23,10 @@ class OrderEdgeSupply extends Edge return array_merge( parent::attributes(), [ - 'comm' + 'comm', + 'cost', + 'time', + 'stts' ] ); } @@ -36,7 +39,10 @@ class OrderEdgeSupply extends Edge return array_merge( parent::attributeLabels(), [ - 'comm' => 'Комментарий к заказу' + 'comm' => 'Комментарий', + 'cost' => 'Цена', + 'time' => 'Время', + 'stts' => 'Статус' ] ); } @@ -50,12 +56,26 @@ class OrderEdgeSupply extends Edge parent::rules(), [ [ - [ - 'comm' - ], + 'comm', 'string', 'length' => [0, 300], 'message' => '{attribute} должен быть строкой от 0 до 300 символов' + ], + [ + 'stts', + 'string', + 'length' => [0, 15], + 'message' => '{attribute} должен быть строкой от 0 до 15 символов' + ], + [ + 'cost', + 'integer', + 'message' => '{attribute} должна быть числом' + ], + [ + 'time', + 'integer', + 'message' => '{attribute} должно быть числом' ] ] ); diff --git a/mirzaev/skillparts/system/models/SupplyEdgeProduct.php b/mirzaev/skillparts/system/models/SupplyEdgeProduct.php index f93801f..eeba9c5 100644 --- a/mirzaev/skillparts/system/models/SupplyEdgeProduct.php +++ b/mirzaev/skillparts/system/models/SupplyEdgeProduct.php @@ -69,6 +69,11 @@ class SupplyEdgeProduct extends Edge implements OfferInterface return self::findOne([self::getIdFieldName1c() => $ocid]); } + public static function searchBySupplyId(string $_id, int $limit = 1): array + { + return self::find()->where(['_from' => $_id])->limit($limit)->all(); + } + /** * Название поля в котором хранится ID из 1C */ diff --git a/mirzaev/skillparts/system/views/orders/index.php b/mirzaev/skillparts/system/views/orders/index.php index 9a8b694..f7e435c 100644 --- a/mirzaev/skillparts/system/views/orders/index.php +++ b/mirzaev/skillparts/system/views/orders/index.php @@ -40,13 +40,8 @@ if ( - - -
+
-
-
+
+
- + -

+

+ + + +

@@ -134,10 +133,10 @@ if (
-
+

Выберите поставку

-
+

Статус:

- Здесь будет информация об общей цене и о максимальном сроке доставки которые будут меняться по мере настройки и подтверждения наличия поставок - Подтвердить + Подтвердить
+
-
diff --git a/mirzaev/skillparts/system/web/js/cart.js b/mirzaev/skillparts/system/web/js/cart.js index f38e6e0..cd40168 100644 --- a/mirzaev/skillparts/system/web/js/cart.js +++ b/mirzaev/skillparts/system/web/js/cart.js @@ -269,7 +269,6 @@ function cart_list_comment_save(catn, element) { // Запись аттрибута (предзагрузка) element.setAttribute('onclick', 'return cart_list_comment_edit(\'' + catn + '\', this);'); - $.ajax({ url: '/cart/' + catn + '/edit/comm', type: 'post', diff --git a/mirzaev/skillparts/system/web/js/orders_panel.js b/mirzaev/skillparts/system/web/js/orders_panel.js index a9ddc0a..f6b40df 100644 --- a/mirzaev/skillparts/system/web/js/orders_panel.js +++ b/mirzaev/skillparts/system/web/js/orders_panel.js @@ -1,13 +1,60 @@ -function orders_supply_edit(target, order_number) { +function order_init(order_key) { + // Инициализация панели + let panel = document.getElementById(order_key + '_panel'); + + // Инициализация кнопки + let button = document.getElementById(order_key + '_button'); + + let supplies_are_confirmed = true; + + for (let i = 0; i <= panel.children[2].children[0].children.length - 1; i++) { + // Инициализация + let target = panel.children[2].children[0].children[i]; + + console.log(i); + + if ((target === undefined || target.children[1] === undefined || target.children[1].children[0] === undefined) && !target.classList.contains('dropdown-divider')) { + + supplies_are_confirmed = false; + } + } + + if (supplies_are_confirmed) { + + button.classList.remove('disabled'); + } + + return false; +} + +function order_accept(order_key) { + $.ajax({ + url: 'orders/' + order_key + '/accept', + type: 'post', + dataType: 'json', + data: { + '_csrf': yii.getCsrfToken() + }, + success: orders_response_success, + error: orders_response_error + }); + + return false; +} + +function orders_supply_edit(supply_key, order_key) { + // Инициализация + let supply = document.getElementById(supply_key + '_supply'); + // Поиск панели для вывода информации - let panel = document.getElementById('orders_panel_edit_' + order_number); + let panel = document.getElementById('orders_panel_edit_' + order_key); // Поиск всех кнопок с поставками let rows = document.getElementsByClassName('row_supply'); // Деактивация остальных кнопок for (let i = 0; i < rows.length; i++) { - if (rows[i].parentElement.parentElement.getAttribute('id') === 'orders_panel_supplies_' + order_number) { + if (rows[i].parentElement.getAttribute('id') === 'orders_panel_supplies_' + order_key) { // Если это кнопка конкретно с этого заказа rows[i].classList.remove('row_supply_active'); @@ -15,9 +62,204 @@ function orders_supply_edit(target, order_number) { } // Активация выбранной кнопки - target.classList.add('row_supply_active'); + supply.classList.add('row_supply_active'); - panel.innerHTML = target.getAttribute('id'); + // Запись индикатора загрузки + panel.innerHTML = '

Загрузка

'; - return false + $.ajax({ + url: 'orders/supply/' + supply_key + '/read', + type: 'post', + dataType: 'json', + data: { + '_csrf': yii.getCsrfToken() + }, + success: function (data, status) { + // Удаление индикатора загрузки + panel.innerHTML = ''; + + // Цена + if (document.getElementById(supply.getAttribute('id') + '_cost') === null) { + // Инициализация контейнера + let container = document.createElement('div'); + container.setAttribute('id', supply.getAttribute('id') + '_cost'); + container.setAttribute('class', 'row mb-3 px-3'); + + // Инициализация названия + let name = document.createElement('p'); + name.setAttribute('id', supply.getAttribute('id') + '_cost_name'); + name.setAttribute('class', 'col-2 text-center'); + name.innerText = 'Цена'; + + // Инициализация поля + let input = document.createElement('input'); + input.setAttribute('id', supply.getAttribute('id') + '_cost_input'); + input.setAttribute('class', 'col-10 form-control'); + input.setAttribute('type', 'number'); + if (data.cost !== undefined) { + input.setAttribute('value', data.cost); + } else { + input.setAttribute('value', 0); + } + input.setAttribute('aria-invalid', 'false'); + + // Запись в документ + panel.appendChild(container); + container.appendChild(name); + container.appendChild(input); + }; + + // Время доставки + if (document.getElementById(supply.getAttribute('id') + '_time') === null) { + // Инициализация контейнера + let container = document.createElement('div'); + container.setAttribute('id', supply.getAttribute('id') + '_time'); + container.setAttribute('class', 'row mb-3 px-3'); + + // Инициализация названия + let name = document.createElement('p'); + name.setAttribute('id', supply.getAttribute('id') + '_time_name'); + name.setAttribute('class', 'col-2 text-center'); + name.innerText = 'Время'; + + // Инициализация поля + let input = document.createElement('input'); + input.setAttribute('id', supply.getAttribute('id') + '_time_input'); + input.setAttribute('class', 'col-10 form-control'); + input.setAttribute('type', 'number'); + if (data.time !== undefined) { + input.setAttribute('value', data.time); + } else { + input.setAttribute('value', 0); + } + input.setAttribute('aria-invalid', 'false'); + + // Запись в документ + panel.appendChild(container); + container.appendChild(name); + container.appendChild(input); + }; + + // Комментарий + if (document.getElementById(supply.getAttribute('id') + '_comm') === null) { + // Инициализация контейнера + let container = document.createElement('div'); + container.setAttribute('id', supply.getAttribute('id') + '_comm'); + container.setAttribute('class', 'row mb-3 px-3'); + + // Инициализация поля + let textarea = document.createElement('textarea'); + textarea.setAttribute('id', supply.getAttribute('id') + '_comm_input'); + textarea.setAttribute('class', 'col-12 form-control'); + textarea.setAttribute('cols', '50'); + textarea.setAttribute('rows', '3'); + if (data.comm === undefined) { + textarea.innerText = 'Комментарий к заказу'; + } else { + textarea.innerText = data.comm; + } + + // Запись в документ + panel.appendChild(container); + container.appendChild(textarea); + }; + + // Статус подтверждения + if (document.getElementById(supply.getAttribute('id') + '_stts') === null) { + // Инициализация контейнера + let container = document.createElement('div'); + container.setAttribute('id', supply.getAttribute('id') + '_stts'); + container.setAttribute('class', 'row px-3'); + + // Инициализация индикатора + let span = document.createElement('span'); + span.setAttribute('id', supply.getAttribute('id') + '_stts_indicator_icon'); + span.setAttribute('class', 'ml-auto my-auto fas fa-check'); + + // Инициализация кнопки + let button = document.createElement('a'); + button.setAttribute('id', supply.getAttribute('id') + '_stts_button'); + button.setAttribute('type', 'button'); + button.setAttribute('role', 'button'); + button.setAttribute('onclick', 'return orders_supply_comm_write(this, \'' + supply_key + '\', \'' + order_key + '\');'); + if (data.stts === undefined || data.stts == 0) { + button.setAttribute('class', 'col-12 btn button_blue button_clean'); + button.innerText = 'Подтвердить'; + } else { + button.setAttribute('class', 'col-12 btn button_blue button_clean disabled'); + button.innerText = 'Подтверждено'; + + // Инициализация + let title = document.getElementById(supply.getAttribute('id') + '_stts_indicator'); + + console.log(title.children[0]); + + if (title.children[0] === undefined) { + // Индикатор не найден + + // Запись индикатора + title.appendChild(span); + } + } + + // Запись в документ + panel.appendChild(container); + container.appendChild(button); + + // Реинициализация + order_init(order_key); + }; + + orders_response_success(data, status); + }, + error: orders_response_error + }); + + return false; +} + +function orders_supply_comm_write(button, supply_key, order_key) { + // Инициализация + let supply = document.getElementById(supply_key + '_supply'); + + $.ajax({ + url: 'orders/supply/' + supply_key + '/write/stts', + type: 'post', + dataType: 'json', + data: { + '_csrf': yii.getCsrfToken(), + 'stts': 1 + }, + success: function (data, status) { + // Инициализация индикатора + let span = document.createElement('span'); + span.setAttribute('id', supply.getAttribute('id') + '_stts_indicator_icon'); + span.setAttribute('class', 'ml-auto my-auto fas fa-check'); + + if (data.stts === undefined || data.stts == 0) { + button.setAttribute('class', 'col-12 btn button_blue button_clean'); + button.innerText = 'Подтвердить'; + } else { + button.setAttribute('class', 'col-12 btn button_blue button_clean disabled'); + button.innerText = 'Подтверждено'; + + // Инициализация + let title = document.getElementById(supply.getAttribute('id') + '_stts_indicator'); + + if (title.children[0] === undefined) { + // Индикатор не найден + + // Запись индикатора + title.appendChild(span); + } + // Реинициализация + order_init(order_key); + } + + orders_response_success(data, status); + }, + error: orders_response_error + }); + + return false; }