Initial commit: apps.supersamsev.ru
This commit is contained in:
commit
54475e7d3d
17284 files changed
+98268
No files matched your search
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.3.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Middleware\ErrorHandlerMiddleware;
|
||||
use Cake\Http\BaseApplication;
|
||||
use Cake\Routing\Middleware\AssetMiddleware;
|
||||
use Cake\Routing\Middleware\RoutingMiddleware;
|
||||
|
||||
/**
|
||||
* Application setup class.
|
||||
*
|
||||
* This defines the bootstrapping logic and middleware layers you
|
||||
* want to use in your application.
|
||||
*/
|
||||
class Application extends BaseApplication
|
||||
{
|
||||
/**
|
||||
* Setup the middleware queue your application will use.
|
||||
*
|
||||
* @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
|
||||
* @return \Cake\Http\MiddlewareQueue The updated middleware queue.
|
||||
*/
|
||||
public function middleware($middlewareQueue)
|
||||
{
|
||||
$middlewareQueue
|
||||
// Catch any exceptions in the lower layers,
|
||||
// and make an error page/response
|
||||
->add(ErrorHandlerMiddleware::class)
|
||||
|
||||
// Handle plugin/theme assets like CakePHP normally does.
|
||||
->add(AssetMiddleware::class)
|
||||
|
||||
// Add routing middleware.
|
||||
->add(new RoutingMiddleware($this));
|
||||
|
||||
return $middlewareQueue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App\Console;
|
||||
|
||||
if (!defined('STDIN')) {
|
||||
define('STDIN', fopen('php://stdin', 'r'));
|
||||
}
|
||||
|
||||
use Cake\Utility\Security;
|
||||
use Composer\Script\Event;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Provides installation hooks for when this application is installed via
|
||||
* composer. Customize this class to suit your needs.
|
||||
*/
|
||||
class Installer
|
||||
{
|
||||
|
||||
/**
|
||||
* An array of directories to be made writable
|
||||
*/
|
||||
const WRITABLE_DIRS = [
|
||||
'logs',
|
||||
'tmp',
|
||||
'tmp/cache',
|
||||
'tmp/cache/models',
|
||||
'tmp/cache/persistent',
|
||||
'tmp/cache/views',
|
||||
'tmp/sessions',
|
||||
'tmp/tests'
|
||||
];
|
||||
|
||||
/**
|
||||
* Does some routine installation tasks so people don't have to.
|
||||
*
|
||||
* @param \Composer\Script\Event $event The composer event object.
|
||||
* @throws \Exception Exception raised by validator.
|
||||
* @return void
|
||||
*/
|
||||
public static function postInstall(Event $event)
|
||||
{
|
||||
$io = $event->getIO();
|
||||
|
||||
$rootDir = dirname(dirname(__DIR__));
|
||||
|
||||
static::createAppConfig($rootDir, $io);
|
||||
static::createWritableDirectories($rootDir, $io);
|
||||
|
||||
// ask if the permissions should be changed
|
||||
if ($io->isInteractive()) {
|
||||
$validator = function ($arg) {
|
||||
if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
|
||||
return $arg;
|
||||
}
|
||||
throw new Exception('This is not a valid answer. Please choose Y or n.');
|
||||
};
|
||||
$setFolderPermissions = $io->askAndValidate(
|
||||
'<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ',
|
||||
$validator,
|
||||
10,
|
||||
'Y'
|
||||
);
|
||||
|
||||
if (in_array($setFolderPermissions, ['Y', 'y'])) {
|
||||
static::setFolderPermissions($rootDir, $io);
|
||||
}
|
||||
} else {
|
||||
static::setFolderPermissions($rootDir, $io);
|
||||
}
|
||||
|
||||
static::setSecuritySalt($rootDir, $io);
|
||||
|
||||
if (class_exists('\Cake\Codeception\Console\Installer')) {
|
||||
\Cake\Codeception\Console\Installer::customizeCodeceptionBinary($event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the config/app.php file if it does not exist.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function createAppConfig($dir, $io)
|
||||
{
|
||||
$appConfig = $dir . '/config/app.php';
|
||||
$defaultConfig = $dir . '/config/app.default.php';
|
||||
if (!file_exists($appConfig)) {
|
||||
copy($defaultConfig, $appConfig);
|
||||
$io->write('Created `config/app.php` file');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the `logs` and `tmp` directories.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function createWritableDirectories($dir, $io)
|
||||
{
|
||||
foreach (static::WRITABLE_DIRS as $path) {
|
||||
$path = $dir . '/' . $path;
|
||||
if (!file_exists($path)) {
|
||||
mkdir($path);
|
||||
$io->write('Created `' . $path . '` directory');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set globally writable permissions on the "tmp" and "logs" directory.
|
||||
*
|
||||
* This is not the most secure default, but it gets people up and running quickly.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function setFolderPermissions($dir, $io)
|
||||
{
|
||||
// Change the permissions on a path and output the results.
|
||||
$changePerms = function ($path, $perms, $io) {
|
||||
// Get permission bits from stat(2) result.
|
||||
$currentPerms = fileperms($path) & 0777;
|
||||
if (($currentPerms & $perms) == $perms) {
|
||||
return;
|
||||
}
|
||||
|
||||
$res = chmod($path, $currentPerms | $perms);
|
||||
if ($res) {
|
||||
$io->write('Permissions set on ' . $path);
|
||||
} else {
|
||||
$io->write('Failed to set permissions on ' . $path);
|
||||
}
|
||||
};
|
||||
|
||||
$walker = function ($dir, $perms, $io) use (&$walker, $changePerms) {
|
||||
$files = array_diff(scandir($dir), ['.', '..']);
|
||||
foreach ($files as $file) {
|
||||
$path = $dir . '/' . $file;
|
||||
|
||||
if (!is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$changePerms($path, $perms, $io);
|
||||
$walker($path, $perms, $io);
|
||||
}
|
||||
};
|
||||
|
||||
$worldWritable = bindec('0000000111');
|
||||
$walker($dir . '/tmp', $worldWritable, $io);
|
||||
$changePerms($dir . '/tmp', $worldWritable, $io);
|
||||
$changePerms($dir . '/logs', $worldWritable, $io);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security.salt value in the application's config file.
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @return void
|
||||
*/
|
||||
public static function setSecuritySalt($dir, $io)
|
||||
{
|
||||
$newKey = hash('sha256', Security::randomBytes(64));
|
||||
static::setSecuritySaltInFile($dir, $io, $newKey, 'app.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security.salt value in a given file
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @param string $newKey key to set in the file
|
||||
* @param string $file A path to a file relative to the application's root
|
||||
* @return void
|
||||
*/
|
||||
public static function setSecuritySaltInFile($dir, $io, $newKey, $file)
|
||||
{
|
||||
$config = $dir . '/config/' . $file;
|
||||
$content = file_get_contents($config);
|
||||
|
||||
$content = str_replace('__SALT__', $newKey, $content, $count);
|
||||
|
||||
if ($count == 0) {
|
||||
$io->write('No Security.salt placeholder to replace.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$result = file_put_contents($config, $content);
|
||||
if ($result) {
|
||||
$io->write('Updated Security.salt value in config/' . $file);
|
||||
|
||||
return;
|
||||
}
|
||||
$io->write('Unable to update Security.salt value.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the APP_NAME value in a given file
|
||||
*
|
||||
* @param string $dir The application's root directory.
|
||||
* @param \Composer\IO\IOInterface $io IO interface to write to console.
|
||||
* @param string $appName app name to set in the file
|
||||
* @param string $file A path to a file relative to the application's root
|
||||
* @return void
|
||||
*/
|
||||
public static function setAppNameInFile($dir, $io, $appName, $file)
|
||||
{
|
||||
$config = $dir . '/config/' . $file;
|
||||
$content = file_get_contents($config);
|
||||
$content = str_replace('__APP_NAME__', $appName, $content, $count);
|
||||
|
||||
if ($count == 0) {
|
||||
$io->write('No __APP_NAME__ placeholder to replace.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$result = file_put_contents($config, $content);
|
||||
if ($result) {
|
||||
$io->write('Updated __APP_NAME__ value in config/' . $file);
|
||||
|
||||
return;
|
||||
}
|
||||
$io->write('Unable to update __APP_NAME__ value.');
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class CalcDoorsController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['display', 'calcDoors', 'calcDoorsPrint']);
|
||||
$this->viewBuilder()->setLayout('calc_doors');
|
||||
}
|
||||
|
||||
|
||||
public function display() {
|
||||
$savedOrderData = null;
|
||||
|
||||
if($encOrderId = $this->request->getQuery('oid')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('CutOrders')->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['params'] = @json_decode($savedOrderData['params'], true);
|
||||
$savedOrderData['created'] = date_timestamp_get(date_create($savedOrderData['created'])) * 1000;
|
||||
$savedOrderData['order_calc_results'] = @json_decode($savedOrderData['order_calc_results'], true);
|
||||
$savedOrderData['eOId'] = $encOrderId;
|
||||
|
||||
$savedOrderData['printOrderUrl'] = str_replace("/calc-doors", "/calc-doors-print", $savedOrderData['view_order_url']);
|
||||
unset($savedOrderData['view_order_url']);
|
||||
$this->set(compact('savedOrderData'));
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($savedOrderData)) {
|
||||
$this->redirect(['controller' => 'Cut', 'action' => 'display']);
|
||||
//temporary
|
||||
}
|
||||
|
||||
$this->set('jsConfig', $this->getAppJsConfig("calcDoors", false, $savedOrderData));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function calcDoors() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
ini_set('max_input_time', '0');
|
||||
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (!empty($data['selectedDoorData'])) {
|
||||
if (!isset($data['selectedDoorData']['params'])) {
|
||||
$data['selectedDoorData']['params'] = [];
|
||||
}
|
||||
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$additionalActionsAllowedIPs = explode("\n", $this->config['global']['additionalActionsAllowedIPs']['value']);
|
||||
$this->config['global']['additionalActionsAllowed'] = empty($additionalActionsAllowedIPs) || in_array($this->request->clientIP(), $additionalActionsAllowedIPs);
|
||||
|
||||
if(!empty($data['selectedDoorData']['eOId'])) {
|
||||
$encryptedOrderId = $data['selectedDoorData']['eOId'];
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('CutOrders')->decryptCustomData($encryptedOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$order = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$this->config['global']['additionalActionsAllowed'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->config['global']['additionalActionsAllowed'])) {
|
||||
$data['selectedDoorData']['params']['discount'] = 0;
|
||||
}
|
||||
|
||||
$result['selectedDoorData'] = $data['selectedDoorData'];
|
||||
if (!isset($result['selectedDoorData']['order_calc_results'])) {
|
||||
$result['selectedDoorData']['order_calc_results'] = [];
|
||||
}
|
||||
|
||||
if (!empty($data['selectedDoorData']['params']['doorId'])) {
|
||||
$configDoor = TableRegistry::getTableLocator()->get('CalcDoors')->find('all')->where([
|
||||
'id' => $data['selectedDoorData']['params']['doorId']
|
||||
])->first();
|
||||
|
||||
$doorPrices = [];
|
||||
$manufacturerPrices = [];
|
||||
$manufacturerLimits = [];
|
||||
|
||||
if (!empty($configDoor)) {
|
||||
$configDoor = $configDoor->toArray();
|
||||
$doorPrices = @json_decode($configDoor['params'], true);
|
||||
|
||||
$configManufacturer = TableRegistry::getTableLocator()->get('CalcDoorsSettings')->find('all')->where([
|
||||
'group' => 'prices_' . $configDoor['manufacturer_id']
|
||||
])->all()->toArray();
|
||||
|
||||
foreach($configManufacturer as $li) {
|
||||
$manufacturerPrices[$li['key']] = $li['value'];
|
||||
}
|
||||
|
||||
$configManufacturer = TableRegistry::getTableLocator()->get('CalcDoorsSettings')->find('all')->where([
|
||||
'group' => 'limits_' . $configDoor['manufacturer_id']
|
||||
])->all()->toArray();
|
||||
|
||||
foreach($configManufacturer as $li) {
|
||||
$manufacturerLimits[$li['key']] = $li['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$params = $data['selectedDoorData']['params'];
|
||||
$warnings = [];
|
||||
switch($configDoor['manufacturer_id']) {
|
||||
case "aristo":
|
||||
$width = isset($params['width']) ? (int)str_replace(",", ".", $params['width']) : 0;
|
||||
$height = isset($params['height']) ? (int)str_replace(",", ".", $params['height']) : 0;
|
||||
$doorsCount = isset($params['doorsCount']) ? (int)str_replace(",", ".", $params['doorsCount']) : 0;
|
||||
|
||||
if ($height > 0) {
|
||||
if ($height < $manufacturerLimits['minDoorHeight']) {
|
||||
$warnings[] = "Минимальная высота проёма - " . $manufacturerLimits['minDoorHeight'] . "мм";
|
||||
}
|
||||
|
||||
if (empty($doorPrices['profileVertHigherLimit']) && ($height > $doorPrices['profileVertHeight'])) {
|
||||
$warnings[] = "Проём не должен превышать высоту " . $doorPrices['profileVertHeight'] . "мм";
|
||||
} else {
|
||||
if ($height > $manufacturerLimits['maxDoorHeight']) {
|
||||
$warnings[] = "Проём не должен превышать высоту " . $manufacturerLimits['maxDoorHeight'] . "мм";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($width > 0) {
|
||||
if ($width < $manufacturerLimits['minDoorWidth']) {
|
||||
$warnings[] = "Минимальная ширина проёма - " . $manufacturerLimits['minDoorWidth'] . "мм";
|
||||
} else {
|
||||
if ($doorsCount > 0) {
|
||||
$widthPerDoor = $width / $doorsCount;
|
||||
|
||||
if ($widthPerDoor < $manufacturerLimits['minDoorWidth']) {
|
||||
$warnings[] = "Минимальная ширина двери - " . $manufacturerLimits['minDoorWidth'] . "мм";
|
||||
}
|
||||
|
||||
if ($widthPerDoor > $manufacturerLimits['maxDoorWidth']) {
|
||||
$warnings[] = "Максимальная ширина двери - " . $manufacturerLimits['maxDoorWidth'] . "мм, на такой проём ставится " . counterPluralForm(ceil($width / $manufacturerLimits['maxDoorWidth']), ["", "", ""], ["дверь", "двери", "дверей"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($data['orderEmailNotify']) && empty($data['printOnly'])) { //do not recount on email send or print
|
||||
$orderCalcResults = [];
|
||||
|
||||
switch($configDoor['manufacturer_id']) {
|
||||
case "aristo":
|
||||
if (empty($warnings)) {
|
||||
if ($doorsCount > 0) {
|
||||
$orderCalcResults['zerkalo'] = ($width * $height / 1000000) * 1.1;
|
||||
$orderCalcResults['plenka'] = ($width / 500) * ($height / 1000) * 1.22;
|
||||
$orderCalcResults['plenkaorakal'] = ($width * $height / 1000000);
|
||||
$orderCalcResults['steklo'] = ($width * $height / 1000000) * 1.1;
|
||||
|
||||
$orderCalcResults['zerkalo'] = toFixed2($orderCalcResults['zerkalo'] / $doorsCount) . "/" . toFixed2($orderCalcResults['zerkalo']);
|
||||
$orderCalcResults['plenka'] = toFixed2($orderCalcResults['plenka'] / $doorsCount) . "/" . toFixed2($orderCalcResults['plenka']);
|
||||
$orderCalcResults['uplotnitelPK80'] = toFixed2($height * 2 / 1000 + $width / $doorsCount / 1000 * 2) . "/" . toFixed2($height * 2 / 1000 + $width / 1000 * 2);
|
||||
|
||||
$orderCalcResults['plenkaorakal'] = toFixed2($orderCalcResults['plenkaorakal'] / $doorsCount) . "/" . toFixed2($orderCalcResults['plenkaorakal']);
|
||||
$orderCalcResults['steklo'] = toFixed2($orderCalcResults['steklo'] / $doorsCount) . "/" . toFixed2($orderCalcResults['steklo']);
|
||||
|
||||
$orderCalcResults['dsp10mm'] = ($widthPerDoor <= $manufacturerLimits['maxDoorWidth'] ? "0.5 листа" : "1 лист");
|
||||
}
|
||||
|
||||
$discount = isset($params['discount']) ? min((int)(str_replace(",", ".", $params['discount'])), 100) : 0;
|
||||
|
||||
$orderCalcResults['ramaSrednayaCount'] = isset($params['ramaSrednaya']) ? (float)str_replace(",", ".", $params['ramaSrednaya']) : 0;
|
||||
|
||||
$orderCalcResults['zagimDlyaShlegelyaCount'] = isset($params['zagimDlyaShlegelya']) ? (float)str_replace(",", ".", $params['zagimDlyaShlegelya']) : 0;
|
||||
$orderCalcResults['uplotnitelPK80Count'] = isset($params['uplotnitelPK80']) ? (float)str_replace(",", ".", $params['uplotnitelPK80']) : 0;
|
||||
|
||||
$orderCalcResults['zerkaloSerebroCount'] = isset($params['zerkaloSerebroCount']) ? (float)str_replace(",", ".", $params['zerkaloSerebroCount']) : 0; //round($height * $width / 1000000*1.1 ,2);
|
||||
$orderCalcResults['plenkaBezopasnostiZerkalCount'] = isset($params['plenkaBezopasnostiZerkalCount']) ? (float)str_replace(",", ".", $params['plenkaBezopasnostiZerkalCount']) : 0;
|
||||
//isset($_POST['dsp10mm']) ? (float) stripslashes(htmlspecialchars($_POST['dsp10mm'])) : 0;
|
||||
$orderCalcResults['dsp10mmCount'] = isset($params['dsp10mm']) ? (float)str_replace(",", ".", $params['dsp10mm']) : 0;
|
||||
$orderCalcResults['plenkaOrakalCount'] = isset($params['plenkaOrakalCount']) ? (float)str_replace(",", ".", $params['plenkaOrakalCount']) : 0;
|
||||
$orderCalcResults['StekloCount'] = isset($params['StekloCount']) ? (float)str_replace(",", ".", $params['StekloCount']) : 0;
|
||||
|
||||
$orderCalcResults['price'] = 0;
|
||||
$orderCalcResults['profilePrice'] = 0;
|
||||
|
||||
$orderCalcResults['profileVertCount'] = $doorsCount * 2;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['profileVertPrice'] = $orderCalcResults['profileVertCount'] * (($height > $doorPrices['profileVertHeight']) && !empty($doorPrices['profileVertHigherLimit']) ? $doorPrices['profileVertHigherLimit'] : $doorPrices['profileVertBelowLimit']);
|
||||
|
||||
$orderCalcResults['napravlyaushayaVerhCount'] = $width / 1000;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['napravlyaushayaVerhPrice'] = $orderCalcResults['napravlyaushayaVerhCount'] * $doorPrices['napravlyaushayaVerh'] / 5.4;
|
||||
|
||||
$orderCalcResults['napravlyaushayaNizCount'] = $width / 1000;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['napravlyaushayaNizPrice'] = $orderCalcResults['napravlyaushayaNizCount'] * $doorPrices['napravlyaushayaNiz'] / 5.4;
|
||||
|
||||
$orderCalcResults['ramaGorizontNizCount'] = $width / 1000 * 1.1;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['ramaGorizontNizPrice'] = $orderCalcResults['ramaGorizontNizCount'] * $doorPrices['ramaGorizontNiz'] / 5.4;
|
||||
|
||||
$orderCalcResults['ramaGorizontVerhCount'] = $width / 1000 * 1.1;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['ramaGorizontVerhPrice'] = $orderCalcResults['ramaGorizontVerhCount'] * $doorPrices['ramaGorizontVerh'] / 5.4;
|
||||
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['ramaSrednayaPrice'] = $orderCalcResults['ramaSrednayaCount'] * $doorPrices['ramaSrednaya'] / 5.4;
|
||||
|
||||
$orderCalcResults['komplektRolikovCount'] = $doorsCount;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['komplektRolikovPrice'] = $orderCalcResults['komplektRolikovCount'] * $manufacturerPrices['komplektRolikov'];
|
||||
|
||||
$orderCalcResults['stoporCount'] = $doorsCount;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['stoporPrice'] = $orderCalcResults['stoporCount'] * $manufacturerPrices['stopor'];
|
||||
|
||||
$orderCalcResults['shlegelCount'] = $height * 4 / 1000;
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['shlegelPrice'] = $orderCalcResults['shlegelCount'] * $manufacturerPrices['shlegel'];
|
||||
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['zagimDlyaShlegelyaPrice'] = $orderCalcResults['zagimDlyaShlegelyaCount'] * $manufacturerPrices['zagimDlyaShlegelya'];
|
||||
$orderCalcResults['profilePrice'] += $orderCalcResults['uplotnitelPK80Price'] = $orderCalcResults['uplotnitelPK80Count'] * $manufacturerPrices['uplotnitelPK80'];
|
||||
$orderCalcResults['profilePrice'] = $orderCalcResults['profilePrice'] - $orderCalcResults['profilePrice'] * $discount / 100;
|
||||
$orderCalcResults['price'] += $orderCalcResults['profilePrice'];
|
||||
|
||||
|
||||
$orderCalcResults['napolneniePrice'] = 0;
|
||||
$orderCalcResults['napolneniePrice'] += $orderCalcResults['zerkaloSerebroPrice'] = $orderCalcResults['zerkaloSerebroCount'] * $manufacturerPrices['zerkaloSerebro'];
|
||||
$orderCalcResults['napolneniePrice'] += $orderCalcResults['plenkaBezopasnostiZerkalPrice'] = $orderCalcResults['plenkaBezopasnostiZerkalCount'] * $manufacturerPrices['plenkaBezopasnostiZerkal'];
|
||||
$orderCalcResults['napolneniePrice'] += $orderCalcResults['dsp10mmPrice'] = $orderCalcResults['dsp10mmCount'] * $manufacturerPrices['dsp10mm'];
|
||||
$orderCalcResults['napolneniePrice'] += $orderCalcResults['plenkaOrakalPrice'] = $orderCalcResults['plenkaOrakalCount'] * $manufacturerPrices['plenkaOrakal'];
|
||||
$orderCalcResults['napolneniePrice'] += $orderCalcResults['StekloPrice'] = $orderCalcResults['StekloCount'] * $manufacturerPrices['Steklo'];
|
||||
$orderCalcResults['price'] += $orderCalcResults['napolneniePrice'];
|
||||
|
||||
$orderCalcResults['sborkeDveriCount'] = $doorsCount;
|
||||
$orderCalcResults['sverlenieOtverstiyNaDverCount'] = isset($params['sverlenieOtverstiyNaDver']) ? (float)str_replace(",", ".", $params['sverlenieOtverstiyNaDver']) : 0;
|
||||
$orderCalcResults['rabotaSlognayaRamkaPramayaCount'] = isset($params['rabotaSlognayaRamkaPramaya']) ? (float)str_replace(",", ".", $params['rabotaSlognayaRamkaPramaya']) : 0;
|
||||
$orderCalcResults['rabotaSlognayaRamkaKosayaCount'] = isset($params['rabotaSlognayaRamkaKosaya']) ? (float)str_replace(",", ".", $params['rabotaSlognayaRamkaKosaya']) : 0;
|
||||
$orderCalcResults['rabotaSlognayaRamkaZigzagCount'] = isset($params['rabotaSlognayaRamkaZigzag']) ? (float)str_replace(",", ".", $params['rabotaSlognayaRamkaZigzag']) : 0;
|
||||
|
||||
$orderCalcResults['porezkaMaterialaCount'] = 1;
|
||||
$orderCalcResults['porezkaMaterialaPercent'] = 5;
|
||||
$orderCalcResults['porezkaMaterialaPrice'] = ($orderCalcResults['profilePrice'] + $orderCalcResults['napolneniePrice']) * $orderCalcResults['porezkaMaterialaPercent'] / 100; //5%
|
||||
|
||||
|
||||
$orderCalcResults['peremichkiCount'] = isset($params['peremichki']) ? (float)str_replace(",", ".", $params['peremichki']) : 0;
|
||||
$orderCalcResults['rabotaSlognayaCount'] = $width / ($doorsCount > 0 ? $doorsCount : 1) * $orderCalcResults['peremichkiCount'] / 1000;
|
||||
$orderCalcResults['rabotaPrice'] = 0;
|
||||
$orderCalcResults['rabotaPrice'] += $orderCalcResults['sborkeDveriPrice'] = $orderCalcResults['sborkeDveriCount'] * $manufacturerPrices['sborkeDveri'];
|
||||
$orderCalcResults['rabotaPrice'] += $orderCalcResults['porezkaMaterialaTotalPrice'] = $orderCalcResults['porezkaMaterialaCount'] * $orderCalcResults['porezkaMaterialaPrice'];
|
||||
$orderCalcResults['rabotaPrice'] += $orderCalcResults['sverlenieOtverstiyNaDverPrice'] = $orderCalcResults['sverlenieOtverstiyNaDverCount'] * $manufacturerPrices['sverlenieOtverstiyNaDver'];
|
||||
$orderCalcResults['rabotaPrice'] += $orderCalcResults['rabotaSlognayaPrice'] = $orderCalcResults['rabotaSlognayaCount'] * $manufacturerPrices['rabotaSlognaya'];
|
||||
$orderCalcResults['price'] += $orderCalcResults['rabotaPrice'];
|
||||
|
||||
$orderCalcResults['price'] = toFixed2Price($orderCalcResults['price']);
|
||||
$orderCalcResults['rabotaPrice'] = toFixed2($orderCalcResults['rabotaPrice']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$result['selectedDoorData']['order_calc_results'] = $orderCalcResults;
|
||||
} else {
|
||||
$result['selectedDoorData']['order_calc_results'] = $data['selectedDoorData']['order_calc_results'];
|
||||
}
|
||||
|
||||
if (isset($result['selectedDoorData']['params']['width']) && empty($result['selectedDoorData']['params']['width'])) {
|
||||
$result['selectedDoorData']['params']['width'] = "";
|
||||
}
|
||||
|
||||
if (isset($result['selectedDoorData']['params']['height']) && empty($result['selectedDoorData']['params']['height'])) {
|
||||
$result['selectedDoorData']['params']['height'] = "";
|
||||
}
|
||||
|
||||
$result['status'] = 'success';
|
||||
$result['warnings'] = $warnings;
|
||||
|
||||
|
||||
if (empty($warnings)) {
|
||||
if (!empty($data['orderEmailNotify']) || !empty($data['printOnly'])) {
|
||||
$sendOrderEmailNotify = true;
|
||||
|
||||
if (!empty($data['branchId']) && ($data['branchId'] == "printOnly")) { //send print notify only from allowed ips, hide button for others
|
||||
if (empty($this->config['global']['additionalActionsAllowed'])) {
|
||||
$sendOrderEmailNotify = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sendOrderEmailNotify) {
|
||||
$authUserId = $this->Auth->user('id');
|
||||
$authUserId = (!empty($authUserId) ? $authUserId : null);
|
||||
|
||||
$data['selectedDoorData'] = $result['selectedDoorData'];
|
||||
$orderEmailNotifySentResults = $ordersTable->orderEmailNotify($data, $this->config, $this->request->clientIP(), $authUserId, $configDoor);
|
||||
|
||||
$result['orderEmailNotifySent'] = $orderEmailNotifySentResults['orderEmailNotifySent'];
|
||||
$result['printOrderUrl'] = $orderEmailNotifySentResults['printOrderUrl'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result['message'] = 'Не выбран производитель и цвет дверей.';
|
||||
}
|
||||
} else {
|
||||
$result['message'] = 'Нет данных.';
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['message'] = 'Нет данных.';
|
||||
}
|
||||
|
||||
echo json_encode($result);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function calcDoorsPrint() {
|
||||
$isOrderFound = false;
|
||||
|
||||
if($encOrderId = $this->request->getQuery('oid')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('CutOrders')->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$orderFileName = $savedOrderData->order_num . '.zip';
|
||||
$orderFileDir = ROOT . '/files/calc_doors_orders/';
|
||||
|
||||
if (!is_dir($orderFileDir) || !file_exists($orderFileDir.$orderFileName)) {
|
||||
} else {
|
||||
$zip = new \ZipArchive;
|
||||
if ($zip->open($orderFileDir . $orderFileName) === true) {
|
||||
$unpackedDir = $orderFileDir . 'unpacked/';
|
||||
$zip->extractTo($unpackedDir);
|
||||
$zip->close();
|
||||
|
||||
$pdfFilename = $savedOrderData->order_num. "_specification" . ".pdf";
|
||||
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-disposition: inline; filename="' . $pdfFilename . '"');
|
||||
header('Content-Length: ' . filesize($unpackedDir.$pdfFilename));
|
||||
header('Cache-Control: public, must-revalidate, max-age=0');
|
||||
header('Pragma: public');
|
||||
|
||||
readfile($unpackedDir.$pdfFilename);
|
||||
array_map("unlink", glob($unpackedDir.$savedOrderData->order_num."*"));
|
||||
$isOrderFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isOrderFound) {
|
||||
$this->redirect(['controller' => 'CalcDoors', 'action' => 'display']);
|
||||
} else {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,682 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class CutController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['display', 'cut', 'getDetailsListFromPost', 'cutPrint']);
|
||||
$this->viewBuilder()->setLayout('cut');
|
||||
}
|
||||
|
||||
|
||||
public function display() {
|
||||
$savedOrderData = null;
|
||||
|
||||
if($encOrderId = $this->request->getQuery('oid')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$decryptedData = $ordersTable->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['sheet_data'] = @json_decode($savedOrderData['sheet_data'], true);
|
||||
$savedOrderData['created'] = date_timestamp_get(date_create($savedOrderData['created'])) * 1000;
|
||||
$savedOrderData['details'] = @json_decode($savedOrderData['details'], true);
|
||||
if (!empty($savedOrderData['details']['details'])) {
|
||||
foreach ($savedOrderData['details']['details'] as $key => $detail) {
|
||||
if (!empty($detail['label'])) {
|
||||
$savedOrderData['details']['details'][$key]['label'] = html_entity_decode($detail['label']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$savedOrderData['order_cut_results'] = @json_decode($savedOrderData['order_cut_results'], true);
|
||||
if (!empty($savedOrderData['order_cut_results']['price'])) {
|
||||
$savedOrderData['order_cut_results']['price'] = toFixed2Price(str_replace(" ", "", $savedOrderData['order_cut_results']['price']));
|
||||
}
|
||||
|
||||
$savedOrderData['eOId'] = $encOrderId;
|
||||
|
||||
$savedOrderData['printOrderSpecUrl'] = str_replace("/cut", "/cut-print/spec", $savedOrderData['view_order_url']);
|
||||
$savedOrderData['printOrderCutUrl'] = str_replace("/cut", "/cut-print/cut", $savedOrderData['view_order_url']);
|
||||
unset($savedOrderData['view_order_url']);
|
||||
$this->set(compact('savedOrderData'));
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->set('jsConfig', $this->getAppJsConfig("cut", false, $savedOrderData));
|
||||
}
|
||||
|
||||
public function cut() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
ini_set('max_input_time', '0');
|
||||
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (!empty($data['details'])) {
|
||||
$sheetPrice = 0;
|
||||
$sheetWidth = 0;
|
||||
$sheetHeight = 0;
|
||||
$notchPrice = 0;
|
||||
$facePrice = 0;
|
||||
$groovePrice = 0;
|
||||
|
||||
$data['sheetData'] = [];
|
||||
|
||||
if (!empty($data['selectedSheetData']['sheetId'])) {
|
||||
$additionalActionsAllowedIPs = explode("\n", $this->config['global']['additionalActionsAllowedIPs']['value']);
|
||||
$this->config['global']['additionalActionsAllowed'] = empty($additionalActionsAllowedIPs) || in_array($this->request->clientIP(), $additionalActionsAllowedIPs);
|
||||
|
||||
if(!empty($data['eOId'])) {
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('CutOrders')->decryptCustomData($data['eOId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$order = TableRegistry::getTableLocator()->get('CalcDoorsOrders')->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$this->config['global']['additionalActionsAllowed'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$configSheet = TableRegistry::getTableLocator()->get('CutSheets')->find('all')->where([
|
||||
'id' => $data['selectedSheetData']['sheetId']
|
||||
])->first();
|
||||
|
||||
if (!empty($configSheet)) {
|
||||
$configSheet = $configSheet->toArray();
|
||||
$sheetDimension = TableRegistry::getTableLocator()->get('CutSheetDimensions')->find('all')->where([
|
||||
'id' => $configSheet['sheet_dimension_id']
|
||||
])->first();
|
||||
|
||||
|
||||
if (!empty($sheetDimension)) {
|
||||
$configSheet['fullWidth'] = $sheetDimension['width'];
|
||||
$configSheet['fullHeight'] = $sheetDimension['height'];
|
||||
|
||||
$face = $this->config['common']['face']['value'];
|
||||
$sheetWidth = $configSheet['fullWidth'] - 2 * $face;
|
||||
$sheetHeight = $configSheet['fullHeight'] - 2 * $face;
|
||||
$sheetPrice = $configSheet['price'];
|
||||
$notchPrice = $this->config['prices']['notchPrice']['value'];
|
||||
$facePrice = $this->config['prices']['facePrice']['value'];
|
||||
$groovePrice = $this->config['groovePrices']['groove']['value'];
|
||||
|
||||
$data['sheetData']['sheetData'] = $configSheet;
|
||||
$data['sheetData']['sheetDimension'] = $sheetDimension->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$price = 0;
|
||||
|
||||
$data['selectedBordersData'] = [];
|
||||
foreach ([1, 2] as $borderId) {
|
||||
if (!empty($data['selectedSheetData']['border' . $borderId . 'Id'])) {
|
||||
$bCount = (!empty($data['selectedSheetData']['border' . $borderId . 'Count']) ? $data['selectedSheetData']['border' . $borderId . 'Count'] : 0);
|
||||
if (!empty($bCount)) {
|
||||
$border = TableRegistry::getTableLocator()->get('CutBorders')->find('all')->where([
|
||||
'id' => $data['selectedSheetData']['border' . $borderId . 'Id']
|
||||
])->first();
|
||||
|
||||
if (!empty($border)) {
|
||||
if (!empty($data['selectedSheetData']['border' . $borderId . 'Height'])) {
|
||||
$borderDimension = TableRegistry::getTableLocator()->get('CutBorderDimensions')->find('all')->where([
|
||||
'id' => $data['selectedSheetData']['border' . $borderId . 'Height']
|
||||
])->first();
|
||||
|
||||
if (!empty($borderDimension)) {
|
||||
$selectBorderDimension = TableRegistry::getTableLocator()->get('CutBorderAvailableDimensions')->find('all')->where([
|
||||
'border_id' => $data['selectedSheetData']['border' . $borderId . 'Id'],
|
||||
'border_dimension_id' => $data['selectedSheetData']['border' . $borderId . 'Height'],
|
||||
])->first();
|
||||
|
||||
if (!empty($selectBorderDimension)) {
|
||||
$price += ($bCount / 1000 * $borderDimension['gluing_price']) + ($bCount / 1000 * 1.1 * $selectBorderDimension['price']);
|
||||
|
||||
$data['selectedBordersData']['border' . $borderId . 'SelectBorderDimension'] = $selectBorderDimension->toArray();
|
||||
$data['selectedBordersData']['border' . $borderId . 'BorderDimension'] = $borderDimension->toArray();
|
||||
$data['selectedBordersData']['border' . $borderId . 'Border'] = $border->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cornersText = [];
|
||||
if (!empty($data['detailsCorners'])) {
|
||||
foreach ($data['details'] as $detailKey => $detail) {
|
||||
if (!empty($detail['width']) && ((int)$detail['width'] > 0) &&
|
||||
!empty($detail['height']) && ((int)$detail['height'] > 0) &&
|
||||
!empty($detail['count']) && ((int)$detail['count'] > 0) &&
|
||||
!empty($data['detailsCorners'][$detail['id']])) {
|
||||
|
||||
$detailCorners = $data['detailsCorners'][$detail['id']];
|
||||
$currentCornerText = [];
|
||||
$currentCornerPrice = [
|
||||
'cut' => 0,
|
||||
'radius' => 0
|
||||
];
|
||||
|
||||
|
||||
foreach ($this->config['cornerPositions'] as $cornerPositionKey => $cornerPosition) {
|
||||
if (!empty($detailCorners[$cornerPositionKey]) && ($detailCorners[$cornerPositionKey]['value'] != 'none')) {
|
||||
if ($detailCorners[$cornerPositionKey]['value'] == 'cut') {
|
||||
if (!empty($detailCorners[$cornerPositionKey]['diagonalCut'])) {
|
||||
$currentCornerText[] = $cornerPosition["shortLabel"] . " - диагональный срез";
|
||||
} else {
|
||||
$currentCornerText[] = $cornerPosition["shortLabel"] . " - срез " . $detailCorners[$cornerPositionKey]['x'] . "x" . $detailCorners[$cornerPositionKey]['y'] . " мм";
|
||||
}
|
||||
|
||||
if (empty($currentCornerPrice['cut'])) {
|
||||
$currentCornerPrice['cut'] = $this->config['cornerPrices']['cut']['value']; //одна цена за любое кол-во срезов
|
||||
}
|
||||
}
|
||||
|
||||
if ($detailCorners[$cornerPositionKey]['value'] == 'radius') {
|
||||
$currentCornerText[] = $cornerPosition["shortLabel"] . " - скругление " . $detailCorners[$cornerPositionKey]['radius'] . "мм";
|
||||
|
||||
foreach ($this->config['cornerPrices'] as $rpKey => $rpPrice) {
|
||||
if (strpos($rpKey, "radius-") === 0) {
|
||||
$rpKey = str_replace("radius-", "", $rpKey);
|
||||
|
||||
if (is_numeric($rpKey)) {
|
||||
if ($detailCorners[$cornerPositionKey]['radius'] <= $rpKey) {
|
||||
$currentCornerPrice['radius'] += $rpPrice['value'];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$rpKey = (int)str_replace("+", "", $rpKey);
|
||||
if ($detailCorners[$cornerPositionKey]['radius'] > $rpKey) {
|
||||
$currentCornerPrice['radius'] += $rpPrice['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($currentCornerText)) {
|
||||
$cornersText[$detailKey + 1] = [
|
||||
'detailLabel' => (!empty($detail['label']) ? $detail['label'] : ''),
|
||||
'corners' => join(", ", $currentCornerText)
|
||||
];
|
||||
}
|
||||
|
||||
$price += ($currentCornerPrice['cut'] + $currentCornerPrice['radius']) * (int)$detail['count'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$groovesText = [];
|
||||
$groovesTotal = [];
|
||||
$grooveCount = 0;
|
||||
if (!empty($data['detailsGrooves'])) {
|
||||
foreach ($data['details'] as $detailKey => $detail) {
|
||||
if (!empty($detail['width']) && ((int)$detail['width'] > 0) &&
|
||||
!empty($detail['height']) && ((int)$detail['height'] > 0) &&
|
||||
!empty($detail['count']) && ((int)$detail['count'] > 0) &&
|
||||
!empty($data['detailsGrooves'][$detail['id']])) {
|
||||
|
||||
$detailGrooves = $data['detailsGrooves'][$detail['id']];
|
||||
$currentGrooveText = $currentGrooveText2 = $currentGrooveText3 = [];
|
||||
|
||||
foreach ($this->config['groovePositions'] as $groovePositionKey => $groovePosition) {
|
||||
if (!empty($detailGrooves[$groovePositionKey]) && !empty($detailGrooves[$groovePositionKey]['enabled'])) {
|
||||
$currentGrooveDepth = $detailGrooves[$groovePositionKey]['depth'];
|
||||
$currentGrooveWidth = $detailGrooves[$groovePositionKey]['width'];
|
||||
|
||||
$currentGrooveText[] = mb_strtolower($groovePosition["label"]) . " - отступ от края детали " . $detailGrooves[$groovePositionKey]['offset'] . "мм, глубина пропила " . $currentGrooveDepth . "мм, ширина пропила " . $currentGrooveWidth . "мм";
|
||||
|
||||
if (!isset($groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth])) {
|
||||
$groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth] = [
|
||||
'label' => "глубина пропила " . $currentGrooveDepth . "мм, ширина пропила " . $currentGrooveWidth . "мм",
|
||||
'count' => 0
|
||||
];
|
||||
}
|
||||
|
||||
if (in_array($groovePositionKey, ["top", "bottom"])) {
|
||||
$grooveCount += (int)$detail['width'] * (int)$detail['count'];
|
||||
$groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth]['count'] += (int)$detail['width'] * (int)$detail['count'];
|
||||
|
||||
$currentGrooveText2Tmp = 'по.'.$groovePosition["labelShort2"]." " . (int)$detail['width'];
|
||||
} else {
|
||||
$grooveCount += (int)$detail['height'] * (int)$detail['count'];
|
||||
$groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth]['count'] += (int)$detail['height'] * (int)$detail['count'];
|
||||
|
||||
$currentGrooveText2Tmp = 'по.'.$groovePosition["labelShort2"]." " . (int)$detail['height'];
|
||||
}
|
||||
|
||||
$currentGrooveText2Tmp .= "_" . (!empty($detailGrooves[$groovePositionKey]['offset']) ? $detailGrooves[$groovePositionKey]['offset'] . '*' : '') . $currentGrooveWidth . '*' . $currentGrooveDepth;
|
||||
$currentGrooveText2[] = $currentGrooveText2Tmp;
|
||||
$currentGrooveText3[] = 'паз.' . $currentGrooveText2Tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($currentGrooveText)) {
|
||||
$groovesText[$detailKey + 1] = [
|
||||
'detailLabel' => (!empty($detail['label']) ? $detail['label'] : ''),
|
||||
'grooves' => join(", ", $currentGrooveText),
|
||||
'grooves2' => join(", ", $currentGrooveText2),
|
||||
'grooves3' => join(", ", $currentGrooveText3)
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$sheets = [];
|
||||
$notchCount = 0;
|
||||
$initialDetails = $this->getDetailsListFromPost($data['details']);
|
||||
|
||||
if (empty($data['orderEmailNotify']) && empty($data['printOnly'])) { //do not recount on email send
|
||||
$fitOrders = ["toTop"/*, "toRight", "toBottom"*/];
|
||||
|
||||
foreach($fitOrders as $fitOrder) {
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$detailsSortFunctions = [
|
||||
'cmpDetailsByBothSides',
|
||||
'cmpDetailsByBothSidesReversed',
|
||||
'cmpDetailsByWidth',
|
||||
'cmpDetailsByWidthReversed',
|
||||
'cmpDetailsByHeight',
|
||||
'cmpDetailsByHeightReversed',
|
||||
''
|
||||
];
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$detailsSortFunctions = [
|
||||
'cmpDetailsByBothSidesForToTop'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($detailsSortFunctions as $detailsSortFunction) {
|
||||
//$detailsToFitCheckArray = [];
|
||||
//$details = $this->getDetailsListFromPost($data['details']);
|
||||
$details = $initialDetails;
|
||||
|
||||
foreach ($details as $key => $detail) {
|
||||
$details[$key] = (object)$detail;
|
||||
}
|
||||
|
||||
if (!empty($detailsSortFunction)) {
|
||||
usort($details, $detailsSortFunction);
|
||||
}
|
||||
|
||||
//debug($details);exit;
|
||||
|
||||
//$detailsToFitCheckArray[] = $postDetails;
|
||||
|
||||
$currentSheets = [];
|
||||
$currentSheetIndex = 0;
|
||||
$currentNotchCount = 0;
|
||||
|
||||
//foreach ($detailsToFitCheckArray as $details) {
|
||||
while (!empty($details)) {
|
||||
$packer = new Packer();
|
||||
$packer->fitDetails($details, $sheetWidth, $sheetHeight, $this->config['common']['notch']['value'], $currentNotchCount, $fitOrder);
|
||||
|
||||
$currentSheets[$currentSheetIndex] = [
|
||||
'id' => $currentSheetIndex + 1,
|
||||
'details' => []
|
||||
];
|
||||
|
||||
foreach ($details as $key => $detail) {
|
||||
if (!empty($detail->fit)) {
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$detail->top = $detail->fit->top;
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$detail->top = $detail->fit->bottom - $detail->height;
|
||||
}
|
||||
}
|
||||
|
||||
$detail->left = $detail->fit->left;
|
||||
unset($detail->fit);
|
||||
|
||||
$currentSheets[$currentSheetIndex]['details'][] = $detail;
|
||||
unset($details[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$currentSheetIndex++;
|
||||
}
|
||||
|
||||
if (empty($sheets) || (count($currentSheets) < count($sheets))) {
|
||||
$sheets = $currentSheets;
|
||||
$notchCount = $currentNotchCount;
|
||||
|
||||
if (count($sheets) == 1) { //no need to calculate more cause of minimal sheets count
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
//exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$faceCount = count($sheets) * ($configSheet['fullWidth'] + $configSheet['fullHeight']) * 2;
|
||||
|
||||
$price += $sheetPrice * count($sheets) +
|
||||
$notchCount / 1000 * $notchPrice + // цена пропила
|
||||
$faceCount / 1000 * $facePrice + // цена торцевания
|
||||
$grooveCount / 1000 * $groovePrice // цена пазов
|
||||
;
|
||||
|
||||
|
||||
$sheets = array_values($sheets);
|
||||
$notchCount = str_replace(".00", "", number_format(ceil($notchCount + $faceCount) / 1000, 2, ".", ""));
|
||||
|
||||
$grooveCount = ($grooveCount > 0 ? str_replace(".00", "", number_format(ceil($grooveCount) / 1000, 2, ".", "")) : "");
|
||||
|
||||
$result['price'] = str_replace(".00", "", number_format(ceil($price * 100) / 100, 2, ".", " "));
|
||||
} else {
|
||||
$sheets = $data['sheets'];
|
||||
$notchCount = $data['notchCount'];
|
||||
$grooveCount = $data['grooveCount'];
|
||||
$result['price'] = $data['price'];
|
||||
}
|
||||
|
||||
$result['sheets'] = $sheets;
|
||||
$result['notchCount'] = $notchCount;
|
||||
$result['grooveCount'] = $grooveCount;
|
||||
$result['status'] = 'success';
|
||||
|
||||
if (!empty($data['orderEmailNotify']) || !empty($data['printOnly'])) {
|
||||
$sendOrderEmailNotify = true;
|
||||
|
||||
if (!empty($data['branchId']) && in_array($data['branchId'], ["printNotify", "printOnly"])) { //send print notify only from allowed ips, hide button for others
|
||||
if (empty($this->config['global']['additionalActionsAllowed'])) {
|
||||
$sendOrderEmailNotify = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sendOrderEmailNotify) {
|
||||
$authUserId = $this->Auth->user('id');
|
||||
$authUserId = (!empty($authUserId) ? $authUserId : null);
|
||||
|
||||
$orderEmailNotifySentResults = TableRegistry::getTableLocator()->get('CutOrders')->orderEmailNotify($data, $this->config, count($sheets), $cornersText, $groovesText, $groovesTotal, $this->request->clientIP(), $authUserId, $result['price']);
|
||||
|
||||
$result['orderEmailNotifySent'] = $orderEmailNotifySentResults['orderEmailNotifySent'];
|
||||
$result['printOrderSpecUrl'] = $orderEmailNotifySentResults['printOrderSpecUrl'];
|
||||
$result['printOrderCutUrl'] = $orderEmailNotifySentResults['printOrderCutUrl'];
|
||||
|
||||
if(!empty($result['orderEmailNotifySent'])
|
||||
&& ($result['orderEmailNotifySent'] == "success")
|
||||
&& (in_array($this->request->clientIP(), ["78.30.242.25"]))
|
||||
) {
|
||||
$result['fullCleanupOnSuccess'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result['message'] = 'Не выбрана фактура листа.';
|
||||
}
|
||||
} else {
|
||||
$result['message'] = 'Нет данных.';
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['message'] = 'Нет данных.';
|
||||
}
|
||||
|
||||
echo json_encode($result);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function getDetailsListFromPost($postDetails = []) {
|
||||
$details = [];
|
||||
$detailsCount = 0;
|
||||
|
||||
foreach ($postDetails as $detail) {
|
||||
if (!empty($detail['width']) && ((int)$detail['width'] > 0) &&
|
||||
!empty($detail['height']) && ((int)$detail['height'] > 0) &&
|
||||
!empty($detail['count']) && ((int)$detail['count'] > 0)) {
|
||||
for ($i = 1; $i <= (int)$detail['count']; $i++) {
|
||||
$detailsCount++;
|
||||
|
||||
$details[$detailsCount] = [
|
||||
'id' => $detailsCount,
|
||||
'detailId' => $detail['id'],
|
||||
'width' => $detail['width'],
|
||||
'height' => $detail['height'],
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $details;
|
||||
}
|
||||
|
||||
public function cutPrint($printType) {
|
||||
$isOrderFound = false;
|
||||
|
||||
if($encOrderId = $this->request->getQuery('oid')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$decryptedData = $ordersTable->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$orderFileName = $savedOrderData->order_num . '.zip';
|
||||
$orderFileDir = ROOT . '/files/cut_orders/';
|
||||
|
||||
if (!is_dir($orderFileDir) || !file_exists($orderFileDir.$orderFileName)) {
|
||||
} else {
|
||||
$zip = new \ZipArchive;
|
||||
if ($zip->open($orderFileDir . $orderFileName) === true) {
|
||||
$unpackedDir = $orderFileDir . 'unpacked/';
|
||||
$zip->extractTo($unpackedDir);
|
||||
$zip->close();
|
||||
|
||||
$fileAdd = ($printType == "cut" ? "cut" : "specification");
|
||||
|
||||
$pdfFilename = $savedOrderData->order_num. "_" . $fileAdd . ".pdf";
|
||||
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-disposition: inline; filename="' . $pdfFilename . '"');
|
||||
header('Content-Length: ' . filesize($unpackedDir.$pdfFilename));
|
||||
header('Cache-Control: public, must-revalidate, max-age=0');
|
||||
header('Pragma: public');
|
||||
|
||||
readfile($unpackedDir.$pdfFilename);
|
||||
@unlink($unpackedDir.$pdfFilename);
|
||||
array_map("unlink", glob($unpackedDir.$savedOrderData->order_num."*"));
|
||||
$isOrderFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isOrderFound) {
|
||||
$this->redirect(['controller' => 'Cut', 'action' => 'display']);
|
||||
} else {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Packer {
|
||||
public $root;
|
||||
public $notch;
|
||||
|
||||
public function fitDetails(&$blocks, $sheetWidth, $sheetHeight, $notch, &$notchCount, $fitOrder = "toRight") {
|
||||
//debug($blocks);exit;
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$this->root = (object)array(
|
||||
'left' => 0,
|
||||
'top' => 0,
|
||||
'width' => $sheetWidth,
|
||||
'height' => $sheetHeight,
|
||||
'isUsed' => false,
|
||||
);
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$this->root = (object)array(
|
||||
'left' => 0,
|
||||
'bottom' => $sheetHeight,
|
||||
'width' => $sheetWidth,
|
||||
'height' => $sheetHeight,
|
||||
'isUsed' => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->notch = $notch;
|
||||
|
||||
foreach ($blocks as &$block) {
|
||||
$node = $this->findNode($this->root, $block->width, $block->height, $fitOrder);
|
||||
|
||||
if ($node) {
|
||||
$block->fit = $this->splitNode($node, $block->width, $block->height, $fitOrder);
|
||||
|
||||
//пропил
|
||||
if ($block->fit->left + $block->width < $sheetWidth) {
|
||||
$notchCount += $block->height;
|
||||
}
|
||||
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
if ($block->fit->top + $block->height < $sheetHeight) {
|
||||
$notchCount += $block->width;
|
||||
}
|
||||
|
||||
if (($block->fit->left + $block->width < $sheetWidth) && ($block->fit->top + $block->height < $sheetHeight)) {
|
||||
//деталь не полностью прилегает к краям - добавляем угол пропила
|
||||
$notchCount += $this->notch;
|
||||
}
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
if ($block->fit->bottom - $block->height > 0) {
|
||||
$notchCount += $block->width;
|
||||
}
|
||||
|
||||
if (($block->fit->left + $block->width < $sheetWidth) && ($block->fit->bottom - $block->height > 0)) {
|
||||
//деталь не полностью прилегает к краям - добавляем угол пропила
|
||||
$notchCount += $this->notch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function findNode(&$root, $width, $height, $fitOrder = "toRight") {
|
||||
if (@$root->isUsed) {
|
||||
if ($fitOrder == "toRight") {
|
||||
$node = $this->findNode($root->right, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node = $this->findNode($root->bottom, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
if ($fitOrder == "toBottom") {
|
||||
$node = $this->findNode($root->bottom, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node = $this->findNode($root->right, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
if ($fitOrder == "toTop") {
|
||||
$node = $this->findNode($root->right, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node = $this->findNode($root->top, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (($width <= $root->width) && ($height <= $root->height)) {
|
||||
return $root;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function splitNode(&$node, $width, $height, $fitOrder) {
|
||||
$node->isUsed = true;
|
||||
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$node->right = (object)array(
|
||||
'left' => $node->left + $width + $this->notch,
|
||||
'top' => $node->top,
|
||||
'width' => $node->width - $width - $this->notch,
|
||||
'height' => $height,
|
||||
);
|
||||
|
||||
$node->bottom = (object)array(
|
||||
'left' => $node->left,
|
||||
'top' => $node->top + $height + $this->notch,
|
||||
'width' => $node->width,
|
||||
'height' => $node->height - $height - $this->notch,
|
||||
);
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$node->right = (object)array(
|
||||
'left' => $node->left + $width + $this->notch,
|
||||
'bottom' => $node->bottom,
|
||||
'width' => $node->width - $width - $this->notch,
|
||||
'height' => $height,
|
||||
);
|
||||
|
||||
$node->top = (object)array(
|
||||
'left' => $node->left,
|
||||
'bottom' => $node->bottom - $height - $this->notch,
|
||||
'width' => $node->width,
|
||||
'height' => $node->height - $height - $this->notch,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class DeliveryController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['display']);
|
||||
$this->viewBuilder()->setLayout('delivery');
|
||||
}
|
||||
|
||||
|
||||
public function display($city = null) {
|
||||
$isCityFound = false;
|
||||
if (!empty($city)) {
|
||||
$deliveryTable = TableRegistry::getTableLocator()->get('Delivery');
|
||||
|
||||
$delivery = $deliveryTable->find('all')->where(['slug' => $city, 'is_deleted' => false])->first();
|
||||
if (!empty($delivery)) {
|
||||
$delivery = $delivery->toArray();
|
||||
|
||||
$this->set('apiKey', $this->config['global']['yandexMapApiKey']['value']);
|
||||
$this->set('siteTitle', $delivery['label']);
|
||||
$this->set('delivery', $delivery);
|
||||
$isCityFound = true;
|
||||
}
|
||||
|
||||
//var_dump($this->getAppJsConfig("delivery", false));
|
||||
$this->set('jsConfig', $this->getAppJsConfig("delivery", false));
|
||||
}
|
||||
|
||||
if (empty($isCityFound)) {
|
||||
$this->redirect('/404');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
class ErrorController extends AppController {
|
||||
|
||||
public $config = null;
|
||||
|
||||
public function initialize() {
|
||||
$this->loadComponent('RequestHandler');
|
||||
}
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event) {
|
||||
parent::beforeRender($event);
|
||||
|
||||
$this->viewBuilder()->setTemplatePath('Error');
|
||||
$this->config = $this->getAppConfig("");
|
||||
$this->set('jsConfig', $this->getAppJsConfig("", false));
|
||||
}
|
||||
|
||||
public function afterFilter(Event $event) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,682 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class FasadController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['display', 'fasad', 'getDetailsListFromPost', 'fasadPrint']);
|
||||
$this->viewBuilder()->setLayout('fasad');
|
||||
}
|
||||
|
||||
|
||||
public function display() {
|
||||
$savedOrderData = null;
|
||||
|
||||
if($encOrderId = $this->request->getQuery('oid')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('FasadOrders');
|
||||
$decryptedData = $ordersTable->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['sheet_data'] = @json_decode($savedOrderData['sheet_data'], true);
|
||||
$savedOrderData['created'] = date_timestamp_get(date_create($savedOrderData['created'])) * 1000;
|
||||
$savedOrderData['details'] = @json_decode($savedOrderData['details'], true);
|
||||
if (!empty($savedOrderData['details']['details'])) {
|
||||
foreach ($savedOrderData['details']['details'] as $key => $detail) {
|
||||
if (!empty($detail['label'])) {
|
||||
$savedOrderData['details']['details'][$key]['label'] = html_entity_decode($detail['label']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$savedOrderData['order_fasad_results'] = @json_decode($savedOrderData['order_fasad_results'], true);
|
||||
if (!empty($savedOrderData['order_fasad_results']['price'])) {
|
||||
$savedOrderData['order_fasad_results']['price'] = toFixed2Price(str_replace(" ", "", $savedOrderData['order_fasad_results']['price']));
|
||||
}
|
||||
|
||||
$savedOrderData['eOId'] = $encOrderId;
|
||||
|
||||
$savedOrderData['printOrderSpecUrl'] = str_replace("/fasad", "/fasad-print/spec", $savedOrderData['view_order_url']);
|
||||
$savedOrderData['printOrderFasadUrl'] = str_replace("/fasad", "/fasad-print/fasad", $savedOrderData['view_order_url']);
|
||||
unset($savedOrderData['view_order_url']);
|
||||
$this->set(compact('savedOrderData'));
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->set('jsConfig', $this->getAppJsConfig("fasad", false, $savedOrderData));
|
||||
}
|
||||
|
||||
public function fasad() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
ini_set('max_input_time', '0');
|
||||
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (!empty($data['details'])) {
|
||||
$sheetPrice = 0;
|
||||
$sheetWidth = 0;
|
||||
$sheetHeight = 0;
|
||||
$notchPrice = 0;
|
||||
$facePrice = 0;
|
||||
$groovePrice = 0;
|
||||
|
||||
$data['sheetData'] = [];
|
||||
|
||||
if (!empty($data['selectedSheetData']['sheetId'])) {
|
||||
$additionalActionsAllowedIPs = explode("\n", $this->config['global']['additionalActionsAllowedIPs']['value']);
|
||||
$this->config['global']['additionalActionsAllowed'] = empty($additionalActionsAllowedIPs) || in_array($this->request->clientIP(), $additionalActionsAllowedIPs);
|
||||
|
||||
if(!empty($data['eOId'])) {
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('FasadOrders')->decryptCustomData($data['eOId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$order = TableRegistry::getTableLocator()->get('CalcDoorsOrders')->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$this->config['global']['additionalActionsAllowed'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$configSheet = TableRegistry::getTableLocator()->get('FasadSheets')->find('all')->where([
|
||||
'id' => $data['selectedSheetData']['sheetId']
|
||||
])->first();
|
||||
|
||||
if (!empty($configSheet)) {
|
||||
$configSheet = $configSheet->toArray();
|
||||
$sheetDimension = TableRegistry::getTableLocator()->get('FasadSheetDimensions')->find('all')->where([
|
||||
'id' => $configSheet['sheet_dimension_id']
|
||||
])->first();
|
||||
|
||||
|
||||
if (!empty($sheetDimension)) {
|
||||
$configSheet['fullWidth'] = $sheetDimension['width'];
|
||||
$configSheet['fullHeight'] = $sheetDimension['height'];
|
||||
|
||||
$face = $this->config['common']['face']['value'];
|
||||
$sheetWidth = $configSheet['fullWidth'] - 2 * $face;
|
||||
$sheetHeight = $configSheet['fullHeight'] - 2 * $face;
|
||||
$sheetPrice = $configSheet['price'];
|
||||
$notchPrice = $this->config['prices']['notchPrice']['value'];
|
||||
$facePrice = $this->config['prices']['facePrice']['value'];
|
||||
$groovePrice = $this->config['groovePrices']['groove']['value'];
|
||||
|
||||
$data['sheetData']['sheetData'] = $configSheet;
|
||||
$data['sheetData']['sheetDimension'] = $sheetDimension->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$price = 0;
|
||||
|
||||
$data['selectedBordersData'] = [];
|
||||
foreach ([1, 2] as $borderId) {
|
||||
if (!empty($data['selectedSheetData']['border' . $borderId . 'Id'])) {
|
||||
$bCount = (!empty($data['selectedSheetData']['border' . $borderId . 'Count']) ? $data['selectedSheetData']['border' . $borderId . 'Count'] : 0);
|
||||
if (!empty($bCount)) {
|
||||
$border = TableRegistry::getTableLocator()->get('FasadBorders')->find('all')->where([
|
||||
'id' => $data['selectedSheetData']['border' . $borderId . 'Id']
|
||||
])->first();
|
||||
|
||||
if (!empty($border)) {
|
||||
if (!empty($data['selectedSheetData']['border' . $borderId . 'Height'])) {
|
||||
$borderDimension = TableRegistry::getTableLocator()->get('FasadBorderDimensions')->find('all')->where([
|
||||
'id' => $data['selectedSheetData']['border' . $borderId . 'Height']
|
||||
])->first();
|
||||
|
||||
if (!empty($borderDimension)) {
|
||||
$selectBorderDimension = TableRegistry::getTableLocator()->get('FasadBorderAvailableDimensions')->find('all')->where([
|
||||
'border_id' => $data['selectedSheetData']['border' . $borderId . 'Id'],
|
||||
'border_dimension_id' => $data['selectedSheetData']['border' . $borderId . 'Height'],
|
||||
])->first();
|
||||
|
||||
if (!empty($selectBorderDimension)) {
|
||||
$price += ($bCount / 1000 * $borderDimension['gluing_price']) + ($bCount / 1000 * 1.1 * $selectBorderDimension['price']);
|
||||
|
||||
$data['selectedBordersData']['border' . $borderId . 'SelectBorderDimension'] = $selectBorderDimension->toArray();
|
||||
$data['selectedBordersData']['border' . $borderId . 'BorderDimension'] = $borderDimension->toArray();
|
||||
$data['selectedBordersData']['border' . $borderId . 'Border'] = $border->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cornersText = [];
|
||||
if (!empty($data['detailsCorners'])) {
|
||||
foreach ($data['details'] as $detailKey => $detail) {
|
||||
if (!empty($detail['width']) && ((int)$detail['width'] > 0) &&
|
||||
!empty($detail['height']) && ((int)$detail['height'] > 0) &&
|
||||
!empty($detail['count']) && ((int)$detail['count'] > 0) &&
|
||||
!empty($data['detailsCorners'][$detail['id']])) {
|
||||
|
||||
$detailCorners = $data['detailsCorners'][$detail['id']];
|
||||
$currentCornerText = [];
|
||||
$currentCornerPrice = [
|
||||
'cut' => 0,
|
||||
'radius' => 0
|
||||
];
|
||||
|
||||
|
||||
foreach ($this->config['cornerPositions'] as $cornerPositionKey => $cornerPosition) {
|
||||
if (!empty($detailCorners[$cornerPositionKey]) && ($detailCorners[$cornerPositionKey]['value'] != 'none')) {
|
||||
if ($detailCorners[$cornerPositionKey]['value'] == 'cut') {
|
||||
if (!empty($detailCorners[$cornerPositionKey]['diagonalCut'])) {
|
||||
$currentCornerText[] = $cornerPosition["shortLabel"] . " - диагональный срез";
|
||||
} else {
|
||||
$currentCornerText[] = $cornerPosition["shortLabel"] . " - срез " . $detailCorners[$cornerPositionKey]['x'] . "x" . $detailCorners[$cornerPositionKey]['y'] . " мм";
|
||||
}
|
||||
|
||||
if (empty($currentCornerPrice['cut'])) {
|
||||
$currentCornerPrice['cut'] = $this->config['cornerPrices']['cut']['value']; //одна цена за любое кол-во срезов
|
||||
}
|
||||
}
|
||||
|
||||
if ($detailCorners[$cornerPositionKey]['value'] == 'radius') {
|
||||
$currentCornerText[] = $cornerPosition["shortLabel"] . " - скругление " . $detailCorners[$cornerPositionKey]['radius'] . "мм";
|
||||
|
||||
foreach ($this->config['cornerPrices'] as $rpKey => $rpPrice) {
|
||||
if (strpos($rpKey, "radius-") === 0) {
|
||||
$rpKey = str_replace("radius-", "", $rpKey);
|
||||
|
||||
if (is_numeric($rpKey)) {
|
||||
if ($detailCorners[$cornerPositionKey]['radius'] <= $rpKey) {
|
||||
$currentCornerPrice['radius'] += $rpPrice['value'];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$rpKey = (int)str_replace("+", "", $rpKey);
|
||||
if ($detailCorners[$cornerPositionKey]['radius'] > $rpKey) {
|
||||
$currentCornerPrice['radius'] += $rpPrice['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($currentCornerText)) {
|
||||
$cornersText[$detailKey + 1] = [
|
||||
'detailLabel' => (!empty($detail['label']) ? $detail['label'] : ''),
|
||||
'corners' => join(", ", $currentCornerText)
|
||||
];
|
||||
}
|
||||
|
||||
$price += ($currentCornerPrice['cut'] + $currentCornerPrice['radius']) * (int)$detail['count'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$groovesText = [];
|
||||
$groovesTotal = [];
|
||||
$grooveCount = 0;
|
||||
if (!empty($data['detailsGrooves'])) {
|
||||
foreach ($data['details'] as $detailKey => $detail) {
|
||||
if (!empty($detail['width']) && ((int)$detail['width'] > 0) &&
|
||||
!empty($detail['height']) && ((int)$detail['height'] > 0) &&
|
||||
!empty($detail['count']) && ((int)$detail['count'] > 0) &&
|
||||
!empty($data['detailsGrooves'][$detail['id']])) {
|
||||
|
||||
$detailGrooves = $data['detailsGrooves'][$detail['id']];
|
||||
$currentGrooveText = $currentGrooveText2 = $currentGrooveText3 = [];
|
||||
|
||||
foreach ($this->config['groovePositions'] as $groovePositionKey => $groovePosition) {
|
||||
if (!empty($detailGrooves[$groovePositionKey]) && !empty($detailGrooves[$groovePositionKey]['enabled'])) {
|
||||
$currentGrooveDepth = $detailGrooves[$groovePositionKey]['depth'];
|
||||
$currentGrooveWidth = $detailGrooves[$groovePositionKey]['width'];
|
||||
|
||||
$currentGrooveText[] = mb_strtolower($groovePosition["label"]) . " - отступ от края детали " . $detailGrooves[$groovePositionKey]['offset'] . "мм, глубина пропила " . $currentGrooveDepth . "мм, ширина пропила " . $currentGrooveWidth . "мм";
|
||||
|
||||
if (!isset($groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth])) {
|
||||
$groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth] = [
|
||||
'label' => "глубина пропила " . $currentGrooveDepth . "мм, ширина пропила " . $currentGrooveWidth . "мм",
|
||||
'count' => 0
|
||||
];
|
||||
}
|
||||
|
||||
if (in_array($groovePositionKey, ["top", "bottom"])) {
|
||||
$grooveCount += (int)$detail['width'] * (int)$detail['count'];
|
||||
$groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth]['count'] += (int)$detail['width'] * (int)$detail['count'];
|
||||
|
||||
$currentGrooveText2Tmp = 'по.'.$groovePosition["labelShort2"]." " . (int)$detail['width'];
|
||||
} else {
|
||||
$grooveCount += (int)$detail['height'] * (int)$detail['count'];
|
||||
$groovesTotal[$currentGrooveDepth."_".$currentGrooveWidth]['count'] += (int)$detail['height'] * (int)$detail['count'];
|
||||
|
||||
$currentGrooveText2Tmp = 'по.'.$groovePosition["labelShort2"]." " . (int)$detail['height'];
|
||||
}
|
||||
|
||||
$currentGrooveText2Tmp .= "_" . (!empty($detailGrooves[$groovePositionKey]['offset']) ? $detailGrooves[$groovePositionKey]['offset'] . '*' : '') . $currentGrooveWidth . '*' . $currentGrooveDepth;
|
||||
$currentGrooveText2[] = $currentGrooveText2Tmp;
|
||||
$currentGrooveText3[] = 'паз.' . $currentGrooveText2Tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($currentGrooveText)) {
|
||||
$groovesText[$detailKey + 1] = [
|
||||
'detailLabel' => (!empty($detail['label']) ? $detail['label'] : ''),
|
||||
'grooves' => join(", ", $currentGrooveText),
|
||||
'grooves2' => join(", ", $currentGrooveText2),
|
||||
'grooves3' => join(", ", $currentGrooveText3)
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$sheets = [];
|
||||
$notchCount = 0;
|
||||
$initialDetails = $this->getDetailsListFromPost($data['details']);
|
||||
|
||||
if (empty($data['orderEmailNotify']) && empty($data['printOnly'])) { //do not recount on email send
|
||||
$fitOrders = ["toTop"/*, "toRight", "toBottom"*/];
|
||||
|
||||
foreach($fitOrders as $fitOrder) {
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$detailsSortFunctions = [
|
||||
'cmpDetailsByBothSides',
|
||||
'cmpDetailsByBothSidesReversed',
|
||||
'cmpDetailsByWidth',
|
||||
'cmpDetailsByWidthReversed',
|
||||
'cmpDetailsByHeight',
|
||||
'cmpDetailsByHeightReversed',
|
||||
''
|
||||
];
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$detailsSortFunctions = [
|
||||
'cmpDetailsByBothSidesForToTop'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($detailsSortFunctions as $detailsSortFunction) {
|
||||
//$detailsToFitCheckArray = [];
|
||||
//$details = $this->getDetailsListFromPost($data['details']);
|
||||
$details = $initialDetails;
|
||||
|
||||
foreach ($details as $key => $detail) {
|
||||
$details[$key] = (object)$detail;
|
||||
}
|
||||
|
||||
if (!empty($detailsSortFunction)) {
|
||||
usort($details, $detailsSortFunction);
|
||||
}
|
||||
|
||||
//debug($details);exit;
|
||||
|
||||
//$detailsToFitCheckArray[] = $postDetails;
|
||||
|
||||
$currentSheets = [];
|
||||
$currentSheetIndex = 0;
|
||||
$currentNotchCount = 0;
|
||||
|
||||
//foreach ($detailsToFitCheckArray as $details) {
|
||||
while (!empty($details)) {
|
||||
$packer = new Packer();
|
||||
$packer->fitDetails($details, $sheetWidth, $sheetHeight, $this->config['common']['notch']['value'], $currentNotchCount, $fitOrder);
|
||||
|
||||
$currentSheets[$currentSheetIndex] = [
|
||||
'id' => $currentSheetIndex + 1,
|
||||
'details' => []
|
||||
];
|
||||
|
||||
foreach ($details as $key => $detail) {
|
||||
if (!empty($detail->fit)) {
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$detail->top = $detail->fit->top;
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$detail->top = $detail->fit->bottom - $detail->height;
|
||||
}
|
||||
}
|
||||
|
||||
$detail->left = $detail->fit->left;
|
||||
unset($detail->fit);
|
||||
|
||||
$currentSheets[$currentSheetIndex]['details'][] = $detail;
|
||||
unset($details[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$currentSheetIndex++;
|
||||
}
|
||||
|
||||
if (empty($sheets) || (count($currentSheets) < count($sheets))) {
|
||||
$sheets = $currentSheets;
|
||||
$notchCount = $currentNotchCount;
|
||||
|
||||
if (count($sheets) == 1) { //no need to calculate more cause of minimal sheets count
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
//exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$faceCount = count($sheets) * ($configSheet['fullWidth'] + $configSheet['fullHeight']) * 2;
|
||||
|
||||
$price += $sheetPrice * count($sheets) +
|
||||
$notchCount / 1000 * $notchPrice + // цена пропила
|
||||
$faceCount / 1000 * $facePrice + // цена торцевания
|
||||
$grooveCount / 1000 * $groovePrice // цена пазов
|
||||
;
|
||||
|
||||
|
||||
$sheets = array_values($sheets);
|
||||
$notchCount = str_replace(".00", "", number_format(ceil($notchCount + $faceCount) / 1000, 2, ".", ""));
|
||||
|
||||
$grooveCount = ($grooveCount > 0 ? str_replace(".00", "", number_format(ceil($grooveCount) / 1000, 2, ".", "")) : "");
|
||||
|
||||
$result['price'] = str_replace(".00", "", number_format(ceil($price * 100) / 100, 2, ".", " "));
|
||||
} else {
|
||||
$sheets = $data['sheets'];
|
||||
$notchCount = $data['notchCount'];
|
||||
$grooveCount = $data['grooveCount'];
|
||||
$result['price'] = $data['price'];
|
||||
}
|
||||
|
||||
$result['sheets'] = $sheets;
|
||||
$result['notchCount'] = $notchCount;
|
||||
$result['grooveCount'] = $grooveCount;
|
||||
$result['status'] = 'success';
|
||||
|
||||
if (!empty($data['orderEmailNotify']) || !empty($data['printOnly'])) {
|
||||
$sendOrderEmailNotify = true;
|
||||
|
||||
if (!empty($data['branchId']) && in_array($data['branchId'], ["printNotify", "printOnly"])) { //send print notify only from allowed ips, hide button for others
|
||||
if (empty($this->config['global']['additionalActionsAllowed'])) {
|
||||
$sendOrderEmailNotify = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sendOrderEmailNotify) {
|
||||
$authUserId = $this->Auth->user('id');
|
||||
$authUserId = (!empty($authUserId) ? $authUserId : null);
|
||||
|
||||
$orderEmailNotifySentResults = TableRegistry::getTableLocator()->get('FasadOrders')->orderEmailNotify($data, $this->config, count($sheets), $cornersText, $groovesText, $groovesTotal, $this->request->clientIP(), $authUserId, $result['price']);
|
||||
|
||||
$result['orderEmailNotifySent'] = $orderEmailNotifySentResults['orderEmailNotifySent'];
|
||||
$result['printOrderSpecUrl'] = $orderEmailNotifySentResults['printOrderSpecUrl'];
|
||||
$result['printOrderFasadUrl'] = $orderEmailNotifySentResults['printOrderFasadUrl'];
|
||||
|
||||
if(!empty($result['orderEmailNotifySent'])
|
||||
&& ($result['orderEmailNotifySent'] == "success")
|
||||
&& (in_array($this->request->clientIP(), ["78.30.242.25"]))
|
||||
) {
|
||||
$result['fullCleanupOnSuccess'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result['message'] = 'Не выбрана фактура листа.';
|
||||
}
|
||||
} else {
|
||||
$result['message'] = 'Нет данных.';
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['message'] = 'Нет данных.';
|
||||
}
|
||||
|
||||
echo json_encode($result);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function getDetailsListFromPost($postDetails = []) {
|
||||
$details = [];
|
||||
$detailsCount = 0;
|
||||
|
||||
foreach ($postDetails as $detail) {
|
||||
if (!empty($detail['width']) && ((int)$detail['width'] > 0) &&
|
||||
!empty($detail['height']) && ((int)$detail['height'] > 0) &&
|
||||
!empty($detail['count']) && ((int)$detail['count'] > 0)) {
|
||||
for ($i = 1; $i <= (int)$detail['count']; $i++) {
|
||||
$detailsCount++;
|
||||
|
||||
$details[$detailsCount] = [
|
||||
'id' => $detailsCount,
|
||||
'detailId' => $detail['id'],
|
||||
'width' => $detail['width'],
|
||||
'height' => $detail['height'],
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $details;
|
||||
}
|
||||
|
||||
public function fasadPrint($printType) {
|
||||
$isOrderFound = false;
|
||||
|
||||
if($encOrderId = $this->request->getQuery('oid')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('FasadOrders');
|
||||
$decryptedData = $ordersTable->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $ordersTable->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$orderFileName = $savedOrderData->order_num . '.zip';
|
||||
$orderFileDir = ROOT . '/files/fasad_orders/';
|
||||
|
||||
if (!is_dir($orderFileDir) || !file_exists($orderFileDir.$orderFileName)) {
|
||||
} else {
|
||||
$zip = new \ZipArchive;
|
||||
if ($zip->open($orderFileDir . $orderFileName) === true) {
|
||||
$unpackedDir = $orderFileDir . 'unpacked/';
|
||||
$zip->extractTo($unpackedDir);
|
||||
$zip->close();
|
||||
|
||||
$fileAdd = ($printType == "fasad" ? "fasad" : "specification");
|
||||
|
||||
$pdfFilename = $savedOrderData->order_num. "_" . $fileAdd . ".pdf";
|
||||
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-disposition: inline; filename="' . $pdfFilename . '"');
|
||||
header('Content-Length: ' . filesize($unpackedDir.$pdfFilename));
|
||||
header('Cache-Control: public, must-revalidate, max-age=0');
|
||||
header('Pragma: public');
|
||||
|
||||
readfile($unpackedDir.$pdfFilename);
|
||||
@unlink($unpackedDir.$pdfFilename);
|
||||
array_map("unlink", glob($unpackedDir.$savedOrderData->order_num."*"));
|
||||
$isOrderFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isOrderFound) {
|
||||
$this->redirect(['controller' => 'Fasad', 'action' => 'display']);
|
||||
} else {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Packer {
|
||||
public $root;
|
||||
public $notch;
|
||||
|
||||
public function fitDetails(&$blocks, $sheetWidth, $sheetHeight, $notch, &$notchCount, $fitOrder = "toRight") {
|
||||
//debug($blocks);exit;
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$this->root = (object)array(
|
||||
'left' => 0,
|
||||
'top' => 0,
|
||||
'width' => $sheetWidth,
|
||||
'height' => $sheetHeight,
|
||||
'isUsed' => false,
|
||||
);
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$this->root = (object)array(
|
||||
'left' => 0,
|
||||
'bottom' => $sheetHeight,
|
||||
'width' => $sheetWidth,
|
||||
'height' => $sheetHeight,
|
||||
'isUsed' => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->notch = $notch;
|
||||
|
||||
foreach ($blocks as &$block) {
|
||||
$node = $this->findNode($this->root, $block->width, $block->height, $fitOrder);
|
||||
|
||||
if ($node) {
|
||||
$block->fit = $this->splitNode($node, $block->width, $block->height, $fitOrder);
|
||||
|
||||
//пропил
|
||||
if ($block->fit->left + $block->width < $sheetWidth) {
|
||||
$notchCount += $block->height;
|
||||
}
|
||||
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
if ($block->fit->top + $block->height < $sheetHeight) {
|
||||
$notchCount += $block->width;
|
||||
}
|
||||
|
||||
if (($block->fit->left + $block->width < $sheetWidth) && ($block->fit->top + $block->height < $sheetHeight)) {
|
||||
//деталь не полностью прилегает к краям - добавляем угол пропила
|
||||
$notchCount += $this->notch;
|
||||
}
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
if ($block->fit->bottom - $block->height > 0) {
|
||||
$notchCount += $block->width;
|
||||
}
|
||||
|
||||
if (($block->fit->left + $block->width < $sheetWidth) && ($block->fit->bottom - $block->height > 0)) {
|
||||
//деталь не полностью прилегает к краям - добавляем угол пропила
|
||||
$notchCount += $this->notch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function findNode(&$root, $width, $height, $fitOrder = "toRight") {
|
||||
if (@$root->isUsed) {
|
||||
if ($fitOrder == "toRight") {
|
||||
$node = $this->findNode($root->right, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node = $this->findNode($root->bottom, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
if ($fitOrder == "toBottom") {
|
||||
$node = $this->findNode($root->bottom, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node = $this->findNode($root->right, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
if ($fitOrder == "toTop") {
|
||||
$node = $this->findNode($root->right, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$node = $this->findNode($root->top, $width, $height, $fitOrder);
|
||||
if ($node) {
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (($width <= $root->width) && ($height <= $root->height)) {
|
||||
return $root;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function splitNode(&$node, $width, $height, $fitOrder) {
|
||||
$node->isUsed = true;
|
||||
|
||||
if (in_array($fitOrder, ['toRight', 'toBottom'])) {
|
||||
$node->right = (object)array(
|
||||
'left' => $node->left + $width + $this->notch,
|
||||
'top' => $node->top,
|
||||
'width' => $node->width - $width - $this->notch,
|
||||
'height' => $height,
|
||||
);
|
||||
|
||||
$node->bottom = (object)array(
|
||||
'left' => $node->left,
|
||||
'top' => $node->top + $height + $this->notch,
|
||||
'width' => $node->width,
|
||||
'height' => $node->height - $height - $this->notch,
|
||||
);
|
||||
} else {
|
||||
if (in_array($fitOrder, ['toTop'])) {
|
||||
$node->right = (object)array(
|
||||
'left' => $node->left + $width + $this->notch,
|
||||
'bottom' => $node->bottom,
|
||||
'width' => $node->width - $width - $this->notch,
|
||||
'height' => $height,
|
||||
);
|
||||
|
||||
$node->top = (object)array(
|
||||
'left' => $node->left,
|
||||
'bottom' => $node->bottom - $height - $this->notch,
|
||||
'width' => $node->width,
|
||||
'height' => $node->height - $height - $this->notch,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
class CalcDoorsOrdersController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["calcDoors"]));
|
||||
}
|
||||
|
||||
|
||||
function index($clientId = null) {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("calcDoors", true, null, $clientId));
|
||||
}
|
||||
|
||||
function getOrders() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
$result['orders'] = $this->getOrdersList("calcDoors", $data);
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function downloadOrderFiles($orderId = null) {
|
||||
if (!empty($orderId)) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $orderId, 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$orderFileName = $order->order_num . '.zip';
|
||||
$orderFileDir = ROOT . '/files/calc_doors_orders/';
|
||||
$fullOrderFileName = $orderFileDir.$orderFileName;
|
||||
|
||||
if (!is_dir($orderFileDir) || !file_exists($fullOrderFileName)) {
|
||||
} else {
|
||||
header('Content-Length: ' . filesize($fullOrderFileName));
|
||||
header('Content-Type: ' . mime_content_type($fullOrderFileName));
|
||||
header('Content-Disposition: attachment; filename="' . $orderFileName . '"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
readfile($fullOrderFileName);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'CalcDoorsOrders', 'action' => 'index', 'prefix' => 'manager']);
|
||||
}
|
||||
|
||||
function takeOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id']) && !empty($data['ready_date'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
if (!empty($order->manager_id)) {
|
||||
if ($order->manager_id == $this->Auth->user('id')) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ уже взят Вами на исполнение'
|
||||
];
|
||||
} else {
|
||||
$user = TableRegistry::getTableLocator()->get('Users')->get($order->manager_id);
|
||||
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ уже взят на исполнение пользователем ' . $user['name']
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result["manager_id"] = $order->manager_id = $this->Auth->user('id');
|
||||
$order->taken_date = $result["taken_date"] = date('Y-m-d H:i:s'); //todo
|
||||
|
||||
if (is_string($data['ready_date'])) {
|
||||
$data['ready_date'] = strtotime($data['ready_date']);
|
||||
} else {
|
||||
$data['ready_date'] = $data['ready_date'] / 1000;
|
||||
}
|
||||
|
||||
$order->ready_date = $result["ready_date"] = date('Y-m-d H:i:s', $data['ready_date']);
|
||||
$result["taken_date"] = $this->patchTimestampForJS($result['taken_date'], 0);
|
||||
$result["ready_date"] = date_timestamp_get($this->patchTimestampForJS($result['ready_date'], 0, false)) * 1000;
|
||||
|
||||
$ordersTable->save($order);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function adminDeleteOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$ordersTable->delete($order);
|
||||
@unlink(ROOT . '/files/calc_doors_orders/'.$order->order_num . '.zip');
|
||||
|
||||
//$ordersTable->revertOrderDbStatistics($order);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данного заказа'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function adminTakeOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CalcDoorsOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
if (empty($data['manager_id'])) {
|
||||
$data['manager_id'] = null;
|
||||
$data['ready_date'] = null;
|
||||
} else {
|
||||
if ($data['manager_id'] != $order->manager_id) {
|
||||
$manager = TableRegistry::getTableLocator()->get('Users')->find()->where(['id' => $data['manager_id']])->first();
|
||||
if (!empty($manager)) {
|
||||
$ordersTable->resendOrderEmailNotify($order, $manager['email'], $this->config);
|
||||
}
|
||||
}
|
||||
}
|
||||
$result["manager_id"] = $order->manager_id = $data['manager_id'];
|
||||
$order->taken_date = $result["taken_date"] = date('Y-m-d H:i:s');
|
||||
|
||||
if ($data['ready_date'] != null) {
|
||||
if (is_string($data['ready_date'])) {
|
||||
$data['ready_date'] = strtotime($data['ready_date']);
|
||||
} else {
|
||||
$data['ready_date'] = $data['ready_date'] / 1000;
|
||||
}
|
||||
|
||||
$order->ready_date = $result["ready_date"] = date('Y-m-d H:i:s', $data['ready_date']);
|
||||
} else {
|
||||
$order->ready_date = $result["ready_date"] = null;
|
||||
}
|
||||
|
||||
$result["taken_date"] = $this->patchTimestampForJS($result['taken_date'], 0);
|
||||
|
||||
if ($data['ready_date'] != null) {
|
||||
$result["ready_date"] = date_timestamp_get($this->patchTimestampForJS($result['ready_date'], 0, false)) * 1000;
|
||||
}
|
||||
|
||||
$ordersTable->save($order);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для изменения данного заказа'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
class CalcDoorsSettingsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["calcDoors"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("calcDoors", true));
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('CalcDoorsSettings');
|
||||
|
||||
switch($data['action']) {
|
||||
case 'saveGroup':
|
||||
if (!empty($data['settings'])) {
|
||||
foreach($data['settings'] as $groupId => $groupData) {
|
||||
foreach($groupData as $s) {
|
||||
if (!in_array($s['id'], ['lastUpdateDate', 'lastUpdateManagerId'])) {
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $s['id'],
|
||||
'group' => $groupId
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $s['value'];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $s['id'],
|
||||
'value' => $s['value'],
|
||||
'group' => $groupId
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("calcDoors", $data['settingsGroup'], $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function addUpdateDoor() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$doorsTable = TableRegistry::getTableLocator()->get('CalcDoors');
|
||||
|
||||
$isOk = false;
|
||||
|
||||
unset($data['image']);
|
||||
$data['params'] = @json_encode($data['params']);
|
||||
|
||||
if (empty($data['id'])) { //add
|
||||
$door = $doorsTable->newEntity();
|
||||
$door = $doorsTable->patchEntity($door, $data);
|
||||
|
||||
if ($doorsTable->save($door)) {
|
||||
$isOk = true;
|
||||
$result['newDoorId'] = $door->id;
|
||||
}
|
||||
} else { //update
|
||||
$door = $doorsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($door)) {
|
||||
$doorsTable->patchEntity($door, $data);
|
||||
if ($doorsTable->save($door)) {
|
||||
$isOk = true;
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Дверь не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['doors'] = $this->getDoorsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("calcDoors", 'doors', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteDoor() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$doorsTable = TableRegistry::getTableLocator()->get('CalcDoors');
|
||||
$door = $doorsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($door)) {
|
||||
$doorsTable->delete($door);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("calcDoors", 'doors', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
if (!empty($door->image)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'doors' . DS . $door->image);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Дверь не найдена'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Недостаточно прав для удаления данной двери'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function uploadImage() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$isOk = false;
|
||||
|
||||
if (!empty($data['type']) && !empty($data['file']["name"]) && empty($data['file']["error"])) {
|
||||
$fileInfo = getimagesize($data['file']["tmp_name"]);
|
||||
$extension = image_type_to_extension($fileInfo[2]);
|
||||
$extension = str_replace("jpeg", "jpg", $extension);
|
||||
|
||||
switch($data['type']) {
|
||||
case "doorImage":
|
||||
$doorsTable = TableRegistry::getTableLocator()->get('CalcDoors');
|
||||
$door = $doorsTable->find()->where(['id' => $data['id']])->first();
|
||||
$subFolder = "doors";
|
||||
|
||||
if (!empty($door)) {
|
||||
$uploadDir = WWW_ROOT . 'img' . DS . $subFolder . DS;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
if (!empty($door->image)) {
|
||||
@unlink($uploadDir.$door->image);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($data['file']["name"] . time()) . time()) . $extension;
|
||||
if (move_uploaded_file($data['file']["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
$door->image = $tmpFileName;
|
||||
$doorsTable->patchEntity($door, $data);
|
||||
|
||||
if ($doorsTable->save($door)) {
|
||||
$isOk = true;
|
||||
$result['image'] = $tmpFileName;
|
||||
$updateGroup = "doors";
|
||||
}
|
||||
};
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Дверь не найдена'
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($isOk && (!empty($updateGroup))) {
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("calcDoors", $updateGroup, $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use PHPExcel;
|
||||
use PHPExcel_Writer_Excel5;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
class CalcDoorsStatisticsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["calcDoors"]));
|
||||
}
|
||||
|
||||
|
||||
function index() {
|
||||
$jsConfig = $this->getAppJsConfig("calcDoors", true);
|
||||
$jsConfig['statistics']['data'] = $this->formatStatisticsPrice($jsConfig['statistics']['data']);
|
||||
$jsConfig['statistics']['total'] = $this->formatStatisticsPrice([$jsConfig['statistics']['total']])[0];
|
||||
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
|
||||
function getStatistics() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
$result['statistics'] = $this->getCalcDoorsStatisticsData($data);
|
||||
$result['statistics']['data'] = $this->formatStatisticsPrice($result['statistics']['data']);
|
||||
$result['statistics']['total'] = $this->formatStatisticsPrice([$result['statistics']['total']])[0];
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function exportClients($year) {
|
||||
$statistics = $this->getCalcDoorsStatisticsData([
|
||||
"select" => "clients",
|
||||
"year" => $year
|
||||
]);
|
||||
|
||||
$xlsData = [
|
||||
[
|
||||
"ФИО",
|
||||
"Email",
|
||||
"Телефон",
|
||||
"Кол-во заказов",
|
||||
"Сумма, руб.",
|
||||
"Фактическая сумма, руб.",
|
||||
]
|
||||
];
|
||||
|
||||
foreach($statistics["data"] as $li) {
|
||||
$xlsData[] = [
|
||||
"name" => $li["name"],
|
||||
"email" => $li["email"],
|
||||
"phone" => $li["phone"],
|
||||
"count" => $li["count"],
|
||||
"price" => $li["price"],
|
||||
"actual_price" => $li["actual_price"]
|
||||
];
|
||||
}
|
||||
|
||||
$xlsSubject = "Clients Export";
|
||||
|
||||
$objPHPExcel = new Spreadsheet();
|
||||
$objPHPExcel->setActiveSheetIndex(0);
|
||||
$objPHPExcel->getActiveSheet()->setTitle('База клиентов');
|
||||
|
||||
$objPHPExcel->getProperties()->setCreator($xlsSubject)
|
||||
->setLastModifiedBy($xlsSubject)
|
||||
->setTitle($xlsSubject);
|
||||
|
||||
$objPHPExcel->getActiveSheet()->fromArray($xlsData, null, 'A1');
|
||||
|
||||
$xlsWriter = new Xls($objPHPExcel);
|
||||
$filename = "doors-clients-export_".date('d-m-Y')."_".date("H-i").".xls";
|
||||
header('Content-type: application/vnd.ms-excel');
|
||||
header('Content-disposition: attachment; filename="' . $filename . '"');
|
||||
$xlsWriter->save('php://output');
|
||||
|
||||
ob_flush();
|
||||
exit;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
class CutOrdersController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["cut"]));
|
||||
}
|
||||
|
||||
|
||||
function index($clientId = null) {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("cut", true, null, $clientId));
|
||||
}
|
||||
|
||||
function getOrders() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
$result['orders'] = $this->getOrdersList("cut", $data);
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function downloadOrderFiles($orderId = null) {
|
||||
if (!empty($orderId)) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $orderId, 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$orderFileName = $order->order_num . '.zip';
|
||||
$orderFileDir = ROOT . '/files/cut_orders/';
|
||||
$fullOrderFileName = $orderFileDir.$orderFileName;
|
||||
|
||||
if (!is_dir($orderFileDir) || !file_exists($fullOrderFileName)) {
|
||||
} else {
|
||||
header('Content-Length: ' . filesize($fullOrderFileName));
|
||||
header('Content-Type: ' . mime_content_type($fullOrderFileName));
|
||||
header('Content-Disposition: attachment; filename="' . $orderFileName . '"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
readfile($fullOrderFileName);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'CutOrders', 'action' => 'index', 'prefix' => 'manager']);
|
||||
}
|
||||
|
||||
function takeOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
if (!empty($order->manager_id)) {
|
||||
if ($order->manager_id == $this->Auth->user('id')) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ уже взят Вами на исполнение'
|
||||
];
|
||||
} else {
|
||||
$user = TableRegistry::getTableLocator()->get('Users')->get($order->manager_id);
|
||||
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ уже взят на исполнение пользователем ' . $user['name']
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result["manager_id"] = $order->manager_id = $this->Auth->user('id');
|
||||
$order->taken_date = $result["taken_date"] = date('Y-m-d H:i:s');
|
||||
|
||||
$result["taken_date"] = $this->patchTimestampForJS($result['taken_date'], 0);
|
||||
|
||||
$ordersTable->save($order);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function adminDeleteOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$ordersTable->delete($order);
|
||||
@unlink(ROOT . '/files/cut_orders/'.$order->order_num . '.zip');
|
||||
|
||||
$ordersTable->revertOrderDbStatistics($order);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данного заказа'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function adminTakeOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
if (empty($data['manager_id'])) {
|
||||
$data['manager_id'] = null;
|
||||
} else {
|
||||
if ($data['manager_id'] != $order->manager_id) {
|
||||
$manager = TableRegistry::getTableLocator()->get('Users')->find()->where(['id' => $data['manager_id']])->first();
|
||||
if (!empty($manager)) {
|
||||
$ordersTable->resendOrderEmailNotify($order, $manager['email'], $this->config);
|
||||
}
|
||||
}
|
||||
}
|
||||
$result["manager_id"] = $order->manager_id = $data['manager_id'];
|
||||
$order->taken_date = $result["taken_date"] = date('Y-m-d H:i:s');
|
||||
|
||||
$result["taken_date"] = $this->patchTimestampForJS($result['taken_date'], 0);
|
||||
|
||||
$ordersTable->save($order);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для изменения данного заказа'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function convertAstraToBazis() {
|
||||
$data = $this->request->getData();
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
if (!empty($data['file']['tmp_name'])) {
|
||||
$importResult = TableRegistry::getTableLocator()->get('CutOrders')->importConvertAstraToBazisFile($data['file']);
|
||||
if ($importResult['status'] == 'success') {
|
||||
$result = $importResult;
|
||||
} else {
|
||||
$result['errors'] = $importResult['errors'];
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function getConvertedAstraToBazisFile($filename, $name) {
|
||||
$fileDir = ROOT . '/files/astra_to_bazis_convert/';
|
||||
$fullFileName = $fileDir.$filename;
|
||||
|
||||
if (!is_dir($fileDir) || !file_exists($fullFileName)) {
|
||||
} else {
|
||||
header('Content-Length: ' . filesize($fullFileName));
|
||||
header('Content-Type: ' . mime_content_type($fullFileName));
|
||||
header('Content-Disposition: attachment; filename="' . $name . '"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
readfile($fullFileName);
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'CutOrders', 'action' => 'index', 'prefix' => 'manager']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,625 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
class CutSettingsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["cut"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("cut", true));
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('CutSettings');
|
||||
|
||||
switch($data['action']) {
|
||||
case 'saveGroup':
|
||||
if (!empty($data['settings'])) {
|
||||
foreach($data['settings'] as $groupId => $groupData) {
|
||||
foreach($groupData as $s) {
|
||||
if (!in_array($s['id'], ['lastUpdateDate', 'lastUpdateManagerId'])) {
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $s['id'],
|
||||
'group' => $groupId
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $s['value'];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $s['id'],
|
||||
'value' => $s['value'],
|
||||
'group' => $groupId
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", $data['settingsGroup'], $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function addUpdateBorderDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$borderDimensionsTable = TableRegistry::getTableLocator()->get('CutBorderDimensions');
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
|
||||
$isOk = false;
|
||||
if (empty($data['id'])) { //add
|
||||
$borderDimension = $borderDimensionsTable->newEntity();
|
||||
$borderDimension = $borderDimensionsTable->patchEntity($borderDimension, $data);
|
||||
|
||||
if ($borderDimensionsTable->save($borderDimension)) {
|
||||
$isOk = true;
|
||||
}
|
||||
|
||||
} else { //update
|
||||
$borderDimension = $borderDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($borderDimension)) {
|
||||
$currentIsActive = $borderDimension->is_active;
|
||||
|
||||
$borderDimensionsTable->patchEntity($borderDimension, $data);
|
||||
if ($borderDimensionsTable->save($borderDimension)) {
|
||||
$isOk = true;
|
||||
|
||||
if (!empty($currentIsActive) && empty($borderDimension['is_active'])) {
|
||||
TableRegistry::getTableLocator()->get('CutBorderAvailableDimensions')->deleteAll([
|
||||
'border_dimension_id' => $data['id']
|
||||
]);
|
||||
|
||||
TableRegistry::getTableLocator()->get('CutBorders')->updateAll(
|
||||
['is_active' => false],
|
||||
['id not in (select distinct border_id from cut_border_available_dimensions)']
|
||||
);
|
||||
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->updateAll(
|
||||
['default_border_id' => null],
|
||||
['default_border_id not in (select distinct border_id from cut_border_available_dimensions)']
|
||||
);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'borders', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
$result['borders'] = $this->getCutBordersListForJS();
|
||||
$result['sheets'] = $this->getCutSheetsListForJS();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Толщина кромки не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['borderDimensions'] = $this->getCutBorderDimensionsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'borderDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteBorderDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$borderAvailableDimensionsTable = TableRegistry::getTableLocator()->get('CutBorderAvailableDimensions');
|
||||
$borderAvailableDimension = $borderAvailableDimensionsTable->find()->where(['border_dimension_id' => $data['id']])->count();
|
||||
|
||||
if (empty($borderAvailableDimension)) {
|
||||
$borderDimensionsTable = TableRegistry::getTableLocator()->get('CutBorderDimensions');
|
||||
$borderDimension = $borderDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($borderDimension)) {
|
||||
$borderDimensionsTable->delete($borderDimension);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'borderDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Толщина кромки не найдена'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'warning',
|
||||
'error' => 'Удаление невозможно, так как существуют кромки с данной толщиной.'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данный толщины кромки'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function addUpdateSheetDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$sheetDimensionsTable = TableRegistry::getTableLocator()->get('CutSheetDimensions');
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
|
||||
$isOk = false;
|
||||
if (empty($data['id'])) { //add
|
||||
$sheetDimension = $sheetDimensionsTable->newEntity();
|
||||
$sheetDimension = $sheetDimensionsTable->patchEntity($sheetDimension, $data);
|
||||
|
||||
if ($sheetDimensionsTable->save($sheetDimension)) {
|
||||
$isOk = true;
|
||||
}
|
||||
|
||||
} else { //update
|
||||
$sheetDimension = $sheetDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($sheetDimension)) {
|
||||
$currentIsActive = $sheetDimension->is_active;
|
||||
|
||||
$sheetDimensionsTable->patchEntity($sheetDimension, $data);
|
||||
if ($sheetDimensionsTable->save($sheetDimension)) {
|
||||
$isOk = true;
|
||||
|
||||
if (!empty($currentIsActive) && empty($sheetDimension['is_active'])) {
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->updateAll(
|
||||
['is_active' => false],
|
||||
['sheet_dimension_id' => $data['id']]
|
||||
);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
$result['sheets'] = $this->getCutSheetsListForJS();;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Размер листа не найден'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['sheetDimensions'] = $this->getCutSheetDimensionsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'sheetDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteSheetDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
$sheets = $sheetsTable->find()->where(['sheet_dimension_id' => $data['id']])->count();
|
||||
|
||||
if (empty($sheets)) {
|
||||
$sheetDimensionsTable = TableRegistry::getTableLocator()->get('CutSheetDimensions');
|
||||
$sheetDimension = $sheetDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($sheetDimension)) {
|
||||
$sheetDimensionsTable->delete($sheetDimension);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'sheetDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Размер листа не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'warning',
|
||||
'error' => 'Удаление невозможно, так как существуют ДСП с данным размером.'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данный толщины кромки'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function addUpdateSheet() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
|
||||
$isOk = false;
|
||||
|
||||
if (empty($data['default_border_id'])) {
|
||||
$data['default_border_id'] = null;
|
||||
}
|
||||
|
||||
unset($data['image']);
|
||||
unset($data['thumb']);
|
||||
unset($data['quantityIn1C']);
|
||||
|
||||
if (empty($data['id'])) { //add
|
||||
$checkFor1C = $sheetsTable->find()->where(['sheetIdFor1C' => $data['sheetIdFor1C']])->first();
|
||||
if (empty($checkFor1C)) {
|
||||
$sheet = $sheetsTable->newEntity();
|
||||
$sheet = $sheetsTable->patchEntity($sheet, $data);
|
||||
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$isOk = true;
|
||||
$result['newSheetId'] = $sheet->id;
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП с таким 1C ID уже есть в базе'
|
||||
];
|
||||
}
|
||||
} else { //update
|
||||
$checkFor1C = $sheetsTable->find()->where([
|
||||
'sheetIdFor1C' => $data['sheetIdFor1C'],
|
||||
'id !=' => $data['id']
|
||||
])->first();
|
||||
if (empty($checkFor1C)) {
|
||||
$sheet = $sheetsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($sheet)) {
|
||||
$sheetsTable->patchEntity($sheet, $data);
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$isOk = true;
|
||||
|
||||
//todo process images if required
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП не найдена'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП с таким 1C ID уже есть в базе'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['sheets'] = $this->getCutSheetsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteSheet() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
$sheet = $sheetsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($sheet)) {
|
||||
$sheetsTable->delete($sheet);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
if (!empty($sheet->image)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'sheets' . DS . $sheet->image);
|
||||
}
|
||||
|
||||
if (!empty($sheet->thumb)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'sheets' . DS . $sheet->thumb);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП не найдена'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данной ДСП'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function deleteBorder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$bordersTable = TableRegistry::getTableLocator()->get('CutBorders');
|
||||
$border = $bordersTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($border)) {
|
||||
$bordersTable->delete($border);
|
||||
|
||||
TableRegistry::getTableLocator()->get('CutBorderAvailableDimensions')->deleteAll([
|
||||
'border_id' => $data['id']
|
||||
]);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'borders', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
if (!empty($border->image)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'borders' . DS . $border->image);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Кромка не найдена'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данной кромки'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function addUpdateBorder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$bordersTable = TableRegistry::getTableLocator()->get('CutBorders');
|
||||
$isOk = false;
|
||||
|
||||
unset($data['image']);
|
||||
|
||||
if (empty($data['id'])) { //add
|
||||
$border = $bordersTable->newEntity();
|
||||
$border = $bordersTable->patchEntity($border, $data);
|
||||
|
||||
if ($bordersTable->save($border)) {
|
||||
$isOk = true;
|
||||
$result['newBorderId'] = $border->id;
|
||||
}
|
||||
} else { //update
|
||||
$border = $bordersTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($border)) {
|
||||
$bordersTable->patchEntity($border, $data);
|
||||
if ($bordersTable->save($border)) {
|
||||
$isOk = true;
|
||||
|
||||
//todo process images if required
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Кромка не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$availableDimensions = Hash::extract($data['available_dimensions'], '{n}.border_dimension_id');
|
||||
TableRegistry::getTableLocator()->get('CutBorderAvailableDimensions')->deleteAll([
|
||||
'border_id' => $border->id,
|
||||
'border_dimension_id not in ' => $availableDimensions
|
||||
]);
|
||||
|
||||
$result['borders'] = $this->getCutBordersListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", 'borders', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function uploadImage() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$isOk = false;
|
||||
|
||||
if (!empty($data['type']) && !empty($data['file']["name"]) && empty($data['file']["error"])) {
|
||||
$fileInfo = getimagesize($data['file']["tmp_name"]);
|
||||
$extension = image_type_to_extension($fileInfo[2]);
|
||||
$extension = str_replace("jpeg", "jpg", $extension);
|
||||
|
||||
switch($data['type']) {
|
||||
case "sheetImage":
|
||||
case "sheetThumb":
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
$sheet = $sheetsTable->find()->where(['id' => $data['id']])->first();
|
||||
$subFolder = ($data['type'] == "sheetImage" ? "sheets" : "sheet_thumbs");
|
||||
|
||||
if (!empty($sheet)) {
|
||||
$uploadDir = WWW_ROOT . 'img' . DS . $subFolder . DS;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
if (($data['type'] == "sheetImage") && !empty($sheet->image)) {
|
||||
@unlink($uploadDir.$sheet->image);
|
||||
}
|
||||
|
||||
if (($data['type'] == "sheetThumb") && !empty($sheet->thumb)) {
|
||||
@unlink($uploadDir.$sheet->thumb);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($data['file']["name"] . time()) . time()) . $extension;
|
||||
if (move_uploaded_file($data['file']["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
if ($data['type'] == "sheetImage") {
|
||||
$sheet->image = $tmpFileName;
|
||||
} else {
|
||||
$sheet->thumb = $tmpFileName;
|
||||
}
|
||||
$sheetsTable->patchEntity($sheet, $data);
|
||||
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$isOk = true;
|
||||
$result['image'] = $tmpFileName;
|
||||
$updateGroup = "sheets";
|
||||
}
|
||||
};
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП не найдена'
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
case "borderImage":
|
||||
$bordersTable = TableRegistry::getTableLocator()->get('CutBorders');
|
||||
$border = $bordersTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($border)) {
|
||||
$uploadDir = WWW_ROOT . 'img' . DS . 'borders' . DS;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
if (!empty($border->image)) {
|
||||
@unlink($uploadDir.$border->image);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($data['file']["name"] . time()) . time()) . $extension;
|
||||
if (move_uploaded_file($data['file']["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
$border->image = $tmpFileName;
|
||||
$bordersTable->patchEntity($border, $data);
|
||||
|
||||
if ($bordersTable->save($border)) {
|
||||
$isOk = true;
|
||||
$result['image'] = $tmpFileName;
|
||||
$updateGroup = "borders";
|
||||
}
|
||||
};
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Кромка не найдена'
|
||||
];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($isOk && (!empty($updateGroup))) {
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("cut", $updateGroup, $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
class CutStatisticsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["cut"]));
|
||||
}
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("cut", true));
|
||||
}
|
||||
|
||||
function getStatistics() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
$result['statistics'] = $this->getCutStatisticsData($data);
|
||||
$result['statistics']['data'] = $this->formatStatisticsPrice($result['statistics']['data']);
|
||||
$result['statistics']['total'] = $this->formatStatisticsPrice([$result['statistics']['total']])[0];
|
||||
$result['statistics']['totalByMonth'] = $this->formatStatisticsPrice([$result['statistics']['totalByMonth']])[0];
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function exportClients($year) {
|
||||
$statistics = $this->getCutStatisticsData([
|
||||
"select" => "clients",
|
||||
"year" => $year
|
||||
]);
|
||||
|
||||
$xlsData = [
|
||||
[
|
||||
"ФИО",
|
||||
"Email",
|
||||
"Телефон",
|
||||
"Кол-во заказов",
|
||||
"Сумма, руб."
|
||||
]
|
||||
];
|
||||
|
||||
foreach($statistics["data"] as $li) {
|
||||
$xlsData[] = [
|
||||
"name" => $li["name"],
|
||||
"email" => $li["email"],
|
||||
"phone" => $li["phone"],
|
||||
"count" => $li["count"],
|
||||
"price" => $li["price"]
|
||||
];
|
||||
}
|
||||
|
||||
$xlsSubject = "Clients Export";
|
||||
|
||||
$objPHPExcel = new Spreadsheet();
|
||||
$objPHPExcel->setActiveSheetIndex(0);
|
||||
$objPHPExcel->getActiveSheet()->setTitle('База клиентов');
|
||||
|
||||
$objPHPExcel->getProperties()->setCreator($xlsSubject)
|
||||
->setLastModifiedBy($xlsSubject)
|
||||
->setTitle($xlsSubject);
|
||||
|
||||
$objPHPExcel->getActiveSheet()->fromArray($xlsData, null, 'A1');
|
||||
|
||||
$xlsWriter = new Xls($objPHPExcel);
|
||||
$filename = "cut-clients-export_".date('d-m-Y')."_".date("H-i").".xls";
|
||||
header('Content-type: application/vnd.ms-excel');
|
||||
header('Content-disposition: attachment; filename="' . $filename . '"');
|
||||
$xlsWriter->save('php://output');
|
||||
|
||||
ob_flush();
|
||||
exit;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
|
||||
|
||||
class DeliveryJournalController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["deliveryJournal"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("deliveryJournal", true);
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
|
||||
switch($data['action']) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
|
||||
class EmailSubscribesController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["emailSubscribes"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("emailSubscribes", true);
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("EmailSubscribes");
|
||||
$subscribesRecipientsTable = TableRegistry::getTableLocator()->get("EmailSubscribeRecipients");
|
||||
$subscribesAttachmentsTable = TableRegistry::getTableLocator()->get("EmailSubscribeAttachments");
|
||||
|
||||
switch($data['action']) {
|
||||
case "getSubscribes":
|
||||
$subscribeId = (int) $data['subscribeId'];
|
||||
|
||||
if (!empty($subscribeId)) {
|
||||
|
||||
} else {
|
||||
$result['subscribes'] = $this->getSubscribesList("EmailSubscribes", $data);
|
||||
}
|
||||
|
||||
$result['status'] = "success";
|
||||
break;
|
||||
|
||||
|
||||
case "setSubscribeStatus":
|
||||
$subscribeId = (int) $data['subscribeId'];
|
||||
$newStatus = $data['newStatus'];
|
||||
|
||||
if (!empty($subscribeId) && !empty($newStatus)) {
|
||||
$subscribe = $subscribesTable->find('all')->where(['id' => $subscribeId])->first();
|
||||
|
||||
if (!empty($subscribe)) {
|
||||
if ($this->isSubscribeUpdateAllowed($subscribe['status'])) {
|
||||
$isStatusChangeAllowed = true;
|
||||
|
||||
if ($newStatus == "deleted") {
|
||||
if (($subscribe['createdBy'] != $this->Auth->user('id')) && ($this->Auth->user('role') != 'admin')) {
|
||||
$isStatusChangeAllowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isStatusChangeAllowed) {
|
||||
$subscribe->status = $newStatus;
|
||||
|
||||
if ($newStatus == "queued") {
|
||||
$subscribe->queuedBy = $this->Auth->user('id');
|
||||
$subscribe->stoppedBy = null;
|
||||
}
|
||||
|
||||
if ($newStatus == "stopped") {
|
||||
$subscribe->stoppedBy = $this->Auth->user('id');
|
||||
}
|
||||
|
||||
if ($subscribesTable->save($subscribe)) {
|
||||
$result['status'] = "success";
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Недостаточно прав для изменения статуса рассылки';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Редактирование активной или завершенной рассылки недоступно';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Рассылка не найдена!';
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "addSubscribe":
|
||||
if (!empty($data['subject'])) {
|
||||
$data['created'] = date('Y-m-d H:i:s');
|
||||
$data['createdBy'] = $this->Auth->user('id');
|
||||
$data['status'] = "stopped";
|
||||
|
||||
$subscribe = $subscribesTable->newEntity();
|
||||
$subscribe = $subscribesTable->patchEntity($subscribe, $data);
|
||||
|
||||
if ($subscribesTable->save($subscribe)) {
|
||||
$result['subscribe'] = $this->getSubscribeData("EmailSubscribes", $subscribe->id);
|
||||
$result['status'] = "success";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "updateSubscribe":
|
||||
if (!empty($data['id'])) {
|
||||
$subscribe = $this->getSubscribeData("EmailSubscribes", $data['id']);
|
||||
|
||||
if (!empty($subscribe)) {
|
||||
if ($this->isSubscribeUpdateAllowed($subscribe['status'])) {
|
||||
unset($data['created']);
|
||||
unset($data['createdBy']);
|
||||
unset($data['queuedBy']);
|
||||
unset($data['stoppedBy']);
|
||||
unset($data['errorsCount']);
|
||||
unset($data['sentCount']);
|
||||
unset($data['startTime']);
|
||||
unset($data['status']);
|
||||
unset($data['successCount']);
|
||||
$data['recipientsCount'] = count($data['email_subscribe_recipients']);
|
||||
|
||||
if (!empty($data['email_subscribe_recipients'])) {
|
||||
foreach ($data['email_subscribe_recipients'] as $recipientKey => $recipient) {
|
||||
unset($data['email_subscribe_recipients'][$recipientKey]['sendStatus']);
|
||||
unset($data['email_subscribe_recipients'][$recipientKey]['statusMessage']);
|
||||
unset($data['email_subscribe_recipients'][$recipientKey]['sendDate']);
|
||||
}
|
||||
}
|
||||
|
||||
$subscribe = $subscribesTable->get($data['id']);
|
||||
$subscribe = $subscribesTable->patchEntity($subscribe, $data);
|
||||
|
||||
if ($subscribesTable->save($subscribe)) {
|
||||
if (!empty($data['recipientsToDelete'])) {
|
||||
foreach ($data['recipientsToDelete'] as $recipientToDelete) {
|
||||
$subscribesRecipientsTable->deleteAll([
|
||||
'subscribeId' => $data['id'],
|
||||
'id' => $recipientToDelete
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['attachmentsToDelete'])) {
|
||||
foreach ($data['attachmentsToDelete'] as $attachmentToDelete) {
|
||||
$currentAttachment = $subscribesAttachmentsTable->find()->where([
|
||||
'subscribeId' => $data['id'],
|
||||
'id' => $attachmentToDelete
|
||||
])->first();
|
||||
|
||||
if (!empty($currentAttachment)) {
|
||||
if (!empty($currentAttachment['filename'])) {
|
||||
@unlink(ROOT . DS . 'files' . DS . 'email_subscribes' . DS . $currentAttachment['filename']);
|
||||
}
|
||||
$subscribesAttachmentsTable->delete($currentAttachment);
|
||||
|
||||
}
|
||||
|
||||
$subscribesAttachmentsTable->deleteAll([
|
||||
'subscribeId' => $data['id'],
|
||||
'id' => $attachmentToDelete
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$result['subscribe'] = $subscribe;
|
||||
$result['status'] = "success";
|
||||
}
|
||||
|
||||
$result['status'] = "success";
|
||||
} else {
|
||||
$result['errors'][] = 'Редактирование активной или завершенной рассылки недоступно';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Рассылка не найдена!';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case "getSubscribeData":
|
||||
if (!empty($data['subscribeId'])) {
|
||||
$subscribe = $this->getSubscribeData("EmailSubscribes", $data['subscribeId']);
|
||||
|
||||
if (!empty($subscribe)) {
|
||||
$result['subscribe'] = $subscribe;
|
||||
$result['status'] = "success";
|
||||
} else {
|
||||
$result['errors'][] = 'Рассылка не найдена!';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "importSubscribeRecipients":
|
||||
$source = !empty($data['file']['tmp_name']) ? $data['file']['tmp_name'] : '';
|
||||
$subscribeId = (!empty($data['subscribeId']) ? (int) $data['subscribeId'] : null);
|
||||
|
||||
if (!empty($source) && !empty($subscribeId)) {
|
||||
$importResult = $subscribesTable->importSubscribesList($source);
|
||||
$result['importNewSubscribersCount'] = 0;
|
||||
$result['importNewSubscribersCountTotal'] = 0;
|
||||
|
||||
if (count($importResult['list']) > 0) {
|
||||
$result['status'] = 'success';
|
||||
$result['importNewSubscribersCountTotal'] = count($importResult['list']);
|
||||
|
||||
$subscribers = (!empty($data['email_subscribe_recipients']) ? $data['email_subscribe_recipients'] : []);
|
||||
if (!empty($subscribers)) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
unset($importResult['list'][$subscriber['email']]); //cleanup duplicates
|
||||
}
|
||||
}
|
||||
$result['importNewSubscribersCount'] = count($importResult['list']);
|
||||
|
||||
if (!empty($importResult['list'])) {
|
||||
foreach($importResult['list'] as $newSubscriberEmail => $newSubscriberName) {
|
||||
$subscribers[] = [
|
||||
"name" => $newSubscriberName,
|
||||
"email" => $newSubscriberEmail,
|
||||
"sendStatus" => "queued"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
usort($subscribers, function($a, $b) {
|
||||
return strcmp($a['name'], $b['name']);
|
||||
});
|
||||
|
||||
foreach($subscribers as $key => $subscriber) { //fix "null" due to incorrect upload field values
|
||||
foreach($subscriber as $subKey => $value) {
|
||||
if ($value == "null") {
|
||||
$subscriber[$subKey] = null;
|
||||
}
|
||||
}
|
||||
|
||||
$subscribers[$key] = $subscriber;
|
||||
}
|
||||
|
||||
$result['importSubscribers'] = $subscribers;
|
||||
} else {
|
||||
$result['errors'][] = 'Неверный формат файла или список получателей пуст.';
|
||||
}
|
||||
|
||||
$result['incorrectList'] = $importResult['incorrectList'];
|
||||
$result['importNewSubscribersCountTotal'] += count($importResult['incorrectList']);
|
||||
if (count($result['incorrectList'])) {
|
||||
$result['status'] = 'success';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
|
||||
//debug($result);exit;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case "importSubscribeAttachments":
|
||||
$subscribeId = (!empty($data['subscribeId']) ? (int) $data['subscribeId'] : null);
|
||||
|
||||
if (!empty($data['file']) && !empty($subscribeId)) {
|
||||
$importResult = $subscribesTable->importSubscribeAttachments($data['file']);
|
||||
if (count($importResult['list']) > 0) {
|
||||
$result['status'] = 'success';
|
||||
$result['importNewAttachmentsCountTotal'] = count($importResult['list']);
|
||||
|
||||
$attachments = (!empty($data['email_subscribe_attachments']) ? $data['email_subscribe_attachments'] : []);
|
||||
if (!empty($attachments)) {
|
||||
foreach($attachments as $attachment) {
|
||||
$b64 = base64_encode($attachment['name']);
|
||||
@unlink(ROOT . DS . 'files' . DS . 'email_subscribes' . DS . $importResult['list'][$b64]['filename']);
|
||||
unset($importResult['list'][$b64]); //cleanup duplicates
|
||||
}
|
||||
}
|
||||
$result['importNewAttachmentsCount'] = count($importResult['list']);
|
||||
|
||||
|
||||
if (!empty($importResult['list'])) {
|
||||
foreach($importResult['list'] as $importFileName => $importFile) {
|
||||
$attachments[] = [
|
||||
"name" => $importFile['name'],
|
||||
"filename" => $importFile['filename'],
|
||||
"filesize" => $importFile['filesize'],
|
||||
"mime" => $importFile['mime']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
usort($attachments, function($a, $b) {
|
||||
return strcmp($a['name'], $b['name']);
|
||||
});
|
||||
|
||||
foreach($attachments as $key => $attachment) { //fix "null" due to incorrect upload field values
|
||||
foreach($attachment as $subKey => $value) {
|
||||
if ($value == "null") {
|
||||
$attachment[$subKey] = null;
|
||||
}
|
||||
}
|
||||
|
||||
$attachments[$key] = $attachment;
|
||||
}
|
||||
|
||||
$result['importAttachments'] = $attachments;
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case "uploadSubscribeImage":
|
||||
$subscribeId = (!empty($data['subscribeId']) ? (int) $data['subscribeId'] : null);
|
||||
|
||||
if (!empty($data['file']) && !empty($subscribeId)) {
|
||||
$importResult = $subscribesTable->uploadSubscribeImage($data['file']);
|
||||
if (count($importResult['list']) > 0) {
|
||||
$result['status'] = 'success';
|
||||
$result['image'] = $importResult['list'][0];
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public function getSubscribeAttachment($filename, $name) {
|
||||
if (!empty($filename)) {
|
||||
$filename = ROOT . DS . 'files' . DS . 'email_subscribes' . DS . $filename;
|
||||
if (file_exists($filename)) {
|
||||
header('Content-Length: ' . filesize($filename));
|
||||
header('Content-Type: ' . mime_content_type($filename));
|
||||
header('Content-Disposition: attachment; filename="' . $name . '"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
readfile($filename);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'EmailSubscribes', 'action' => 'index', 'prefix' => 'manager']);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function getSubscribeAttachmentImage($filename) {
|
||||
if (!empty($filename)) {
|
||||
$filename = ROOT . DS . 'files' . DS . 'email_subscribes' . DS . $filename;
|
||||
if (file_exists($filename)) {
|
||||
header('Content-Length: ' . filesize($filename));
|
||||
header('Content-Type: ' . mime_content_type($filename));
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header("Cache-control: public");
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 60*60*24*365) . " GMT");
|
||||
readfile($filename);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'EmailSubscribes', 'action' => 'index', 'prefix' => 'manager']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
class FasadOrdersController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["fasad"]));
|
||||
}
|
||||
|
||||
|
||||
function index($clientId = null) {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("fasad", true, null, $clientId));
|
||||
}
|
||||
|
||||
function getOrders() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
$result['orders'] = $this->getOrdersList("fasad", $data);
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function downloadOrderFiles($orderId = null) {
|
||||
if (!empty($orderId)) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('FasadOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $orderId, 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$orderFileName = $order->order_num . '.zip';
|
||||
$orderFileDir = ROOT . '/files/fasad_orders/';
|
||||
$fullOrderFileName = $orderFileDir.$orderFileName;
|
||||
|
||||
if (!is_dir($orderFileDir) || !file_exists($fullOrderFileName)) {
|
||||
} else {
|
||||
header('Content-Length: ' . filesize($fullOrderFileName));
|
||||
header('Content-Type: ' . mime_content_type($fullOrderFileName));
|
||||
header('Content-Disposition: attachment; filename="' . $orderFileName . '"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
readfile($fullOrderFileName);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'FasadOrders', 'action' => 'index', 'prefix' => 'manager']);
|
||||
}
|
||||
|
||||
function takeOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('FasadOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
if (!empty($order->manager_id)) {
|
||||
if ($order->manager_id == $this->Auth->user('id')) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ уже взят Вами на исполнение'
|
||||
];
|
||||
} else {
|
||||
$user = TableRegistry::getTableLocator()->get('Users')->get($order->manager_id);
|
||||
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ уже взят на исполнение пользователем ' . $user['name']
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result["manager_id"] = $order->manager_id = $this->Auth->user('id');
|
||||
$order->taken_date = $result["taken_date"] = date('Y-m-d H:i:s');
|
||||
|
||||
$result["taken_date"] = $this->patchTimestampForJS($result['taken_date'], 0);
|
||||
|
||||
$ordersTable->save($order);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function adminDeleteOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('FasadOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$ordersTable->delete($order);
|
||||
@unlink(ROOT . '/files/fasad_orders/'.$order->order_num . '.zip');
|
||||
|
||||
$ordersTable->revertOrderDbStatistics($order);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данного заказа'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function adminTakeOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('FasadOrders');
|
||||
$order = $ordersTable->find()->where(['id' => $data['id'], 'order_type' => 'order'])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
if (empty($data['manager_id'])) {
|
||||
$data['manager_id'] = null;
|
||||
} else {
|
||||
if ($data['manager_id'] != $order->manager_id) {
|
||||
$manager = TableRegistry::getTableLocator()->get('Users')->find()->where(['id' => $data['manager_id']])->first();
|
||||
if (!empty($manager)) {
|
||||
$ordersTable->resendOrderEmailNotify($order, $manager['email'], $this->config);
|
||||
}
|
||||
}
|
||||
}
|
||||
$result["manager_id"] = $order->manager_id = $data['manager_id'];
|
||||
$order->taken_date = $result["taken_date"] = date('Y-m-d H:i:s');
|
||||
|
||||
$result["taken_date"] = $this->patchTimestampForJS($result['taken_date'], 0);
|
||||
|
||||
$ordersTable->save($order);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Заказ не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для изменения данного заказа'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function convertAstraToBazis() {
|
||||
$data = $this->request->getData();
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
if (!empty($data['file']['tmp_name'])) {
|
||||
$importResult = TableRegistry::getTableLocator()->get('FasadOrders')->importConvertAstraToBazisFile($data['file']);
|
||||
if ($importResult['status'] == 'success') {
|
||||
$result = $importResult;
|
||||
} else {
|
||||
$result['errors'] = $importResult['errors'];
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function getConvertedAstraToBazisFile($filename, $name) {
|
||||
$fileDir = ROOT . '/files/astra_to_bazis_convert/';
|
||||
$fullFileName = $fileDir.$filename;
|
||||
|
||||
if (!is_dir($fileDir) || !file_exists($fullFileName)) {
|
||||
} else {
|
||||
header('Content-Length: ' . filesize($fullFileName));
|
||||
header('Content-Type: ' . mime_content_type($fullFileName));
|
||||
header('Content-Disposition: attachment; filename="' . $name . '"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
readfile($fullFileName);
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->redirect(['controller' => 'FasadOrders', 'action' => 'index', 'prefix' => 'manager']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,625 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
class FasadSettingsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["fasad"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("fasad", true));
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('FasadSettings');
|
||||
|
||||
switch($data['action']) {
|
||||
case 'saveGroup':
|
||||
if (!empty($data['settings'])) {
|
||||
foreach($data['settings'] as $groupId => $groupData) {
|
||||
foreach($groupData as $s) {
|
||||
if (!in_array($s['id'], ['lastUpdateDate', 'lastUpdateManagerId'])) {
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $s['id'],
|
||||
'group' => $groupId
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $s['value'];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $s['id'],
|
||||
'value' => $s['value'],
|
||||
'group' => $groupId
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", $data['settingsGroup'], $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function addUpdateBorderDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$borderDimensionsTable = TableRegistry::getTableLocator()->get('FasadBorderDimensions');
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
|
||||
$isOk = false;
|
||||
if (empty($data['id'])) { //add
|
||||
$borderDimension = $borderDimensionsTable->newEntity();
|
||||
$borderDimension = $borderDimensionsTable->patchEntity($borderDimension, $data);
|
||||
|
||||
if ($borderDimensionsTable->save($borderDimension)) {
|
||||
$isOk = true;
|
||||
}
|
||||
|
||||
} else { //update
|
||||
$borderDimension = $borderDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($borderDimension)) {
|
||||
$currentIsActive = $borderDimension->is_active;
|
||||
|
||||
$borderDimensionsTable->patchEntity($borderDimension, $data);
|
||||
if ($borderDimensionsTable->save($borderDimension)) {
|
||||
$isOk = true;
|
||||
|
||||
if (!empty($currentIsActive) && empty($borderDimension['is_active'])) {
|
||||
TableRegistry::getTableLocator()->get('FasadBorderAvailableDimensions')->deleteAll([
|
||||
'border_dimension_id' => $data['id']
|
||||
]);
|
||||
|
||||
TableRegistry::getTableLocator()->get('FasadBorders')->updateAll(
|
||||
['is_active' => false],
|
||||
['id not in (select distinct border_id from fasad_border_available_dimensions)']
|
||||
);
|
||||
|
||||
TableRegistry::getTableLocator()->get('FasadSheets')->updateAll(
|
||||
['default_border_id' => null],
|
||||
['default_border_id not in (select distinct border_id from fasad_border_available_dimensions)']
|
||||
);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'borders', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
$result['borders'] = $this->getFasadBordersListForJS();
|
||||
$result['sheets'] = $this->getFasadSheetsListForJS();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Толщина кромки не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['borderDimensions'] = $this->getFasadBorderDimensionsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'borderDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteBorderDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$borderAvailableDimensionsTable = TableRegistry::getTableLocator()->get('FasadBorderAvailableDimensions');
|
||||
$borderAvailableDimension = $borderAvailableDimensionsTable->find()->where(['border_dimension_id' => $data['id']])->count();
|
||||
|
||||
if (empty($borderAvailableDimension)) {
|
||||
$borderDimensionsTable = TableRegistry::getTableLocator()->get('FasadBorderDimensions');
|
||||
$borderDimension = $borderDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($borderDimension)) {
|
||||
$borderDimensionsTable->delete($borderDimension);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'borderDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Толщина кромки не найдена'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'warning',
|
||||
'error' => 'Удаление невозможно, так как существуют кромки с данной толщиной.'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данный толщины кромки'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function addUpdateSheetDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$sheetDimensionsTable = TableRegistry::getTableLocator()->get('FasadSheetDimensions');
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
|
||||
$isOk = false;
|
||||
if (empty($data['id'])) { //add
|
||||
$sheetDimension = $sheetDimensionsTable->newEntity();
|
||||
$sheetDimension = $sheetDimensionsTable->patchEntity($sheetDimension, $data);
|
||||
|
||||
if ($sheetDimensionsTable->save($sheetDimension)) {
|
||||
$isOk = true;
|
||||
}
|
||||
|
||||
} else { //update
|
||||
$sheetDimension = $sheetDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($sheetDimension)) {
|
||||
$currentIsActive = $sheetDimension->is_active;
|
||||
|
||||
$sheetDimensionsTable->patchEntity($sheetDimension, $data);
|
||||
if ($sheetDimensionsTable->save($sheetDimension)) {
|
||||
$isOk = true;
|
||||
|
||||
if (!empty($currentIsActive) && empty($sheetDimension['is_active'])) {
|
||||
TableRegistry::getTableLocator()->get('FasadSheets')->updateAll(
|
||||
['is_active' => false],
|
||||
['sheet_dimension_id' => $data['id']]
|
||||
);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
$result['sheets'] = $this->getFasadSheetsListForJS();;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Размер листа не найден'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['sheetDimensions'] = $this->getFasadSheetDimensionsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'sheetDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteSheetDimension() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('FasadSheets');
|
||||
$sheets = $sheetsTable->find()->where(['sheet_dimension_id' => $data['id']])->count();
|
||||
|
||||
if (empty($sheets)) {
|
||||
$sheetDimensionsTable = TableRegistry::getTableLocator()->get('FasadSheetDimensions');
|
||||
$sheetDimension = $sheetDimensionsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($sheetDimension)) {
|
||||
$sheetDimensionsTable->delete($sheetDimension);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'sheetDimensions', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Размер листа не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'warning',
|
||||
'error' => 'Удаление невозможно, так как существуют ДСП с данным размером.'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данный толщины кромки'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function addUpdateSheet() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('FasadSheets');
|
||||
|
||||
$isOk = false;
|
||||
|
||||
if (empty($data['default_border_id'])) {
|
||||
$data['default_border_id'] = null;
|
||||
}
|
||||
|
||||
unset($data['image']);
|
||||
unset($data['thumb']);
|
||||
unset($data['quantityIn1C']);
|
||||
|
||||
if (empty($data['id'])) { //add
|
||||
$checkFor1C = $sheetsTable->find()->where(['sheetIdFor1C' => $data['sheetIdFor1C']])->first();
|
||||
if (empty($checkFor1C)) {
|
||||
$sheet = $sheetsTable->newEntity();
|
||||
$sheet = $sheetsTable->patchEntity($sheet, $data);
|
||||
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$isOk = true;
|
||||
$result['newSheetId'] = $sheet->id;
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП с таким 1C ID уже есть в базе'
|
||||
];
|
||||
}
|
||||
} else { //update
|
||||
$checkFor1C = $sheetsTable->find()->where([
|
||||
'sheetIdFor1C' => $data['sheetIdFor1C'],
|
||||
'id !=' => $data['id']
|
||||
])->first();
|
||||
if (empty($checkFor1C)) {
|
||||
$sheet = $sheetsTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($sheet)) {
|
||||
$sheetsTable->patchEntity($sheet, $data);
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$isOk = true;
|
||||
|
||||
//todo process images if required
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП не найдена'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП с таким 1C ID уже есть в базе'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['sheets'] = $this->getFasadSheetsListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteSheet() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('FasadSheets');
|
||||
$sheet = $sheetsTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($sheet)) {
|
||||
$sheetsTable->delete($sheet);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'sheets', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
if (!empty($sheet->image)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'sheets' . DS . $sheet->image);
|
||||
}
|
||||
|
||||
if (!empty($sheet->thumb)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'sheets' . DS . $sheet->thumb);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП не найдена'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данной ДСП'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function deleteBorder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$bordersTable = TableRegistry::getTableLocator()->get('FasadBorders');
|
||||
$border = $bordersTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($border)) {
|
||||
$bordersTable->delete($border);
|
||||
|
||||
TableRegistry::getTableLocator()->get('FasadBorderAvailableDimensions')->deleteAll([
|
||||
'border_id' => $data['id']
|
||||
]);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'borders', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
if (!empty($border->image)) {
|
||||
@unlink(WWW_ROOT . 'img' . DS . 'borders' . DS . $border->image);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Кромка не найдена'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данной кромки'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function addUpdateBorder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$bordersTable = TableRegistry::getTableLocator()->get('FasadBorders');
|
||||
$isOk = false;
|
||||
|
||||
unset($data['image']);
|
||||
|
||||
if (empty($data['id'])) { //add
|
||||
$border = $bordersTable->newEntity();
|
||||
$border = $bordersTable->patchEntity($border, $data);
|
||||
|
||||
if ($bordersTable->save($border)) {
|
||||
$isOk = true;
|
||||
$result['newBorderId'] = $border->id;
|
||||
}
|
||||
} else { //update
|
||||
$border = $bordersTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($border)) {
|
||||
$bordersTable->patchEntity($border, $data);
|
||||
if ($bordersTable->save($border)) {
|
||||
$isOk = true;
|
||||
|
||||
//todo process images if required
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Кромка не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$availableDimensions = Hash::extract($data['available_dimensions'], '{n}.border_dimension_id');
|
||||
TableRegistry::getTableLocator()->get('FasadBorderAvailableDimensions')->deleteAll([
|
||||
'border_id' => $border->id,
|
||||
'border_dimension_id not in ' => $availableDimensions
|
||||
]);
|
||||
|
||||
$result['borders'] = $this->getFasadBordersListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", 'borders', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function uploadImage() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$isOk = false;
|
||||
|
||||
if (!empty($data['type']) && !empty($data['file']["name"]) && empty($data['file']["error"])) {
|
||||
$fileInfo = getimagesize($data['file']["tmp_name"]);
|
||||
$extension = image_type_to_extension($fileInfo[2]);
|
||||
$extension = str_replace("jpeg", "jpg", $extension);
|
||||
|
||||
switch($data['type']) {
|
||||
case "sheetImage":
|
||||
case "sheetThumb":
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('FasadSheets');
|
||||
$sheet = $sheetsTable->find()->where(['id' => $data['id']])->first();
|
||||
$subFolder = ($data['type'] == "sheetImage" ? "fasad_sheets" : "fasad_sheet_thumbs");
|
||||
|
||||
if (!empty($sheet)) {
|
||||
$uploadDir = WWW_ROOT . 'img' . DS . $subFolder . DS;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
if (($data['type'] == "sheetImage") && !empty($sheet->image)) {
|
||||
@unlink($uploadDir.$sheet->image);
|
||||
}
|
||||
|
||||
if (($data['type'] == "sheetThumb") && !empty($sheet->thumb)) {
|
||||
@unlink($uploadDir.$sheet->thumb);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($data['file']["name"] . time()) . time()) . $extension;
|
||||
if (move_uploaded_file($data['file']["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
if ($data['type'] == "sheetImage") {
|
||||
$sheet->image = $tmpFileName;
|
||||
} else {
|
||||
$sheet->thumb = $tmpFileName;
|
||||
}
|
||||
$sheetsTable->patchEntity($sheet, $data);
|
||||
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$isOk = true;
|
||||
$result['image'] = $tmpFileName;
|
||||
$updateGroup = "sheets";
|
||||
}
|
||||
};
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'ДСП не найдена'
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
case "borderImage":
|
||||
$bordersTable = TableRegistry::getTableLocator()->get('FasadBorders');
|
||||
$border = $bordersTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($border)) {
|
||||
$uploadDir = WWW_ROOT . 'img' . DS . 'fasad_borders' . DS;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
if (!empty($border->image)) {
|
||||
@unlink($uploadDir.$border->image);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($data['file']["name"] . time()) . time()) . $extension;
|
||||
if (move_uploaded_file($data['file']["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
$border->image = $tmpFileName;
|
||||
$bordersTable->patchEntity($border, $data);
|
||||
|
||||
if ($bordersTable->save($border)) {
|
||||
$isOk = true;
|
||||
$result['image'] = $tmpFileName;
|
||||
$updateGroup = "borders";
|
||||
}
|
||||
};
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Кромка не найдена'
|
||||
];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($isOk && (!empty($updateGroup))) {
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("fasad", $updateGroup, $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
class FasadStatisticsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["fasad"]));
|
||||
}
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("fasad", true));
|
||||
}
|
||||
|
||||
function getStatistics() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
$result['statistics'] = $this->getFasadStatisticsData($data);
|
||||
$result['statistics']['data'] = $this->formatStatisticsPrice($result['statistics']['data']);
|
||||
$result['statistics']['total'] = $this->formatStatisticsPrice([$result['statistics']['total']])[0];
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function exportClients($year) {
|
||||
$statistics = $this->getFasadStatisticsData([
|
||||
"select" => "clients",
|
||||
"year" => $year
|
||||
]);
|
||||
|
||||
$xlsData = [
|
||||
[
|
||||
"ФИО",
|
||||
"Email",
|
||||
"Телефон",
|
||||
"Кол-во заказов",
|
||||
"Сумма, руб."
|
||||
]
|
||||
];
|
||||
|
||||
foreach($statistics["data"] as $li) {
|
||||
$xlsData[] = [
|
||||
"name" => $li["name"],
|
||||
"email" => $li["email"],
|
||||
"phone" => $li["phone"],
|
||||
"count" => $li["count"],
|
||||
"price" => $li["price"]
|
||||
];
|
||||
}
|
||||
|
||||
$xlsSubject = "Clients Export";
|
||||
|
||||
$objPHPExcel = new Spreadsheet();
|
||||
$objPHPExcel->setActiveSheetIndex(0);
|
||||
$objPHPExcel->getActiveSheet()->setTitle('База клиентов');
|
||||
|
||||
$objPHPExcel->getProperties()->setCreator($xlsSubject)
|
||||
->setLastModifiedBy($xlsSubject)
|
||||
->setTitle($xlsSubject);
|
||||
|
||||
$objPHPExcel->getActiveSheet()->fromArray($xlsData, null, 'A1');
|
||||
|
||||
$xlsWriter = new Xls($objPHPExcel);
|
||||
$filename = "fasad-clients-export_".date('d-m-Y')."_".date("H-i").".xls";
|
||||
header('Content-type: application/vnd.ms-excel');
|
||||
header('Content-disposition: attachment; filename="' . $filename . '"');
|
||||
$xlsWriter->save('php://output');
|
||||
|
||||
ob_flush();
|
||||
exit;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use App\Controller\AppController;
|
||||
|
||||
class ManagersController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["cut", "calcDoors", "fasad", "smsSubscribes", "emailSubscribes"]));
|
||||
}
|
||||
|
||||
function index() {
|
||||
//TODO redirect by default app from profile
|
||||
$this->redirect(['controller' => 'CutOrders', 'action' => 'index', 'prefix' => 'manager']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,711 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use App\Controller\ElplatMerchantAPI;
|
||||
use App\Controller\CloudPaymentsMerchantAPI;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use SMSRU;
|
||||
|
||||
class OrderPaymentController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["orderPayment"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event) {
|
||||
}
|
||||
|
||||
private function searchOrderPaymentOrders($result, $data) {
|
||||
/*$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$ordersList = $orderPaymentTable->find('all')->all();
|
||||
foreach($ordersList as $key => $order) {
|
||||
$order['data'] = json_decode($order['data'], true);
|
||||
|
||||
if (!empty($order['data']['telephone'])) {
|
||||
$order->telephone = cleanupPhone($order['data']['telephone']);
|
||||
|
||||
if (strlen($order->telephone) == 10) {
|
||||
$order->telephone = "7" . $order->telephone;
|
||||
}
|
||||
|
||||
//$order->telephone = formatPhone($order->telephone);
|
||||
} else {
|
||||
$order->telephone = '';
|
||||
}
|
||||
unset($order['data']);
|
||||
|
||||
$order->name = trim($order->name);
|
||||
|
||||
if (!empty($order->payment)) {
|
||||
$order->payment = json_decode($order->payment, true);
|
||||
$order->paid_date = $order->payment[count($order->payment) - 1]['DateTime'];
|
||||
unset($order->payment);
|
||||
}
|
||||
|
||||
$orderPaymentTable->save($order);
|
||||
}*/
|
||||
|
||||
$search = preg_replace("/%{2,}/", "%", "%" . preg_replace("/[^\w\d]/ui", "%" , $data['search']) . "%");
|
||||
if ($search == "%") {
|
||||
$search = "";
|
||||
}
|
||||
|
||||
$status = (!empty($data['paymentStatus']) ? trim($data['paymentStatus']) : null);
|
||||
$searchPhone = "%".cleanupPhone(trim($data['search']))."%";
|
||||
$paymentGateway = (!empty($data['paymentGateway']) ? trim($data['paymentGateway']) : null);
|
||||
//var_dump($search);
|
||||
$conditions = [];
|
||||
if (!empty($search)) {
|
||||
$searchSum = trim(str_replace(["р.", "р", "₽", " "], "", mb_strtolower($data['search'])));
|
||||
|
||||
$conditions[] = ['OR' => [
|
||||
'order_num LIKE' => $search,
|
||||
'name LIKE' => $search,
|
||||
'telephone LIKE' => $searchPhone,
|
||||
'summa_order_decimal' => $searchSum
|
||||
]];
|
||||
}
|
||||
|
||||
|
||||
if (!empty($data['dateFrom'])) {
|
||||
if (is_string($data['dateFrom'])) {
|
||||
$data['dateFrom'] = strtotime($data['dateFrom']);
|
||||
} else {
|
||||
$data['dateFrom'] = $data['dateFrom'] / 1000;
|
||||
}
|
||||
$conditions[] = ['expiry_date >=' => $this->patchTimestampForJS(date('Y-m-d 00:00:00', $data['dateFrom']), -24, true, 'Y-m-d H:i:s')];
|
||||
}
|
||||
|
||||
if (!empty($data['dateTo'])) {
|
||||
if (is_string($data['dateTo'])) {
|
||||
$data['dateTo'] = strtotime($data['dateTo']);
|
||||
} else {
|
||||
$data['dateTo'] = $data['dateTo'] / 1000;
|
||||
}
|
||||
$conditions[] = ['expiry_date <=' => $this->patchTimestampForJS(date('Y-m-d 23:59:59', $data['dateTo']), -24, true, 'Y-m-d H:i:s')];
|
||||
}
|
||||
|
||||
if (!empty($status)) {
|
||||
if ($status == 'Оплачен') {
|
||||
$conditions[] = ['payment is not null'];
|
||||
}
|
||||
|
||||
if ($status == 'Не оплачен') {
|
||||
$conditions[] = ['payment is null'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($paymentGateway)) {
|
||||
$conditions[] = ['paymentGateway' => $paymentGateway];
|
||||
}
|
||||
|
||||
$result['totalOrders'] = 0;
|
||||
$conditions = array_merge($conditions, ['isDeleted' => false]);
|
||||
|
||||
$currentPage = (!empty($data['currentPage']) ? (int)$data['currentPage']: 1);
|
||||
$numPerPage = (!empty($data['numPerPage']) ? (int)$data['numPerPage']: 25);
|
||||
|
||||
$sort = [
|
||||
'field' => 'expiry_date',
|
||||
'direction' => 'desc'
|
||||
];
|
||||
|
||||
if (!empty($data['sortFields'])) {
|
||||
switch($data['sortFields']['field']) {
|
||||
case 'order_num':
|
||||
case 'name':
|
||||
case 'summa_order_decimal':
|
||||
case 'telephone':
|
||||
case 'expiry_date':
|
||||
case 'paymentGateway':
|
||||
$sort['field'] = $data['sortFields']['field'];
|
||||
break;
|
||||
|
||||
|
||||
case 'statusJs':
|
||||
$sort['field'] = 'paid_date';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($data['sortFields']['direction'], ['asc', 'desc'])) {
|
||||
$sort['direction'] = 'desc';
|
||||
} else {
|
||||
$sort['direction'] = $data['sortFields']['direction'];
|
||||
}
|
||||
|
||||
//var_dump($conditions);exit;
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$ordersList = $orderPaymentTable->find('all')->where($conditions)
|
||||
->order([$sort['field'] => $sort['direction']])->page($currentPage, $numPerPage)->all();
|
||||
|
||||
if (!empty($ordersList)) {
|
||||
$ordersList = $ordersList->toArray();
|
||||
foreach($ordersList as $key => $order) {
|
||||
$order['data'] = json_decode($order['data'], true);
|
||||
$ordersList[$key]['expiry_date'] = date_timestamp_get($this->patchTimestampForJS($order['expiry_date'], 24, false)) * 1000;
|
||||
|
||||
$ordersList[$key]['summa_order_decimal'] = $order['summa_order_decimal'];
|
||||
$ordersList[$key]['summa_order'] = $order['data']['summa_order'];
|
||||
$ordersList[$key]['name'] = $order['name'];
|
||||
|
||||
if (!empty($order['telephone'])) {
|
||||
$ordersList[$key]['telephoneOriginal'] = $order['data']['telephone'];
|
||||
$order['telephone'] = formatPhone($order['telephone']);
|
||||
}
|
||||
|
||||
unset($ordersList[$key]['data']);
|
||||
|
||||
if (!empty($order['paid_date'])) {
|
||||
$ordersList[$key]['status'] = 'Оплачен';
|
||||
//$ordersList[$key]['paidDate'] = $this->patchTimestampForJS($order['payment'][count($order['payment']) - 1]['DateTime'], -3, true, 'd.m.Y H:i');
|
||||
$ordersList[$key]['paidDate'] = $this->patchTimestampForJS($order['paid_date'], -3, true, 'd.m.Y H:i');
|
||||
$ordersList[$key]['statusJs'] = $this->patchTimestampForJS($order['paid_date'], -3, true, 'U');;
|
||||
unset($ordersList[$key]['payment']);
|
||||
|
||||
} else {
|
||||
$ordersList[$key]['status'] = 'Не оплачен';
|
||||
$ordersList[$key]['statusJs'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$result['totalOrders'] = $orderPaymentTable->find('all')->where($conditions)->count();
|
||||
|
||||
$result['unpaidCount'] = $orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'OR' => [
|
||||
['payment is null'],
|
||||
['payment is not null', 'summa_order_decimal_paid' => 0]
|
||||
]
|
||||
]))->count();
|
||||
$result['unpaidTotal'] = str_replace(".00", "", toFixed2Price($orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'OR' => [
|
||||
['payment is null'],
|
||||
['payment is not null', 'summa_order_decimal_paid' => 0]
|
||||
]
|
||||
]))->sumOf('summa_order_decimal')));
|
||||
|
||||
$result['paidCount'] = $orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'payment is not null',
|
||||
'summa_order_decimal_paid > ' => 0
|
||||
]))->count();
|
||||
$result['paidTotal'] = str_replace(".00", "", toFixed2Price($orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'payment is not null',
|
||||
'summa_order_decimal_paid >' => 0
|
||||
]))->sumOf('summa_order_decimal_paid')));
|
||||
}
|
||||
|
||||
$result['ordersList'] = (!empty($ordersList) ? $ordersList : []);
|
||||
|
||||
$result['status'] = "success";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("orderPayment", true);
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
switch($data['action']) {
|
||||
case "searchOrders":
|
||||
$result = $this->searchOrderPaymentOrders($result, $data);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function adminDeleteOrder() {
|
||||
/*$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$ordersList = $orderPaymentTable->find('all')->where(['payment is not null'])->select([
|
||||
'id','payment'
|
||||
])->all();
|
||||
foreach($ordersList as $order) {
|
||||
$order->summa_order_decimal_paid = 0;
|
||||
$order['payment'] = json_decode($order['payment'], true);
|
||||
|
||||
foreach($order['payment'] as $payment) {
|
||||
$order->summa_order_decimal_paid += $payment['Amount'];
|
||||
|
||||
unset($order['payment']);
|
||||
$orderPaymentTable->save($order);
|
||||
}
|
||||
}*/
|
||||
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$order = $orderPaymentTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$order->isDeleted = true;
|
||||
$orderPaymentTable->save($order);
|
||||
|
||||
$result = $this->searchOrderPaymentOrders($result, $data);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данного счета'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function getElplatPaymentHistory() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
if (!empty($savedOrderData)) {
|
||||
$history = $elplatPaymentsTable->find()->where([
|
||||
'orderPaymentId' => $data['id'],
|
||||
'status IN' => ["success", "refund", "failure"]
|
||||
])->order(['id' => 'asc'])->all()->toArray();
|
||||
|
||||
if (!empty($history)) {
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
|
||||
$result['history'] = [];
|
||||
foreach($history as $li) {
|
||||
$tmp = [
|
||||
'date' => $this->patchTimestampForJS($li['updated'], 0, true, 'd.m.Y H:i'),
|
||||
];
|
||||
|
||||
$li['responseData'] = @json_decode($li['responseData'], true);
|
||||
switch($li['status']) {
|
||||
case 'success':
|
||||
$tmp['description'] = 'Оплата счета ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['responseData']['allAmount'] / 100)).'р.';
|
||||
break;
|
||||
|
||||
case 'failure':
|
||||
$tmp['description'] = 'Ошибка оплаты счета ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = '';
|
||||
break;
|
||||
|
||||
case 'refund':
|
||||
$tmp['description'] = $li['responseData']['refundDescription'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['responseData']['refundAmount'])).'р.';
|
||||
|
||||
if (!empty($li['responseData']['refundManagerId'])) {
|
||||
$refundManager = $usersTable->find()->where([
|
||||
'id' => $li['responseData']['refundManagerId']
|
||||
])->first();
|
||||
|
||||
if (!empty($refundManager)) {
|
||||
$tmp['refundManager'] = $refundManager->name;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$result['history'][] = $tmp;
|
||||
}
|
||||
|
||||
$result['refundAmount'] = $savedOrderData['summa_order_decimal_paid'];
|
||||
$result['refundDescription'] = "Возрат средств по счету ".$savedOrderData['order_num']." - ".str_replace(".00", "", toFixed2Price($savedOrderData['summa_order_decimal_paid']))."р.";
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function makeElplatRefund() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$orderPayment = $elplatPaymentsTable->find()->where([
|
||||
'orderPaymentId' => $data['id'],
|
||||
'qrcId is not null',
|
||||
"qrcId != ''",
|
||||
'status' => 'success'
|
||||
])->first();
|
||||
|
||||
if (!empty($orderPayment) && !empty($orderPayment->responseData)) {
|
||||
$orderPayment->responseData = @json_decode($orderPayment->responseData, true);
|
||||
|
||||
$elplatCredentials = Configure::read('elplat');
|
||||
$elplatCredentials = $elplatCredentials[$savedOrderData['domain']];
|
||||
|
||||
$elplat = new ElplatMerchantAPI();
|
||||
|
||||
$refundData = [
|
||||
'login' => $elplatCredentials['login'],
|
||||
"passwd" => $elplatCredentials['passwd'],
|
||||
"ebl27" => $orderPayment->responseData['ebl27'],
|
||||
"amount" => round($data['refundAmount'] * 100),
|
||||
"orgId" => $elplatCredentials['orgId'],
|
||||
"descr" => $data['refundDescription'],
|
||||
];
|
||||
|
||||
|
||||
$hashId = $elplat->getElplatHashId($refundData);
|
||||
unset($refundData['passwd']);
|
||||
|
||||
$request = $elplat->createQr($elplatCredentials['apiUrl'], array_merge($refundData, [
|
||||
"type" => "undone",
|
||||
'hashId' => $hashId,
|
||||
'vTerminal' => $elplatCredentials['login']
|
||||
]));
|
||||
|
||||
if (!empty($request['info']['status'])) {
|
||||
$request['info']['refundDescription'] = $data['refundDescription'];
|
||||
$request['info']['refundAmount'] = $data['refundAmount'];
|
||||
$request['info']['refundManagerId'] = $this->Auth->user('id');
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$elplatRefund = $elplatPaymentsTable->newEntity([
|
||||
'orderPaymentId' => $data['id'],
|
||||
'qrData' => '',
|
||||
'qrcId' => '',
|
||||
'responseData' => json_encode($request['info']),
|
||||
'status' => 'refund',
|
||||
'created' => $now,
|
||||
'updated' => $now,
|
||||
]);
|
||||
|
||||
$elplatPaymentsTable->save($elplatRefund);
|
||||
|
||||
//////////////////////////
|
||||
$tmpOrder = $orderPaymentTable->get($data['id']);
|
||||
$tmpOrder->summa_order_decimal_paid -= $data['refundAmount'];
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
$xml .= '<time>' . date('Y-m-d H:i:s') . '</time><paid>refund</paid><paid_summa>' . $data['refundAmount'] . '</paid_summa><gateway>СБП</gateway>';
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
|
||||
if (empty($tmpOrder->summa_order_decimal_paid)) {
|
||||
$tmpOrder->payment = null;
|
||||
$tmpOrder->paid_date = null;
|
||||
}
|
||||
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(TMP . $filename, false, $filename);
|
||||
///////////
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["refund"])) {
|
||||
$tmpOrder->files["refund"] = [];
|
||||
}
|
||||
$tmpOrder->files["refund"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
$result['status'] = 'success';
|
||||
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
|
||||
} else {
|
||||
//todo some notify and queue here !!!
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify($xml, $filename, $savedOrderData, "refund", "возврата средств по счету");
|
||||
file_put_contents(TMP . 'callbackElplatRefundData' . date('Y-m-d_H-i-s') . '.error.ftpuploaderror.txt', json_encode($data));
|
||||
};
|
||||
fclose($tmpFile);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
//todo some notify and queue here !!!
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify($xml, $filename, $savedOrderData);
|
||||
file_put_contents(TMP . 'callbackElplatRefundData' . date('Y-m-d_H-i-s') . '.error.ftpconnecterror.txt', json_encode($data));
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => $request['info']['descr']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function getCloudPaymentsPaymentHistory() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
if (!empty($savedOrderData)) {
|
||||
$history = json_decode($savedOrderData->payment, true);
|
||||
|
||||
if (!empty($history)) {
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
|
||||
$result['history'] = [];
|
||||
foreach($history as $li) {
|
||||
$tmp = [
|
||||
//'date' => $this->patchTimestampForJS($li['updated'], 0, true, 'd.m.Y H:i'),
|
||||
'date' => $this->patchTimestampForJS($li['DateTime'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
|
||||
$li['responseData'] = @json_decode($li['responseData'], true);
|
||||
switch($li['OperationType']) {
|
||||
case 'Payment':
|
||||
$tmp['description'] = 'Оплата счета ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['Amount'])).'р.';
|
||||
break;
|
||||
|
||||
case 'Refund':
|
||||
$tmp['description'] = 'Возврат средств по счету ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['Amount'])).'р.';
|
||||
//refundAmount add to response data
|
||||
|
||||
if (!is_array($li['Data'])) {
|
||||
$li['Data'] = @json_decode($li['Data'], true);
|
||||
}
|
||||
|
||||
if (!empty($li['Data']['refundManagerId'])) {
|
||||
$refundManager = $usersTable->find()->where([
|
||||
'id' => $li['Data']['refundManagerId']
|
||||
])->first();
|
||||
|
||||
if (!empty($refundManager)) {
|
||||
$tmp['refundManager'] = $refundManager->name;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$result['history'][] = $tmp;
|
||||
}
|
||||
|
||||
$result['refundAmount'] = $savedOrderData['summa_order_decimal_paid'];
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function makeCloudPaymentsRefund() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$cloudPaymentsCredentials = Configure::read('cloudPayments');
|
||||
$cloudPaymentsCredentials = $cloudPaymentsCredentials[$savedOrderData['domain']];
|
||||
|
||||
$cloudPayments = new CloudPaymentsMerchantAPI();
|
||||
|
||||
$paymentTransactionId = null;
|
||||
$savedOrderData->payment = json_decode($savedOrderData->payment, true);
|
||||
foreach ($savedOrderData->payment as $payment) {
|
||||
if ($payment["OperationType"] == "Payment") {
|
||||
$paymentTransactionId = $payment['TransactionId'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($paymentTransactionId)) {
|
||||
$refundData = [
|
||||
'paymentPublicId' => $cloudPaymentsCredentials['paymentPublicId'],
|
||||
"apiKey" => $cloudPaymentsCredentials['apiKey'],
|
||||
|
||||
"TransactionId" => $paymentTransactionId,
|
||||
"Amount" => $data['refundAmount'],
|
||||
'requestLocation' => 'payments/refund',
|
||||
'JsonData' => [
|
||||
'encOrderId' => $savedOrderData['encryptOrderId'],
|
||||
'refundManagerId' => $this->Auth->user('id'),
|
||||
]
|
||||
];
|
||||
|
||||
$request = $cloudPayments->createRefund($cloudPaymentsCredentials['apiUrl'], $refundData);
|
||||
|
||||
if (!empty($request["Success"])) {
|
||||
$result['status'] = 'success';
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => (!empty($request['Message']) ? $request['Message'] : "Произошла ошибка при возврате средств. Проверьте данные и попробуйте снова.")
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//$this->db->query("INSERT INTO `" . DB_PREFIX . "elplat_payments` SET order_id = '" . $orderId . "', qrData = '', qrcId = '', responseData = '" . $this->db->escape(json_encode($refundInfo)) . "', status = 'refund', created = NOW(), updated = NOW()");
|
||||
@@ -0,0 +1,694 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use App\Controller\ElplatMerchantAPI;
|
||||
use App\Controller\CloudPaymentsMerchantAPI;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use SMSRU;
|
||||
|
||||
class OrderPaymentController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["orderPayment"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event) {
|
||||
}
|
||||
|
||||
private function searchOrderPaymentOrders($result, $data) {
|
||||
/*$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$ordersList = $orderPaymentTable->find('all')->all();
|
||||
foreach($ordersList as $key => $order) {
|
||||
$order['data'] = json_decode($order['data'], true);
|
||||
|
||||
if (!empty($order['data']['telephone'])) {
|
||||
$order->telephone = cleanupPhone($order['data']['telephone']);
|
||||
|
||||
if (strlen($order->telephone) == 10) {
|
||||
$order->telephone = "7" . $order->telephone;
|
||||
}
|
||||
|
||||
//$order->telephone = formatPhone($order->telephone);
|
||||
} else {
|
||||
$order->telephone = '';
|
||||
}
|
||||
unset($order['data']);
|
||||
|
||||
$order->name = trim($order->name);
|
||||
|
||||
if (!empty($order->payment)) {
|
||||
$order->payment = json_decode($order->payment, true);
|
||||
$order->paid_date = $order->payment[count($order->payment) - 1]['DateTime'];
|
||||
unset($order->payment);
|
||||
}
|
||||
|
||||
$orderPaymentTable->save($order);
|
||||
}*/
|
||||
|
||||
$search = preg_replace("/%{2,}/", "%", "%" . preg_replace("/[^\w\d]/ui", "%" , $data['search']) . "%");
|
||||
$status = (!empty($data['paymentStatus']) ? trim($data['paymentStatus']) : null);
|
||||
$searchPhone = "%".cleanupPhone(trim($data['search']))."%";
|
||||
$paymentGateway = (!empty($data['paymentGateway']) ? trim($data['paymentGateway']) : null);
|
||||
|
||||
$conditions = [];
|
||||
if (!empty($search)) {
|
||||
$searchSum = trim(str_replace(["р.", "р", "₽", " "], "", mb_strtolower($data['search'])));
|
||||
|
||||
$conditions[] = ['OR' => [
|
||||
'order_num LIKE' => $search,
|
||||
'name LIKE' => $search,
|
||||
'telephone LIKE' => $searchPhone,
|
||||
'summa_order_decimal' => $searchSum
|
||||
]];
|
||||
}
|
||||
|
||||
|
||||
if (!empty($data['dateFrom'])) {
|
||||
if (is_string($data['dateFrom'])) {
|
||||
$data['dateFrom'] = strtotime($data['dateFrom']);
|
||||
} else {
|
||||
$data['dateFrom'] = $data['dateFrom'] / 1000;
|
||||
}
|
||||
$conditions[] = ['expiry_date >=' => $this->patchTimestampForJS(date('Y-m-d 00:00:00', $data['dateFrom']), -24, true, 'Y-m-d H:i:s')];
|
||||
}
|
||||
|
||||
if (!empty($data['dateTo'])) {
|
||||
if (is_string($data['dateTo'])) {
|
||||
$data['dateTo'] = strtotime($data['dateTo']);
|
||||
} else {
|
||||
$data['dateTo'] = $data['dateTo'] / 1000;
|
||||
}
|
||||
$conditions[] = ['expiry_date <=' => $this->patchTimestampForJS(date('Y-m-d 23:59:59', $data['dateTo']), -24, true, 'Y-m-d H:i:s')];
|
||||
}
|
||||
|
||||
if (!empty($status)) {
|
||||
if ($status == 'Оплачен') {
|
||||
$conditions[] = ['payment is not null'];
|
||||
}
|
||||
|
||||
if ($status == 'Не оплачен') {
|
||||
$conditions[] = ['payment is null'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($paymentGateway)) {
|
||||
$conditions[] = ['paymentGateway' => $paymentGateway];
|
||||
}
|
||||
|
||||
$result['totalOrders'] = 0;
|
||||
$conditions = array_merge($conditions, ['isDeleted' => false]);
|
||||
|
||||
$currentPage = (!empty($data['currentPage']) ? (int)$data['currentPage']: 1);
|
||||
$numPerPage = (!empty($data['numPerPage']) ? (int)$data['numPerPage']: 25);
|
||||
|
||||
$sort = [
|
||||
'field' => 'expiry_date',
|
||||
'direction' => 'desc'
|
||||
];
|
||||
|
||||
if (!empty($data['sortFields'])) {
|
||||
switch($data['sortFields']['field']) {
|
||||
case 'order_num':
|
||||
case 'name':
|
||||
case 'summa_order_decimal':
|
||||
case 'telephone':
|
||||
case 'expiry_date':
|
||||
case 'paymentGateway':
|
||||
$sort['field'] = $data['sortFields']['field'];
|
||||
break;
|
||||
|
||||
|
||||
case 'statusJs':
|
||||
$sort['field'] = 'paid_date';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($data['sortFields']['direction'], ['asc', 'desc'])) {
|
||||
$sort['direction'] = 'desc';
|
||||
} else {
|
||||
$sort['direction'] = $data['sortFields']['direction'];
|
||||
}
|
||||
|
||||
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$ordersList = $orderPaymentTable->find('all')->where($conditions)
|
||||
->order([$sort['field'] => $sort['direction']])->page($currentPage, $numPerPage)->all();
|
||||
|
||||
if (!empty($ordersList)) {
|
||||
$ordersList = $ordersList->toArray();
|
||||
foreach($ordersList as $key => $order) {
|
||||
$order['data'] = json_decode($order['data'], true);
|
||||
$ordersList[$key]['expiry_date'] = date_timestamp_get($this->patchTimestampForJS($order['expiry_date'], 24, false)) * 1000;
|
||||
|
||||
$ordersList[$key]['summa_order_decimal'] = $order['summa_order_decimal'];
|
||||
$ordersList[$key]['summa_order'] = $order['data']['summa_order'];
|
||||
$ordersList[$key]['name'] = $order['name'];
|
||||
|
||||
if (!empty($order['telephone'])) {
|
||||
$ordersList[$key]['telephoneOriginal'] = $order['data']['telephone'];
|
||||
$order['telephone'] = formatPhone($order['telephone']);
|
||||
}
|
||||
|
||||
unset($ordersList[$key]['data']);
|
||||
|
||||
if (!empty($order['paid_date'])) {
|
||||
$ordersList[$key]['status'] = 'Оплачен';
|
||||
//$ordersList[$key]['paidDate'] = $this->patchTimestampForJS($order['payment'][count($order['payment']) - 1]['DateTime'], -3, true, 'd.m.Y H:i');
|
||||
$ordersList[$key]['paidDate'] = $this->patchTimestampForJS($order['paid_date'], -3, true, 'd.m.Y H:i');
|
||||
$ordersList[$key]['statusJs'] = $this->patchTimestampForJS($order['paid_date'], -3, true, 'U');;
|
||||
unset($ordersList[$key]['payment']);
|
||||
|
||||
} else {
|
||||
$ordersList[$key]['status'] = 'Не оплачен';
|
||||
$ordersList[$key]['statusJs'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$result['totalOrders'] = $orderPaymentTable->find('all')->where($conditions)->count();
|
||||
|
||||
$result['unpaidCount'] = $orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'OR' => [
|
||||
['payment is null'],
|
||||
['payment is not null', 'summa_order_decimal_paid' => 0]
|
||||
]
|
||||
]))->count();
|
||||
$result['unpaidTotal'] = str_replace(".00", "", toFixed2Price($orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'OR' => [
|
||||
['payment is null'],
|
||||
['payment is not null', 'summa_order_decimal_paid' => 0]
|
||||
]
|
||||
]))->sumOf('summa_order_decimal')));
|
||||
|
||||
$result['paidCount'] = $orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'payment is not null',
|
||||
'summa_order_decimal_paid > ' => 0
|
||||
]))->count();
|
||||
$result['paidTotal'] = str_replace(".00", "", toFixed2Price($orderPaymentTable->find('all')->where(array_merge($conditions, [
|
||||
'payment is not null',
|
||||
'summa_order_decimal_paid >' => 0
|
||||
]))->sumOf('summa_order_decimal_paid')));
|
||||
}
|
||||
|
||||
$result['ordersList'] = (!empty($ordersList) ? $ordersList : []);
|
||||
|
||||
$result['status'] = "success";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("orderPayment", true);
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
switch($data['action']) {
|
||||
case "searchOrders":
|
||||
$result = $this->searchOrderPaymentOrders($result, $data);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function adminDeleteOrder() {
|
||||
/*$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$ordersList = $orderPaymentTable->find('all')->where(['payment is not null'])->select([
|
||||
'id','payment'
|
||||
])->all();
|
||||
foreach($ordersList as $order) {
|
||||
$order->summa_order_decimal_paid = 0;
|
||||
$order['payment'] = json_decode($order['payment'], true);
|
||||
|
||||
foreach($order['payment'] as $payment) {
|
||||
$order->summa_order_decimal_paid += $payment['Amount'];
|
||||
|
||||
unset($order['payment']);
|
||||
$orderPaymentTable->save($order);
|
||||
}
|
||||
}*/
|
||||
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get("OrderPayment");
|
||||
$order = $orderPaymentTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$order->isDeleted = true;
|
||||
$orderPaymentTable->save($order);
|
||||
|
||||
$result = $this->searchOrderPaymentOrders($result, $data);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данного счета'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function getElplatPaymentHistory() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
if (!empty($savedOrderData)) {
|
||||
$history = $elplatPaymentsTable->find()->where([
|
||||
'orderPaymentId' => $data['id'],
|
||||
'status IN' => ["success", "refund", "failure"]
|
||||
])->order(['id' => 'asc'])->all()->toArray();
|
||||
|
||||
if (!empty($history)) {
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
|
||||
$result['history'] = [];
|
||||
foreach($history as $li) {
|
||||
$tmp = [
|
||||
'date' => $this->patchTimestampForJS($li['updated'], 0, true, 'd.m.Y H:i'),
|
||||
];
|
||||
|
||||
$li['responseData'] = @json_decode($li['responseData'], true);
|
||||
switch($li['status']) {
|
||||
case 'success':
|
||||
$tmp['description'] = 'Оплата счета ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['responseData']['allAmount'] / 100)).'р.';
|
||||
break;
|
||||
|
||||
case 'failure':
|
||||
$tmp['description'] = 'Ошибка оплаты счета ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = '';
|
||||
break;
|
||||
|
||||
case 'refund':
|
||||
$tmp['description'] = $li['responseData']['refundDescription'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['responseData']['refundAmount'])).'р.';
|
||||
|
||||
if (!empty($li['responseData']['refundManagerId'])) {
|
||||
$refundManager = $usersTable->find()->where([
|
||||
'id' => $li['responseData']['refundManagerId']
|
||||
])->first();
|
||||
|
||||
if (!empty($refundManager)) {
|
||||
$tmp['refundManager'] = $refundManager->name;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$result['history'][] = $tmp;
|
||||
}
|
||||
|
||||
$result['refundAmount'] = $savedOrderData['summa_order_decimal_paid'];
|
||||
$result['refundDescription'] = "Возрат средств по счету ".$savedOrderData['order_num']." - ".str_replace(".00", "", toFixed2Price($savedOrderData['summa_order_decimal_paid']))."р.";
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function makeElplatRefund() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$orderPayment = $elplatPaymentsTable->find()->where([
|
||||
'orderPaymentId' => $data['id'],
|
||||
'qrcId is not null',
|
||||
"qrcId != ''",
|
||||
'status' => 'success'
|
||||
])->first();
|
||||
|
||||
if (!empty($orderPayment) && !empty($orderPayment->responseData)) {
|
||||
$orderPayment->responseData = @json_decode($orderPayment->responseData, true);
|
||||
|
||||
$elplatCredentials = Configure::read('elplat');
|
||||
$elplatCredentials = $elplatCredentials[$savedOrderData['domain']];
|
||||
|
||||
$elplat = new ElplatMerchantAPI();
|
||||
|
||||
$refundData = [
|
||||
'login' => $elplatCredentials['login'],
|
||||
"passwd" => $elplatCredentials['passwd'],
|
||||
"ebl27" => $orderPayment->responseData['ebl27'],
|
||||
"amount" => round($data['refundAmount'] * 100),
|
||||
"orgId" => $elplatCredentials['orgId'],
|
||||
"descr" => $data['refundDescription'],
|
||||
];
|
||||
|
||||
|
||||
$hashId = $elplat->getElplatHashId($refundData);
|
||||
unset($refundData['passwd']);
|
||||
|
||||
$request = $elplat->createQr($elplatCredentials['apiUrl'], array_merge($refundData, [
|
||||
"type" => "undone",
|
||||
'hashId' => $hashId,
|
||||
'vTerminal' => $elplatCredentials['login']
|
||||
]));
|
||||
|
||||
if (!empty($request['info']['status'])) {
|
||||
$request['info']['refundDescription'] = $data['refundDescription'];
|
||||
$request['info']['refundAmount'] = $data['refundAmount'];
|
||||
$request['info']['refundManagerId'] = $this->Auth->user('id');
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$elplatRefund = $elplatPaymentsTable->newEntity([
|
||||
'orderPaymentId' => $data['id'],
|
||||
'qrData' => '',
|
||||
'qrcId' => '',
|
||||
'responseData' => json_encode($request['info']),
|
||||
'status' => 'refund',
|
||||
'created' => $now,
|
||||
'updated' => $now,
|
||||
]);
|
||||
|
||||
$elplatPaymentsTable->save($elplatRefund);
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
$tmpOrder = $orderPaymentTable->get($data['id']);
|
||||
$tmpOrder->summa_order_decimal_paid -= $data['refundAmount'];
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
$xml .= '<time>' . date('Y-m-d H:i:s') . '</time><paid>refund</paid><paid_summa>' . $data['refundAmount'] . '</paid_summa><gateway>СБП</gateway>';
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
if (empty($tmpOrder->summa_order_decimal_paid)) {
|
||||
$tmpOrder->payment = null;
|
||||
$tmpOrder->paid_date = null;
|
||||
}
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["refund"])) {
|
||||
$tmpOrder->files["refund"] = [];
|
||||
}
|
||||
$tmpOrder->files["refund"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
$result['status'] = 'success';
|
||||
};
|
||||
fclose($tmpFile);
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(TMP . $filename, false, $filename);
|
||||
|
||||
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => $request['info']['descr']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function getCloudPaymentsPaymentHistory() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
if (!empty($savedOrderData)) {
|
||||
$history = json_decode($savedOrderData->payment, true);
|
||||
|
||||
if (!empty($history)) {
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
|
||||
$result['history'] = [];
|
||||
foreach($history as $li) {
|
||||
$tmp = [
|
||||
//'date' => $this->patchTimestampForJS($li['updated'], 0, true, 'd.m.Y H:i'),
|
||||
'date' => $this->patchTimestampForJS($li['DateTime'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
|
||||
$li['responseData'] = @json_decode($li['responseData'], true);
|
||||
switch($li['OperationType']) {
|
||||
case 'Payment':
|
||||
$tmp['description'] = 'Оплата счета ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['Amount'])).'р.';
|
||||
break;
|
||||
|
||||
case 'Refund':
|
||||
$tmp['description'] = 'Возврат средств по счету ' . $savedOrderData['order_num'];
|
||||
$tmp['amount'] = str_replace(".00", "", toFixed2Price($li['Amount'])).'р.';
|
||||
//refundAmount add to response data
|
||||
|
||||
if (!is_array($li['Data'])) {
|
||||
$li['Data'] = @json_decode($li['Data'], true);
|
||||
}
|
||||
|
||||
if (!empty($li['Data']['refundManagerId'])) {
|
||||
$refundManager = $usersTable->find()->where([
|
||||
'id' => $li['Data']['refundManagerId']
|
||||
])->first();
|
||||
|
||||
if (!empty($refundManager)) {
|
||||
$tmp['refundManager'] = $refundManager->name;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$result['history'][] = $tmp;
|
||||
}
|
||||
|
||||
$result['refundAmount'] = $savedOrderData['summa_order_decimal_paid'];
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function makeCloudPaymentsRefund() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
|
||||
if ($this->isAuthorized(['admin', 'kassir'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $data['id'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$cloudPaymentsCredentials = Configure::read('cloudPayments');
|
||||
$cloudPaymentsCredentials = $cloudPaymentsCredentials[$savedOrderData['domain']];
|
||||
|
||||
$cloudPayments = new CloudPaymentsMerchantAPI();
|
||||
|
||||
$paymentTransactionId = null;
|
||||
$savedOrderData->payment = json_decode($savedOrderData->payment, true);
|
||||
foreach ($savedOrderData->payment as $payment) {
|
||||
if ($payment["OperationType"] == "Payment") {
|
||||
$paymentTransactionId = $payment['TransactionId'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($paymentTransactionId)) {
|
||||
$refundData = [
|
||||
'paymentPublicId' => $cloudPaymentsCredentials['paymentPublicId'],
|
||||
"apiKey" => $cloudPaymentsCredentials['apiKey'],
|
||||
|
||||
"TransactionId" => $paymentTransactionId,
|
||||
"Amount" => $data['refundAmount'],
|
||||
'requestLocation' => 'payments/refund',
|
||||
'JsonData' => [
|
||||
'encOrderId' => $savedOrderData['encryptOrderId'],
|
||||
'refundManagerId' => $this->Auth->user('id'),
|
||||
]
|
||||
];
|
||||
|
||||
$request = $cloudPayments->createRefund($cloudPaymentsCredentials['apiUrl'], $refundData);
|
||||
|
||||
if (!empty($request["Success"])) {
|
||||
$result['status'] = 'success';
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => (!empty($request['Message']) ? $request['Message'] : "Произошла ошибка при возврате средств. Проверьте данные и попробуйте снова.")
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для возврата средств по данному счету'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//$this->db->query("INSERT INTO `" . DB_PREFIX . "elplat_payments` SET order_id = '" . $orderId . "', qrData = '', qrcId = '', responseData = '" . $this->db->escape(json_encode($refundInfo)) . "', status = 'refund', created = NOW(), updated = NOW()");
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
|
||||
|
||||
class OrdersInfoController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["ordersInfo"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event) {
|
||||
}
|
||||
|
||||
private function searchOrdersInfoOrders($result, $data) {
|
||||
$search = preg_replace("/%{2,}/", "%", "%" . preg_replace("/[^\w\d]/ui", "%" , $data['search']) . "%");
|
||||
|
||||
$searchPhone = "%".cleanupPhone(trim($data['search']))."%";
|
||||
//if (strlen($searchPhone) == 10) {
|
||||
// $searchPhone = "7" . $searchPhone;
|
||||
//}
|
||||
//$searchPhone = formatPhone($searchPhone);
|
||||
|
||||
$conditions = [];
|
||||
if (!empty($search)) {
|
||||
$conditions[] = ['OR' => [
|
||||
'nom LIKE' => $search,
|
||||
'fio LIKE' => $search,
|
||||
'tel LIKE' => $searchPhone,
|
||||
//'tel' => $searchPhone,
|
||||
//'(tel LIKE "' . $search . '") OR (tel LIKE "' => $searchPhone . '")'
|
||||
]];
|
||||
}
|
||||
|
||||
$result['totalOrders'] = 0;
|
||||
$conditions = array_merge($conditions, ['isDeleted' => false]);
|
||||
|
||||
$currentPage = (!empty($data['currentPage']) ? (int)$data['currentPage']: 1);
|
||||
$numPerPage = (!empty($data['numPerPage']) ? (int)$data['numPerPage']: 25);
|
||||
|
||||
$sort = [
|
||||
'field' => 'created',
|
||||
'direction' => 'desc'
|
||||
];
|
||||
|
||||
if (!empty($data['sortFields'])) {
|
||||
switch($data['sortFields']['field']) {
|
||||
case 'nom':
|
||||
case 'fio':
|
||||
case 'tel':
|
||||
case 'totalSum':
|
||||
case 'created':
|
||||
$sort['field'] = $data['sortFields']['field'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($data['sortFields']['direction'], ['asc', 'desc'])) {
|
||||
$sort['direction'] = 'desc';
|
||||
} else {
|
||||
$sort['direction'] = $data['sortFields']['direction'];
|
||||
}
|
||||
|
||||
$ordersInfoTable = TableRegistry::getTableLocator()->get("OrdersInfo");
|
||||
$ordersList = $ordersInfoTable->find('all')->where($conditions)->order([$sort['field'] => $sort['direction']])->page($currentPage, $numPerPage)->all();
|
||||
|
||||
if (!empty($ordersList)) {
|
||||
$ordersList = $ordersList->toArray();
|
||||
foreach($ordersList as $key => $order) {
|
||||
$order['data'] = json_decode($order['data'], true);
|
||||
$order['tel'] = formatPhone($order['tel']);
|
||||
$order['created'] = $this->patchTimestampForJS($order['created'], 0, true, 'd.m.Y');
|
||||
}
|
||||
|
||||
$result['totalOrders'] = $ordersInfoTable->find('all')->where($conditions)->count();
|
||||
$result['ordersTotalSum'] = str_replace(".00", "", toFixed2Price($ordersInfoTable->find('all')->where($conditions)->sumOf('totalSum')));
|
||||
}
|
||||
|
||||
$result['ordersList'] = (!empty($ordersList) ? $ordersList : []);
|
||||
|
||||
$result['status'] = "success";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("ordersInfo", true);
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
switch($data['action']) {
|
||||
case "searchOrders":
|
||||
$result = $this->searchOrdersInfoOrders($result, $data);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function adminDeleteOrder() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$ordersInfoTable = TableRegistry::getTableLocator()->get("OrdersInfo");
|
||||
$order = $ordersInfoTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($order)) {
|
||||
$order->isDeleted = true;
|
||||
$ordersInfoTable->save($order);
|
||||
|
||||
$result = $this->searchOrdersInfoOrders($result, $data);
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Счет не найден'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Недостаточно прав для удаления данного счета'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
class OrdersInfoSettingsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["ordersInfo"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("ordersInfo", true));
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('OrdersInfoSettings');
|
||||
|
||||
switch($data['action']) {
|
||||
case 'saveGroup':
|
||||
if (!empty($data['settings'])) {
|
||||
foreach($data['settings'] as $groupId => $groupData) {
|
||||
foreach($groupData as $s) {
|
||||
if (!in_array($s['id'], ['lastUpdateDate', 'lastUpdateManagerId'])) {
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $s['id'],
|
||||
'group' => $groupId
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $s['value'];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $s['id'],
|
||||
'value' => $s['value'],
|
||||
'group' => $groupId
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("ordersInfo", $data['settingsGroup'], $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
class SettingsController extends AppController {
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["cut", "calcDoors", "fasad"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function index() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("", true));
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
|
||||
switch($data['action']) {
|
||||
case 'saveGroup':
|
||||
if (!empty($data['settings'])) {
|
||||
foreach($data['settings'] as $groupId => $groupData) {
|
||||
foreach($groupData as $s) {
|
||||
if (!in_array($s['id'], ['lastUpdateDate', 'lastUpdateManagerId'])) {
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $s['id'],
|
||||
'group' => $groupId
|
||||
])->first();
|
||||
|
||||
if (in_array($s['id'], ["smtpParams"])) {
|
||||
$s['value'] = @json_encode($s['value']);
|
||||
}
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $s['value'];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $s['id'],
|
||||
'value' => $s['value'],
|
||||
'group' => $groupId
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", $data['settingsGroup'], $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
function addUpdateBranch() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$branchesTable = TableRegistry::getTableLocator()->get('Branches');
|
||||
|
||||
$isOk = false;
|
||||
if (empty($data['id'])) { //add
|
||||
$currentBranch = $branchesTable->newEntity();
|
||||
$currentBranch = $branchesTable->newEntity();
|
||||
$currentBranch = $branchesTable->patchEntity($currentBranch, $data);
|
||||
|
||||
if ($branchesTable->save($currentBranch)) {
|
||||
$isOk = true;
|
||||
}
|
||||
|
||||
} else { //update
|
||||
$currentBranch = $branchesTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($currentBranch)) {
|
||||
$branchesTable->patchEntity($currentBranch, $data);
|
||||
if ($branchesTable->save($currentBranch)) {
|
||||
$isOk = true;
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Контакт-менеджер не найден'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
if (!empty($data['is_default'])) {
|
||||
$branchesTable->updateAll(
|
||||
['is_default' => false],
|
||||
['id !=' => $currentBranch->id]
|
||||
);
|
||||
}
|
||||
|
||||
$result['branches'] = $this->getBranchesListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'branches', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteBranch() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$branchesTable = TableRegistry::getTableLocator()->get('Branches');
|
||||
$branch = $branchesTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($branch)) {
|
||||
$branchesTable->updateAll(
|
||||
['is_deleted' => true],
|
||||
['id' => $data['id']]
|
||||
);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'branches', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Контакт-менеджер не найден'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function addUpdateDelivery() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$deliveryTable = TableRegistry::getTableLocator()->get('Delivery');
|
||||
|
||||
$isOk = false;
|
||||
if (empty($data['id'])) { //add
|
||||
$currentDelivery = $deliveryTable->newEntity();
|
||||
$currentDelivery = $deliveryTable->patchEntity($currentDelivery, $data);
|
||||
|
||||
if ($deliveryTable->save($currentDelivery)) {
|
||||
$isOk = true;
|
||||
}
|
||||
|
||||
} else { //update
|
||||
$currentDelivery = $deliveryTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($currentDelivery)) {
|
||||
$deliveryTable->patchEntity($currentDelivery, $data);
|
||||
if ($deliveryTable->save($currentDelivery)) {
|
||||
$isOk = true;
|
||||
|
||||
if (!empty($currentDelivery['shopShippingId'])) {
|
||||
$updateArray = [
|
||||
$currentDelivery->shopShippingId,
|
||||
$currentDelivery->shopOrderMinTotal,
|
||||
$currentDelivery->costPerKm,
|
||||
$currentDelivery->minimalCost,
|
||||
$currentDelivery->location
|
||||
];
|
||||
|
||||
exec("/var/www/supersam24.ru/impex/bin/cake updateDelivery ".join(" ", $updateArray));
|
||||
exec("/var/www/supersamsev.ru/impex/bin/cake updateDelivery ".join(" ", $updateArray));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Доставка не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
$result['delivery'] = $this->getDeliveryListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'delivery', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function deleteDelivery() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$deliveryTable = TableRegistry::getTableLocator()->get('Delivery');
|
||||
$delivery = $deliveryTable->find()->where(['id' => $data['id']])->first();
|
||||
|
||||
if (!empty($delivery)) {
|
||||
$deliveryTable->updateAll(
|
||||
['is_deleted' => true],
|
||||
['id' => $data['id']]
|
||||
);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'delivery', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Доставка не найдена'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use SMSRU;
|
||||
|
||||
class SmsOrdersReadyController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["smsOrdersReady"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("smsOrdersReady", true);
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
$smsOrdersReadTable = TableRegistry::getTableLocator()->get("SmsOrdersReady");
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
|
||||
$currentPage = (!empty($data['currentPage']) ? (int)$data['currentPage']: 1);
|
||||
$numPerPage = (!empty($data['numPerPage']) ? (int)$data['numPerPage']: 25);
|
||||
|
||||
$sort = [
|
||||
'field' => 'created',
|
||||
'direction' => 'desc'
|
||||
];
|
||||
|
||||
if (!empty($data['sortFields'])) {
|
||||
switch($data['sortFields']['field']) {
|
||||
case 'message':
|
||||
case 'phone':
|
||||
case 'sentDate':
|
||||
case 'status':
|
||||
$sort['field'] = $data['sortFields']['field'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($data['sortFields']['direction'], ['asc', 'desc'])) {
|
||||
$sort['direction'] = 'desc';
|
||||
} else {
|
||||
$sort['direction'] = $data['sortFields']['direction'];
|
||||
}
|
||||
|
||||
|
||||
switch($data['action']) {
|
||||
case "searchSms":
|
||||
$search = preg_replace("/%{2,}/", "%", "%" . preg_replace("/[^\w\d]/ui", "%" , $data['search']) . "%");
|
||||
$smsType = (!empty($data['smsType']) ? trim($data['smsType']) : 'order');
|
||||
$status = (!empty($data['smsStatus']) ? trim($data['smsStatus']) : null);
|
||||
//$search = "%" . str_replace([" ", "-", "+", "(", ")", ".", ",", "/", "*"], "%", trim($data['search'])) . "%";
|
||||
|
||||
$conditions = [];
|
||||
if ($smsType != 'any') {
|
||||
$conditions[] = ['smsType' => $smsType];
|
||||
};
|
||||
|
||||
$searchPhone = "%".cleanupPhone(trim($data['search']))."%";
|
||||
|
||||
if (!empty($search)) {
|
||||
$conditions[] = ['OR' => [
|
||||
'phone LIKE' => $search,
|
||||
'message LIKE' => $search,
|
||||
'status LIKE' => $searchPhone,
|
||||
]];
|
||||
}
|
||||
|
||||
if (!empty($status)) {
|
||||
$conditions[] = ['status' => $status];
|
||||
}
|
||||
|
||||
$smsList = $smsOrdersReadTable->find('all')->where($conditions)->order([$sort['field'] => $sort['direction']])->page($currentPage, $numPerPage)->all();
|
||||
|
||||
if (!empty($smsList)) {
|
||||
$smsList = $smsList->toArray();
|
||||
foreach($smsList as $key => $sms) {
|
||||
$smsList[$key]['phone'] = formatPhone($sms['phone']);
|
||||
$smsList[$key]['sentDate'] = date_timestamp_get($sms['sentDate']) * 1000;
|
||||
|
||||
if (mb_stripos($sms['message'], 'Ваш код подтверждения') !== false) {
|
||||
$smsList[$key]['message'] = preg_replace('/[0-9]/', '*', $sms['message']);
|
||||
}
|
||||
|
||||
if (!empty($sms['statusTime'])) {
|
||||
$smsList[$key]['statusTime'] = date_timestamp_get($sms['statusTime']) * 1000;
|
||||
}
|
||||
|
||||
$result['totalSms'] = $smsOrdersReadTable->find('all')->where($conditions)->count();
|
||||
}
|
||||
}
|
||||
|
||||
$result['smsList'] = (!empty($smsList) ? $smsList : []);
|
||||
|
||||
$result['status'] = "success";
|
||||
|
||||
$updates = $settingsTable->getSettingsUpdateDate("", 'smsOrdersReady', false);
|
||||
$result = array_merge($result, $updates);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case "importSms":
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$source = !empty($data['file']['tmp_name']) ? $data['file']['tmp_name'] : '';
|
||||
|
||||
if (!empty($source)) {
|
||||
$importResult = $smsOrdersReadTable->importSms($source);
|
||||
if ($importResult['totalCount'] > 0) {
|
||||
$result['status'] = 'success';
|
||||
$result['importCount'] = $importResult['importCount'];
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'smsOrdersReady', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
} else {
|
||||
$result['errors'][] = 'Неверный формат файла или список информационных sms пуст.';
|
||||
}
|
||||
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Недостаточно прав';
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use App\Controller\AppController;
|
||||
use SMSRU;
|
||||
|
||||
class SmsSubscribesController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized([], ["smsSubscribes"]));
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function index() {
|
||||
$jsConfig = $this->getAppJsConfig("smsSubscribes", true);
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("SmsSubscribes");
|
||||
$subscribesRecipientsTable = TableRegistry::getTableLocator()->get("SmsSubscribeRecipients");
|
||||
|
||||
switch($data['action']) {
|
||||
case "getSubscribes":
|
||||
$subscribeId = (int) $data['subscribeId'];
|
||||
|
||||
if (!empty($subscribeId)) {
|
||||
|
||||
} else {
|
||||
$result['subscribes'] = $this->getSubscribesList("SmsSubscribes", $data);
|
||||
}
|
||||
|
||||
$result['status'] = "success";
|
||||
break;
|
||||
|
||||
|
||||
case "setSubscribeStatus":
|
||||
$subscribeId = (int) $data['subscribeId'];
|
||||
$newStatus = $data['newStatus'];
|
||||
|
||||
if (!empty($subscribeId) && !empty($newStatus)) {
|
||||
$subscribe = $subscribesTable->find('all')->where(['id' => $subscribeId])->first();
|
||||
|
||||
if (!empty($subscribe)) {
|
||||
if ($this->isSubscribeUpdateAllowed($subscribe['status'])) {
|
||||
$isStatusChangeAllowed = true;
|
||||
|
||||
if ($newStatus == "deleted") {
|
||||
if (($subscribe['createdBy'] != $this->Auth->user('id')) && ($this->Auth->user('role') != 'admin')) {
|
||||
$isStatusChangeAllowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isStatusChangeAllowed) {
|
||||
$subscribe->status = $newStatus;
|
||||
|
||||
if ($newStatus == "queued") {
|
||||
$subscribe->queuedBy = $this->Auth->user('id');
|
||||
$subscribe->stoppedBy = null;
|
||||
}
|
||||
|
||||
if ($newStatus == "stopped") {
|
||||
$subscribe->stoppedBy = $this->Auth->user('id');
|
||||
}
|
||||
|
||||
if ($subscribesTable->save($subscribe)) {
|
||||
$result['status'] = "success";
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Недостаточно прав для изменения статуса рассылки';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Редактирование активной или завершенной рассылки недоступно';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Рассылка не найдена!';
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "addSubscribe":
|
||||
if (!empty($data['message'])) {
|
||||
$data['created'] = date('Y-m-d H:i:s');
|
||||
$data['createdBy'] = $this->Auth->user('id');
|
||||
$data['status'] = "stopped";
|
||||
|
||||
$subscribe = $subscribesTable->newEntity();
|
||||
$subscribe = $subscribesTable->patchEntity($subscribe, $data);
|
||||
|
||||
if ($subscribesTable->save($subscribe)) {
|
||||
$result['subscribe'] = $this->getSubscribeData("SmsSubscribes", $subscribe->id);
|
||||
$result['status'] = "success";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "updateSubscribe":
|
||||
if (!empty($data['id'])) {
|
||||
$subscribe = $this->getSubscribeData("SmsSubscribes", $data['id']);
|
||||
|
||||
if (!empty($subscribe)) {
|
||||
if ($this->isSubscribeUpdateAllowed($subscribe['status'])) {
|
||||
unset($data['created']);
|
||||
unset($data['createdBy']);
|
||||
unset($data['queuedBy']);
|
||||
unset($data['stoppedBy']);
|
||||
unset($data['errorsCount']);
|
||||
unset($data['sentCount']);
|
||||
unset($data['startTime']);
|
||||
unset($data['status']);
|
||||
unset($data['successCount']);
|
||||
$data['recipientsCount'] = count($data['sms_subscribe_recipients']);
|
||||
|
||||
if (!empty($data['sms_subscribe_recipients'])) {
|
||||
foreach ($data['sms_subscribe_recipients'] as $recipientKey => $recipient) {
|
||||
unset($data['sms_subscribe_recipients'][$recipientKey]['sendStatus']);
|
||||
unset($data['sms_subscribe_recipients'][$recipientKey]['statusMessage']);
|
||||
unset($data['sms_subscribe_recipients'][$recipientKey]['smsRuMessageId']);
|
||||
unset($data['sms_subscribe_recipients'][$recipientKey]['sendDate']);
|
||||
}
|
||||
}
|
||||
|
||||
$subscribe = $subscribesTable->get($data['id']);
|
||||
$subscribe = $subscribesTable->patchEntity($subscribe, $data);
|
||||
|
||||
if ($subscribesTable->save($subscribe)) {
|
||||
if (!empty($data['recipientsToDelete'])) {
|
||||
foreach ($data['recipientsToDelete'] as $recipientToDelete) {
|
||||
$subscribesRecipientsTable->deleteAll([
|
||||
'subscribeId' => $data['id'],
|
||||
'id' => $recipientToDelete
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$result['subscribe'] = $subscribe;
|
||||
$result['status'] = "success";
|
||||
}
|
||||
|
||||
$result['status'] = "success";
|
||||
} else {
|
||||
$result['errors'][] = 'Редактирование активной или завершенной рассылки недоступно';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Рассылка не найдена!';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case "getSubscribeData":
|
||||
if (!empty($data['subscribeId'])) {
|
||||
$subscribe = $this->getSubscribeData("SmsSubscribes", $data['subscribeId']);
|
||||
|
||||
if (!empty($subscribe)) {
|
||||
$result['subscribe'] = $subscribe;
|
||||
$result['status'] = "success";
|
||||
} else {
|
||||
$result['errors'][] = 'Рассылка не найдена!';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "importSubscribeRecipients":
|
||||
$source = !empty($data['file']['tmp_name']) ? $data['file']['tmp_name'] : '';
|
||||
$subscribeId = (!empty($data['subscribeId']) ? (int) $data['subscribeId'] : null);
|
||||
|
||||
if (!empty($source) && !empty($subscribeId)) {
|
||||
$importResult = $subscribesTable->importSubscribesList($source);
|
||||
$result['importNewSubscribersCount'] = 0;
|
||||
$result['importNewSubscribersCountTotal'] = 0;
|
||||
|
||||
if (count($importResult['list']) > 0) {
|
||||
$result['status'] = 'success';
|
||||
$result['importNewSubscribersCountTotal'] = count($importResult['list']);
|
||||
|
||||
$subscribers = (!empty($data['sms_subscribe_recipients']) ? $data['sms_subscribe_recipients'] : []);
|
||||
if (!empty($subscribers)) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
unset($importResult['list'][$subscriber['phone']]); //cleanup duplicates
|
||||
}
|
||||
}
|
||||
$result['importNewSubscribersCount'] = count($importResult['list']);
|
||||
|
||||
if (!empty($importResult['list'])) {
|
||||
foreach($importResult['list'] as $newSubscriberPhone => $newSubscriberName) {
|
||||
$subscribers[] = [
|
||||
"name" => $newSubscriberName,
|
||||
"phone" => $newSubscriberPhone,
|
||||
"sendStatus" => "queued"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
usort($subscribers, function($a, $b) {
|
||||
return strcmp($a['name'], $b['name']);
|
||||
});
|
||||
|
||||
foreach($subscribers as $key => $subscriber) { //fix "null" due to incorrect upload field values
|
||||
foreach($subscriber as $subKey => $value) {
|
||||
if ($value == "null") {
|
||||
$subscriber[$subKey] = null;
|
||||
}
|
||||
}
|
||||
|
||||
$subscribers[$key] = $subscriber;
|
||||
}
|
||||
|
||||
$result['importSubscribers'] = $subscribers;
|
||||
} else {
|
||||
$result['errors'][] = 'Неверный формат файла или список получателей пуст.';
|
||||
}
|
||||
|
||||
$result['incorrectList'] = $importResult['incorrectList'];
|
||||
$result['importNewSubscribersCountTotal'] += count($importResult['incorrectList']);
|
||||
if (count($result['incorrectList'])) {
|
||||
$result['status'] = 'success';
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Ошибка загрузки файла.';
|
||||
}
|
||||
break;
|
||||
|
||||
case "getSmsRuBalance":
|
||||
if ($this->Auth->user('role') == 'admin') {
|
||||
$smsRu = new SMSRU($jsConfig['global']['smsRuApiKey']['value']);
|
||||
$balance = $smsRu->getBalance();
|
||||
|
||||
if ($balance->status == "OK") {
|
||||
$result['status'] = 'success';
|
||||
$result['balance'] = str_replace(".00", "", number_format(max($balance->balance - Configure::read('smsMinimalBalance'), 0), 2, '.', '')); //as requested
|
||||
//$result['balance'] = max($balance->balance - Configure::read('smsMinimalBalance'), 0); //as requested
|
||||
} else {
|
||||
$result['errors'][] = $balance->status_text;
|
||||
}
|
||||
} else {
|
||||
$result['errors'][] = 'Произошла ошибка при запросе баланса, повторите позднее!';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
} else {
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
namespace App\Controller\Manager;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Auth\DefaultPasswordHasher;
|
||||
use App\Controller\AppController;
|
||||
|
||||
class UsersController extends AppController {
|
||||
|
||||
public function beforeFilter(Event $event) {
|
||||
parent::beforeFilter($event);
|
||||
$this->viewBuilder()->setLayout('manager');
|
||||
|
||||
$this->set('isAuthorized', $this->isAuthorized());
|
||||
}
|
||||
|
||||
public function beforeRender(Event $event)
|
||||
{
|
||||
$this->Auth->allow(['*']);
|
||||
}
|
||||
|
||||
public function login() {
|
||||
if ($this->isAuthorized()) {
|
||||
$this->redirect([
|
||||
'controller' => 'Managers',
|
||||
'action' => 'index',
|
||||
'prefix' => 'manager'
|
||||
]);
|
||||
} else {
|
||||
$this->viewBuilder()->setLayout('manager_login');
|
||||
|
||||
$jsConfig = $this->getAppJsConfig("", false);
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
$data = $this->request->getData();
|
||||
$jsConfig["defaultLoginApp"] = $data['defaultLoginApp'] = str_replace("string:", "", $data['defaultLoginApp']);
|
||||
|
||||
$user = $this->Auth->identify();
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
|
||||
if ($user) {
|
||||
if (!empty($user['is_active'])) {
|
||||
$user["available_apps"] = @json_decode($user["available_apps"], true);
|
||||
$this->Auth->setUser($user);
|
||||
|
||||
$usersTable->updateAll([
|
||||
'logging_attempts' => 0
|
||||
],[
|
||||
'id' => $user['id']
|
||||
]);
|
||||
|
||||
if (!empty($data['defaultLoginApp']) && in_array($data['defaultLoginApp'], $user["available_apps"])) {
|
||||
$this->request->getSession()->write('currentApp', $data['defaultLoginApp']);
|
||||
|
||||
return $this->redirect($this->config["appsList"][$data['defaultLoginApp']]["adminUrl"]);
|
||||
} else {
|
||||
$this->request->getSession()->write('currentApp', "cut");
|
||||
return $this->redirect($this->Auth->redirectUrl());
|
||||
}
|
||||
} else {
|
||||
$this->Flash->error('Ваш аккаунт неактивен.<br/>Обратитесь к администратору для активации.');
|
||||
}
|
||||
} else {
|
||||
$existsUsername = $usersTable->find()->where([
|
||||
'username' => $data['username']
|
||||
])->first();
|
||||
|
||||
if (!empty($existsUsername)) {
|
||||
$existsUsername->logging_attempts = $existsUsername->logging_attempts + 1;
|
||||
if ($existsUsername->logging_attempts >= 5) {
|
||||
$existsUsername->is_active = false;
|
||||
}
|
||||
|
||||
$usersTable->save($existsUsername);
|
||||
}
|
||||
|
||||
$this->Flash->error('Неверное имя пользователя или пароль.');
|
||||
}
|
||||
} else {
|
||||
$jsConfig["defaultLoginApp"] = "cut";
|
||||
}
|
||||
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
$this->request->getSession()->delete('currentApp');
|
||||
return $this->redirect($this->Auth->logout());
|
||||
}
|
||||
|
||||
|
||||
public function index() {
|
||||
|
||||
}
|
||||
|
||||
public function usersList() {
|
||||
$this->checkRegisteredAsAdmin();
|
||||
$this->set('jsConfig', $this->getAppJsConfig("", true));
|
||||
|
||||
}
|
||||
|
||||
function addUpdateUser() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data)) {
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
if (!empty($data['password']) && ($data['password'] != $data['passwordRepeat'])) {
|
||||
$result = [
|
||||
'status' => 'warning',
|
||||
'warning' => 'Пароль и подтверждение пароля не совпадают'
|
||||
];
|
||||
} else {
|
||||
$isOk = false;
|
||||
unset($data['last_active']);
|
||||
|
||||
if (empty($data['id'])) { //add
|
||||
$similarUsernameUser = $usersTable->find()->where(['username' => $data['username']])->first();
|
||||
if (empty($similarUsernameUser)) {
|
||||
$newUser = $usersTable->newEntity();
|
||||
$data["available_apps"] = json_encode($data["available_apps"]);
|
||||
$newUser = $usersTable->patchEntity($newUser, $data);
|
||||
|
||||
if ($usersTable->save($newUser)) {
|
||||
$isOk = true;
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Такое имя пользователя/email уже зарегистрированы'
|
||||
];
|
||||
}
|
||||
} else { //update
|
||||
$currentUser = $usersTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($currentUser)) {
|
||||
$similarUsernameUser = $usersTable->find()->where(['username' => $data['username'], 'id !=' => $data['id']])->first();
|
||||
if (empty($similarUsernameUser)) {
|
||||
if ($data['id'] == $this->Auth->user('id')) {
|
||||
unset($data['role']);
|
||||
unset($data['is_active']);
|
||||
|
||||
if (!empty($data['password']) && empty($data['currentPassword'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Необходимо указать текущий пароль'
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($data['password']) && !empty($data['currentPassword'])) {
|
||||
if (!(new DefaultPasswordHasher)->check($data['currentPassword'], $currentUser->password)) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Неверно указан текущий пароль'
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['is_active']) && empty($currentUser['is_active'])) {
|
||||
$data['logging_attempts'] = 0;
|
||||
}
|
||||
|
||||
if ($result['status'] == "success") {
|
||||
$data["available_apps"] = json_encode($data["available_apps"]);
|
||||
$usersTable->patchEntity($currentUser, $data);
|
||||
if ($usersTable->save($currentUser)) {
|
||||
$isOk = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Такое имя пользователя/email уже зарегистрированы'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Пользователь не найден'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isOk) {
|
||||
if (!empty($data['availableToOrderDefault'])) {
|
||||
$usersTable->updateAll(
|
||||
['availableToOrderDefault' => false],
|
||||
['id !=' => $currentUser->id]
|
||||
);
|
||||
}
|
||||
|
||||
$result['users'] = $this->getUsersListForJS();
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'users', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Недостаточно прав для добавление пользователя'
|
||||
];
|
||||
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Недостаточно прав для добавление пользователя'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
function delete() {
|
||||
$result = [
|
||||
'status' => 'success'
|
||||
];
|
||||
|
||||
if ($this->isAuthorized(['admin'])) {
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['id'])) {
|
||||
$orderCut = TableRegistry::getTableLocator()->get('CutOrders')->find()->where(['manager_id' => $data['id'], 'order_type' => 'order'])->count();
|
||||
$orderCalcDoors = TableRegistry::getTableLocator()->get('CalcDoorsOrders')->find()->where(['manager_id' => $data['id'], 'order_type' => 'order'])->count();
|
||||
$orderFasad = TableRegistry::getTableLocator()->get('FasadOrders')->find()->where(['manager_id' => $data['id'], 'order_type' => 'order'])->count();
|
||||
|
||||
if (empty($orderCut) && empty($orderCalcDoors) && empty($orderFasad)) {
|
||||
$usersTable = TableRegistry::getTableLocator()->get('Users');
|
||||
$user = $usersTable->find()->where(['id' => $data['id']])->first();
|
||||
if (!empty($user)) {
|
||||
if ($data['id'] == $this->Auth->user('id')) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Вы не можете удалить свой аккаунт'
|
||||
];
|
||||
} else {
|
||||
$usersTable->delete($user);
|
||||
|
||||
$updates = TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'users', $this->Auth->user('id'));
|
||||
$result = array_merge($result, $updates);
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'error' => 'Пользователь не найден'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'warning',
|
||||
'warning' => 'Удаление пользователя невозможно, так как у него есть заказы на исполнении.'
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'warning' => 'Недостаточно прав для удаления данного пользователя'
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,961 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Routing\Router;
|
||||
|
||||
class OrderPaymentController extends AppController
|
||||
{
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(
|
||||
[
|
||||
'display',
|
||||
'getPaymentStatus',
|
||||
'callbackPay',
|
||||
'callbackRefund',
|
||||
'createElplatPaymentQr',
|
||||
'callbackElplat',
|
||||
'getElpatPaymentStatus'
|
||||
]
|
||||
);
|
||||
$this->viewBuilder()->setLayout('order_payment');
|
||||
}
|
||||
|
||||
public function display($encOrderId = null)
|
||||
{
|
||||
if (!empty($encOrderId)) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['data'] = json_decode($savedOrderData['data'], true);
|
||||
$appsDomain = $savedOrderData['domain'];
|
||||
|
||||
if (empty($_SERVER['HTTP_CUSTOMHOST']) && !empty($_SERVER['SERVER_NAME']) && ($appsDomain != $_SERVER['SERVER_NAME'])) {
|
||||
$this->redirect("https://" . $appsDomain . "/order-payment/" . $encOrderId, 301);
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['HTTP_CUSTOMHOST']) && ($_SERVER['HTTP_CUSTOMHOST'] != $appsDomain)) {
|
||||
$this->set("customAppsRedirect", "https://" . $appsDomain . "/order-payment/" . $encOrderId);
|
||||
}
|
||||
|
||||
if (!empty($savedOrderData['expiry_date'])) {
|
||||
// Рассчитываем время истечения заявки: 23:59 предыдущего дня от expiry_date
|
||||
$expiryTimestamp = strtotime($savedOrderData['expiry_date']);
|
||||
$endOfPreviousDay = strtotime('-1 day', strtotime(date('Y-m-d 23:59:59', $expiryTimestamp)));
|
||||
|
||||
// Проверяем, истек ли срок заявки
|
||||
$isExpired = time() > $endOfPreviousDay;
|
||||
} else {
|
||||
// Если expiry_date отсутствует, помечаем заявку как истекшую
|
||||
$isExpired = true;
|
||||
}
|
||||
|
||||
if (!$isExpired
|
||||
|| $this->isAuthorized(['admin'], ["orderPayment"], false)
|
||||
) {
|
||||
$savedOrderData['encOrderId'] = $encOrderId;
|
||||
|
||||
if (!empty($savedOrderData['paid_date'])) {
|
||||
//var_dump($savedOrderData['paid_date']);
|
||||
//$savedOrderData['payment'] = json_decode($savedOrderData['payment'], true);
|
||||
$savedOrderData['payment'] = [
|
||||
//'DateTime' => $this->patchTimestampForJS($savedOrderData['payment'][count($savedOrderData['payment']) - 1]['DateTime'], -3, true, 'd.m.Y H:i')
|
||||
'DateTime' => $this->patchTimestampForJS(
|
||||
$savedOrderData['paid_date'],
|
||||
-3,
|
||||
true,
|
||||
'd.m.Y H:i'
|
||||
)
|
||||
];
|
||||
} else {
|
||||
$savedOrderData['payment'] = null;
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = [
|
||||
'data' => [
|
||||
'manager_tel' => $savedOrderData['data']['manager_tel']
|
||||
],
|
||||
'link_expired' => true,
|
||||
'order_num' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$jsConfig = $this->getAppJsConfig("orderPayment", false, $savedOrderData);
|
||||
$jsConfig["appsDomain"] = $appsDomain;
|
||||
$jsConfig["rootUrl"] = "https://" . str_replace("apps.", "", $appsDomain);
|
||||
$jsConfig["rootAppsUrl"] = "https://" . $appsDomain;
|
||||
|
||||
$paymentPublicId = "";
|
||||
if (!empty($savedOrderData['targetGateway']) && ($savedOrderData['targetGateway'] == 'РНКБ')) {
|
||||
if (!empty($savedOrderData['domain'])) {
|
||||
$paymentPublicIds = Configure::read("cloudPayments");
|
||||
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersamsev.ru":
|
||||
case "apps.supersam24.ru":
|
||||
$paymentPublicId = $paymentPublicIds[$savedOrderData['domain']]['paymentPublicId'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$jsConfig["paymentPublicId"] = $paymentPublicId;
|
||||
|
||||
$elplatQrEnabled = false;
|
||||
if (!empty($savedOrderData['targetGateway']) && ($savedOrderData['targetGateway'] == 'СБП')) {
|
||||
if (!empty($savedOrderData['domain'])) {
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.prometeysev.ru":
|
||||
case "apps.supersam24.ru":
|
||||
case "apps.supersamsev.ru":
|
||||
$elplatQrEnabled = true;
|
||||
$this->config['common']['siteTitle']['value'] = $jsConfig["primarySiteTitle"];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$jsConfig["elplatQrEnabled"] = $elplatQrEnabled;
|
||||
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
$this->set(
|
||||
'siteTitle',
|
||||
$this->config['common']['siteTitle']['value'] . " - " . 'Оплата счета ' . $savedOrderData['order_num']
|
||||
);
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (empty($savedOrderData)) {
|
||||
$this->redirect('/404');
|
||||
}
|
||||
}
|
||||
|
||||
public function getPaymentStatus()
|
||||
{
|
||||
$result = [
|
||||
'status' => true
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['encOrderId'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['encOrderId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
if (!empty($savedOrderData['paid_date'])) {
|
||||
$result['status'] = true;
|
||||
//$savedOrderData['payment'] = json_decode($savedOrderData['payment'], true);
|
||||
$result['payment'] = [
|
||||
//'DateTime' => $this->patchTimestampForJS($savedOrderData['payment'][count($savedOrderData['payment']) - 1]['DateTime'], -3, true, 'd.m.Y H:i')
|
||||
'paid_date' => $this->patchTimestampForJS(
|
||||
$savedOrderData['paid_date'],
|
||||
-3,
|
||||
true,
|
||||
'd.m.Y H:i'
|
||||
)
|
||||
];
|
||||
} else {
|
||||
$result['status'] = false;
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function callbackPay()
|
||||
{
|
||||
$result = [
|
||||
'code' => 13
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['Data'])) {
|
||||
$data['Data'] = @json_decode(html_entity_decode($data['Data']), true);
|
||||
file_put_contents(TMP . 'callbackPayData' . date('Y-m-d_H-i-s') . '.txt', json_encode($data));
|
||||
|
||||
if (!empty($data['Status']) && ($data['Status'] == 'Completed')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['Data']['encOrderId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['data'] = json_decode($savedOrderData['data'], true);
|
||||
$savedOrderData['payment'] = json_decode($savedOrderData['payment'], true);
|
||||
|
||||
if ($savedOrderData['data']['summa_order_decimal'] == $data['Amount']) {
|
||||
$uploadXmlToFtp = false;
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
|
||||
$isTransactionAlreadyExists = false;
|
||||
if (!empty($savedOrderData['payment'])) {
|
||||
foreach ($savedOrderData['payment'] as $payment) {
|
||||
if ($payment['TransactionId'] == $data['TransactionId']) {
|
||||
$isTransactionAlreadyExists = true;
|
||||
$result['code'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($savedOrderData['payment'])) {
|
||||
$uploadXmlToFtp = true;
|
||||
|
||||
$xml .= '<time>' . $this->patchTimestampForJS(
|
||||
$data['DateTime'],
|
||||
-3,
|
||||
true,
|
||||
'Y-m-d H:i:s'
|
||||
) . '</time><paid>ok</paid><paid_summa>' . $data['Amount'] . '</paid_summa><gateway>РНКБ</gateway>';
|
||||
} else {
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$uploadXmlToFtp = true;
|
||||
|
||||
$xml .= '<time>' . $this->patchTimestampForJS(
|
||||
$data['DateTime'],
|
||||
-3,
|
||||
true,
|
||||
'Y-m-d H:i:s'
|
||||
) . '</time><paid>order_already</paid><paid_summa>' . $data['Amount'] . '</paid_summa><gateway>РНКБ</gateway>';
|
||||
}
|
||||
}
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
////////////////
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
|
||||
$tmpOrder = $orderPaymentTable->get($decryptedData['orderId']);
|
||||
if (empty($tmpOrder->payment)) {
|
||||
$tmpOrder->payment = [];
|
||||
} else {
|
||||
$tmpOrder->payment = json_decode($tmpOrder->payment, true);
|
||||
}
|
||||
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$tmpOrder->payment[] = $data;
|
||||
$tmpOrder->summa_order_decimal_paid += $data['Amount'];
|
||||
}
|
||||
|
||||
$tmpOrder->paid_date = $tmpOrder->payment[count($tmpOrder->payment) - 1]['DateTime'];
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
$tmpOrder->paymentGateway = "CloudPayments";
|
||||
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
$result['code'] = 0;
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(
|
||||
TMP . $filename,
|
||||
false,
|
||||
$filename
|
||||
);
|
||||
///////////////
|
||||
|
||||
if ($uploadXmlToFtp) {
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect(
|
||||
$ftpParams['ip'],
|
||||
(!empty($ftpParams['port']) ? $ftpParams['port'] : 21),
|
||||
5
|
||||
);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login(
|
||||
$ftpConnectionId,
|
||||
$ftpParams['username'],
|
||||
$ftpParams['password']
|
||||
);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["payment"])) {
|
||||
$tmpOrder->files["payment"] = [];
|
||||
}
|
||||
$tmpOrder->files["payment"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
//todo some notify and queue here !!!
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify(
|
||||
$xml,
|
||||
$filename,
|
||||
$savedOrderData
|
||||
);
|
||||
file_put_contents(
|
||||
TMP . 'callbackCloudPaymentsPayData' . date(
|
||||
'Y-m-d_H-i-s'
|
||||
) . '.error.ftpuploaderror.txt',
|
||||
json_encode($data)
|
||||
);
|
||||
};
|
||||
fclose($tmpFile);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
//todo some notify and queue here !!!
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify(
|
||||
$xml,
|
||||
$filename,
|
||||
$savedOrderData
|
||||
);
|
||||
file_put_contents(
|
||||
TMP . 'callbackCloudPaymentsPayData' . date(
|
||||
'Y-m-d_H-i-s'
|
||||
) . '.error.ftpconnecterror.txt',
|
||||
json_encode($data)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function callbackRefund()
|
||||
{
|
||||
$result = [
|
||||
'code' => 13
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (!empty($data['Data'])) {
|
||||
if (!is_array($data['Data'])) {
|
||||
$data['Data'] = @json_decode(html_entity_decode($data['Data']), true);
|
||||
}
|
||||
|
||||
file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.txt', json_encode($data));
|
||||
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['Data']['encOrderId'], $this->config);
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.1.txt', json_encode($decryptedData));
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
])->first();
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.2.txt', json_encode($savedOrderData));
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
/////////////////
|
||||
//$refundAmount = 0;
|
||||
$tmpOrder = $orderPaymentTable->get($decryptedData['orderId']);
|
||||
|
||||
$isTransactionAlreadyExists = false;
|
||||
if (!empty($tmpOrder->payment)) {
|
||||
$tmpOrder->payment = json_decode($tmpOrder->payment, true);
|
||||
//foreach ($tmpOrder->payment as $paymentKey => $payment) {
|
||||
// if ($payment['TransactionId'] == $data['PaymentTransactionId']) {
|
||||
// unset($tmpOrder->payment[$paymentKey]);
|
||||
|
||||
$isTransactionAlreadyExists = false;
|
||||
foreach ($tmpOrder->payment as $payment) {
|
||||
if ($payment['TransactionId'] == $data['TransactionId']) {
|
||||
$isTransactionAlreadyExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
//}
|
||||
} else {
|
||||
$tmpOrder->payment = [];
|
||||
}
|
||||
$tmpOrder->payment[] = $data;
|
||||
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$tmpOrder->summa_order_decimal_paid -= $data['Amount'];
|
||||
$refundAmount = $data['Amount'];
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.6.txt', json_encode($tmpOrder));
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
$xml .= '<time>' . $this->patchTimestampForJS(
|
||||
$data['DateTime'],
|
||||
-3,
|
||||
true,
|
||||
'Y-m-d H:i:s'
|
||||
) . '</time><paid>refund</paid><paid_summa>' . $refundAmount . '</paid_summa><gateway>РНКБ</gateway>';
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
|
||||
if (empty($tmpOrder->summa_order_decimal_paid)) {
|
||||
//$tmpOrder->payment = null;
|
||||
$tmpOrder->paid_date = null;
|
||||
}
|
||||
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
$result['code'] = 0;
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(
|
||||
TMP . $filename,
|
||||
false,
|
||||
$filename
|
||||
);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect(
|
||||
$ftpParams['ip'],
|
||||
(!empty($ftpParams['port']) ? $ftpParams['port'] : 21),
|
||||
5
|
||||
);
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.3.txt', json_encode($ftpConnectionId));
|
||||
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.4.txt', json_encode($ftpTargetDir));
|
||||
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.5.txt', json_encode($isTransactionAlreadyExists));
|
||||
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
|
||||
/*if (empty($tmpOrder->payment)) {
|
||||
$tmpOrder->payment = null;
|
||||
$tmpOrder->paid_date = null;
|
||||
} else {
|
||||
$tmpOrder->paid_date = $tmpOrder->payment[count($tmpOrder->payment) - 1]['DateTime'];
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
}*/
|
||||
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.7.txt', json_encode($tmpOrder));
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["refund"])) {
|
||||
$tmpOrder->files["refund"] = [];
|
||||
}
|
||||
$tmpOrder->files["refund"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify(
|
||||
$xml,
|
||||
$filename,
|
||||
$savedOrderData,
|
||||
"refund",
|
||||
"возврата средств по счету"
|
||||
);
|
||||
file_put_contents(
|
||||
TMP . 'callbackCloudPaymentsRefundData' . date(
|
||||
'Y-m-d_H-i-s'
|
||||
) . '.error.ftpuploaderror.txt',
|
||||
json_encode($data)
|
||||
);
|
||||
//todo some notify and queue here !!!
|
||||
};
|
||||
} else {
|
||||
$result['code'] = 0;
|
||||
}
|
||||
|
||||
fclose($tmpFile);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify(
|
||||
$xml,
|
||||
$filename,
|
||||
$savedOrderData,
|
||||
"refund",
|
||||
"возврата средств по счету"
|
||||
);
|
||||
file_put_contents(
|
||||
TMP . 'callbackCloudPaymentsRefundData' . date(
|
||||
'Y-m-d_H-i-s'
|
||||
) . '.error.ftpconnecterror.txt',
|
||||
json_encode($data)
|
||||
);
|
||||
//todo some notify and queue here !!!
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
public function createElplatPaymentQr()
|
||||
{
|
||||
$result = [
|
||||
'status' => false
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['encOrderId'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['encOrderId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
if (empty($savedOrderData['paid_date'])) {
|
||||
$elplatCredentials = Configure::read('elplat');
|
||||
$elplatCredentials = $elplatCredentials[$savedOrderData['domain']];
|
||||
|
||||
$elplat = new ElplatMerchantAPI();
|
||||
|
||||
$orderData = json_decode($savedOrderData['data'], true);
|
||||
|
||||
$paymentPurposeL1 = "";
|
||||
$paymentPurposeL2 = "";
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$paymentPurposeL1 = 'Оплата счета ' . $orderData['invoice_no'] . ', СуперСам';
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$paymentPurposeL1 = 'Оплата счета ' . $orderData['invoice_no'] . ', СуперСам';
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$paymentPurposeL1 = 'Оплата счета ' . $orderData['invoice_no'] . ', ';
|
||||
$paymentPurposeL2 = 'ООО ТЦ "Прометей"';
|
||||
break;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'login' => $elplatCredentials['login'],
|
||||
"passwd" => $elplatCredentials['passwd'],
|
||||
"callback" => "https://" . $savedOrderData['domain'] . Router::url(
|
||||
['controller' => 'OrderPayment', 'action' => 'callback_elplat']
|
||||
),
|
||||
"qrcType" => "02",
|
||||
"currency" => "RUB",
|
||||
"orgId" => $elplatCredentials['orgId'],
|
||||
"amount" => round($savedOrderData['summa_order_decimal'] * 100),
|
||||
"paymentPurpose" => $paymentPurposeL1 . $paymentPurposeL2,
|
||||
"email" => (!empty($orderData['email']) ? $orderData['email'] : '')
|
||||
];
|
||||
|
||||
$hashId = $elplat->getElplatHashId($data);
|
||||
unset($data['passwd']);
|
||||
|
||||
$request = $elplat->createQr($elplatCredentials['apiUrl'], array_merge($data, [
|
||||
"type" => "createQr",
|
||||
'elplatPhone' => $elplatCredentials['elplatPhone'],
|
||||
'hashId' => $hashId
|
||||
]));
|
||||
|
||||
if (!empty($request['info']['status'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$elplatPayment = $elplatPaymentsTable->newEntity([
|
||||
'orderPaymentId' => $decryptedData['orderId'],
|
||||
'qrData' => $request['info']['qrData'],
|
||||
'qrcId' => $request['info']['qrcId'],
|
||||
'responseData' => null,
|
||||
'status' => 'pending',
|
||||
'created' => $now,
|
||||
'updated' => $now,
|
||||
]);
|
||||
|
||||
$elplatPaymentsTable->save($elplatPayment);
|
||||
|
||||
$result['status'] = true;
|
||||
$result['qrInfo'] = $request['info'];
|
||||
$result['paymentPurposeL1'] = $paymentPurposeL1;
|
||||
$result['paymentPurposeL2'] = $paymentPurposeL2;
|
||||
$result['paymentAmount'] = $orderData['summa_order'] . 'р.';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function getElpatPaymentStatus()
|
||||
{
|
||||
$result = [
|
||||
'status' => 'failure'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['qrcId'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$qrData = $elplatPaymentsTable->find('all')->where([
|
||||
'qrcId ' => $data['qrcId'],
|
||||
])->first();
|
||||
|
||||
if (!empty($qrData)) {
|
||||
$result['status'] = $qrData['status'];
|
||||
|
||||
$orderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $qrData['orderPaymentId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if ($result['status'] != 'success') {
|
||||
//check for payments by other qr
|
||||
|
||||
if (!empty($orderData) && !empty($orderData['paid_date'])) {
|
||||
$result['status'] = 'success';
|
||||
|
||||
$result['payment'] = [
|
||||
'paid_date' => $this->patchTimestampForJS($orderData['paid_date'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result['payment'] = [
|
||||
'paid_date' => $this->patchTimestampForJS($orderData['paid_date'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//$result['status'] = 'success';
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function callbackElplat()
|
||||
{
|
||||
if (!$this->checkIsElplatCallbackIpAllowed()) {
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (empty($data)) {
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
}
|
||||
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.txt', json_encode($data));
|
||||
|
||||
if (isset($data['payStatus'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$qrData = $elplatPaymentsTable->find('all')->where([
|
||||
'qrcId ' => $data['qrcId'],
|
||||
])->first();
|
||||
|
||||
if (empty($qrData)) {
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $qrData['orderPaymentId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (empty($savedOrderData)) {
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
if (((int)$data['allAmount']) < ((int)($savedOrderData['summa_order_decimal'] * 100))) {
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
$qrStatus = "failure";
|
||||
if ($data['payStatus'] == 1) {
|
||||
$qrStatus = "success";
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
|
||||
$xml .= '<time>' . date(
|
||||
'Y-m-d H:i:s'
|
||||
) . '</time><paid>ok</paid><paid_summa>' . ($data['allAmount'] / 100) . '</paid_summa><gateway>СБП</gateway>';
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
////////////////////
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
|
||||
$tmpOrder = $orderPaymentTable->get($savedOrderData['id']);
|
||||
|
||||
$tmpOrder->payment = [];
|
||||
$tmpOrder->payment[] = $data;
|
||||
$tmpOrder->summa_order_decimal_paid = $data['allAmount'] / 100;
|
||||
|
||||
$tmpOrder->paid_date = date('Y-m-d H:i:s', strtotime("-3 hours"));
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
$tmpOrder->paymentGateway = "Elplat";
|
||||
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(
|
||||
TMP . $filename,
|
||||
false,
|
||||
$filename
|
||||
);
|
||||
////////////////////
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect(
|
||||
$ftpParams['ip'],
|
||||
(!empty($ftpParams['port']) ? $ftpParams['port'] : 21),
|
||||
5
|
||||
);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["payment"])) {
|
||||
$tmpOrder->files["payment"] = [];
|
||||
}
|
||||
$tmpOrder->files["payment"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
} else {
|
||||
//todo some notify and queue here !!!
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify($xml, $filename, $savedOrderData);
|
||||
file_put_contents(
|
||||
TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.ftpuploaderror.txt',
|
||||
json_encode($data)
|
||||
);
|
||||
};
|
||||
fclose($tmpFile);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
$orderPaymentTable->ftpOrderPaymentUploadErrorNotify($xml, $filename, $savedOrderData);
|
||||
file_put_contents(
|
||||
TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.ftpconnecterror.txt',
|
||||
json_encode($data)
|
||||
);
|
||||
//todo some notify and queue here !!!
|
||||
}
|
||||
}
|
||||
|
||||
$qrData->responseData = json_encode($data);
|
||||
$qrData->status = $qrStatus;
|
||||
$qrData->updated = date('Y-m-d H:i:s');
|
||||
$elplatPaymentsTable->save($qrData);
|
||||
|
||||
|
||||
ob_clean();
|
||||
header_remove();
|
||||
header("Content-type: application/json");
|
||||
http_response_code(200);
|
||||
echo json_encode(["status" => true]);
|
||||
exit;
|
||||
} else {
|
||||
die('NOTOK');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkIsElplatCallbackIpAllowed()
|
||||
{
|
||||
$allow = false;
|
||||
$allowedIps = ['91.223.44.0/24'];
|
||||
$ipToCheck = $this->request->clientIP();
|
||||
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
|
||||
$ipToCheck = $_SERVER['HTTP_X_REAL_IP'];
|
||||
}
|
||||
|
||||
foreach ($allowedIps as $ip_allow) {
|
||||
// If IP has / means CIDR notation
|
||||
if (strpos($ip_allow, '/') === false) {
|
||||
// Check Single IP
|
||||
if (inet_pton($ipToCheck) == inet_pton($ip_allow)) {
|
||||
$allow = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Check IP range
|
||||
list($subnet, $bits) = explode('/', $ip_allow);
|
||||
|
||||
// Convert subnet to binary string of $bits length
|
||||
$subnet = unpack('H*', inet_pton($subnet)); // Subnet in Hex
|
||||
|
||||
foreach ($subnet as $i => $h) {
|
||||
$subnet[$i] = base_convert($h, 16, 2);
|
||||
} // Array of Binary
|
||||
$subnet = substr(implode('', $subnet), 0, $bits); // Subnet in Binary, only network bits
|
||||
|
||||
// Convert remote IP to binary string of $bits length
|
||||
$ip = unpack('H*', inet_pton($ipToCheck)); // IP in Hex
|
||||
foreach ($ip as $i => $h) {
|
||||
$ip[$i] = base_convert($h, 16, 2);
|
||||
} // Array of Binary
|
||||
$ip = substr(implode('', $ip), 0, $bits); // IP in Binary, only network bits
|
||||
|
||||
// Check network bits match
|
||||
if ($subnet == $ip) {
|
||||
$allow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $allow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,803 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Core\Configure;use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Routing\Router;
|
||||
|
||||
class OrderPaymentController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['display', 'getPaymentStatus', 'callbackPay', 'callbackRefund', 'createElplatPaymentQr', 'callbackElplat', 'getElpatPaymentStatus']);
|
||||
$this->viewBuilder()->setLayout('order_payment');
|
||||
}
|
||||
|
||||
public function display($encOrderId = null) {
|
||||
if(!empty($encOrderId)) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($encOrderId, $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['data'] = json_decode($savedOrderData['data'], true);
|
||||
$appsDomain = $savedOrderData['domain'];
|
||||
|
||||
if (empty($_SERVER['HTTP_CUSTOMHOST']) && !empty($_SERVER['SERVER_NAME']) && ($appsDomain != $_SERVER['SERVER_NAME'])) {
|
||||
$this->redirect("https://".$appsDomain."/order-payment/".$encOrderId, 301);
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['HTTP_CUSTOMHOST']) && ($_SERVER['HTTP_CUSTOMHOST'] != $appsDomain)) {
|
||||
$this->set("customAppsRedirect", "https://".$appsDomain."/order-payment/".$encOrderId);
|
||||
}
|
||||
|
||||
if (!empty($savedOrderData['paid_date'])
|
||||
|| !empty($savedOrderData['expiry_date']) && (date('Y-m-d H:i:s', strtotime($savedOrderData['expiry_date'])) >= date('Y-m-d H:i:s'))
|
||||
|| ($this->isAuthorized([], ["orderPayment"], false))
|
||||
) {
|
||||
$savedOrderData['encOrderId'] = $encOrderId;
|
||||
|
||||
if (!empty($savedOrderData['paid_date'])) {
|
||||
|
||||
//var_dump($savedOrderData['paid_date']);
|
||||
//$savedOrderData['payment'] = json_decode($savedOrderData['payment'], true);
|
||||
$savedOrderData['payment'] = [
|
||||
//'DateTime' => $this->patchTimestampForJS($savedOrderData['payment'][count($savedOrderData['payment']) - 1]['DateTime'], -3, true, 'd.m.Y H:i')
|
||||
'DateTime' => $this->patchTimestampForJS($savedOrderData['paid_date'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
} else {
|
||||
$savedOrderData['payment'] = null;
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = [
|
||||
'data' => [
|
||||
'manager_tel' => $savedOrderData['data']['manager_tel']
|
||||
],
|
||||
'link_expired' => true,
|
||||
'order_num' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$jsConfig = $this->getAppJsConfig("orderPayment", false, $savedOrderData);
|
||||
$jsConfig["appsDomain"] = $appsDomain;
|
||||
$jsConfig["rootUrl"] = "https://" . str_replace("apps.", "", $appsDomain);
|
||||
$jsConfig["rootAppsUrl"] = "https://" . $appsDomain;
|
||||
|
||||
$paymentPublicId = "";
|
||||
if (!empty($savedOrderData['targetGateway']) && ($savedOrderData['targetGateway'] == 'РНКБ')) {
|
||||
if (!empty($savedOrderData['domain'])) {
|
||||
$paymentPublicIds = Configure::read("cloudPayments");
|
||||
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.supersamsev.ru":
|
||||
case "apps.supersam24.ru":
|
||||
$paymentPublicId = $paymentPublicIds[$savedOrderData['domain']]['paymentPublicId'];
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
$jsConfig["paymentPublicId"] = $paymentPublicId;
|
||||
|
||||
$elplatQrEnabled = false;
|
||||
if (!empty($savedOrderData['targetGateway']) && ($savedOrderData['targetGateway'] == 'СБП')) {
|
||||
if (!empty($savedOrderData['domain'])) {
|
||||
switch ($savedOrderData['domain']) {
|
||||
case "apps.prometeysev.ru":
|
||||
case "apps.supersam24.ru":
|
||||
case "apps.supersamsev.ru":
|
||||
$elplatQrEnabled = true;
|
||||
$this->config['common']['siteTitle']['value'] = $jsConfig["primarySiteTitle"];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$jsConfig["elplatQrEnabled"] = $elplatQrEnabled;
|
||||
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
$this->set('siteTitle', $this->config['common']['siteTitle']['value'] . " - " . 'Оплата счета ' . $savedOrderData['order_num']);
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (empty($savedOrderData)) {
|
||||
$this->redirect('/404');
|
||||
}
|
||||
}
|
||||
|
||||
public function getPaymentStatus() {
|
||||
$result = [
|
||||
'status' => true
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if(!empty($data['encOrderId'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['encOrderId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
if (!empty($savedOrderData['paid_date'])) {
|
||||
$result['status'] = true;
|
||||
//$savedOrderData['payment'] = json_decode($savedOrderData['payment'], true);
|
||||
$result['payment'] = [
|
||||
//'DateTime' => $this->patchTimestampForJS($savedOrderData['payment'][count($savedOrderData['payment']) - 1]['DateTime'], -3, true, 'd.m.Y H:i')
|
||||
'paid_date' => $this->patchTimestampForJS($savedOrderData['paid_date'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
} else {
|
||||
$result['status'] = false;
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function callbackPay() {
|
||||
$result = [
|
||||
'code' => 13
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['Data'])) {
|
||||
$data['Data'] = @json_decode(html_entity_decode($data['Data']), true);
|
||||
file_put_contents(TMP . 'callbackPayData' . date('Y-m-d_H-i-s') . '.txt', json_encode($data));
|
||||
|
||||
if (!empty($data['Status']) && ($data['Status'] == 'Completed')) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['Data']['encOrderId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$savedOrderData['data'] = json_decode($savedOrderData['data'], true);
|
||||
$savedOrderData['payment'] = json_decode($savedOrderData['payment'], true);
|
||||
|
||||
if ($savedOrderData['data']['summa_order_decimal'] == $data['Amount']) {
|
||||
$uploadXmlToFtp = false;
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
|
||||
$isTransactionAlreadyExists = false;
|
||||
if (!empty($savedOrderData['payment'])) {
|
||||
foreach ($savedOrderData['payment'] as $payment) {
|
||||
if ($payment['TransactionId'] == $data['TransactionId']) {
|
||||
$isTransactionAlreadyExists = true;
|
||||
$result['code'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($savedOrderData['payment'])) {
|
||||
$uploadXmlToFtp = true;
|
||||
|
||||
$xml .= '<time>' . $this->patchTimestampForJS($data['DateTime'], -3, true, 'Y-m-d H:i:s') . '</time><paid>ok</paid><paid_summa>'.$data['Amount'].'</paid_summa><gateway>РНКБ</gateway>';
|
||||
} else {
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$uploadXmlToFtp = true;
|
||||
|
||||
$xml .= '<time>' . $this->patchTimestampForJS($data['DateTime'], -3, true, 'Y-m-d H:i:s') . '</time><paid>order_already</paid><paid_summa>'.$data['Amount'].'</paid_summa><gateway>РНКБ</gateway>';
|
||||
}
|
||||
}
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
if ($uploadXmlToFtp) {
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
$tmpOrder = $orderPaymentTable->get($decryptedData['orderId']);
|
||||
|
||||
if (empty($tmpOrder->payment)) {
|
||||
$tmpOrder->payment = [];
|
||||
} else {
|
||||
$tmpOrder->payment = json_decode($tmpOrder->payment, true);
|
||||
}
|
||||
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$tmpOrder->payment[] = $data;
|
||||
$tmpOrder->summa_order_decimal_paid += $data['Amount'];
|
||||
}
|
||||
|
||||
$tmpOrder->paid_date = $tmpOrder->payment[count($tmpOrder->payment) - 1]['DateTime'];
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
$tmpOrder->paymentGateway = "CloudPayments";
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["payment"])) {
|
||||
$tmpOrder->files["payment"] = [];
|
||||
}
|
||||
$tmpOrder->files["payment"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
$result['code'] = 0;
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
};
|
||||
fclose($tmpFile);
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(TMP . $filename, false, $filename);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function callbackRefund() {
|
||||
$result = [
|
||||
'code' => 13
|
||||
];
|
||||
|
||||
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (!empty($data['Data'])) {
|
||||
if (!is_array($data['Data'])) {
|
||||
$data['Data'] = @json_decode(html_entity_decode($data['Data']), true);
|
||||
}
|
||||
|
||||
file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.txt', json_encode($data));
|
||||
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['Data']['encOrderId'], $this->config);
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.1.txt', json_encode($decryptedData));
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
])->first();
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.2.txt', json_encode($savedOrderData));
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.3.txt', json_encode($ftpConnectionId));
|
||||
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.4.txt', json_encode($ftpTargetDir));
|
||||
|
||||
//$refundAmount = 0;
|
||||
$tmpOrder = $orderPaymentTable->get($decryptedData['orderId']);
|
||||
|
||||
$isTransactionAlreadyExists = false;
|
||||
if (!empty($tmpOrder->payment)) {
|
||||
$tmpOrder->payment = json_decode($tmpOrder->payment, true);
|
||||
//foreach ($tmpOrder->payment as $paymentKey => $payment) {
|
||||
// if ($payment['TransactionId'] == $data['PaymentTransactionId']) {
|
||||
// unset($tmpOrder->payment[$paymentKey]);
|
||||
|
||||
$isTransactionAlreadyExists = false;
|
||||
foreach ($tmpOrder->payment as $payment) {
|
||||
if ($payment['TransactionId'] == $data['TransactionId']) {
|
||||
$isTransactionAlreadyExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
//}
|
||||
} else {
|
||||
$tmpOrder->payment = [];
|
||||
}
|
||||
$tmpOrder->payment[] = $data;
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.5.txt', json_encode($isTransactionAlreadyExists));
|
||||
|
||||
if (!$isTransactionAlreadyExists) {
|
||||
$tmpOrder->summa_order_decimal_paid -= $data['Amount'];
|
||||
$refundAmount = $data['Amount'];
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.6.txt', json_encode($tmpOrder));
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
$xml .= '<time>' . $this->patchTimestampForJS($data['DateTime'], -3, true, 'Y-m-d H:i:s') . '</time><paid>refund</paid><paid_summa>' . $refundAmount . '</paid_summa><gateway>РНКБ</gateway>';
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
/*if (empty($tmpOrder->payment)) {
|
||||
$tmpOrder->payment = null;
|
||||
$tmpOrder->paid_date = null;
|
||||
} else {
|
||||
$tmpOrder->paid_date = $tmpOrder->payment[count($tmpOrder->payment) - 1]['DateTime'];
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
}*/
|
||||
|
||||
if (empty($tmpOrder->summa_order_decimal_paid)) {
|
||||
//$tmpOrder->payment = null;
|
||||
$tmpOrder->paid_date = null;
|
||||
}
|
||||
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.7.txt', json_encode($tmpOrder));
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["refund"])) {
|
||||
$tmpOrder->files["refund"] = [];
|
||||
}
|
||||
$tmpOrder->files["refund"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
$result['code'] = 0;
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
//file_put_contents(TMP . 'callbackRefundData' . date('Y-m-d_H-i-s') . '.8.txt', json_encode($tmpOrder));
|
||||
};
|
||||
} else {
|
||||
$result['code'] = 0;
|
||||
}
|
||||
|
||||
fclose($tmpFile);
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(TMP . $filename, false, $filename);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
//$result['code'] = 1;
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
|
||||
public function createElplatPaymentQr() {
|
||||
$result = [
|
||||
'status' => false
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if(!empty($data['encOrderId'])) {
|
||||
$ordersTable = TableRegistry::getTableLocator()->get('CutOrders');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
$decryptedData = $ordersTable->decryptCustomData($data['encOrderId'], $this->config);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $decryptedData['orderId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (!empty($savedOrderData)) {
|
||||
if (empty($savedOrderData['paid_date'])) {
|
||||
$elplatCredentials = Configure::read('elplat');
|
||||
$elplatCredentials = $elplatCredentials[$savedOrderData['domain']];
|
||||
|
||||
$elplat = new ElplatMerchantAPI();
|
||||
|
||||
$orderData = json_decode($savedOrderData['data'], true);
|
||||
|
||||
$paymentPurposeL1 = "";
|
||||
$paymentPurposeL2 = "";
|
||||
switch($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$paymentPurposeL1 = 'Оплата счета ' . $orderData['invoice_no'] . ', СуперСам';
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$paymentPurposeL1 = 'Оплата счета ' . $orderData['invoice_no'] . ', СуперСам';
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$paymentPurposeL1 = 'Оплата счета ' . $orderData['invoice_no'] . ', ';
|
||||
$paymentPurposeL2 = 'ООО ТЦ "Прометей"';
|
||||
break;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'login' => $elplatCredentials['login'],
|
||||
"passwd" => $elplatCredentials['passwd'],
|
||||
"callback" => "https://" . $savedOrderData['domain'] . Router::url(['controller' => 'OrderPayment', 'action' => 'callback_elplat']),
|
||||
"qrcType" => "02",
|
||||
"currency" => "RUB",
|
||||
"orgId" => $elplatCredentials['orgId'],
|
||||
"amount" => round($savedOrderData['summa_order_decimal'] * 100),
|
||||
"paymentPurpose" => $paymentPurposeL1.$paymentPurposeL2,
|
||||
"email" => (!empty($orderData['email']) ? $orderData['email'] : '')
|
||||
];
|
||||
|
||||
$hashId = $elplat->getElplatHashId($data);
|
||||
unset($data['passwd']);
|
||||
|
||||
$request = $elplat->createQr($elplatCredentials['apiUrl'], array_merge($data, [
|
||||
"type" => "createQr",
|
||||
'elplatPhone' => $elplatCredentials['elplatPhone'],
|
||||
'hashId' => $hashId
|
||||
]));
|
||||
|
||||
if (!empty($request['info']['status'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$elplatPayment = $elplatPaymentsTable->newEntity([
|
||||
'orderPaymentId' => $decryptedData['orderId'],
|
||||
'qrData' => $request['info']['qrData'],
|
||||
'qrcId' => $request['info']['qrcId'],
|
||||
'responseData' => null,
|
||||
'status' => 'pending',
|
||||
'created' => $now,
|
||||
'updated' => $now,
|
||||
]);
|
||||
|
||||
$elplatPaymentsTable->save($elplatPayment);
|
||||
|
||||
$result['status'] = true;
|
||||
$result['qrInfo'] = $request['info'];
|
||||
$result['paymentPurposeL1'] = $paymentPurposeL1;
|
||||
$result['paymentPurposeL2'] = $paymentPurposeL2;
|
||||
$result['paymentAmount'] = $orderData['summa_order'].'р.';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$savedOrderData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function getElpatPaymentStatus() {
|
||||
$result = [
|
||||
'status' => 'failure'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if(!empty($data['qrcId'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$qrData = $elplatPaymentsTable->find('all')->where([
|
||||
'qrcId ' => $data['qrcId'],
|
||||
])->first();
|
||||
|
||||
if (!empty($qrData)) {
|
||||
$result['status'] = $qrData['status'];
|
||||
|
||||
$orderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $qrData['orderPaymentId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if ($result['status'] != 'success') {
|
||||
//check for payments by other qr
|
||||
|
||||
if (!empty($orderData) && !empty($orderData['paid_date'])) {
|
||||
$result['status'] = 'success';
|
||||
|
||||
$result['payment'] = [
|
||||
'paid_date' => $this->patchTimestampForJS($orderData['paid_date'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$result['payment'] = [
|
||||
'paid_date' => $this->patchTimestampForJS($orderData['paid_date'], -3, true, 'd.m.Y H:i')
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//$result['status'] = 'success';
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
public function callbackElplat() {
|
||||
if (!$this->checkIsElplatCallbackIpAllowed()) {
|
||||
$ipToCheck = $this->request->clientIP();
|
||||
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
|
||||
$ipToCheck = $_SERVER['HTTP_X_REAL_IP'];
|
||||
}
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.txt', json_encode(['incorrect callback ip ' . $ipToCheck]));
|
||||
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
$data = $this->request->getData();
|
||||
|
||||
if (empty($data)) {
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
}
|
||||
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.txt', json_encode($data));
|
||||
|
||||
if(isset($data['payStatus'])) {
|
||||
$elplatPaymentsTable = TableRegistry::getTableLocator()->get('ElplatPayments');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$qrData = $elplatPaymentsTable->find('all')->where([
|
||||
'qrcId ' => $data['qrcId'],
|
||||
])->first();
|
||||
|
||||
if (empty($qrData)) {
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.qrnotfoundindb.txt', json_encode($data));
|
||||
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
$savedOrderData = $orderPaymentTable->find('all')->where([
|
||||
'id' => $qrData['orderPaymentId'],
|
||||
'isDeleted' => false,
|
||||
])->first();
|
||||
|
||||
if (empty($savedOrderData)) {
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.ordernotfoundindb.txt', json_encode($data));
|
||||
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
if (((int)$data['allAmount']) < ((int)($savedOrderData['summa_order_decimal'] * 100))) {
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.incorrectallamount.txt', json_encode($data));
|
||||
|
||||
die('NOTOK');
|
||||
}
|
||||
|
||||
$qrStatus = "failure";
|
||||
if ($data['payStatus'] == 1) {
|
||||
$qrStatus = "success";
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="windows-1251"?><orders><invoice_no>' . $savedOrderData['order_num'] . '</invoice_no>';
|
||||
|
||||
$xml .= '<time>' . date('Y-m-d H:i:s') . '</time><paid>ok</paid><paid_summa>'.($data['allAmount']/100).'</paid_summa><gateway>СБП</gateway>';
|
||||
$xml .= '</orders>';
|
||||
$xml = mb_convert_encoding(str_replace("\n", "", $xml), "Windows-1251", "UTF-8");
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
$ftpTargetDir = "";
|
||||
switch($savedOrderData['domain']) {
|
||||
case "apps.supersam24.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiring24Out'];
|
||||
break;
|
||||
|
||||
case "apps.supersamsev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringOut'];
|
||||
break;
|
||||
|
||||
case "apps.prometeysev.ru":
|
||||
$ftpTargetDir = $ftpParams['acquiringPrometeyOut'];
|
||||
break;
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpTargetDir);
|
||||
|
||||
$tmpFile = tmpfile();
|
||||
fwrite($tmpFile, $xml);
|
||||
rewind($tmpFile);
|
||||
|
||||
$filename = 'acquiring_in_' . date('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(4)) . '.xml';
|
||||
if (ftp_fput($ftpConnectionId, $filename, $tmpFile, FTP_BINARY, 0)) {
|
||||
|
||||
$tmpOrder = $orderPaymentTable->get($savedOrderData['id']);
|
||||
|
||||
$tmpOrder->payment = [];
|
||||
$tmpOrder->payment[] = $data;
|
||||
$tmpOrder->summa_order_decimal_paid = $data['allAmount'] / 100;
|
||||
|
||||
$tmpOrder->paid_date = date('Y-m-d H:i:s', strtotime("-3 hours"));
|
||||
$tmpOrder->payment = json_encode($tmpOrder->payment);
|
||||
$tmpOrder->paymentGateway = "Elplat";
|
||||
|
||||
/*if (empty($tmpOrder->files)) {
|
||||
$tmpOrder->files = [];
|
||||
} else {
|
||||
$tmpOrder->files = json_decode($tmpOrder->files, true);
|
||||
}
|
||||
|
||||
if (empty($tmpOrder->files["payment"])) {
|
||||
$tmpOrder->files["payment"] = [];
|
||||
}
|
||||
$tmpOrder->files["payment"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $filename,
|
||||
"xml" => $xml
|
||||
];
|
||||
|
||||
$tmpOrder->files = json_encode($tmpOrder->files);*/
|
||||
|
||||
$orderPaymentTable->save($tmpOrder);
|
||||
} else {
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.ftpuploaderror.txt', json_encode($data));
|
||||
};
|
||||
fclose($tmpFile);
|
||||
|
||||
file_put_contents(TMP . $filename, $xml);
|
||||
TableRegistry::getTableLocator()->get('CutSheets')->putImportFileToArchive(TMP . $filename, false, $filename);
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.ftpconnecterror.txt', json_encode($data));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$qrData->responseData = json_encode($data);
|
||||
$qrData->status = $qrStatus;
|
||||
$qrData->updated = date('Y-m-d H:i:s');
|
||||
$elplatPaymentsTable->save($qrData);
|
||||
|
||||
//file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.success.ftpuploadok.txt', json_encode($data));
|
||||
|
||||
ob_clean();
|
||||
header_remove();
|
||||
header("Content-type: application/json");
|
||||
http_response_code(200);
|
||||
echo json_encode(["status" => true]);
|
||||
exit;
|
||||
} else {
|
||||
file_put_contents(TMP . 'callbackElplatPayData' . date('Y-m-d_H-i-s') . '.error.paystatust0.txt', json_encode($data));
|
||||
|
||||
die('NOTOK');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkIsElplatCallbackIpAllowed() {
|
||||
$allow = false;
|
||||
$allowedIps = ['91.223.44.0/24'];
|
||||
$ipToCheck = $this->request->clientIP();
|
||||
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
|
||||
$ipToCheck = $_SERVER['HTTP_X_REAL_IP'];
|
||||
}
|
||||
|
||||
foreach($allowedIps as $ip_allow) {
|
||||
// If IP has / means CIDR notation
|
||||
if(strpos($ip_allow, '/') === false) {
|
||||
// Check Single IP
|
||||
if(inet_pton($ipToCheck) == inet_pton($ip_allow)) {
|
||||
$allow = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Check IP range
|
||||
list($subnet, $bits) = explode('/', $ip_allow);
|
||||
|
||||
// Convert subnet to binary string of $bits length
|
||||
$subnet = unpack('H*', inet_pton($subnet)); // Subnet in Hex
|
||||
|
||||
foreach($subnet as $i => $h) $subnet[$i] = base_convert($h, 16, 2); // Array of Binary
|
||||
$subnet = substr(implode('', $subnet), 0, $bits); // Subnet in Binary, only network bits
|
||||
|
||||
// Convert remote IP to binary string of $bits length
|
||||
$ip = unpack('H*', inet_pton($ipToCheck)); // IP in Hex
|
||||
foreach($ip as $i => $h) $ip[$i] = base_convert($h, 16, 2); // Array of Binary
|
||||
$ip = substr(implode('', $ip), 0, $bits); // IP in Binary, only network bits
|
||||
|
||||
// Check network bits match
|
||||
if($subnet == $ip) {
|
||||
$allow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $allow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\Event;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class OrdersInfoController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['display', 'authorize']);
|
||||
$this->viewBuilder()->setLayout('orders_info');
|
||||
}
|
||||
|
||||
|
||||
public function display() {
|
||||
$jsConfig = $this->getAppJsConfig("ordersInfo", false);
|
||||
$jsConfig['isPhoneAuthorized'] = false;
|
||||
|
||||
if (!empty($_COOKIE['oip'])) {
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('CutOrders')->decryptCustomData($_COOKIE['oip'], $this->config);
|
||||
if (!empty($decryptedData['phone'])) {
|
||||
$jsConfig['isPhoneAuthorized'] = true;
|
||||
$jsConfig['authorizedPhone'] = $decryptedData['phone'];
|
||||
} else {
|
||||
@setcookie("oip", "", time() - 3600, "/", NULL, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
$data = $this->request->getData();
|
||||
if (!empty($data['action'])) {
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
'errors' => [],
|
||||
'isPhoneAuthorized' => $jsConfig['isPhoneAuthorized']
|
||||
];
|
||||
if (!empty($jsConfig['authorizedPhone'])) {
|
||||
$result['authorizedPhone'] = $jsConfig['authorizedPhone'];
|
||||
|
||||
switch($data['action']) {
|
||||
case "searchOrders":
|
||||
$result = $this->searchOrdersInfoOrders($result, $data);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
$this->set('jsConfig', $jsConfig);
|
||||
}
|
||||
|
||||
private function searchOrdersInfoOrders($result, $data) {
|
||||
//$result['authorizedPhone'] = '+117 (978) 260-77-53';
|
||||
$searchPhone = "%".cleanupPhone(trim($result['authorizedPhone']))."%";
|
||||
|
||||
$conditions = [];
|
||||
if (!empty($searchPhone)) {
|
||||
$conditions[] = [
|
||||
'tel LIKE' => $searchPhone,
|
||||
];
|
||||
}
|
||||
|
||||
$result['totalOrders'] = 0;
|
||||
$conditions = array_merge($conditions, ['isDeleted' => false]);
|
||||
|
||||
$currentPage = (!empty($data['currentPage']) ? (int)$data['currentPage']: 1);
|
||||
$numPerPage = (!empty($data['numPerPage']) ? (int)$data['numPerPage']: 25);
|
||||
|
||||
$sort = [
|
||||
'field' => 'created',
|
||||
'direction' => 'desc'
|
||||
];
|
||||
|
||||
if (!empty($data['sortFields'])) {
|
||||
switch($data['sortFields']['field']) {
|
||||
case 'nom':
|
||||
case 'fio':
|
||||
case 'totalSum':
|
||||
case 'created':
|
||||
$sort['field'] = $data['sortFields']['field'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($data['sortFields']['direction'], ['asc', 'desc'])) {
|
||||
$sort['direction'] = 'desc';
|
||||
} else {
|
||||
$sort['direction'] = $data['sortFields']['direction'];
|
||||
}
|
||||
|
||||
|
||||
$ordersInfoTable = TableRegistry::getTableLocator()->get("OrdersInfo");
|
||||
$ordersList = $ordersInfoTable->find('all')->where($conditions)->order([$sort['field'] => $sort['direction']])->page($currentPage, $numPerPage)->all();
|
||||
|
||||
if (!empty($ordersList)) {
|
||||
$ordersList = $ordersList->toArray();
|
||||
foreach($ordersList as $key => $order) {
|
||||
$order['data'] = json_decode($order['data'], true);
|
||||
$order['tel'] = formatPhone($order['tel']);
|
||||
$order['created'] = $this->patchTimestampForJS($order['created'], 0, true, 'd.m.Y');
|
||||
}
|
||||
|
||||
$result['totalOrders'] = $ordersInfoTable->find('all')->where($conditions)->count();
|
||||
$result['ordersTotalSum'] = str_replace(".00", "", toFixed2Price($ordersInfoTable->find('all')->where($conditions)->sumOf('totalSum')));
|
||||
}
|
||||
|
||||
$result['ordersList'] = (!empty($ordersList) ? $ordersList : []);
|
||||
$result['status'] = "success";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function authorize() {
|
||||
$result = [
|
||||
'status' => 'error'
|
||||
];
|
||||
|
||||
$data = $this->request->getData();
|
||||
if(!empty($data['action'])) {
|
||||
switch($data['action']) {
|
||||
case "sendConfirmCode":
|
||||
if (!empty($data['phoneToAuthorize'])) {
|
||||
$ordersInfoAuthTable = TableRegistry::getTableLocator()->get("OrdersInfoAuth");
|
||||
|
||||
if (!empty($data['confirmCodeHash'])) {
|
||||
$confirmCode = $ordersInfoAuthTable->find('all')->where([
|
||||
'hash' => $data['confirmCodeHash'],
|
||||
'phone' => $data['phoneToAuthorize']
|
||||
])->first();
|
||||
|
||||
if (!empty($confirmCode)) {
|
||||
if ((date('Y-m-d H:i:s', strtotime('-120 seconds')) > date('Y-m-d H:i:s', strtotime($confirmCode['created'])))) {
|
||||
$ordersInfoAuthTable->delete($confirmCode);
|
||||
} else {
|
||||
$result['errors'] = ['Ошибка отправки SMS с кодом подтверждения. Пожалуйста, повторите позднее.'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($result['errors'])) {
|
||||
$confirmCode = $ordersInfoAuthTable->generateConfirmCode();
|
||||
$result['errors'] = ['Ошибка отправки SMS с кодом подтверждения. Пожалуйста, повторите позднее.'];
|
||||
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
$smsRuApiKey = $settingsTable->find()->where([
|
||||
'key' => 'smsRuApiKey',
|
||||
'group' => 'global'
|
||||
])->first();
|
||||
|
||||
if (!empty($smsRuApiKey)) {
|
||||
$smsResult = TableRegistry::getTableLocator()->get('CutOrders')->sendSms([$data['phoneToAuthorize']], "СуперСам. Ваш код подтверждения: " . $confirmCode, $smsRuApiKey->value, "", true);
|
||||
//$smsResult = TableRegistry::getTableLocator()->get('CutOrders')->sendSms(['+7 (978) 1462978'], "Ваш код подтвеждения: " . $confirmCode, $smsRuApiKey->value, "");
|
||||
if (!empty($smsResult->status) && ($smsResult->status == 'OK')) {
|
||||
$created = date('Y-m-d H:i:s');
|
||||
$currentConfirmCode = $ordersInfoAuthTable->newEntity([
|
||||
'phone' => $data['phoneToAuthorize'],
|
||||
'confirm_code' => $confirmCode,
|
||||
'created' => $created,
|
||||
'hash' => $ordersInfoAuthTable->generateCustomHash($data['phoneToAuthorize'] . $created)
|
||||
]);
|
||||
|
||||
if ($ordersInfoAuthTable->save($currentConfirmCode)) {
|
||||
$result['status'] = "success";
|
||||
$result['confirmCodeIsSent'] = true;
|
||||
$result['confirmCodeHash'] = $currentConfirmCode['hash'];
|
||||
unset($result['errors']);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case "checkConfirmCode":
|
||||
if (!empty($data['phoneToAuthorize'])) {
|
||||
$ordersInfoAuthTable = TableRegistry::getTableLocator()->get("OrdersInfoAuth");
|
||||
|
||||
$confirmCode = $ordersInfoAuthTable->find('all')->where([
|
||||
'hash' => $data['confirmCodeHash'],
|
||||
'phone' => $data['phoneToAuthorize']
|
||||
])->first();
|
||||
|
||||
if (!empty($confirmCode)) {
|
||||
if ($confirmCode['try_count'] >= 3) {
|
||||
$result['errors'] = ['Вы слишком много раз неверно ввели код подтверждения. Повторите попытку позже.'];
|
||||
$result['tooManyCodeInputRetries'] = true;
|
||||
} else {
|
||||
if ($confirmCode['confirm_code'] == $data['confirmCode']) {
|
||||
$encryptedPhone = TableRegistry::getTableLocator()->get('CutOrders')->encryptCustomData(
|
||||
$data['phoneToAuthorize'],
|
||||
'phone',
|
||||
["encrypt" => Configure::read("encrypt")]
|
||||
);
|
||||
@setcookie("oip", $encryptedPhone, time() + 3 * 30 * 24 * 3600, "/", NULL, true, false); //3 months
|
||||
|
||||
$ordersInfoAuthTable->delete($confirmCode);
|
||||
$result['isPhoneAuthorized'] = true;
|
||||
$result['status'] = "success";
|
||||
} else {
|
||||
$confirmCode->try_count++;
|
||||
$ordersInfoAuthTable->save($confirmCode);
|
||||
|
||||
if ($confirmCode['try_count'] >= 3) {
|
||||
$result['errors'] = ['Вы слишком много раз неверно ввели код подтверждения. Повторите попытку позже.'];
|
||||
$result['tooManyCodeInputRetries'] = true;
|
||||
} else {
|
||||
$result['errors'] = ['Неверно указан код подтверждения. Повторите попытку.'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result['errors'] = ['Неверно указан код подтверждения. Повторите попытку.'];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->jsonSimpleResponse($result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
|
||||
class PagesController extends AppController {
|
||||
public function beforeFilter(Event $event)
|
||||
{
|
||||
parent::beforeFilter($event);
|
||||
$this->Auth->allow(['services']);
|
||||
$this->viewBuilder()->setLayout('pages');
|
||||
}
|
||||
|
||||
public function services() {
|
||||
$this->set('jsConfig', $this->getAppJsConfig("", false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Model\Entity;
|
||||
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
use Cake\Auth\DefaultPasswordHasher;
|
||||
|
||||
class User extends Entity {
|
||||
|
||||
protected $_accessible = [
|
||||
'*' => true,
|
||||
'id' => false
|
||||
];
|
||||
|
||||
protected function _setPassword($password) {
|
||||
return (new DefaultPasswordHasher)->hash($password);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class BranchesTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('branches');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Routing\Router;
|
||||
use DBF;
|
||||
use PHPExcel;
|
||||
use PHPExcel_Writer_Excel5;
|
||||
use SMSRU;
|
||||
//use mPDF;
|
||||
use Mpdf\Mpdf;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
class CalcDoorsOrdersTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('calc_doors_orders');
|
||||
}
|
||||
|
||||
public function orderEmailNotify($data, $cutConfig, $clientIP, $authUserId = null, $configDoor) {
|
||||
$result = 'error';
|
||||
|
||||
$selectedBranch = (!empty($data['branchId']) && !empty($cutConfig['branches'][$data['branchId']]) ? $cutConfig['branches'][$data['branchId']] : null);
|
||||
$selectedBranchId = (!empty($data['branchId']) && !empty($cutConfig['branches'][$data['branchId']]) ? $data['branchId'] : null);
|
||||
|
||||
if (empty($selectedBranch)) {
|
||||
foreach($cutConfig['branches'] as $key => $li) {
|
||||
if (!empty($li['is_default'])) {
|
||||
$selectedBranch = $li;
|
||||
$selectedBranchId = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$orderPhone = (!empty($data['orderPhone']) ? htmlentities($data['orderPhone']) : "");
|
||||
$orderAddress = (!empty($data['orderAddress']) ? htmlentities($data['orderAddress']) : "не указан");
|
||||
$orderName = (!empty($data['orderName']) ? htmlentities($data['orderName']) : 'не указано');
|
||||
$orderComment = (!empty($data['orderComment']) ? nl2br(htmlentities($data['orderComment'])) : 'не указан');
|
||||
|
||||
$newOrderData = [
|
||||
'name' => $data['orderName'],
|
||||
'email' => $data['orderEmail'],
|
||||
'phone' => $data['orderPhone'],
|
||||
'address' => $data['orderAddress'],
|
||||
'comment' => $data['orderComment'],
|
||||
'price' => (!empty($data['price']) ? $data['price'] : str_replace(" ", "", $data['selectedDoorData']['order_calc_results']['price'])),
|
||||
'actual_price' => (!empty($data['actualPrice']) ? $data['actualPrice'] : str_replace(" ", "", $data['selectedDoorData']['order_calc_results']['price'])),
|
||||
|
||||
'params' => json_encode($data['selectedDoorData']['params']),
|
||||
'order_calc_results' => json_encode($data['selectedDoorData']['order_calc_results'])
|
||||
];
|
||||
|
||||
if ($selectedBranchId == "printOnly") {
|
||||
$newOrderData["order_type"] = "print";
|
||||
} else {
|
||||
$newOrderData["order_type"] = "order";
|
||||
$newOrderData["branch_id"] = $selectedBranchId;
|
||||
}
|
||||
|
||||
$orderNum = "";
|
||||
if(!empty($data['eOId'])) {
|
||||
$encryptedOrderId = $data['eOId'];
|
||||
$decryptedData = TableRegistry::getTableLocator()->get('CutOrders')->decryptCustomData($encryptedOrderId, $cutConfig);
|
||||
|
||||
if (!empty($decryptedData['orderId'])) {
|
||||
$order = $this->find('all')->where(['id' => $decryptedData['orderId']])->first();
|
||||
if (!empty($order)) {
|
||||
$this->patchEntity($order, $newOrderData);
|
||||
$orderNum = $order['order_num'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($order)) {
|
||||
$newOrderData['order_num'] = '';
|
||||
$newOrderData['created'] = date('Y-m-d H:i:s');
|
||||
$order = $this->newEntity($newOrderData);
|
||||
$data['eOId'] = false;
|
||||
}
|
||||
|
||||
if ($this->save($order)) {
|
||||
$orderId = $order->id;
|
||||
|
||||
if (empty($encryptedOrderId)) {
|
||||
$encryptedOrderId = TableRegistry::getTableLocator()->get('CutOrders')->encryptCustomData($orderId, 'orderId', $cutConfig);
|
||||
|
||||
if (!empty($encryptedOrderId)) {
|
||||
$viewOrderUrlBase = '/calc-doors?oid=' . $encryptedOrderId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (empty($order->order_num)) {
|
||||
$cutSettingsTable = TableRegistry::getTableLocator()->get('CalcDoorsSettings');
|
||||
$orderNumMonth = date('Y-m-01');
|
||||
$orderNumDefaultCounters = [
|
||||
'order' => 0,
|
||||
'print' => 0
|
||||
];
|
||||
|
||||
$orderNumSetting = $cutSettingsTable->find()->where([
|
||||
'key' => 'orderNumCounter',
|
||||
'group' => 'common'
|
||||
])->first();
|
||||
if (empty($orderNumSetting)) {
|
||||
$orderNumDefaultCounters[$newOrderData["order_type"]]++;
|
||||
$orderNumCounter = 1;
|
||||
|
||||
$orderNumSetting = $cutSettingsTable->newEntity();
|
||||
$orderNumSetting = $cutSettingsTable->patchEntity($orderNumSetting, [
|
||||
'key' => 'orderNumCounter',
|
||||
'value' => json_encode([
|
||||
'month' => $orderNumMonth,
|
||||
'counters' => $orderNumDefaultCounters
|
||||
]),
|
||||
'group' => 'common'
|
||||
]);
|
||||
} else {
|
||||
$orderNumSetting->value = @json_decode($orderNumSetting->value, true);
|
||||
if ($orderNumSetting->value['month'] != $orderNumMonth) {
|
||||
$orderNumSetting->value['month'] = $orderNumMonth;
|
||||
|
||||
$orderNumDefaultCounters[$newOrderData["order_type"]]++;
|
||||
$orderNumCounter = 1;
|
||||
$orderNumSetting->value['counters'] = $orderNumDefaultCounters;
|
||||
} else {
|
||||
$orderNumSetting->value['counters'][$newOrderData["order_type"]]++;
|
||||
$orderNumCounter = $orderNumSetting->value['counters'][$newOrderData["order_type"]];
|
||||
}
|
||||
$orderNumSetting->value = json_encode($orderNumSetting->value);
|
||||
}
|
||||
$cutSettingsTable->save($orderNumSetting);
|
||||
|
||||
$orderNum = $cutConfig['common']['orderNumPrefix']['value'] . date('dmY') . "-" . str_pad($orderNumCounter, $cutConfig['common']['orderNumLength']['value'], "0", STR_PAD_LEFT);
|
||||
if ($newOrderData["order_type"] == "print") {
|
||||
$orderNum .= "-P";
|
||||
}
|
||||
|
||||
$order->order_num = $orderNum;
|
||||
}
|
||||
|
||||
if (!empty($viewOrderUrlBase)) {
|
||||
$viewOrderUrl = '/calc-doors?oid=' . $encryptedOrderId;
|
||||
$order->view_order_url = $viewOrderUrlBase;
|
||||
}
|
||||
|
||||
$this->save($order);
|
||||
|
||||
$orderDate = date('d.m.Y H:i');
|
||||
|
||||
$orderSpec['order'] = '<br/>
|
||||
Номер заказа: ' . ($order->order_type == "order" ? $orderNum : "-"). '<br/>' . '
|
||||
Дата заказа: ' . $orderDate . '<br/>';
|
||||
|
||||
if (($selectedBranchId != "printOnly") && !empty($selectedBranch)) {
|
||||
$orderSpec['order'] .= 'Контакт-менеджер: ' . $selectedBranch['label'] . '<br/>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
$orderSpec['client'] = 'Данные клиента: <br/>
|
||||
ФИО: ' . $orderName . '<br/>' ;
|
||||
|
||||
if (!empty($data['orderEmail'])) {
|
||||
$orderSpec['client'] .= 'E-mail: ' . htmlentities($data['orderEmail']) . '<br/>';
|
||||
}
|
||||
|
||||
if (!empty($orderPhone)) {
|
||||
$orderSpec['client'] .= 'Телефон: ' . $orderPhone . '<br/>';
|
||||
}
|
||||
|
||||
if (!empty($orderAddress)) {
|
||||
$orderSpec['client'] .= 'Адрес доставки: ' . $orderAddress . '<br/>';
|
||||
}
|
||||
|
||||
if (!empty($data['selectedDoorData']['params']['discount'])) {
|
||||
$orderSpec['client'] .= 'Скидка: ' . min((int) $data['selectedDoorData']['params']['discount'], 100) . '%' . '<br/>';
|
||||
}
|
||||
|
||||
if (!empty($data['orderComment'])) {
|
||||
$orderSpec['client'] .= 'Комментарий к заказу: ' . nl2br(htmlentities($data['orderComment'])) . '<br/>';
|
||||
}
|
||||
|
||||
$orderSpec['client'] .= '<br/>
|
||||
ПрофильС: ' . $configDoor['profile'] . " " . $cutConfig["doorsManufacturers"][$configDoor['manufacturer_id']]["label"] . '<br/>' . '
|
||||
Цвет системы: ' . $configDoor['color'] . '<br/>' . '
|
||||
Направ.верх: ' . $configDoor['colorNapravlyaushayaVerh'] . '<br/>' . '
|
||||
Направ.низ: ' . $configDoor['colorNapravlyaushayaNiz'] . '<br/>';
|
||||
|
||||
|
||||
$filename = $orderNum; //. "_" . date('d-m-Y');
|
||||
$specFilename = $filename. "_specification" . ".pdf";
|
||||
$tmpSpecFile = $this->generateSpecFile($data, $cutConfig, $orderSpec, $orderNum, $order["order_type"]);
|
||||
|
||||
if (empty($data['eOId']) && ($selectedBranchId != "printOnly")) { //new order, send email
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer($cutConfig);
|
||||
foreach (explode("\n", $selectedBranch['order_notify_manager_emails']) as $managerEmail) {
|
||||
$managerEmail = trim($managerEmail);
|
||||
if (!empty($managerEmail)) {
|
||||
$mail->addAddress(trim($managerEmail));
|
||||
}
|
||||
}
|
||||
|
||||
$mail->addAttachment($tmpSpecFile, $specFilename);
|
||||
|
||||
$mail->Subject = str_replace("{OrderNum}", $orderNum, $cutConfig['common']['orderNotifySubject']['value']);
|
||||
|
||||
$mail->Body = $cutConfig['common']['orderNotifyBodyStart']['value'];
|
||||
$mail->AltBody = $cutConfig['common']['orderNotifyBodyStart']['value'];
|
||||
|
||||
|
||||
$mail->Body .= '<br/>
|
||||
Номер заказа: ' . ($order->order_type == "order" ? $orderNum : "-") . '<br/>' . '
|
||||
Дата заказа: ' . $orderDate . '<br/>';
|
||||
|
||||
$mail->AltBody .= '
|
||||
Номер заказа: ' . ($order->order_type == "order" ? $orderNum : "-") . '
|
||||
Дата заказа: ' . $orderDate;
|
||||
|
||||
if (!empty($selectedBranch)) {
|
||||
$mail->Body .= 'Контакт-менеджер: ' . $selectedBranch['label'] . '<br/>';
|
||||
|
||||
$mail->AltBody .= '
|
||||
Контакт-менеджер: ' . $selectedBranch['label'];
|
||||
}
|
||||
|
||||
$mail->Body .= '<br/><br/>
|
||||
ФИО: ' . $orderName . '<br/>' . '
|
||||
E-mail: ' . (!empty($data['orderEmail']) ? '<a href="mailto:' . htmlentities($data['orderEmail']) . '">' . htmlentities($data['orderEmail']) . '</a>' : 'не указан') . '<br/>' . '
|
||||
Телефон: ' . (!empty($orderPhone) ? '<a href="tel:' . preg_replace("/[^0-9.]/", "", $orderPhone) . '">' . $orderPhone . '</a>' : 'не указан') . '<br/>' . '
|
||||
Адрес доставки: ' . (!empty($orderAddress) ? $orderAddress : 'не указан') . '<br/>' . '
|
||||
' . (!empty($data['selectedDoorData']['params']['discount']) ? 'Скидка: ' . $data['selectedDoorData']['params']['discount'] . '%' . '<br/>' : '') . '
|
||||
Комментарий: ' . $orderComment . '<br/>';
|
||||
|
||||
|
||||
$mail->AltBody .= '
|
||||
ФИО: ' . $orderName . '
|
||||
E-mail: ' . (!empty($data['orderEmail']) ? htmlentities($data['orderEmail']) : 'не указан') . '
|
||||
Телефон: ' . (!empty($orderPhone) ? $orderPhone : 'не указан') . '
|
||||
Адрес доставки: ' . (!empty($orderAddress) ? $orderAddress : 'не указан') . '
|
||||
' . (!empty($data['selectedDoorData']['params']['discount']) ? 'Скидка: ' . $data['selectedDoorData']['params']['discount'] . '%' : '') . '
|
||||
Комментарий: ' . $orderComment;
|
||||
|
||||
$mail->Body .= '<br/>
|
||||
ПрофильС: ' . $configDoor['profile'] . " " . $cutConfig["doorsManufacturers"][$configDoor['manufacturer_id']]["label"] . '<br/>' . '
|
||||
Цвет системы: ' . $configDoor['color'] . '<br/>' . '
|
||||
Направ.верх: ' . $configDoor['color'] . '<br/>' . '
|
||||
Направ.низ: ' . $configDoor['color'] . '<br/>';
|
||||
|
||||
$mail->AltBody .= '<br/>
|
||||
ПрофильС: ' . $configDoor['profile'] . " " . $cutConfig["doorsManufacturers"][$configDoor['manufacturer_id']]["label"] . '
|
||||
Цвет системы: ' . $configDoor['color'] . '
|
||||
Направ.верх: ' . $configDoor['color'] . '
|
||||
Направ.низ: ' . $configDoor['color'] ;
|
||||
|
||||
if (!empty($viewOrderUrl)) {
|
||||
$mail->Body .= '<br/><br/>
|
||||
<a href="' . Router::fullBaseUrl() . $viewOrderUrl . '">Ссылка для печати заказа</a>';
|
||||
|
||||
$mail->AltBody .= '
|
||||
|
||||
Ссылка для печати заказа: ' . Router::fullBaseUrl() . $viewOrderUrl;
|
||||
}
|
||||
|
||||
|
||||
$order->html_letter = $mail->Body;
|
||||
$order->text_letter = $mail->AltBody;
|
||||
$this->save($order);
|
||||
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
$result = 'success';
|
||||
|
||||
if (!empty($orderNum)) {
|
||||
$zip = new \ZipArchive;
|
||||
if ($zip->open(ROOT . '/files/calc_doors_orders/' . $orderNum . '.zip', \ZipArchive::CREATE | \ZipArchive::OVERWRITE) === true) {
|
||||
$zip->addFile($tmpSpecFile, $specFilename);
|
||||
$zip->close();
|
||||
}
|
||||
}
|
||||
|
||||
@unlink($tmpSpecFile);
|
||||
|
||||
if (empty($data['eOId'])) { //new order, send sms
|
||||
if (!empty($selectedBranch['order_notify_manager_sms'])) {
|
||||
TableRegistry::getTableLocator()->get('CutOrders')->sendSms(explode("\n", $selectedBranch['order_notify_manager_sms']), "Появился новый заказ " . $orderNum, $cutConfig['global']['smsRuApiKey']['value'], $clientIP);
|
||||
}
|
||||
}
|
||||
|
||||
if ($newOrderData["order_type"] == "order") {
|
||||
if (!empty($data['eOId'])) { //save order, revert stat
|
||||
$order->updated_date = date('Y-m-d H:i:s');
|
||||
$order->updated_by_manager = $authUserId;
|
||||
$this->save($order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($cutConfig['global']['additionalActionsAllowed'])) {
|
||||
$viewOrderUrl = "";
|
||||
}
|
||||
|
||||
return [
|
||||
'orderEmailNotifySent' => $result,
|
||||
'printOrderUrl' => (!empty($viewOrderUrl) ? str_replace("/calc-doors", "/calc-doors-print", $viewOrderUrl): "")
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function resendOrderEmailNotify($order, $managerEmail, $cutConfig) {
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer($cutConfig);
|
||||
$mail->addAddress(trim($managerEmail));
|
||||
|
||||
$mail->Subject = str_replace("{OrderNum}", $order->order_num, $cutConfig['common']['orderNotifySubject']['value']);
|
||||
|
||||
$mail->Body = (!empty($order->html_letter) ? $order->html_letter : $cutConfig['common']['orderNotifyBodyStart']['value']);
|
||||
$mail->AltBody = (!empty($order->text_letter) ? $order->text_letter : $cutConfig['common']['orderNotifyBodyStart']['value']);
|
||||
|
||||
$zip = @zip_open(ROOT . '/files/calc_doors_orders/' . $order->order_num . '.zip');
|
||||
if (!empty($zip)) {
|
||||
while ($zip_entry = zip_read($zip)) {
|
||||
$mail->addStringAttachment(zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)), zip_entry_name($zip_entry));
|
||||
}
|
||||
|
||||
@zip_close($zip);
|
||||
}
|
||||
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
function generateSpecFile($data, $cutConfig, $orderSpec, $orderNum, $orderType) {
|
||||
$tmpSpecFile = @tempnam("/tmp", "calc_doors_order_email_spec_pdf");
|
||||
|
||||
|
||||
$html = "<style>
|
||||
body { font-size: 12px; font-family: arial, sans-serif; }
|
||||
table { width: 100%; border: 1px solid #000; border-collapse: collapse; }
|
||||
table th, table td { padding: 5px; border: 1px solid #000; text-align: left; }
|
||||
table td { padding: 3px 5px; }
|
||||
table th { font-weight: normal; }
|
||||
table th.text-center, table td.text-center { text-align: center; }
|
||||
.borderDiv { font-size: 2px; line-height: 10px; }
|
||||
.border1DivTop { border-top: 1px solid #000; }
|
||||
.border1DivBottom { border-bottom: 1px solid #000; }
|
||||
.border2DivTop { border-top: 1px dashed #000;}
|
||||
.border2DivBottom { border-bottom: 1px dashed #000;}
|
||||
.border1divWide { border-top: 2px solid #000; }
|
||||
.border2divWide { border-top: 2px dashed #000; }
|
||||
.border1divWide, .border2divWide { font-size: 4px; }
|
||||
table.table-footer, table.table-header { margin-top: 0; }
|
||||
table.table-footer td, table.table-header td { font-size: 12px; padding: 5px 0 5px 0; }
|
||||
table.table-footer td { padding: 3px 0 3px 0; }
|
||||
table.table-border-less, table.table-border-less td { border: 0 none; }
|
||||
</style>";
|
||||
|
||||
$html .= $orderSpec['order'] . '<br/>';
|
||||
|
||||
$html .= $orderSpec['client'] . '<br/>';
|
||||
|
||||
$params = $data['selectedDoorData']['params'];
|
||||
$calc = $data['selectedDoorData']['order_calc_results'];
|
||||
|
||||
$html .= "Высота проема: " . $params['height'] . "мм" . "<br/>" .
|
||||
"Ширина проема: " . $params['width'] . "мм" . "<br/>" .
|
||||
"Количество дверей: " . $params['doorsCount'] . "шт" . "<br/>";
|
||||
|
||||
$configDoor = TableRegistry::getTableLocator()->get('CalcDoors')->find('all')->where([
|
||||
'id' => $params['doorId']
|
||||
])->first();
|
||||
|
||||
$doorPrices = [];
|
||||
$manufacturerPrices = [];
|
||||
$manufacturerLimits = [];
|
||||
|
||||
if (!empty($configDoor)) {
|
||||
$configDoor = $configDoor->toArray();
|
||||
$doorPrices = @json_decode($configDoor['params'], true);
|
||||
|
||||
$configManufacturer = TableRegistry::getTableLocator()->get('CalcDoorsSettings')->find('all')->where([
|
||||
'group' => 'prices_' . $configDoor['manufacturer_id']
|
||||
])->all()->toArray();
|
||||
|
||||
foreach($configManufacturer as $li) {
|
||||
$manufacturerPrices[$li['key']] = $li['value'];
|
||||
}
|
||||
|
||||
$configManufacturer = TableRegistry::getTableLocator()->get('CalcDoorsSettings')->find('all')->where([
|
||||
'group' => 'limits_' . $configDoor['manufacturer_id']
|
||||
])->all()->toArray();
|
||||
|
||||
foreach($configManufacturer as $li) {
|
||||
$manufacturerLimits[$li['key']] = $li['value'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$html .= '<newpage> <table>
|
||||
<thead><tr><th style="width: 300px;"><b>Наименование</b></th><th><b>Ед.изм</b></th><th><b>Кол-во</b></th><th><b>Цена (руб.)</b></th><th><b>Стоимость (руб.)</b></th></tr></thead><tbody>';
|
||||
|
||||
$html .= '
|
||||
<tr>
|
||||
<td>Профиль вертикальный С</td>
|
||||
<td>шт</td>
|
||||
<td>'.toFixed2($calc['profileVertCount']).'</td>
|
||||
<td>'.toFixed2Price(($params['height'] > $doorPrices['profileVertHeight']) && !empty($doorPrices['profileVertHigherLimit']) ? $doorPrices['profileVertHigherLimit'] : $doorPrices['profileVertBelowLimit']).'</td>
|
||||
<td>'.toFixed2Price($calc['profileVertPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Направляющая верхняя</td>
|
||||
<td>м</td>
|
||||
<td>'.toFixed2($calc['napravlyaushayaVerhCount']).'</td>
|
||||
<td>'.toFixed2Price($doorPrices['napravlyaushayaVerh']).'</td>
|
||||
<td>'.toFixed2Price($calc['napravlyaushayaVerhPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Направляющая нижняя</td>
|
||||
<td>м</td>
|
||||
<td>'.toFixed2($calc['napravlyaushayaNizCount']).'</td>
|
||||
<td>'.toFixed2Price($doorPrices['napravlyaushayaNiz']).'</td>
|
||||
<td>'.toFixed2Price($calc['napravlyaushayaNizPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Рама горизонт.низ</td>
|
||||
<td>м</td>
|
||||
<td>'.toFixed2($calc['ramaGorizontNizCount']).'</td>
|
||||
<td>'.toFixed2Price($doorPrices['ramaGorizontNiz']).'</td>
|
||||
<td>'.toFixed2Price($calc['ramaGorizontNizPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Рама горизонт.верх.</td>
|
||||
<td>м</td>
|
||||
<td>'.toFixed2($calc['ramaGorizontVerhCount']).'</td>
|
||||
<td>'.toFixed2Price($doorPrices['ramaGorizontVerh']).'</td>
|
||||
<td>'.toFixed2Price($calc['ramaGorizontVerhPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Комплект роликов на 1-у дверь</td>
|
||||
<td>комп</td>
|
||||
<td>'.$calc['komplektRolikovCount'].'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['komplektRolikov']).'</td>
|
||||
<td>'.toFixed2Price($calc['komplektRolikovPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Стопор</td>
|
||||
<td>шт</td>
|
||||
<td>'.$calc['stoporCount'].'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['stopor']).'</td>
|
||||
<td>'.toFixed2Price($calc['stoporPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Шлегель</td>
|
||||
<td>м</td>
|
||||
<td>'.toFixed2($calc['shlegelCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['shlegel']).'</td>
|
||||
<td>'.toFixed2Price($calc['shlegelPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Зажим д\шлегеля</td>
|
||||
<td>шт</td>
|
||||
<td>'.$calc['zagimDlyaShlegelyaCount'].'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['zagimDlyaShlegelya']).'</td>
|
||||
<td>'.toFixed2Price($calc['zagimDlyaShlegelyaPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Уплотнитель ПК-80-0104</td>
|
||||
<td>м</td>
|
||||
<td>'.toFixed2($calc['uplotnitelPK80Count']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['uplotnitelPK80']).'</td>
|
||||
<td>'.toFixed2Price($calc['uplotnitelPK80Price']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4"><b>Итого профиля</b></td>
|
||||
<td><b>'.toFixed2Price($calc['profilePrice']).'</b></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>Зеркало серебро</td>
|
||||
<td>кв.м.</td>
|
||||
<td>'.toFixed2($calc['zerkaloSerebroCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['zerkaloSerebro']).'</td>
|
||||
<td>'.toFixed2Price($calc['zerkaloSerebroPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Пленка безопасности д\зеркал</td>
|
||||
<td>пог.м.</td>
|
||||
<td>'.toFixed2($calc['plenkaBezopasnostiZerkalCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['plenkaBezopasnostiZerkal']).'</td>
|
||||
<td>'.toFixed2Price($calc['plenkaBezopasnostiZerkalPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Оракал белый</td>
|
||||
<td>м. кв.</td>
|
||||
<td>'.toFixed2($calc['plenkaOrakalCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['plenkaOrakal']).'</td>
|
||||
<td>'.toFixed2Price($calc['plenkaOrakalPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Стекло</td>
|
||||
<td>кв.м.</td>
|
||||
<td>'.toFixed2($calc['StekloCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['Steklo']).'</td>
|
||||
<td>'.toFixed2Price($calc['StekloPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>ДСП 10мм лист</td>
|
||||
<td>лист</td>
|
||||
<td>'.toFixed2($calc['dsp10mmCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['dsp10mm']).'</td>
|
||||
<td>'.toFixed2Price($calc['dsp10mmPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4"><b>Итого наполнение</b></td>
|
||||
<td><b>'.toFixed2Price($calc['napolneniePrice']).'</b></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>Сборка 1-ой двери</td>
|
||||
<td>кв.м.</td>
|
||||
<td>'.toFixed2($calc['sborkeDveriCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['sborkeDveri']).'</td>
|
||||
<td>'.toFixed2Price($calc['sborkeDveriPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Порезка '.$calc['porezkaMaterialaPercent'].'% от стоимости материала</td>
|
||||
<td>'.$calc['porezkaMaterialaPercent'].'%</td>
|
||||
<td>'.$calc['porezkaMaterialaCount'].'</td>
|
||||
<td>'.toFixed2Price($calc['porezkaMaterialaPrice']).'</td>
|
||||
<td>'.toFixed2Price($calc['porezkaMaterialaTotalPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Сверление отверстий на одну дверь</td>
|
||||
<td>1 дверь</td>
|
||||
<td>'.$calc['sverlenieOtverstiyNaDverCount'].'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['sverlenieOtverstiyNaDver']).'</td>
|
||||
<td>'.toFixed2Price($calc['sverlenieOtverstiyNaDverPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Работа сложная</td>
|
||||
<td></td>
|
||||
<td>'.toFixed2($calc['rabotaSlognayaCount']).'</td>
|
||||
<td>'.toFixed2Price($manufacturerPrices['rabotaSlognaya']).'</td>
|
||||
<td>'.toFixed2Price($calc['rabotaSlognayaPrice']).'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4"><b>Итого работа, руб.</b></td>
|
||||
<td><b>'.toFixed2Price($calc['rabotaPrice']).'</b></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4"><b>Итого, руб.</b></td>
|
||||
<td class="total-price"><b>'.toFixed2Price($calc['price']).'</b></td>
|
||||
</tr>
|
||||
';
|
||||
|
||||
$html .= '</tbody></table><br/>';
|
||||
|
||||
$mpdf = new \Mpdf\Mpdf(Configure::read('mpdfPageParams'));
|
||||
|
||||
$mpdf->SetHTMLHeader('
|
||||
<table width="100%" class="table-header table-border-less">
|
||||
<tr>
|
||||
<td width="80%" style="text-align: left;"><b>Спецификация заказа на изготовление дверей ' . ($orderType == "order" ? $orderNum : "") . '</b></td>
|
||||
<td width="20%" style="text-align: right;">стр. {PAGENO}/{nbpg}</td>
|
||||
</tr>
|
||||
</table>');
|
||||
|
||||
$mpdf->SetHTMLFooter('
|
||||
<table width="100%" class="table-footer table-border-less">
|
||||
<tr>
|
||||
<td width="100%" style="text-align: left;">
|
||||
Подпись данной спецификации подтверждает правильность внесенных мной данных.<br/>
|
||||
После оплаты заказа, корректировка данных не принимается. Изменения вносятся отдельным заказом.
|
||||
<br/><br/>Подпись клиента: __________________________________________________
|
||||
</td>
|
||||
</tr>
|
||||
</table>');
|
||||
|
||||
$mpdf->SetTitle("Спецификация заказа " . ($orderType == "order" ? $orderNum : ""));
|
||||
$mpdf->WriteHTML($html);
|
||||
$mpdf->Output($tmpSpecFile, 'F');
|
||||
|
||||
return $tmpSpecFile;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class CalcDoorsSettingsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('calc_doors_settings');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class CutBorderAvailableDimensionsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('cut_border_available_dimensions');
|
||||
|
||||
|
||||
$this->belongsTo('CutBorderDimensions', [
|
||||
'className' => 'CutBorderDimensions',
|
||||
'foreignKey' => 'border_dimension_id'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class CutBorderDimensionsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('cut_border_dimensions');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class CutBordersTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('cut_borders');
|
||||
|
||||
$this->hasMany('availableDimensions', [
|
||||
'className' => 'CutBorderAvailableDimensions',
|
||||
'foreignKey' => 'border_id'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class CutSettingsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('cut_settings');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class CutSheetDimensionsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('cut_sheet_dimensions');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Utility\Text;
|
||||
|
||||
class CutSheetsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('cut_sheets');
|
||||
}
|
||||
|
||||
|
||||
public function importSheetsDataFromXml($sourceFile, $origFilename = null) {
|
||||
$result = [
|
||||
'count' => 0,
|
||||
'reason' => ''
|
||||
];
|
||||
|
||||
if (!empty($sourceFile) && is_file($sourceFile) && file_exists($sourceFile)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
|
||||
$xml = @simplexml_load_file($sourceFile, 'SimpleXMLIterator');
|
||||
if (!empty($xml)) {
|
||||
$isErrorOccurred = false;
|
||||
|
||||
if (!isset($xml->Raspil) || !isset($xml->Raspil->Tovar)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
} else {
|
||||
foreach ($xml->Raspil->Tovar as $li) {
|
||||
if (!isset($li->id1c)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
break;
|
||||
}
|
||||
|
||||
$id1c = (string)$li->id1c;
|
||||
//$name = (string)$li->name;
|
||||
$kol = (int)$li->kol;
|
||||
$cena = (float)$li->cena;
|
||||
|
||||
$sheet = $sheetsTable->find('all')->where([
|
||||
'sheetIdFor1C' => $id1c
|
||||
])->first();
|
||||
|
||||
if (!empty($sheet)) {
|
||||
$sheet->quantityIn1C = $kol;
|
||||
$sheet->price = $cena;
|
||||
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$result['count']++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isErrorOccurred) {
|
||||
$result['reason'] = 'Возникла ошибка при импорте. Детали ошибки находятся в логе импорта (logs/debug.log).';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isErrorOccurred) {
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта пустой.';
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта не найден.';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function putImportFileToArchive($localFile, $unlinkLocalFile = true, $origFilename = null) {
|
||||
$archiveFolder = ROOT . DS . "archive" . DS. date("Y-m");
|
||||
|
||||
if(!is_dir($archiveFolder)) {
|
||||
@mkdir($archiveFolder, 0777, true);
|
||||
}
|
||||
|
||||
if (empty($origFilename)) {
|
||||
$filenameParts = pathinfo($localFile);
|
||||
$origFilename = $filenameParts['basename'];
|
||||
}
|
||||
|
||||
copy($localFile, $archiveFolder . DS . $origFilename);
|
||||
|
||||
if ($unlinkLocalFile) {
|
||||
@unlink($localFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class ElplatPaymentsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('elplat_payments');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
|
||||
class EmailSubscribeAttachmentsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->belongsTo('EmailSubscribes', [
|
||||
'className' => 'EmailSubscribes',
|
||||
'foreignKey' => 'subscribeId'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
|
||||
class EmailSubscribeRecipientsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->belongsTo('EmailSubscribes', [
|
||||
'className' => 'EmailSubscribes',
|
||||
'foreignKey' => 'subscribeId'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class EmailSubscribesTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->hasMany('emailSubscribeRecipients', [
|
||||
'className' => 'EmailSubscribeRecipients',
|
||||
'foreignKey' => 'subscribeId'
|
||||
]);
|
||||
|
||||
$this->hasMany('emailSubscribeAttachments', [
|
||||
'className' => 'EmailSubscribeAttachments',
|
||||
'foreignKey' => 'subscribeId'
|
||||
]);
|
||||
}
|
||||
|
||||
public function importSubscribesList($source) {
|
||||
$importResult = [
|
||||
'reason' => '',
|
||||
'list' => [],
|
||||
'incorrectList' => []
|
||||
];
|
||||
|
||||
$txt = file_get_contents($source);
|
||||
$rows = explode("\n", $txt);
|
||||
|
||||
foreach($rows as $row) {
|
||||
$row = trim($row);
|
||||
$columns = explode("\t", $row);
|
||||
|
||||
if (!empty($columns) && !empty($columns[0])) {
|
||||
$recipientName = "";
|
||||
$recipientEmail = "";
|
||||
|
||||
foreach($columns as $column) {
|
||||
$column = trim($column);
|
||||
|
||||
if (!empty($column)) {
|
||||
$email = cleanupEmail($column);
|
||||
|
||||
if (strpos($email, "@") !== false) {
|
||||
$recipientEmail = $email;
|
||||
continue;
|
||||
} else {
|
||||
$recipientName = $column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($recipientEmail) && filter_var($recipientEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
$importResult['list'][$recipientEmail] = mb_convert_encoding($recipientName, "UTF-8", "Windows-1251");
|
||||
} else {
|
||||
$importResult['incorrectList'][] = mb_convert_encoding($row, "UTF-8", "Windows-1251");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $importResult;
|
||||
}
|
||||
|
||||
public function importSubscribeAttachments($sourceFiles) {
|
||||
$importResult = [
|
||||
'reason' => '',
|
||||
'list' => []
|
||||
];
|
||||
|
||||
foreach($sourceFiles as $source) {
|
||||
if (file_exists($source['tmp_name']) && empty($source['error'])) {
|
||||
$extension = strtolower(pathinfo($source['name'], PATHINFO_EXTENSION));
|
||||
$extension = str_replace("jpeg", "jpg", $extension);
|
||||
|
||||
if (in_array($extension, ['txt', 'pdf', 'jpg', 'jpeg', 'png', 'xls', 'xlsx', 'doc','docx'])) {
|
||||
$uploadDir = ROOT . DS . 'files' . DS . 'email_subscribes' . DS;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($source["name"] . time())) . "." . $extension;
|
||||
if (move_uploaded_file($source["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
$importResult['list'][base64_encode($source['name'])] = [
|
||||
'name' => $source['name'],
|
||||
'filename' => $tmpFileName,
|
||||
'filesize' => $source['size'],
|
||||
'mime' => mime_content_type($uploadDir . $tmpFileName)
|
||||
];
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $importResult;
|
||||
}
|
||||
|
||||
public function uploadSubscribeImage($source) {
|
||||
$importResult = [
|
||||
'reason' => '',
|
||||
'list' => []
|
||||
];
|
||||
|
||||
if (file_exists($source['tmp_name']) && empty($source['error'])) {
|
||||
$extension = strtolower(pathinfo($source['name'], PATHINFO_EXTENSION));
|
||||
$extension = str_replace("jpeg", "jpg", $extension);
|
||||
|
||||
if (in_array($extension, ['jpg', 'jpeg', 'png', 'bmp'])) {
|
||||
$destDir = DS . 'img' . DS . 'email_subs' . DS;
|
||||
$uploadDir = WWW_ROOT . $destDir;
|
||||
if (!file_exists($uploadDir) && !is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
$tmpFileName = sha1(sha1($source["name"] . time())) . "." . $extension;
|
||||
if (move_uploaded_file($source["tmp_name"], $uploadDir . $tmpFileName)) {
|
||||
$importResult['list'][] = [
|
||||
'name' => $source['name'],
|
||||
'filename' => 'https://' . $_SERVER['HTTP_HOST'] . str_replace("\\", "/", $destDir . $tmpFileName),
|
||||
'filesize' => $source['size'],
|
||||
'mime' => mime_content_type($uploadDir . $tmpFileName)
|
||||
];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return $importResult;
|
||||
}
|
||||
|
||||
|
||||
public function sendSubscribeReport($subscribeId, $additionalStatus = "") {
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], "Служба рассылок СуперСам");
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("EmailSubscribes");
|
||||
$query = $subscribesTable->find('all')->where([
|
||||
'id' => $subscribeId,
|
||||
]);
|
||||
|
||||
$query->contain([
|
||||
'emailSubscribeRecipients' => [
|
||||
'sort' => ['emailSubscribeRecipients.name' => 'ASC', 'emailSubscribeRecipients.email' => 'ASC'],
|
||||
]
|
||||
]);
|
||||
$subscribe = $query->first();
|
||||
$mail->addAddress(trim($subscribe['reportEmail']));
|
||||
//$mail->addBCC("sbtestemail789@gmail.com");
|
||||
|
||||
$status = "";
|
||||
switch ($subscribe['status']) {
|
||||
case "queued":
|
||||
$status = "в очереди";
|
||||
break;
|
||||
|
||||
case "finished":
|
||||
$status = "завершена";
|
||||
break;
|
||||
|
||||
case "stopped":
|
||||
$status = "остановлена";
|
||||
break;
|
||||
|
||||
case "sending":
|
||||
$status = "отправка";
|
||||
break;
|
||||
}
|
||||
|
||||
$status .= (!empty($additionalStatus) ? ', ' . $additionalStatus : '');
|
||||
|
||||
$th = '<th style="padding: 3px 10px 3px 10px; border-top: 1px solid #dee2e6; border-left: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6; text-align: left; font-weight: normal;">';
|
||||
$thLast = '<th style="padding: 3px 10px 3px 10px; border: 1px solid #dee2e6; text-align: left; font-weight: normal;">';
|
||||
|
||||
$td = '<td style="padding: 3px 10px 3px 10px; border-left: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;">';
|
||||
$tdLast = '<td style="padding: 3px 10px 3px 10px; border-left: 1px solid #dee2e6; border-right: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;">';
|
||||
|
||||
$mail->Subject = "Email рассылка «" . $subscribe['subject'] . "» " . $status;
|
||||
$mail->Body =
|
||||
"Рассылка #" . $subscribe['id'] . "<br/>" .
|
||||
"Тема: " . $subscribe['subject'] . "<br/>" .
|
||||
"Создана: " . date('d-m-Y H:i', strtotime($subscribe['created'])) . "<br/>" .
|
||||
"Запуск: " . date('d-m-Y H:i', strtotime($subscribe['startTime'])) . "<br/>" .
|
||||
"Статус: рассылка " . $status . "<br/><br/>"
|
||||
;
|
||||
|
||||
if (!empty($subscribe['email_subscribe_recipients'])) {
|
||||
$mail->Body .= '<table cellpadding="0" cellspacing="0" style="max-width: 1191px;"><thead><tr>'.$th. 'Получатели ('.count($subscribe['email_subscribe_recipients']).'):</th>'.$th.'Email</th>'.$th.'Статус</th>'.$thLast.'Время отправки</th></tr></thead><tbody>';
|
||||
|
||||
foreach ($subscribe['email_subscribe_recipients'] as $recipient) {
|
||||
$mail->Body .= '<tr>' . $td .$recipient['name'].'</td>' . $td .$recipient['email'].'</td>' . $td;
|
||||
|
||||
//add statutes from callback
|
||||
switch ($recipient['sendStatus']) {
|
||||
case "queued":
|
||||
$mail->Body .= '<span style="color: #ffc107!important;">В очереди</span>';
|
||||
break;
|
||||
|
||||
case "success":
|
||||
$mail->Body .= '<span style="color: #28a745!important;">Отправлено</span>';
|
||||
break;
|
||||
|
||||
|
||||
case "error":
|
||||
$mail->Body .= '<span style="color: #dc3545!important; font-weight: 600;">Ошибка' . (!empty($recipient['statusMessage']) ? ': ' . $recipient['statusMessage'] : '');
|
||||
break;
|
||||
}
|
||||
|
||||
$mail->Body .= '</td>' . $tdLast.(!empty($recipient['sendDate']) ? date('d-m-Y H:i', strtotime($recipient['sendDate'])) : '-').'</td></tr>';
|
||||
}
|
||||
} else {
|
||||
$mail->Body .= '<tr><td colspan="4">Список получателей пуст</td></tr>';
|
||||
}
|
||||
|
||||
$mail->Body .= "</tbody></table>";
|
||||
|
||||
if (!empty($subscribe['sentCount'])) {
|
||||
//show status counters
|
||||
$mail->Body .= '<br>Всего отправлено: '.$subscribe['sentCount'];
|
||||
|
||||
if (!empty($subscribe['successCount'])) {
|
||||
$mail->Body .= '<br/>Успешно: '.$subscribe['successCount'].'<br/>';
|
||||
}
|
||||
|
||||
if (!empty($subscribe['errorsCount'])) {
|
||||
$mail->Body .= '<br/>Ошибок: '.$subscribe['successCount'].'<br/>';
|
||||
}
|
||||
}
|
||||
|
||||
$mail->send();
|
||||
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->addAddress("sbtestemail789@gmail.com");
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
public function sendSubscribeIsEmptyReport($subscribe) {
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], "Служба рассылок СуперСам");
|
||||
$mail->addAddress(trim($subscribe['reportEmail']));
|
||||
$mail->Subject = "Email рассылка «" . $subscribe['subject'] . "» остановлена";
|
||||
|
||||
$mail->Body =
|
||||
"Рассылка #" . $subscribe['id'] . "<br/>" .
|
||||
"Тема: " . $subscribe['subject'] . "<br/>" .
|
||||
"Создана: " . date('d-m-Y H:i', strtotime($subscribe['created'])) . "<br/>" .
|
||||
"Запуск: " . date('d-m-Y H:i') . "<br/><br/>" .
|
||||
|
||||
"Статус: рассылка остановлена, так как список получателей пуст."
|
||||
;
|
||||
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
|
||||
public function sendManagerEmailFromXml($sourceFile, $origFilename = null) {
|
||||
$result = [
|
||||
'count' => 0,
|
||||
'reason' => ''
|
||||
];
|
||||
|
||||
if (!empty($sourceFile) && is_file($sourceFile) && file_exists($sourceFile)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
|
||||
$xml = @simplexml_load_file($sourceFile, 'SimpleXMLIterator');
|
||||
debug($xml);
|
||||
if (!empty($xml)) {
|
||||
$isErrorOccurred = false;
|
||||
|
||||
if (!isset($xml->Order) || !isset($xml->Order->Number)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
} else {
|
||||
$smtpParams = TableRegistry::getTableLocator()->get("Settings")->find('all')->where([
|
||||
'key' => 'smtpParams'
|
||||
])->first();
|
||||
$smtpParams = json_decode($smtpParams['value'], true);
|
||||
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], $smtpParams['clientsFrom']['name'], $smtpParams['clientsFrom']['email']);
|
||||
|
||||
$mail->Subject = "";
|
||||
|
||||
$mail->Body = '';
|
||||
$mail->AltBody = strip_tags(html_entity_decode(br2nl($mail->Body)));
|
||||
|
||||
|
||||
$mail->clearAttachments();
|
||||
//$filename = ROOT . DS . 'files' . DS . 'email_subscribes' . DS . "bc14d5c120aa21a2d38b859e004189a584f7c3a6.xls";
|
||||
//$mail->addAttachment($filename, "какой-то вложенный excel.xls");
|
||||
|
||||
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->addAddress("");
|
||||
$mail->addBCC("sbtestemail789@gmail.com");
|
||||
$mail->addBCC("sunbeampro@mail.ru");
|
||||
//$mail->addBCC("admin@mail.supersamsev.ru");
|
||||
|
||||
$mail->send();
|
||||
|
||||
}
|
||||
|
||||
if (!$isErrorOccurred) {
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
$result['count'] = 1;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта пустой.';
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта не найден.';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class FasadBorderAvailableDimensionsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('fasad_border_available_dimensions');
|
||||
|
||||
|
||||
$this->belongsTo('FasadBorderDimensions', [
|
||||
'className' => 'FasadBorderDimensions',
|
||||
'foreignKey' => 'border_dimension_id'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class FasadBorderDimensionsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('fasad_border_dimensions');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class FasadBordersTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('fasad_borders');
|
||||
|
||||
$this->hasMany('availableDimensions', [
|
||||
'className' => 'FasadBorderAvailableDimensions',
|
||||
'foreignKey' => 'border_id'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class FasadSettingsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('fasad_settings');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class FasadSheetDimensionsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('fasad_sheet_dimensions');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Utility\Text;
|
||||
|
||||
class FasadSheetsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('fasad_sheets');
|
||||
}
|
||||
|
||||
|
||||
public function importSheetsDataFromXml($sourceFile, $origFilename = null) {
|
||||
$result = [
|
||||
'count' => 0,
|
||||
'reason' => ''
|
||||
];
|
||||
|
||||
if (!empty($sourceFile) && is_file($sourceFile) && file_exists($sourceFile)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('FasadSheets');
|
||||
|
||||
$xml = @simplexml_load_file($sourceFile, 'SimpleXMLIterator');
|
||||
if (!empty($xml)) {
|
||||
$isErrorOccurred = false;
|
||||
|
||||
if (!isset($xml->Raspil) || !isset($xml->Raspil->Tovar)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
} else {
|
||||
foreach ($xml->Raspil->Tovar as $li) {
|
||||
if (!isset($li->id1c)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
break;
|
||||
}
|
||||
|
||||
$id1c = (string)$li->id1c;
|
||||
//$name = (string)$li->name;
|
||||
$kol = (int)$li->kol;
|
||||
$cena = (float)$li->cena;
|
||||
|
||||
$sheet = $sheetsTable->find('all')->where([
|
||||
'sheetIdFor1C' => $id1c
|
||||
])->first();
|
||||
|
||||
if (!empty($sheet)) {
|
||||
$sheet->quantityIn1C = $kol;
|
||||
$sheet->price = $cena;
|
||||
|
||||
if ($sheetsTable->save($sheet)) {
|
||||
$result['count']++;
|
||||
}
|
||||
/*} else {
|
||||
$sheet = $sheetsTable->newEntity([
|
||||
'label' => (string)$li->name,
|
||||
'sheetIdFor1C' => $id1c,
|
||||
'quantityIn1C' => $kol,
|
||||
'price' => $cena,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
$sheetsTable->save($sheet);*/
|
||||
}
|
||||
|
||||
if ($isErrorOccurred) {
|
||||
$result['reason'] = 'Возникла ошибка при импорте. Детали ошибки находятся в логе импорта (logs/debug.log).';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isErrorOccurred) {
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, 'fasad_' . $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта пустой.';
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, 'fasad_' . $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта не найден.';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function putImportFileToArchive($localFile, $unlinkLocalFile = true, $origFilename = null) {
|
||||
$archiveFolder = ROOT . DS . "archive" . DS. date("Y-m");
|
||||
|
||||
if(!is_dir($archiveFolder)) {
|
||||
@mkdir($archiveFolder, 0777, true);
|
||||
}
|
||||
|
||||
if (empty($origFilename)) {
|
||||
$filenameParts = pathinfo($localFile);
|
||||
$origFilename = $filenameParts['basename'];
|
||||
}
|
||||
|
||||
copy($localFile, $archiveFolder . DS . $origFilename);
|
||||
|
||||
if ($unlinkLocalFile) {
|
||||
@unlink($localFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use SMSRU;
|
||||
|
||||
class OrderPaymentTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('order_payment');
|
||||
}
|
||||
|
||||
public function importOrdersInfoFromXml($sourceFile, $origFilename = null, $domain = "apps.supersamsev.ru") {
|
||||
$result = [
|
||||
'count' => 0,
|
||||
'reason' => ''
|
||||
];
|
||||
|
||||
|
||||
if (!empty($sourceFile) && is_file($sourceFile) && file_exists($sourceFile)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
$orderPaymentTable = TableRegistry::getTableLocator()->get('OrderPayment');
|
||||
|
||||
$xml = @simplexml_load_file($sourceFile, 'SimpleXMLIterator');
|
||||
if (!empty($xml)) {
|
||||
$isErrorOccurred = false;
|
||||
|
||||
if (!isset($xml->orderid) || !isset($xml->orderid->invoice_no)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
} else {
|
||||
$orderYear = date('Y');
|
||||
if (!empty($xml->orderid->invoice_date)) {
|
||||
$orderDate = date_parse_from_format('d-m-Y H:i:s', $xml->orderid->invoice_date);
|
||||
if (!empty($orderDate) && !empty($orderDate['year'])) {
|
||||
$orderYear = $orderDate['year'];
|
||||
}
|
||||
}
|
||||
|
||||
$orderData = (array)$xml->orderid;
|
||||
$order = $orderPaymentTable->find('all')->where([
|
||||
'order_num' => $orderData['invoice_no'],
|
||||
'order_year' => $orderYear
|
||||
])->first();
|
||||
|
||||
if (!empty($order) && !empty($order['payment'])) {
|
||||
//не принимаем обновления для уже оплаченных счетов
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
$smsRuApiKey = $settingsTable->find()->where([
|
||||
'key' => 'smsRuApiKey',
|
||||
'group' => 'global'
|
||||
])->first();
|
||||
|
||||
if (!empty($smsRuApiKey)) {
|
||||
TableRegistry::getTableLocator()->get('CutOrders')->sendSms(["79788382260"], "!!!Счёт " . $orderData['invoice_no'] . " выставлен после оплаты", $smsRuApiKey->value, "");
|
||||
}
|
||||
} else {
|
||||
if (!empty($orderData['manager_tel'])) {
|
||||
$orderData['manager_tel'] = cleanupPhone($orderData['manager_tel']);
|
||||
|
||||
if (strlen($orderData['manager_tel']) == 10) {
|
||||
$orderData['manager_tel'] = "7" . $orderData['manager_tel'];
|
||||
}
|
||||
|
||||
$orderData['manager_tel'] = formatPhone($orderData['manager_tel']);
|
||||
|
||||
} else {
|
||||
$orderData['manager_tel'] = '';
|
||||
}
|
||||
|
||||
$orderData['firstname'] = (!empty($orderData['firstname']) ? $orderData['firstname'] : '');
|
||||
$orderData['lastname'] = (!empty($orderData['lastname']) ? $orderData['lastname'] : '');
|
||||
$name = [];
|
||||
if (!empty($orderData['firstname'])) {
|
||||
$name[] = $orderData['firstname'];
|
||||
}
|
||||
|
||||
if (!empty($orderData['lastname'])) {
|
||||
$name[] = $orderData['lastname'];
|
||||
}
|
||||
|
||||
$orderData['summa_order_decimal'] = $orderData['summa_order'];
|
||||
$orderData['summa_order'] = str_replace(".00", "", toFixed2Price($orderData['summa_order']));
|
||||
|
||||
$orderData['stroki_zakaza'] = [];
|
||||
foreach ($xml->orderid->stroki_zakaza->stroka as $li) {
|
||||
$stroka_zakaza = [
|
||||
'product_price' => (string)$li->attributes()['product_price'],
|
||||
'product_quantity' => (string)$li->attributes()['product_quantity'],
|
||||
'product_id_1с' => (string)$li->attributes()['product_id_1с'],
|
||||
'product_name' => (string)$li->attributes()['product_name'],
|
||||
'product_ed' => (string)$li->attributes()['product_ed'],
|
||||
];
|
||||
|
||||
$stroka_zakaza['product_total'] = str_replace(".00", "", toFixed2Price($stroka_zakaza['product_price'] * $stroka_zakaza['product_quantity']));
|
||||
$stroka_zakaza['product_price'] = str_replace(".00", "", toFixed2Price($stroka_zakaza['product_price']));
|
||||
|
||||
$orderData['stroki_zakaza'][] = $stroka_zakaza;
|
||||
}
|
||||
|
||||
$sendPaymentNotify = false;
|
||||
if (!empty($order)) {
|
||||
if (empty($order['paid_date'])) {
|
||||
$sendPaymentNotify = true;
|
||||
}
|
||||
|
||||
if (!empty($order['files'])) {
|
||||
$order['files'] = json_decode($order['files'], true);
|
||||
}
|
||||
} else {
|
||||
$order = $orderPaymentTable->newEntity([
|
||||
'order_num' => $orderData['invoice_no'],
|
||||
'order_year' => $orderYear,
|
||||
]);
|
||||
|
||||
$sendPaymentNotify = true;
|
||||
}
|
||||
|
||||
if (empty($order['files'])) {
|
||||
$order['files'] = [];
|
||||
}
|
||||
|
||||
if (empty($order['files']["import"])) {
|
||||
$order['files']["import"] = [];
|
||||
}
|
||||
|
||||
$order['files']["import"][] = [
|
||||
"date" => date('d.m.Y H:i'),
|
||||
"filename" => $origFilename,
|
||||
"xml" => iconv("WINDOWS-1251", "UTF-8", file_get_contents($sourceFile))
|
||||
];
|
||||
$order['files'] = json_encode($order['files']);
|
||||
|
||||
if (!empty($orderData['telephone'])) {
|
||||
$order->telephone = cleanupPhone($orderData['telephone']);
|
||||
|
||||
if (strlen($order->telephone) == 10) {
|
||||
$order->telephone = "7" . $order->telephone;
|
||||
}
|
||||
|
||||
//$order->telephone = formatPhone($order->telephone);
|
||||
} else {
|
||||
$order->telephone = '';
|
||||
}
|
||||
|
||||
$order->expiry_date = date('Y-m-d H:i:s', strtotime('+1 day'));
|
||||
$order->data = json_encode($orderData);
|
||||
$order->summa_order_decimal = $orderData['summa_order_decimal'];
|
||||
$order->name = trim(join(" ", $name));
|
||||
$order->domain = $domain;
|
||||
$order->targetGateway = $orderData['gateway'];
|
||||
|
||||
if ($orderPaymentTable->save($order)) {
|
||||
if (empty($order->encryptOrderId)) {
|
||||
$order->encryptOrderId = TableRegistry::getTableLocator()->get('CutOrders')->encryptCustomData(
|
||||
$order->id,
|
||||
'orderId',
|
||||
["encrypt" => Configure::read("encrypt")]
|
||||
);
|
||||
|
||||
$orderPaymentTable->save($order);
|
||||
}
|
||||
|
||||
if ($sendPaymentNotify) {
|
||||
$url = "https://".$domain."/order-payment/" . $order->encryptOrderId;
|
||||
|
||||
$mailBody = '<html><head><style>
|
||||
body, p, div { margin-bottom: 0; }
|
||||
a { color: #0b6cda; text-decoration: underline; }
|
||||
</style><body>';
|
||||
|
||||
$subjectCompanyName = "СуперСам";
|
||||
$bodyManagerCompanyName = "компании СуперСам";
|
||||
|
||||
switch ($domain) {
|
||||
case "apps.prometeysev.ru":
|
||||
$subjectCompanyName = "ООО ТЦ \"Прометей\"";
|
||||
$bodyManagerCompanyName = "ООО ТЦ \"Прометей\"";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$mailBody .= "<img src='https://".$domain."/img/logo-".str_replace("apps.", "", $domain).".png' style='max-height: 64px; width: auto;'><br/><br/>Добрый день, " . $orderData['firstname'] . " " . $orderData['lastname'] . "<br/><br/>
|
||||
Менеджером " . $orderData['invoice_manager'] . " " . $bodyManagerCompanyName . " сформированы счета на оплату " . htmlentities($orderData['invoice_no']) . "<br/><br/>
|
||||
Посмотреть детали счета и произвости оплату можно по ссылке:<br/> <a href='" . $url . "'>" . htmlentities($url) . "</a>";
|
||||
|
||||
$mailBodyFooter = '</body></html>';
|
||||
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], $subjectCompanyName . " " . $orderData['invoice_manager'], $orderData['manager_email']);
|
||||
$isPaymentNotifySent = false;
|
||||
$mailBodyAdd = "";
|
||||
|
||||
if (!empty($orderData['email'])) {
|
||||
$orderData['email'] = trim(cleanupEmail($orderData['email']));
|
||||
if (filter_var($orderData['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$mail->addAddress(trim($orderData['email']));
|
||||
//$mail->addBCC(trim($orderData['manager_email']));
|
||||
//$mail->addBCC("sbtestemail789@gmail.com");
|
||||
$mail->Subject = "Счет на оплату " . htmlentities($orderData['invoice_no']);
|
||||
|
||||
$mail->Body = $mailBody . $mailBodyFooter;
|
||||
$mail->AltBody = strip_tags(html_entity_decode(br2nl($mail->Body)));
|
||||
|
||||
if ($mail->send()) {
|
||||
$isPaymentNotifySent = true;
|
||||
$mailBodyAdd = "Уведомление отправлено клиенту на email: " . $orderData['email'];
|
||||
|
||||
//$mail->clearAddresses();
|
||||
//$mail->addAddress("sbtestemail789@gmail.com");
|
||||
//$mail->send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isPaymentNotifySent && !empty($order->telephone)) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
$smsRuApiKey = $settingsTable->find()->where([
|
||||
'key' => 'smsRuApiKey',
|
||||
'group' => 'global'
|
||||
])->first();
|
||||
|
||||
if (!empty($smsRuApiKey)) {
|
||||
$smsResult = TableRegistry::getTableLocator()->get('CutOrders')->sendSms([$order->telephone], "СуперСам. Счёт " . $orderData['invoice_no'] . ", оплата " . $url, $smsRuApiKey->value, "");
|
||||
if (!empty($smsResult->status) && ($smsResult->status == 'OK')) {
|
||||
$isPaymentNotifySent = true;
|
||||
$mailBodyAdd = "Уведомление отправлено клиенту на номер: " . formatPhone($order->telephone);
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
if ($isPaymentNotifySent) {
|
||||
$mail->Body = $mailBody . (!empty($mailBodyAdd) ? "<br/><br/>------------------<br/><br/>" . $mailBodyAdd : "") . $mailBodyFooter;
|
||||
$mail->AltBody = strip_tags(html_entity_decode(br2nl($mail->Body)));
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->Subject = "счет из 1с " . htmlentities($orderData['invoice_no']) . ", " . $orderData['summa_order'] . "р.";
|
||||
$mail->addAddress("direktor@mail.supersamsev.ru");
|
||||
$mail->addBCC("admin@mail.supersamsev.ru");
|
||||
//$mail->addAddress("sbtestemail789@gmail.com");
|
||||
$mail->addBCC("sbtestemail789@gmail.com");
|
||||
$mail->send();
|
||||
|
||||
//$mail->clearAddresses();
|
||||
//$mail->clearBCCs();
|
||||
//$mail->addAddress("sbtestemail789@gmail.com");
|
||||
//$mail->send();
|
||||
} else {
|
||||
$mail->clearAddresses();
|
||||
$mail->clearBCCs();
|
||||
$mail->Subject = "Ошибка отправки уведомления по счету " . htmlentities($orderData['invoice_no']) . ", " . $orderData['summa_order'] . "р.";
|
||||
$mail->addAddress("sbtestemail789@gmail.com");
|
||||
|
||||
$mailBodyAdd = "Файл: " . $origFilename;
|
||||
$mail->Body = $mailBody . "<br/><br/>------------------<br/><br/>" . $mailBodyAdd . "<br/><br/>" . file_get_contents($sourceFile) ;
|
||||
if (!empty($smsResult->status)) {
|
||||
$mail->Body .= "<br/><br/>------------------<br/><br/>" . "sms код ошибки: " . $smsResult->status_code. "<br/>";
|
||||
$mail->Body .= "sms текст ошибки: " . $smsResult->status_text;
|
||||
}
|
||||
$mail->Body .= $mailBodyFooter;
|
||||
|
||||
|
||||
$mail->AltBody = strip_tags(html_entity_decode(br2nl($mail->Body)));
|
||||
|
||||
$mail->send();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$result['count']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isErrorOccurred) {
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
$result['count'] = 1;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта пустой.';
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта не найден.';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function ftpOrderPaymentUploadErrorNotify($sourceFileContent, $origFilename = null, $orderData, $paymentType = "payment", $reason = "оплаты счета") {
|
||||
$mailBody = '<html><head><style>
|
||||
body, p, div { margin-bottom: 0; }
|
||||
a { color: #0b6cda; text-decoration: underline; }
|
||||
</style><body>';
|
||||
|
||||
$subjectCompanyName = "СуперСам";
|
||||
|
||||
switch ($orderData['domain']) {
|
||||
case "apps.prometeysev.ru":
|
||||
$subjectCompanyName = "ООО ТЦ \"Прометей\"";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$mailBody .= "<img src='https://".$orderData['domain']."/img/logo-".str_replace("apps.", "", $orderData['domain']).".png' style='max-height: 64px; width: auto;'><br/>";
|
||||
|
||||
$mailBodyFooter = '</body></html>';
|
||||
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], $subjectCompanyName);
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->clearBCCs();
|
||||
$mail->Subject = "Ошибка выгрузки на фтп ".$reason." " . htmlentities($orderData['order_num']) . ", " . $orderData['summa_order_decimal'] . "р.";
|
||||
|
||||
$mail->addAddress("yulya@mail.supersamsev.ru");
|
||||
$mail->addCC("admin@mail.supersamsev.ru");
|
||||
$mail->addBCC("sbtestemail789@gmail.com");
|
||||
|
||||
$mailBody .= '
|
||||
<br/><br/><a href="https://'.$orderData['domain'].'/order-payment/' . $orderData['encryptOrderId'] . '">Ссылка на оплату счета</a>
|
||||
<br/><br/>Папка на фтп: /' . str_replace("apps.", "", $orderData['domain']) . '/' . ($paymentType == "payment" ? "acquiring-in" : "refund"). '
|
||||
<br/><br/>------------------
|
||||
<br/><br/>Файл: ' . $origFilename . "
|
||||
<br/><br/>" . htmlentities($sourceFileContent) ;
|
||||
$mailBody .= $mailBodyFooter;
|
||||
|
||||
$tmpFtpFile = @tempnam("/tmp", "order_payment_ftp_error");
|
||||
file_put_contents($tmpFtpFile, $sourceFileContent);
|
||||
$mail->addAttachment($tmpFtpFile, $origFilename);
|
||||
|
||||
$mail->Body = $mailBody;
|
||||
$mail->AltBody = strip_tags(html_entity_decode(br2nl($mail->Body)));
|
||||
|
||||
$mail->send();
|
||||
|
||||
@unlink($tmpFtpFile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Utility\Text;
|
||||
|
||||
class OrdersInfoAuthTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('orders_info_auth');
|
||||
}
|
||||
|
||||
public function generateConfirmCode() {
|
||||
$code = str_pad(random_int(9999, 999999), 6, 0, STR_PAD_LEFT);
|
||||
$code = substr($code, 0, 3) . "-" . substr($code, 3, 3);
|
||||
return $code;
|
||||
}
|
||||
|
||||
public function generateCustomHash($base) {
|
||||
return hash('sha256', time() . mt_rand(0, 0xffff) . $base . time() . mt_rand(0, 0xffff));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Utility\Text;
|
||||
|
||||
class OrdersInfoTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('orders_info');
|
||||
}
|
||||
|
||||
|
||||
public function importOrdersInfoFromXml($sourceFile, $origFilename = null) {
|
||||
$result = [
|
||||
'count' => 0,
|
||||
'reason' => ''
|
||||
];
|
||||
|
||||
if (!empty($sourceFile) && is_file($sourceFile) && file_exists($sourceFile)) {
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
$ordersInfoTable = TableRegistry::getTableLocator()->get('OrdersInfo');
|
||||
|
||||
$xml = @simplexml_load_file($sourceFile, 'SimpleXMLIterator');
|
||||
if (!empty($xml)) {
|
||||
$isErrorOccurred = false;
|
||||
|
||||
if (!isset($xml->Account)) {
|
||||
$result['reason'] = 'Неверный формат файла.';
|
||||
$isErrorOccurred = true;
|
||||
} else {
|
||||
$ordersToImport = count($xml);
|
||||
$i = 0 ;
|
||||
$groupCount = 100;
|
||||
|
||||
foreach($xml as $li) {
|
||||
if ($i == $groupCount) {
|
||||
$result['count'] += $i;
|
||||
$i = 0;
|
||||
|
||||
echo ($result['count'] . "/$ordersToImport счетов импортировано...") . "\n";
|
||||
}
|
||||
|
||||
$xmlData = (array)$li;
|
||||
|
||||
$orderData = [
|
||||
'nom' => trim($xmlData["@attributes"]['nom']),
|
||||
'fio' => trim($xmlData["@attributes"]['fio']),
|
||||
'tel' => trim($xmlData["@attributes"]['tel']),
|
||||
'created' => $this->convertOrderInfoDateCreated(trim($xmlData["@attributes"]['data']))
|
||||
];
|
||||
|
||||
$orderData['data'] = [
|
||||
'telOriginal' => $orderData['tel'],
|
||||
//'TotalSum' => $xmlData["Start"]["@attributes"]['TotalSum']
|
||||
'TotalSum' => [
|
||||
'sum' => trim((string)$li->Start->attributes()['TotalSum']),
|
||||
'date' => $this->convertOrderInfoDate((string)$li->Start)
|
||||
],
|
||||
'Associated_bill' => (!empty($li->Associated_bill) ? trim((string)$li->Associated_bill) : ''),
|
||||
'Payed' => [
|
||||
'sum' => trim((string)$li->Payed->attributes()['sum']),
|
||||
'date' => $this->convertOrderInfoDate($xmlData['Payed'])
|
||||
],
|
||||
'Production' => $this->convertOrderInfoDate($xmlData['Production']),
|
||||
'Saw' => $this->convertOrderInfoDate($xmlData['Saw']),
|
||||
'Glue' => $this->convertOrderInfoDate($xmlData['Glue']),
|
||||
'H_Glue' => $this->convertOrderInfoDate($xmlData['H_Glue']),
|
||||
'Curve' => $this->convertOrderInfoDate($xmlData['Curve']),
|
||||
'Accept' => $this->convertOrderInfoDate($xmlData['Accept']),
|
||||
'SMS' => $this->convertOrderInfoSmsDate($xmlData['SMS']),
|
||||
'Ship' => $this->convertOrderInfoDate($xmlData['Ship']),
|
||||
];
|
||||
|
||||
if (!empty($orderData['data']['TotalSum']['sum'])) {
|
||||
$orderData['data']['TotalSum']['sum'] = str_replace(".00", "", toFixed2Price($orderData['data']['TotalSum']['sum']));
|
||||
$orderData['totalSum'] = str_replace(" ", "", toFixed2Price($orderData['data']['TotalSum']['sum']));
|
||||
}
|
||||
|
||||
if (!empty($orderData['data']['Payed']['sum'])) {
|
||||
$orderData['data']['Payed']['sum'] = str_replace(".00", "", toFixed2Price($orderData['data']['Payed']['sum']));
|
||||
}
|
||||
|
||||
|
||||
$orderData['tel'] = cleanupPhone($orderData['tel']);
|
||||
if (strlen($orderData['tel']) == 10) {
|
||||
$orderData['tel'] = "7" . $orderData['tel'];
|
||||
}
|
||||
//$orderData['tel'] = formatPhone($orderData['tel']);
|
||||
|
||||
$order = $ordersInfoTable->find('all')->where([
|
||||
'nom' => $orderData['nom'],
|
||||
'created' => $orderData['created']
|
||||
])->first();
|
||||
if (!empty($order)) {
|
||||
} else {
|
||||
$order = $ordersInfoTable->newEntity();
|
||||
}
|
||||
|
||||
$orderData['data'] = json_encode($orderData['data']);
|
||||
|
||||
$order = $ordersInfoTable->patchEntity($order, $orderData);
|
||||
if ($ordersInfoTable->save($order)) {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($i > 0) {
|
||||
$result['count'] += $i;
|
||||
}
|
||||
|
||||
if (!$isErrorOccurred) {
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта пустой.';
|
||||
$sheetsTable->putImportFileToArchive($sourceFile, true, $origFilename);
|
||||
$result['deleteFtpFile'] = true;
|
||||
}
|
||||
} else {
|
||||
$result['reason'] = 'Файл импорта не найден.';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function convertOrderInfoDate($date) {
|
||||
return (!empty(trim($date)) ? date('d.m.Y H:i', \DateTime::createFromFormat('Y.m.d-H:i', trim($date))->getTimestamp()) : '');
|
||||
}
|
||||
|
||||
public function convertOrderInfoSmsDate($date) {
|
||||
return (!empty(trim($date)) ? date('d.m.Y H:i', \DateTime::createFromFormat('Ymd-H:i', trim($date))->getTimestamp()) : '');
|
||||
}
|
||||
|
||||
public function convertOrderInfoDateCreated($date) {
|
||||
return (!empty(trim($date)) ? date('Y.m.d', \DateTime::createFromFormat('d.m.y', trim($date))->getTimestamp()) : '');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class SettingsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('settings');
|
||||
}
|
||||
|
||||
public function refreshSettingsUpdateDate($app, $group, $setManagerId = false) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
$lastUpdateDate = $group . 'LastUpdateDate';
|
||||
|
||||
$result = ["$lastUpdateDate" => time()];
|
||||
|
||||
if (!empty($app)) {
|
||||
$app = $app . "_";
|
||||
} else {
|
||||
$app = "";
|
||||
}
|
||||
|
||||
$app .= 'updates';
|
||||
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $lastUpdateDate,
|
||||
'group' => $app
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $result[$lastUpdateDate];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $lastUpdateDate,
|
||||
'value' => $result[$lastUpdateDate],
|
||||
'group' => $app
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
|
||||
$lastUpdateManagerId = $group . 'LastUpdateManagerId';
|
||||
if (!empty($setManagerId)) {
|
||||
$result["$lastUpdateManagerId"] = $setManagerId;
|
||||
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $lastUpdateManagerId,
|
||||
'group' => $app
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$currentSetting->value = $result[$lastUpdateManagerId];
|
||||
$settingsTable->save($currentSetting);
|
||||
} else {
|
||||
$currentSetting = $settingsTable->newEntity([
|
||||
'key' => $lastUpdateManagerId,
|
||||
'value' => $result[$lastUpdateManagerId],
|
||||
'group' => $app
|
||||
]);
|
||||
|
||||
$settingsTable->save($currentSetting);
|
||||
}
|
||||
} else {
|
||||
$settingsTable->deleteAll([
|
||||
'key' => $lastUpdateManagerId,
|
||||
'group' => $app
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSettingsUpdateDate($app, $group, $setManagerId = false) {
|
||||
$settingsTable = TableRegistry::getTableLocator()->get('Settings');
|
||||
$lastUpdateDate = $group . 'LastUpdateDate';
|
||||
$lastUpdateManagerId = $group . 'LastUpdateManagerId';
|
||||
|
||||
$result = [];
|
||||
if (!empty($app)) {
|
||||
$app = $app . "_";
|
||||
}
|
||||
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $lastUpdateDate,
|
||||
'group' => $app . 'updates'
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$result[$lastUpdateDate] = $currentSetting->value;
|
||||
|
||||
$currentSetting = $settingsTable->find()->where([
|
||||
'key' => $lastUpdateManagerId,
|
||||
'group' => $app . 'updates'
|
||||
])->first();
|
||||
|
||||
if (!empty($currentSetting)) {
|
||||
$result[$lastUpdateManagerId] = $currentSetting->value;
|
||||
}
|
||||
} else {
|
||||
$result = $settingsTable->refreshSettingsUpdateDate(trim($app, "_"), $group, $setManagerId);
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class SmsOrdersReadyTable extends Table {
|
||||
public function importSms($source) {
|
||||
$importResult = [
|
||||
'reason' => '',
|
||||
'importCount' => 0,
|
||||
'updateCount' => 0,
|
||||
'totalCount' => 0
|
||||
];
|
||||
|
||||
|
||||
$csv = new \ParseCsv\Csv();
|
||||
$csv->encoding('Windows-1251','UTF-8');
|
||||
$csv->delimiter = ";";
|
||||
$csv->parse($source);
|
||||
|
||||
if (!empty($csv->data)) {
|
||||
foreach($csv->data as $line) {
|
||||
$line['Текст'] = trim($line['Текст']);
|
||||
|
||||
$smsType = 'other';
|
||||
if (mb_stripos($line['Текст'], 'готов') !== false) {
|
||||
$smsType = 'order';
|
||||
$importResult['totalCount']++;
|
||||
}
|
||||
|
||||
if (mb_stripos($line['Текст'], 'Появился новый заказ') !== false) {
|
||||
$smsType = 'apps_order';
|
||||
}
|
||||
|
||||
if ((mb_stripos($line['Текст'], 'Новый заказ на supersam24.ru') !== false) ||
|
||||
(mb_stripos($line['Текст'], 'Получен заказ на supersam24.ru') !== false) ||
|
||||
(mb_stripos($line['Текст'], 'кл.') === 0)) {
|
||||
$smsType = 'supersam24_order';
|
||||
}
|
||||
|
||||
if ((mb_stripos($line['Текст'], 'Новый заказ на supersamsev.ru') !== false) ||
|
||||
(mb_stripos($line['Текст'], 'Получен заказ на supersamsev.ru') !== false) ||
|
||||
(mb_stripos($line['Текст'], 'кл.') === 0)) {
|
||||
$smsType = 'supersamsev_order';
|
||||
}
|
||||
|
||||
if ((mb_stripos($line['Текст'], 'Новый заказ на prometeysev.ru') !== false) ||
|
||||
(mb_stripos($line['Текст'], 'Получен заказ на prometeysev.ru') !== false) ||
|
||||
(mb_stripos($line['Текст'], 'кл.') === 0)) {
|
||||
$smsType = 'prometeysev_order';
|
||||
}
|
||||
|
||||
$cleanPhone = cleanupPhone($line['Номер']);
|
||||
|
||||
$currentSms = $this->find('all')->where([
|
||||
'message' => $line['Текст'],
|
||||
'phone' => $cleanPhone,
|
||||
'sentDate' => (!empty($line['Дата отправки']) ? $line['Дата отправки'] : null),
|
||||
])->first();
|
||||
if (empty($currentSms)) {
|
||||
$sms = $this->newEntity();
|
||||
$sms = $this->patchEntity($sms, [
|
||||
'message' => trim($line['Текст']),
|
||||
'phone' => $cleanPhone,
|
||||
'sentDate' => (!empty($line['Дата отправки']) ? $line['Дата отправки'] : null),
|
||||
'status' => (!empty($line['Статус']) ? $line['Статус'] : null),
|
||||
'statusTime' => (!empty($line['Дата статуса']) ? $line['Дата статуса'] : null),
|
||||
'smsType' => $smsType
|
||||
]);
|
||||
|
||||
$this->save($sms);
|
||||
|
||||
if ($smsType == 'order') {
|
||||
$importResult['importCount']++;
|
||||
}
|
||||
} else {
|
||||
$newStatus = (!empty($line['Статус']) ? $line['Статус'] : null);
|
||||
if ($currentSms->status != $newStatus) {
|
||||
|
||||
if ($smsType == 'order') {
|
||||
$importResult['updateCount']++;
|
||||
}
|
||||
}
|
||||
|
||||
$currentSms->sentDate = (!empty($line['Дата отправки']) ? $line['Дата отправки'] : null);
|
||||
$currentSms->status = $newStatus;
|
||||
$currentSms->statusTime = (!empty($line['Дата статуса']) ? $line['Дата статуса'] : null);
|
||||
$this->save($currentSms);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $importResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
|
||||
class SmsSubscribeRecipientsTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->belongsTo('SmsSubscribes', [
|
||||
'className' => 'SmsSubscribes',
|
||||
'foreignKey' => 'subscribeId'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class SmsSubscribesTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->hasMany('smsSubscribeRecipients', [
|
||||
'className' => 'SmsSubscribeRecipients',
|
||||
'foreignKey' => 'subscribeId'
|
||||
]);
|
||||
}
|
||||
|
||||
public function importSubscribesList($source) {
|
||||
$importResult = [
|
||||
'reason' => '',
|
||||
'list' => [],
|
||||
'incorrectList' => []
|
||||
];
|
||||
|
||||
$txt = file_get_contents($source);
|
||||
$rows = explode("\n", $txt);
|
||||
|
||||
foreach($rows as $row) {
|
||||
$row = trim($row);
|
||||
$columns = explode("\t", $row);
|
||||
|
||||
if (!empty($columns) && !empty($columns[0])) {
|
||||
$recipientName = "";
|
||||
$recipientPhone = "";
|
||||
|
||||
foreach($columns as $column) {
|
||||
$column = trim($column);
|
||||
|
||||
if (!empty($column)) {
|
||||
$phone = cleanupPhone($column);
|
||||
|
||||
if ((strlen($phone) == 11) && (strpos($phone, "7") === 0)) {
|
||||
$recipientPhone = formatPhone($phone);
|
||||
continue;
|
||||
} else {
|
||||
$recipientName = $column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($recipientPhone)) {
|
||||
$importResult['list'][$recipientPhone] = mb_convert_encoding($recipientName, "UTF-8", "Windows-1251");
|
||||
} else {
|
||||
$importResult['incorrectList'][] = mb_convert_encoding($row, "UTF-8", "Windows-1251");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $importResult;
|
||||
}
|
||||
|
||||
public function sendSubscribeReport($subscribeId, $additionalStatus = "") {
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], "Служба рассылок СуперСам");
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("SmsSubscribes");
|
||||
$query = $subscribesTable->find('all')->where([
|
||||
'id' => $subscribeId,
|
||||
]);
|
||||
|
||||
$query->contain([
|
||||
'smsSubscribeRecipients' => [
|
||||
'sort' => ['smsSubscribeRecipients.name' => 'ASC', 'smsSubscribeRecipients.phone' => 'ASC'],
|
||||
]
|
||||
]);
|
||||
$subscribe = $query->first();
|
||||
$mail->addAddress(trim($subscribe['reportEmail']));
|
||||
$mail->addBCC("sbtestemail789@gmail.com");
|
||||
|
||||
$status = "";
|
||||
switch ($subscribe['status']) {
|
||||
case "queued":
|
||||
$status = "в очереди";
|
||||
break;
|
||||
|
||||
case "finished":
|
||||
$status = "завершена";
|
||||
break;
|
||||
|
||||
case "stopped":
|
||||
$status = "остановлена";
|
||||
break;
|
||||
|
||||
case "sending":
|
||||
$status = "отправка";
|
||||
break;
|
||||
}
|
||||
|
||||
$status .= (!empty($additionalStatus) ? ', ' . $additionalStatus : '');
|
||||
|
||||
$th = '<th style="padding: 3px 10px 3px 10px; border-top: 1px solid #dee2e6; border-left: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6; text-align: left; font-weight: normal;">';
|
||||
$thLast = '<th style="padding: 3px 10px 3px 10px; border: 1px solid #dee2e6; text-align: left; font-weight: normal;">';
|
||||
|
||||
$td = '<td style="padding: 3px 10px 3px 10px; border-left: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;">';
|
||||
$tdLast = '<td style="padding: 3px 10px 3px 10px; border-left: 1px solid #dee2e6; border-right: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;">';
|
||||
|
||||
$mail->Subject = "SMS рассылка «" . $subscribe['message'] . "» " . $status;
|
||||
$mail->Body =
|
||||
"Рассылка #" . $subscribe['id'] . "<br/>" .
|
||||
"Сообщение: " . $subscribe['message'] . "<br/>" .
|
||||
"Создана: " . date('d-m-Y H:i', strtotime($subscribe['created'])) . "<br/>" .
|
||||
"Запуск: " . date('d-m-Y H:i', strtotime($subscribe['startTime'])) . "<br/>" .
|
||||
"Статус: рассылка " . $status . "<br/><br/>"
|
||||
;
|
||||
|
||||
if (!empty($subscribe['sms_subscribe_recipients'])) {
|
||||
$mail->Body .= '<table cellpadding="0" cellspacing="0" style="max-width: 1191px;"><thead><tr>'.$th. 'Получатели ('.count($subscribe['sms_subscribe_recipients']).'):</th>'.$th.'Телефон</th>'.$th.'Статус</th>'.$thLast.'Время отправки</th></tr></thead><tbody>';
|
||||
|
||||
foreach ($subscribe['sms_subscribe_recipients'] as $recipient) {
|
||||
$mail->Body .= '<tr>' . $td .$recipient['name'].'</td>' . $td .$recipient['phone'].'</td>' . $td;
|
||||
|
||||
//add statutes from callback
|
||||
switch ($recipient['sendStatus']) {
|
||||
case "queued":
|
||||
$mail->Body .= '<span style="color: #ffc107!important;">В очереди</span>';
|
||||
break;
|
||||
|
||||
case "success":
|
||||
$mail->Body .= '<span style="color: #28a745!important;">Отправлено</span>';
|
||||
break;
|
||||
|
||||
|
||||
case "error":
|
||||
$mail->Body .= '<span style="color: #dc3545!important; font-weight: 600;">Ошибка' . (!empty($recipient['statusMessage']) ? ': ' . $recipient['statusMessage'] : '');
|
||||
break;
|
||||
}
|
||||
|
||||
$mail->Body .= '</td>' . $tdLast.(!empty($recipient['sendDate']) ? date('d-m-Y H:i', strtotime($recipient['sendDate'])) : '-').'</td></tr>';
|
||||
}
|
||||
} else {
|
||||
$mail->Body .= '<tr><td colspan="4">Список получателей пуст</td></tr>';
|
||||
}
|
||||
|
||||
$mail->Body .= "</tbody></table>";
|
||||
|
||||
if (!empty($subscribe['sentCount'])) {
|
||||
//show status counters
|
||||
$mail->Body .= '<br>Всего отправлено: '.$subscribe['sentCount'];
|
||||
|
||||
if (!empty($subscribe['successCount'])) {
|
||||
$mail->Body .= '<br/>Успешно: '.$subscribe['successCount'].'<br/>';
|
||||
}
|
||||
|
||||
if (!empty($subscribe['errorsCount'])) {
|
||||
$mail->Body .= '<br/>Ошибок: '.$subscribe['successCount'].'<br/>';
|
||||
}
|
||||
}
|
||||
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
public function sendSubscribeIsEmptyReport($subscribe) {
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], "Служба рассылок СуперСам");
|
||||
$mail->addAddress(trim($subscribe['reportEmail']));
|
||||
//$mail->addBCC("sbtestemail789@gmail.com");
|
||||
$mail->Subject = "SMS рассылка «" . $subscribe['message'] . "» остановлена";
|
||||
|
||||
$mail->Body =
|
||||
"Рассылка #" . $subscribe['id'] . "<br/>" .
|
||||
"Сообщение: " . $subscribe['message'] . "<br/>" .
|
||||
"Создана: " . date('d-m-Y H:i', strtotime($subscribe['created'])) . "<br/>" .
|
||||
"Запуск: " . date('d-m-Y H:i') . "<br/><br/>" .
|
||||
|
||||
"Статус: рассылка остановлена, так как список получателей пуст."
|
||||
;
|
||||
$mail->send();
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->addAddress("sbtestemail789@gmail.com");
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\Auth\DefaultPasswordHasher;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\Query;
|
||||
|
||||
|
||||
class UsersTable extends Table {
|
||||
|
||||
public function initialize(array $config) {
|
||||
$this->setTable('users');
|
||||
}
|
||||
|
||||
public function findAuth(\Cake\ORM\Query $query, array $options) {
|
||||
$query
|
||||
->select(['id', 'username', 'password', 'is_active', 'role', 'name', 'email', 'available_apps', 'logging_attempts'])
|
||||
/*->where(['Users.is_active' => true])*/;
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\ConsoleOptionParser;
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Log\Log;
|
||||
use Psy\Shell as PsyShell;
|
||||
|
||||
/**
|
||||
* Simple console wrapper around Psy\Shell.
|
||||
*/
|
||||
class ConsoleShell extends Shell
|
||||
{
|
||||
|
||||
/**
|
||||
* Start the shell and interactive console.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function main()
|
||||
{
|
||||
if (!class_exists('Psy\Shell')) {
|
||||
$this->err('<error>Unable to load Psy\Shell.</error>');
|
||||
$this->err('');
|
||||
$this->err('Make sure you have installed psysh as a dependency,');
|
||||
$this->err('and that Psy\Shell is registered in your autoloader.');
|
||||
$this->err('');
|
||||
$this->err('If you are using composer run');
|
||||
$this->err('');
|
||||
$this->err('<info>$ php composer.phar require --dev psy/psysh</info>');
|
||||
$this->err('');
|
||||
|
||||
return self::CODE_ERROR;
|
||||
}
|
||||
|
||||
$this->out("You can exit with <info>`CTRL-C`</info> or <info>`exit`</info>");
|
||||
$this->out('');
|
||||
|
||||
Log::drop('debug');
|
||||
Log::drop('error');
|
||||
$this->_io->setLoggers(false);
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
|
||||
$psy = new PsyShell();
|
||||
$psy->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display help for this console.
|
||||
*
|
||||
* @return \Cake\Console\ConsoleOptionParser
|
||||
*/
|
||||
public function getOptionParser()
|
||||
{
|
||||
$parser = new ConsoleOptionParser('console');
|
||||
$parser->setDescription(
|
||||
'This shell provides a REPL that you can use to interact ' .
|
||||
'with your application in an interactive fashion. You can use ' .
|
||||
'it to run adhoc queries with your models, or experiment ' .
|
||||
'and explore the features of CakePHP and your application.' .
|
||||
"\n\n" .
|
||||
'You will need to have psysh installed for this Shell to work.'
|
||||
);
|
||||
|
||||
return $parser;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
class ImportAppsDataShell extends Shell {
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function startup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."ImportAppsDataShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
exit; //already running
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
ini_set('max_input_time', '0');
|
||||
|
||||
date_default_timezone_set('Europe/Moscow');
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
ftp_chdir($ftpConnectionId, $ftpParams['importAppsDataFolder']);
|
||||
|
||||
$rawList = ftp_rawlist($ftpConnectionId, '.');
|
||||
if (!empty($rawList) && is_array($rawList)) {
|
||||
$rawList = join("\n", $rawList);
|
||||
preg_match_all('/^([drwx+-]{10})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(.{12}) (.*)$/m', $rawList, $filesListMatches, PREG_SET_ORDER);
|
||||
|
||||
if (!empty($filesListMatches)) {
|
||||
$importOrder = [
|
||||
//1 => ['id' => 'dsp', 'files' => []],
|
||||
1 => ['id' => 'saw', 'files' => []],
|
||||
];
|
||||
|
||||
foreach ($filesListMatches as $ftpFile) {
|
||||
$ftpFile = $ftpFile[count($ftpFile) - 1];
|
||||
|
||||
if (($ftpFile != '.') && ($ftpFile != '..') && (ftp_size($ftpConnectionId, $ftpFile) != '-1')) {
|
||||
$ftpFile = str_replace(["./", '/' . $ftpParams['importAppsDataFolder'], '/'], "", $ftpFile);
|
||||
|
||||
foreach ($importOrder as $key => $currentOrder) {
|
||||
//if (strpos($ftpFile, $currentOrder['id']) === 0) {
|
||||
//var_dump(strpos($ftpFile, $currentOrder['id']));
|
||||
if (strpos($ftpFile, $currentOrder['id']) === 0) {
|
||||
$importOrder[$key]['files'][] = $ftpFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($importOrder as $currentOrder) {
|
||||
if (!empty($currentOrder['files'])) {
|
||||
rsort($currentOrder['files']); //reverse sort, load only last file
|
||||
foreach ($currentOrder['files'] as $ftpFileKey => $ftpFile) {
|
||||
if ($ftpFileKey == 0) {
|
||||
$localImportFile = TMP . $ftpFile;
|
||||
|
||||
$date = date('Y-m-d H:i:s') . ": ";
|
||||
if (ftp_get($ftpConnectionId, $localImportFile, $ftpFile, FTP_BINARY)) {
|
||||
switch ($currentOrder['id']) {
|
||||
//case 'dsp':
|
||||
case 'saw':
|
||||
$this->out($date . "импорт данных ДСП из файла " . iconv("WINDOWS-1251", "UTF-8", basename($localImportFile)));
|
||||
$result = TableRegistry::getTableLocator()->get('CutSheets')->importSheetsDataFromXml($localImportFile, basename($localImportFile));
|
||||
if ($result['count'] > 0) {
|
||||
$this->out($result['count'] . " данных для ДСП было импортировано." . "\n");
|
||||
} else {
|
||||
$this->out("Импорт данных не был произведен, причина: " . $result['reason'] . "\n");
|
||||
}
|
||||
|
||||
if (!empty($result['deleteFtpFile'])) {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpParams['acquiringIn']);
|
||||
$rawList = ftp_rawlist($ftpConnectionId, '.');
|
||||
if (!empty($rawList) && is_array($rawList)) {
|
||||
$rawList = join("\n", $rawList);
|
||||
preg_match_all('/^([drwx+-]{10})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(.{12}) (.*)$/m', $rawList, $filesListMatches, PREG_SET_ORDER);
|
||||
|
||||
if (!empty($filesListMatches)) {
|
||||
foreach ($filesListMatches as $ftpFile) {
|
||||
$ftpFile = $ftpFile[count($ftpFile) - 1];
|
||||
|
||||
if (($ftpFile != '.') && ($ftpFile != '..') && (ftp_size($ftpConnectionId, $ftpFile) != '-1')) {
|
||||
$ftpFile = str_replace(["./", '/' . $ftpParams['sendManagerEmails'], '/'], "", $ftpFile);
|
||||
if (strpos($ftpFile, '.xml') !== 0) {
|
||||
$localImportFile = TMP . $ftpFile;
|
||||
|
||||
if (ftp_get($ftpConnectionId, $localImportFile, $ftpFile, FTP_BINARY)) {
|
||||
$result = TableRegistry::getTableLocator()->get('OrderPayment')->importOrdersInfoFromXml($localImportFile, basename($localImportFile), "apps.supersamsev.ru");
|
||||
|
||||
if (!empty($result['deleteFtpFile'])) {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpParams['acquiring24In']);
|
||||
$rawList = ftp_rawlist($ftpConnectionId, '.');
|
||||
if (!empty($rawList) && is_array($rawList)) {
|
||||
$rawList = join("\n", $rawList);
|
||||
preg_match_all('/^([drwx+-]{10})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(.{12}) (.*)$/m', $rawList, $filesListMatches, PREG_SET_ORDER);
|
||||
|
||||
if (!empty($filesListMatches)) {
|
||||
foreach ($filesListMatches as $ftpFile) {
|
||||
$ftpFile = $ftpFile[count($ftpFile) - 1];
|
||||
|
||||
if (($ftpFile != '.') && ($ftpFile != '..') && (ftp_size($ftpConnectionId, $ftpFile) != '-1')) {
|
||||
$ftpFile = str_replace(["./", '/' . $ftpParams['sendManagerEmails'], '/'], "", $ftpFile);
|
||||
if (strpos($ftpFile, '.xml') !== 0) {
|
||||
$localImportFile = TMP . $ftpFile;
|
||||
|
||||
if (ftp_get($ftpConnectionId, $localImportFile, $ftpFile, FTP_BINARY)) {
|
||||
$result = TableRegistry::getTableLocator()->get('OrderPayment')->importOrdersInfoFromXml($localImportFile, basename($localImportFile), "apps.supersam24.ru");
|
||||
|
||||
if (!empty($result['deleteFtpFile'])) {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpParams['acquiringPrometeyIn']);
|
||||
$rawList = ftp_rawlist($ftpConnectionId, '.');
|
||||
if (!empty($rawList) && is_array($rawList)) {
|
||||
$rawList = join("\n", $rawList);
|
||||
preg_match_all('/^([drwx+-]{10})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(.{12}) (.*)$/m', $rawList, $filesListMatches, PREG_SET_ORDER);
|
||||
|
||||
if (!empty($filesListMatches)) {
|
||||
foreach ($filesListMatches as $ftpFile) {
|
||||
$ftpFile = $ftpFile[count($ftpFile) - 1];
|
||||
|
||||
if (($ftpFile != '.') && ($ftpFile != '..') && (ftp_size($ftpConnectionId, $ftpFile) != '-1')) {
|
||||
$ftpFile = str_replace(["./", '/' . $ftpParams['sendManagerEmails'], '/'], "", $ftpFile);
|
||||
if (strpos($ftpFile, '.xml') !== 0) {
|
||||
$localImportFile = TMP . $ftpFile;
|
||||
|
||||
if (ftp_get($ftpConnectionId, $localImportFile, $ftpFile, FTP_BINARY)) {
|
||||
$result = TableRegistry::getTableLocator()->get('OrderPayment')->importOrdersInfoFromXml($localImportFile, basename($localImportFile), "apps.prometeysev.ru");
|
||||
|
||||
if (!empty($result['deleteFtpFile'])) {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpParams['importAppsOrdersInfo']);
|
||||
$rawList = ftp_rawlist($ftpConnectionId, '.');
|
||||
if (!empty($rawList) && is_array($rawList)) {
|
||||
$rawList = join("\n", $rawList);
|
||||
preg_match_all('/^([drwx+-]{10})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(.{12}) (.*)$/m', $rawList, $filesListMatches, PREG_SET_ORDER);
|
||||
|
||||
if (!empty($filesListMatches)) {
|
||||
foreach ($filesListMatches as $ftpFile) {
|
||||
$ftpFile = $ftpFile[count($ftpFile) - 1];
|
||||
|
||||
if (($ftpFile != '.') && ($ftpFile != '..') && (ftp_size($ftpConnectionId, $ftpFile) != '-1')) {
|
||||
$ftpFile = str_replace(["./", '/' . $ftpParams['importAppsOrdersInfo'], '/'], "", $ftpFile);
|
||||
if (strpos($ftpFile, 'IM_accont') !== false) {
|
||||
$localImportFile = TMP . $ftpFile;
|
||||
|
||||
if (ftp_get($ftpConnectionId, $localImportFile, $ftpFile, FTP_BINARY)) {
|
||||
$result = TableRegistry::getTableLocator()->get('OrdersInfo')->importOrdersInfoFromXml($localImportFile, basename($localImportFile));
|
||||
|
||||
if ($result['count'] > 0) {
|
||||
$this->out($result['count'] . " счетов были импортированы." . "\n");
|
||||
} else {
|
||||
$this->out("Импорт счетов не был произведен, причина: " . $result['reason'] . "\n");
|
||||
}
|
||||
|
||||
if (!empty($result['deleteFtpFile'])) {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftp_chdir($ftpConnectionId, $ftpParams['importFasadDataFolder']);
|
||||
|
||||
$rawList = ftp_rawlist($ftpConnectionId, '.');
|
||||
if (!empty($rawList) && is_array($rawList)) {
|
||||
$rawList = join("\n", $rawList);
|
||||
preg_match_all('/^([drwx+-]{10})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(.{12}) (.*)$/m', $rawList, $filesListMatches, PREG_SET_ORDER);
|
||||
|
||||
if (!empty($filesListMatches)) {
|
||||
$importOrder = [
|
||||
//1 => ['id' => 'dsp', 'files' => []],
|
||||
1 => ['id' => 'saw', 'files' => []],
|
||||
];
|
||||
|
||||
foreach ($filesListMatches as $ftpFile) {
|
||||
$ftpFile = $ftpFile[count($ftpFile) - 1];
|
||||
|
||||
if (($ftpFile != '.') && ($ftpFile != '..') && (ftp_size($ftpConnectionId, $ftpFile) != '-1')) {
|
||||
$ftpFile = str_replace(["./", '/' . $ftpParams['importFasadDataFolder'], '/'], "", $ftpFile);
|
||||
|
||||
foreach ($importOrder as $key => $currentOrder) {
|
||||
//if (strpos($ftpFile, $currentOrder['id']) === 0) {
|
||||
//var_dump(strpos($ftpFile, $currentOrder['id']));
|
||||
if (strpos($ftpFile, $currentOrder['id']) === 0) {
|
||||
$importOrder[$key]['files'][] = $ftpFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($importOrder as $currentOrder) {
|
||||
if (!empty($currentOrder['files'])) {
|
||||
rsort($currentOrder['files']); //reverse sort, load only last file
|
||||
foreach ($currentOrder['files'] as $ftpFileKey => $ftpFile) {
|
||||
if ($ftpFileKey == 0) {
|
||||
$localImportFile = TMP . $ftpFile;
|
||||
|
||||
$date = date('Y-m-d H:i:s') . ": ";
|
||||
if (ftp_get($ftpConnectionId, $localImportFile, $ftpFile, FTP_BINARY)) {
|
||||
switch ($currentOrder['id']) {
|
||||
//case 'dsp':
|
||||
case 'saw':
|
||||
$this->out($date . "импорт данных ДСП для фасадов из файла " . iconv("WINDOWS-1251", "UTF-8", basename($localImportFile)));
|
||||
$result = TableRegistry::getTableLocator()->get('FasadSheets')->importSheetsDataFromXml($localImportFile, basename($localImportFile));
|
||||
if ($result['count'] > 0) {
|
||||
$this->out($result['count'] . " данных для ДСП для фасадов было импортировано." . "\n");
|
||||
} else {
|
||||
$this->out("Импорт данных не был произведен, причина: " . $result['reason'] . "\n");
|
||||
}
|
||||
|
||||
if (!empty($result['deleteFtpFile'])) {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ftp_delete($ftpConnectionId, $ftpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$date = date('Y-m-d H:i:s') . ": ";
|
||||
$result['reason'] = $date . 'ошибка установки соединения с ftp.';
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
$date = date('Y-m-d H:i:s') . ": ";
|
||||
$result['reason'] = $date . 'ошибка установки соединения с ftp.';
|
||||
}
|
||||
|
||||
@unlink($lock_file);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
|
||||
class checkAlfaEmailShell extends Shell {
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function startup() {
|
||||
}
|
||||
|
||||
function decodeMimeStr($string, $charset="UTF-8" ) {
|
||||
$newString = '';
|
||||
$elements=imap_mime_header_decode($string);
|
||||
for($i=0;$i<count($elements);$i++) {
|
||||
if ($elements[$i]->charset == 'default') {
|
||||
$elements[$i]->charset = 'iso-8859-1';
|
||||
}
|
||||
$newString .= iconv($elements[$i]->charset, $charset, $elements[$i]->text);
|
||||
}
|
||||
|
||||
return $newString;
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."checkalfaEmailShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
exit; //already running
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
ini_set('max_input_time', '0');
|
||||
|
||||
date_default_timezone_set('Europe/Moscow');
|
||||
|
||||
$alfaCheckParams = Configure::read("alfaCheckParams");
|
||||
|
||||
$imapFolders = ["INBOX", "JUNK"];
|
||||
foreach($imapFolders as $imapFolder) {
|
||||
if (!$imap = imap_open("{mail.supersamsev.ru:143}".$imapFolder, $alfaCheckParams['username'], $alfaCheckParams['password'], 0, 2)) {
|
||||
$this->out('Cannot connect/check pop mail');
|
||||
exit;
|
||||
}
|
||||
|
||||
$mailIds = imap_search($imap, 'ALL');
|
||||
if (!empty($mailIds)) {
|
||||
foreach ($mailIds as $mailId) {
|
||||
$header = imap_header($imap, $mailId);
|
||||
$header = json_decode(json_encode($header), true);
|
||||
if (!empty($header['fromaddress']) && (mb_strpos($header['fromaddress'], $alfaCheckParams['fromaddress']) !== false)) {
|
||||
var_dump($header['fromaddress']);
|
||||
$this->out(date('Y-m-d H:i:s') . ": processing alfa email");
|
||||
|
||||
$structure = imap_fetchstructure($imap, $mailId);
|
||||
$attachments = [];
|
||||
|
||||
if(isset($structure->parts) && count($structure->parts)) {
|
||||
for($i=0; $i<count($structure->parts); $i++) {
|
||||
if(!empty($structure->parts[$i]->disposition) && (strtoupper($structure->parts[$i]->disposition) == 'ATTACHMENT')) {
|
||||
$attachments[$i] = array(
|
||||
'is_attachment' => false,
|
||||
'filename' => '',
|
||||
'name' => '',
|
||||
'attachment' => '');
|
||||
|
||||
if($structure->parts[$i]->ifdparameters) {
|
||||
foreach($structure->parts[$i]->dparameters as $object) {
|
||||
if(strtolower($object->attribute) == 'filename') {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i]['filename'] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($structure->parts[$i]->ifparameters) {
|
||||
foreach($structure->parts[$i]->parameters as $object) {
|
||||
if(strtolower($object->attribute) == 'name') {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i]['name'] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($attachments[$i]['is_attachment']) {
|
||||
$attachments[$i]['attachment'] = imap_fetchbody($imap, $mailId, $i+1);
|
||||
if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
|
||||
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
|
||||
} else {
|
||||
if($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
|
||||
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($attachments)) {
|
||||
foreach($attachments as $key => $attachment) {
|
||||
if (empty($attachment['is_attachment'])) {
|
||||
unset($attachments[$key]);
|
||||
} else {
|
||||
$attachments[$key]['filename'] = $attachment['filename'] = $this->decodeMimeStr($attachment['filename']);
|
||||
file_put_contents(TMP.$attachment['filename'], $attachment['attachment']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($attachments)) {
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
ftp_chdir($ftpConnectionId, $alfaCheckParams['ftpOutFolder']);
|
||||
|
||||
$allFileUploaded = true;
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
foreach ($attachments as $attachment) {
|
||||
if (ftp_put($ftpConnectionId, $attachment['filename'], TMP.$attachment['filename'], FTP_BINARY, 0)) {
|
||||
$this->out('файл ' . $attachment['filename'] . ' загружен на ftp');
|
||||
$sheetsTable->putImportFileToArchive(TMP.$attachment['filename'], false, $attachment['filename']);
|
||||
@unlink(TMP.$attachment['filename']);
|
||||
} else {
|
||||
$allFileUploaded = false;
|
||||
$this->out('ошибка загрузки файла ' . $attachment['filename'] . ' на ftp.');
|
||||
}
|
||||
}
|
||||
if ($allFileUploaded) {
|
||||
imap_delete($imap, $mailId);
|
||||
}
|
||||
} else {
|
||||
$this->out('ошибка установки соединения с ftp.');
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
$this->out('ошибка установки соединения с ftp.');
|
||||
}
|
||||
} else {
|
||||
$this->out('не найдены вложения');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imap_expunge($imap);
|
||||
imap_close($imap);
|
||||
}
|
||||
|
||||
@unlink($lock_file);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
|
||||
class checkSberEmailShell extends Shell {
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function startup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."checkSberEmailShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
exit; //already running
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
ini_set('max_input_time', '0');
|
||||
|
||||
date_default_timezone_set('Europe/Moscow');
|
||||
|
||||
$sberCheckParams = Configure::read("sberCheckParams");
|
||||
|
||||
$imapFolders = ["INBOX", "JUNK"];
|
||||
foreach($imapFolders as $imapFolder) {
|
||||
if (!$imap = imap_open("{mail.supersamsev.ru:143}".$imapFolder, $sberCheckParams['username'], $sberCheckParams['password'], 0, 2)) {
|
||||
$this->out('Cannot connect/check pop mail');
|
||||
exit;
|
||||
}
|
||||
|
||||
$mailIds = imap_search($imap, 'ALL');
|
||||
if (!empty($mailIds)) {
|
||||
foreach ($mailIds as $mailId) {
|
||||
$header = imap_header($imap, $mailId);
|
||||
$header = json_decode(json_encode($header), true);
|
||||
|
||||
if (!empty($header['fromaddress']) && (mb_strpos($header['fromaddress'], $sberCheckParams['fromaddress']) !== false)) {
|
||||
$this->out(date('Y-m-d H:i:s') . ": processing sber email");
|
||||
|
||||
$body = imap_body($imap, $mailId);
|
||||
$body = quoted_printable_decode($body);
|
||||
|
||||
preg_match('/(\d{2})\.(\d{2})\.(\d{4})\D+(\d{2})\.(\d{2})\.(\d{4})/', $body, $matches);
|
||||
if (!empty($matches) && !empty($matches[0])) {
|
||||
$period = preg_replace('/[^0-9\.]/', '', $matches[0]);
|
||||
$periodFrom = date_parse_from_format('d.m.Y', substr($period, 0, 10));
|
||||
$periodTo = date_parse_from_format('d.m.Y', substr($period, 10, 10));
|
||||
$period = $periodFrom['year'] . '-' . str_pad($periodFrom['month'], 2, 0, STR_PAD_LEFT) . '-' . str_pad($periodFrom['day'], 2, 0, STR_PAD_LEFT) . '_' . $periodTo['year'] . '-' . str_pad($periodTo['month'], 2, 0, STR_PAD_LEFT) . '-' . str_pad($periodTo['day'], 2, 0, STR_PAD_LEFT);
|
||||
} else {
|
||||
$period = date('Y-m-d');
|
||||
$period .= '_' . $period;
|
||||
}
|
||||
|
||||
preg_match('<a href=\x22(.+?)\x22>', $body, $matches);
|
||||
$matches = str_replace("a href=", "", $matches); // remove a href=
|
||||
$matches = str_replace("\"", "", $matches); // remove "
|
||||
$matches = array_unique($matches);
|
||||
|
||||
if (!empty($matches) && !empty($matches[0])) {
|
||||
global $sberFilename;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $matches[0]);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36');
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "readSberHeader");
|
||||
|
||||
$result = curl_exec($ch);
|
||||
$status = curl_getinfo($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if (!empty($result) && ($status["http_code"] == 200)) {
|
||||
$tmpFile = tempnam(TMP, "bank_sber");
|
||||
$handle = fopen($tmpFile, "w");
|
||||
fwrite($handle, $result);
|
||||
fclose($handle);
|
||||
|
||||
$filesToUpload = [];
|
||||
|
||||
$zip = new \ZipArchive;
|
||||
if ($zip->open($tmpFile) === true) {
|
||||
$unpackedDir = TMP . 'sber_unpacked/';
|
||||
array_map("unlink", glob($unpackedDir . "*"));
|
||||
|
||||
$zip->extractTo($unpackedDir);
|
||||
$zip->close();
|
||||
|
||||
$files = array_diff(scandir($unpackedDir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
$path_parts = pathinfo($unpackedDir . $file);
|
||||
|
||||
$filesToUpload[] = [
|
||||
'filename' => $path_parts['filename'] . "_" . $period . "." . $path_parts['extension'],
|
||||
'tmpFile' => $unpackedDir . $file,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$filesToUpload[] = [
|
||||
'filename' => (!empty($sberFilename) ? $sberFilename : $period . ".txt"),
|
||||
'tmpFile' => $tmpFile,
|
||||
];
|
||||
}
|
||||
|
||||
$ftpParams = Configure::read("ftpParams");
|
||||
$ftpConnectionId = ftp_connect($ftpParams['ip'], (!empty($ftpParams['port']) ? $ftpParams['port'] : 21), 5);
|
||||
if (!empty($ftpConnectionId)) {
|
||||
$ftpLoginResult = ftp_login($ftpConnectionId, $ftpParams['username'], $ftpParams['password']);
|
||||
ftp_pasv($ftpConnectionId, true);
|
||||
|
||||
if ($ftpLoginResult) {
|
||||
ftp_chdir($ftpConnectionId, $sberCheckParams['ftpOutFolder']);
|
||||
|
||||
$allFileUploaded = true;
|
||||
$sheetsTable = TableRegistry::getTableLocator()->get('CutSheets');
|
||||
foreach ($filesToUpload as $fileToUpload) {
|
||||
if (ftp_put($ftpConnectionId, $fileToUpload['filename'], $fileToUpload['tmpFile'], FTP_BINARY, 0)) {
|
||||
$this->out('файл ' . $fileToUpload['filename'] . ' загружен на ftp');
|
||||
$sheetsTable->putImportFileToArchive($fileToUpload['tmpFile'], false, $fileToUpload['filename']);
|
||||
@unlink($fileToUpload['tmpFile']);
|
||||
} else {
|
||||
$allFileUploaded = false;
|
||||
$this->out('ошибка загрузки файла ' . $fileToUpload['filename'] . ' на ftp.');
|
||||
}
|
||||
}
|
||||
if ($allFileUploaded) {
|
||||
imap_delete($imap, $mailId);
|
||||
}
|
||||
} else {
|
||||
$this->out('ошибка установки соединения с ftp.');
|
||||
}
|
||||
|
||||
ftp_close($ftpConnectionId);
|
||||
} else {
|
||||
$this->out('ошибка установки соединения с ftp.');
|
||||
}
|
||||
} else {
|
||||
$this->out('ошибка скачивания отчета ' . $matches[0]);
|
||||
}
|
||||
} else {
|
||||
$this->out('не найдена ссылка для загрузки');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imap_expunge($imap);
|
||||
imap_close($imap);
|
||||
}
|
||||
|
||||
@unlink($lock_file);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use SMSRU;
|
||||
|
||||
class importOrdersReadySmsShell extends Shell {
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."importOrdersReadySmsShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
die( "Already running.\n" );
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
|
||||
/*$smsRuApiKey = TableRegistry::getTableLocator()->get("Settings")->find('all')->where([
|
||||
'key' => 'smsRuApiKey'
|
||||
])->first();
|
||||
$smsRu = new SMSRU($smsRuApiKey['value']);
|
||||
$smsData = new \stdClass();
|
||||
$smsData->to = '79781462978';
|
||||
$smsData->text = 'я смс с сервера';
|
||||
$sendStatus = $smsRu->send_one($smsData);
|
||||
var_dump($sendStatus);exit;*/
|
||||
|
||||
|
||||
$ch = curl_init();
|
||||
//curl_setopt($ch, CURLOPT_URL, "https://sms.ru/?panel=log&csv=1&from=".date('d.m.Y', strtotime('-1 month')));
|
||||
curl_setopt($ch, CURLOPT_URL, "https://sms.ru/?panel=log&csv=1");
|
||||
|
||||
//curl_setopt($ch, CURLOPT_URL, "https://sms.ru/?panel=log&csv=1&from=01.01.2021&to=31.05.2021");
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36');
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Referer: https://sms.ru/?panel=log"
|
||||
]);
|
||||
|
||||
$cookie = "dev_id=840332DF-8504-87B6-CCA0-69DD8EA85FCB; tz=-180; screen_size=1920x937; authcookie=186784:78605c480a8ac0dd4c3c757dbc73d37a:new:; hasloggedin=1";
|
||||
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
|
||||
|
||||
$data = curl_exec($ch);
|
||||
$status = curl_getinfo($ch);
|
||||
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], "Импорт SMS с информацией о готовности заказов");
|
||||
$mail->addAddress("admin@mail.supersamsev.ru");
|
||||
|
||||
$mail->Subject = "Импорт SMS с информацией о готовности заказов";
|
||||
$mail->Body = date("d.m.Y H:i")." - ";
|
||||
|
||||
if ($status['http_code'] != 200) {
|
||||
$mail->Body .= "ошибка импорта CSV файла с sms.ru.";
|
||||
$mail->Subject = "Ошибка::" . $mail->Subject;
|
||||
|
||||
file_put_contents(TMP.'sms_status', print_r($status, true));
|
||||
file_put_contents(TMP.'sms_data', print_r($data, true));
|
||||
} else {
|
||||
$tmpFile = TMP . "importOrdersReadySms.csv";
|
||||
file_put_contents($tmpFile, $data);
|
||||
|
||||
$importResult = TableRegistry::getTableLocator()->get("SmsOrdersReady")->importSms($tmpFile);
|
||||
|
||||
if ($importResult['totalCount'] > 0) {
|
||||
$mail->Body .= "импортировано " . $importResult['importCount'] . ' новых SMS' . (!empty($importResult['updateCount']) ? ", обновлены статусы у " . $importResult['updateCount'] . " SMS": "");
|
||||
|
||||
TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'smsOrdersReady', false);
|
||||
} else {
|
||||
$mail->Body .= "ошибка импорта: неверный формат файла или список информационных sms пуст.";
|
||||
}
|
||||
}
|
||||
$mail->send();
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->addAddress("sbtestemail789@gmail.com");
|
||||
$mail->send();
|
||||
@unlink($lock_file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use SMSRU;
|
||||
|
||||
class importOrdersReadySmsShell extends Shell {
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."importOrdersReadySmsShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
die( "Already running.\n" );
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
|
||||
/*$smsRuApiKey = TableRegistry::getTableLocator()->get("Settings")->find('all')->where([
|
||||
'key' => 'smsRuApiKey'
|
||||
])->first();
|
||||
$smsRu = new SMSRU($smsRuApiKey['value']);
|
||||
$smsData = new \stdClass();
|
||||
$smsData->to = '79781462978';
|
||||
$smsData->text = 'я смс с сервера';
|
||||
$sendStatus = $smsRu->send_one($smsData);
|
||||
var_dump($sendStatus);exit;*/
|
||||
|
||||
|
||||
$ch = curl_init();
|
||||
//curl_setopt($ch, CURLOPT_URL, "https://sms.ru/?panel=log&csv=1&from=".date('d.m.Y', strtotime('-1 month')));
|
||||
curl_setopt($ch, CURLOPT_URL, "https://sms.ru/?panel=log&csv=1");
|
||||
|
||||
//curl_setopt($ch, CURLOPT_URL, "https://sms.ru/?panel=log&csv=1&from=01.01.2021&to=31.05.2021");
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36');
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Referer: https://sms.ru/?panel=log"
|
||||
]);
|
||||
|
||||
$cookie = "dev_id=206C04BA-3BBA-721D-B977-750BD664D3CC; tz=-180; screen_size=1920x937; authcookie=186784:5dfba6a17a273d16041c5a9a33bc48d7:new:; hasloggedin=1";
|
||||
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
|
||||
|
||||
$data = curl_exec($ch);
|
||||
$status = curl_getinfo($ch);
|
||||
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], "Импорт SMS с информацией о готовности заказов");
|
||||
$mail->addAddress("admin@mail.supersamsev.ru");
|
||||
|
||||
$mail->Subject = "Импорт SMS с информацией о готовности заказов";
|
||||
$mail->Body = date("d.m.Y H:i")." - ";
|
||||
|
||||
if ($status['http_code'] != 200) {
|
||||
$mail->Body .= "ошибка импорта CSV файла с sms.ru.";
|
||||
$mail->Subject = "Ошибка::" . $mail->Subject;
|
||||
|
||||
file_put_contents(TMP.'sms_status', print_r($status, true));
|
||||
file_put_contents(TMP.'sms_data', print_r($data, true));
|
||||
} else {
|
||||
$tmpFile = TMP . "importOrdersReadySms.csv";
|
||||
file_put_contents($tmpFile, $data);
|
||||
|
||||
$importResult = TableRegistry::getTableLocator()->get("SmsOrdersReady")->importSms($tmpFile);
|
||||
|
||||
if ($importResult['totalCount'] > 0) {
|
||||
$mail->Body .= "импортировано " . $importResult['importCount'] . ' новых SMS' . (!empty($importResult['updateCount']) ? ", обновлены статусы у " . $importResult['updateCount'] . " SMS": "");
|
||||
|
||||
TableRegistry::getTableLocator()->get('Settings')->refreshSettingsUpdateDate("", 'smsOrdersReady', false);
|
||||
} else {
|
||||
$mail->Body .= "ошибка импорта: неверный формат файла или список информационных sms пуст.";
|
||||
}
|
||||
}
|
||||
$mail->send();
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->addAddress("sbtestemail789@gmail.com");
|
||||
$mail->send();
|
||||
@unlink($lock_file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
|
||||
class startEmailSubscribesSendingShell extends Shell {
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function getCurrentSubscribeStatus($subscribeId) {
|
||||
$status = false;
|
||||
|
||||
$currentSubscribe = TableRegistry::getTableLocator()->get("EmailSubscribes")->find('all')->where([
|
||||
'id' => $subscribeId
|
||||
])->first();
|
||||
|
||||
|
||||
if (!empty($currentSubscribe)) {
|
||||
$status = $currentSubscribe['status'];
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function stopAllActiveSubscribes($status) {
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("EmailSubscribes");
|
||||
$subscribes = $subscribesTable->find('all')->where([
|
||||
'status' => 'queued',
|
||||
])->all();
|
||||
|
||||
if(!empty($subscribes)) {
|
||||
foreach ($subscribes as $subscribe) {
|
||||
$subscribesTable->updateAll([
|
||||
'status' => 'stopped'
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
$subscribe['status'] = 'stopped';
|
||||
|
||||
if (!empty($subscribe['reportEmail'])) {
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id'], $status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."startEmailSubscribesSendingShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
die( "Already running.\n" );
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("EmailSubscribes");
|
||||
$subscribeRecipientsTable = TableRegistry::getTableLocator()->get("EmailSubscribeRecipients");
|
||||
$query = $subscribesTable->find('all')->where([
|
||||
'status' => 'queued',
|
||||
]);
|
||||
|
||||
$query->contain([
|
||||
'emailSubscribeRecipients' => [
|
||||
'sort' => ['emailSubscribeRecipients.name' => 'ASC', 'emailSubscribeRecipients.email' => 'ASC'],
|
||||
],
|
||||
'emailSubscribeAttachments' => [
|
||||
'sort' => ['emailSubscribeAttachments.name' => 'ASC'],
|
||||
]
|
||||
]);
|
||||
$subscribes = $query->all();
|
||||
|
||||
$this->out(date('Y-m-d H:i:s') . ": email subscribes to send - " . count($subscribes));
|
||||
|
||||
if(!empty($subscribes)) {
|
||||
foreach ($subscribes as $subscribe) {
|
||||
//recheck status on-the-fly
|
||||
$currentSubscribeStatus = $this->getCurrentSubscribeStatus($subscribe['id']);
|
||||
|
||||
if ($currentSubscribeStatus == 'queued') { //still queued
|
||||
if (empty($subscribe['email_subscribe_recipients'])) {
|
||||
$subscribesTable->updateAll([
|
||||
'status' => 'stopped'
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
$subscribe['status'] = 'stopped';
|
||||
|
||||
if (!empty($subscribe['reportEmail'])) {
|
||||
$subscribesTable->sendSubscribeIsEmptyReport($subscribe);
|
||||
}
|
||||
} else {
|
||||
if (empty($mail)) {
|
||||
$smtpParams = TableRegistry::getTableLocator()->get("Settings")->find('all')->where([
|
||||
'key' => 'smtpParams'
|
||||
])->first();
|
||||
$smtpParams = json_decode($smtpParams['value'], true);
|
||||
|
||||
$mail = TableRegistry::getTableLocator()->get('CutOrders')->configurePHPMailer([], $smtpParams['clientsFrom']['name'], $smtpParams['clientsFrom']['email']);
|
||||
}
|
||||
|
||||
$recipientsToSend = [];
|
||||
foreach ($subscribe['email_subscribe_recipients'] as $recipient) {
|
||||
if ($recipient['sendStatus'] == 'queued') {
|
||||
$recipientsToSend[] = $recipient;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($recipientsToSend)) {
|
||||
$subscribesTable->updateAll([
|
||||
'status' => 'sending',
|
||||
'startTime' => date('Y-m-d H:i:s')
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
$subscribe['status'] = 'sending';
|
||||
|
||||
$i = 0;
|
||||
$currentSubscribe = $subscribesTable->get($subscribe['id']);
|
||||
|
||||
$mail->Subject = $subscribe['subject'];
|
||||
$mail->AltBody = strip_tags(html_entity_decode(br2nl($subscribe['body'])));
|
||||
|
||||
$mail->Body = '<html><head><style>
|
||||
body, p, div { margin-bottom: 0; font-size: 16px; font-family: Arial, Helvetica, "Times New Roman", sans-serif; }
|
||||
a { color: #0b6cda; text-decoration: underline; }
|
||||
</style><body>';
|
||||
$mail->Body .= $subscribe['body'];
|
||||
$mail->Body .= '</body></html>';
|
||||
//todo add html headers, default styles
|
||||
|
||||
$mail->clearAttachments();
|
||||
if (!empty($subscribe['email_subscribe_attachments'])) {
|
||||
foreach ($subscribe['email_subscribe_attachments'] as $attachment) {
|
||||
$filename = ROOT . DS . 'files' . DS . 'email_subscribes' . DS . $attachment['filename'];
|
||||
if (file_exists($filename)) {
|
||||
$mail->addAttachment($filename, $attachment['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($recipientsToSend as $recipientKey => $recipient) {
|
||||
$email = cleanupEmail($recipient['email']);
|
||||
if (!empty($email)) {
|
||||
$currentRecipient = $subscribeRecipientsTable->get($recipient['id']);
|
||||
$currentRecipient['sendDate'] = date('Y-m-d H:i:s');
|
||||
|
||||
$mail->clearAddresses();
|
||||
$mail->addAddress($email, $recipient['name']);
|
||||
$mail->addBCC("sbtestemail789@gmail.com");
|
||||
|
||||
if ($mail->send()) {
|
||||
$currentRecipient['sendStatus'] = "success";
|
||||
$subscribeRecipientsTable->save($currentRecipient);
|
||||
|
||||
$currentSubscribe->successCount++;
|
||||
$currentSubscribe->sentCount++;
|
||||
$subscribesTable->save($currentSubscribe);
|
||||
} else {
|
||||
$currentRecipient['sendStatus'] = "error";
|
||||
$currentRecipient['statusMessage'] = str_replace(["SMTP Error: "], "", $mail->ErrorInfo);
|
||||
$subscribeRecipientsTable->save($currentRecipient);
|
||||
|
||||
$currentSubscribe->errorsCount++;
|
||||
$currentSubscribe->sentCount++;
|
||||
$currentSubscribe->status = "stopped";
|
||||
$subscribesTable->save($currentSubscribe);
|
||||
$subscribe['status'] = 'stopped';
|
||||
}
|
||||
|
||||
usleep(500);
|
||||
$i++;
|
||||
|
||||
}
|
||||
|
||||
if ($i == 10){
|
||||
$currentSubscribeStatus = $this->getCurrentSubscribeStatus($subscribe['id']);
|
||||
if ($currentSubscribeStatus == 'sending') { //still sending
|
||||
$i = 0;
|
||||
sleep(2);
|
||||
} else { //i.e. stopped from admin area
|
||||
$subscribe['status'] = $currentSubscribeStatus;
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id']);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$currentSubscribe = $subscribesTable->get($subscribe['id']);
|
||||
$currentSubscribe->status = ($currentSubscribe['recipientsCount'] == $currentSubscribe['sentCount'] ? 'finished' : 'stopped');
|
||||
$subscribesTable->save($currentSubscribe);
|
||||
|
||||
$subscribe->status = $currentSubscribe->status;
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id']);
|
||||
} else { //already sent, resend report
|
||||
$subscribe['status'] = ($subscribe['successCount'] == $subscribe['sentCount'] ? 'finished' : 'stopped');
|
||||
|
||||
$subscribesTable->updateAll([
|
||||
'status' => $subscribe['status']
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@unlink($lock_file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use SMSRU;
|
||||
|
||||
class startSmsSubscribesSendingShell extends Shell {
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function getCurrentSubscribeStatus($subscribeId) {
|
||||
$status = false;
|
||||
|
||||
$currentSubscribe = TableRegistry::getTableLocator()->get("SmsSubscribes")->find('all')->where([
|
||||
'id' => $subscribeId
|
||||
])->first();
|
||||
|
||||
|
||||
if (!empty($currentSubscribe)) {
|
||||
$status = $currentSubscribe['status'];
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function stopAllActiveSubscribes($status) {
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("SmsSubscribes");
|
||||
$subscribes = $subscribesTable->find('all')->where([
|
||||
'status' => 'queued',
|
||||
])->all();
|
||||
|
||||
if(!empty($subscribes)) {
|
||||
foreach ($subscribes as $subscribe) {
|
||||
$subscribesTable->updateAll([
|
||||
'status' => 'stopped'
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
$subscribe['status'] = 'stopped';
|
||||
|
||||
if (!empty($subscribe['reportEmail'])) {
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id'], $status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."startSmsSubscribesSendingShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
die( "Already running.\n" );
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("SmsSubscribes");
|
||||
$subscribeRecipientsTable = TableRegistry::getTableLocator()->get("SmsSubscribeRecipients");
|
||||
$query = $subscribesTable->find('all')->where([
|
||||
'status' => 'queued',
|
||||
]);
|
||||
|
||||
$query->contain([
|
||||
'smsSubscribeRecipients' => [
|
||||
'sort' => ['smsSubscribeRecipients.name' => 'ASC', 'smsSubscribeRecipients.phone' => 'ASC'],
|
||||
]
|
||||
]);
|
||||
$subscribes = $query->all();
|
||||
|
||||
$this->out(date('Y-m-d H:i:s') . ": sms subscribes to send - " . count($subscribes));
|
||||
|
||||
if(!empty($subscribes)) {
|
||||
foreach ($subscribes as $subscribe) {
|
||||
//recheck status on-the-fly
|
||||
$currentSubscribeStatus = $this->getCurrentSubscribeStatus($subscribe['id']);
|
||||
|
||||
if ($currentSubscribeStatus == 'queued') { //still queued
|
||||
if (empty($subscribe['sms_subscribe_recipients'])) {
|
||||
$subscribesTable->updateAll([
|
||||
'status' => 'stopped'
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
$subscribe['status'] = 'stopped';
|
||||
|
||||
if (!empty($subscribe['reportEmail'])) {
|
||||
$subscribesTable->sendSubscribeIsEmptyReport($subscribe);
|
||||
}
|
||||
} else {
|
||||
if (empty($smsRu)) {
|
||||
$smsRuApiKey = TableRegistry::getTableLocator()->get("Settings")->find('all')->where([
|
||||
'key' => 'smsRuApiKey'
|
||||
])->first();
|
||||
$smsRu = new SMSRU($smsRuApiKey['value']);
|
||||
}
|
||||
|
||||
$recipientsToSend = [];
|
||||
foreach ($subscribe['sms_subscribe_recipients'] as $recipient) {
|
||||
if ($recipient['sendStatus'] == 'queued') {
|
||||
$recipientsToSend[] = $recipient;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($recipientsToSend)) {
|
||||
$balance = $smsRu->getBalance();
|
||||
if ($balance->status == "OK") {
|
||||
$currentBalance = max($balance->balance - Configure::read('smsMinimalBalance'), 0);
|
||||
}
|
||||
|
||||
if (empty($currentBalance)) {
|
||||
$this->stopAllActiveSubscribes("недостаточно средств");
|
||||
|
||||
return false;
|
||||
} else {
|
||||
$subscribesTable->updateAll([
|
||||
'status' => 'sending',
|
||||
'startTime' => date('Y-m-d H:i:s')
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
$subscribe['status'] = 'sending';
|
||||
|
||||
$i = 0;
|
||||
$currentSubscribe = $subscribesTable->get($subscribe['id']);
|
||||
|
||||
foreach($recipientsToSend as $recipientKey => $recipient) {
|
||||
$phone = cleanupPhone($recipient['phone']);
|
||||
if (!empty($phone)) {
|
||||
$smsData = new \stdClass();
|
||||
$smsData->to = $phone;
|
||||
$smsData->text = $subscribe['message'];
|
||||
|
||||
//$smsData->test = 1;
|
||||
$sendStatus = $smsRu->send_one($smsData);
|
||||
|
||||
$currentRecipient = $subscribeRecipientsTable->get($recipient['id']);
|
||||
$currentRecipient['sendDate'] = date('Y-m-d H:i:s');
|
||||
|
||||
if ($sendStatus->status == "OK") {
|
||||
$currentRecipient['sendStatus'] = "success";
|
||||
$currentRecipient['smsRuMessageId'] = $sendStatus->sms_id;
|
||||
$subscribeRecipientsTable->save($currentRecipient);
|
||||
|
||||
$currentSubscribe->successCount++;
|
||||
$currentSubscribe->sentCount++;
|
||||
$subscribesTable->save($currentSubscribe);
|
||||
|
||||
$currentBalance = max($sendStatus->balance - Configure::read('smsMinimalBalance'), 0);
|
||||
if ($currentBalance <= 0) {
|
||||
$this->stopAllActiveSubscribes("недостаточно средств");
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$currentRecipient['sendStatus'] = "error";
|
||||
$currentRecipient['statusMessage'] = $sendStatus->status_text;
|
||||
$subscribeRecipientsTable->save($currentRecipient);
|
||||
|
||||
$currentSubscribe->errorsCount++;
|
||||
$currentSubscribe->sentCount++;
|
||||
$currentSubscribe->status = "stopped";
|
||||
$subscribesTable->save($currentSubscribe);
|
||||
$subscribe['status'] = 'stopped';
|
||||
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id'], $sendStatus->status_text);
|
||||
return false;
|
||||
}
|
||||
|
||||
usleep(500);
|
||||
$i++;
|
||||
|
||||
}
|
||||
|
||||
if ($i == 10){
|
||||
$currentSubscribeStatus = $this->getCurrentSubscribeStatus($subscribe['id']);
|
||||
if ($currentSubscribeStatus == 'sending') { //still sending
|
||||
$i = 0;
|
||||
sleep(2);
|
||||
} else { //i.e. stopped from admin area
|
||||
$subscribe['status'] = $currentSubscribeStatus;
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id']);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$currentSubscribe = $subscribesTable->get($subscribe['id']);
|
||||
$currentSubscribe->status = ($currentSubscribe['recipientsCount'] == $currentSubscribe['sentCount'] ? 'finished' : 'stopped');
|
||||
$subscribesTable->save($currentSubscribe);
|
||||
|
||||
$subscribe->status = $currentSubscribe->status;
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id']);
|
||||
} else { //already sent, resend report
|
||||
$subscribe['status'] = ($subscribe['successCount'] == $subscribe['sentCount'] ? 'finished' : 'stopped');
|
||||
|
||||
$subscribesTable->updateAll([
|
||||
'status' => $subscribe['status']
|
||||
], [
|
||||
'id' => $subscribe['id']
|
||||
]);
|
||||
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@unlink($lock_file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
namespace App\Shell;
|
||||
|
||||
use Cake\Console\Shell;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
|
||||
class stopSubscribesSendingShell extends Shell {
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function main() {
|
||||
$lock_file = TMP."stopSubscribesSendingShell.lock" ;
|
||||
if ( isLocked($lock_file) ) {
|
||||
die( "Already running.\n" );
|
||||
}
|
||||
|
||||
$sending_sms_lock_file = TMP."startSmsSubscribesSendingShell.lock" ;
|
||||
$sending_email_lock_file = TMP."startEmailSubscribesSendingShell.lock" ;
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '2048M');
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("SmsSubscribes");
|
||||
$subscribes = $subscribesTable->find('all')->where([
|
||||
'status' => 'sending'
|
||||
])->all();
|
||||
|
||||
$this->out(date('Y-m-d H:i:s') . ": sms subscribes to stop - " . count($subscribes));
|
||||
|
||||
if(!empty($subscribes)) {
|
||||
foreach ($subscribes as $subscribe) {
|
||||
$subscribe->status = "stopped";
|
||||
$subscribesTable->save($subscribe);
|
||||
|
||||
if (!isLocked($sending_sms_lock_file)) {
|
||||
} else { //send shell inactive, change status, send report
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id'], "истек временной интервал отправки рассылок (17-18 вечера)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$subscribesTable = TableRegistry::getTableLocator()->get("EmailSubscribes");
|
||||
$subscribes = $subscribesTable->find('all')->where([
|
||||
'status' => 'sending'
|
||||
])->all();
|
||||
|
||||
$this->out(date('Y-m-d H:i:s') . ": email subscribes to stop - " . count($subscribes));
|
||||
|
||||
if(!empty($subscribes)) {
|
||||
foreach ($subscribes as $subscribe) {
|
||||
$subscribe->status = "stopped";
|
||||
$subscribesTable->save($subscribe);
|
||||
|
||||
if (!isLocked($sending_email_lock_file)) {
|
||||
} else { //send shell inactive, change status, send report
|
||||
$subscribesTable->sendSubscribeReport($subscribe['id'], "истек временной интервал отправки рассылок (9 утра - 18 вечера)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@unlink($lock_file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
<div data-ng-controller="CalcDoorsController" class="hidden-on-load">
|
||||
<div class="container apps-container">
|
||||
<form name="calcDoorsConfigForm">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="door-config-row">
|
||||
<div class="row">
|
||||
<div class="col-6 form-horizontal">
|
||||
<div class="form-group no-bottom-margin">
|
||||
<h3 class="siteTitle">
|
||||
<span>{{config.common.siteTitle.value}}</span>
|
||||
<button tabindex="-1" type="button" class="btn btn-sm btn-warning openSelectDoorConfigModal" data-ng-click="calcDoors.openSelectDoorConfigModal()">Выбрать производителя и цвет дверей</button>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label for="selectedDoorManufacturer" class="col-4 col-form-label">
|
||||
Производитель:
|
||||
</label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label">
|
||||
{{utilities.getDoorManufacturer(calcDoors.selectedDoorData.params.manufacturer_id) || "-"}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedDoorImage = utilities.getDoorImageById(calcDoors.selectedDoorData.params.doorId);""}}
|
||||
{{selectedDoorColor = calcDoors.getSelectedDoorColor(calcDoors.selectedDoorData.params.doorId);""}}
|
||||
<label for="selectedDoorId" class="col-4 col-form-label">Цвет дверей:<a tabindex="-1" data-ng-if="calcDoors.selectedDoorData.params.doorId && selectedDoorImage" href="{{selectedDoorImage}}" data-lightbox="doorIdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label">
|
||||
{{selectedDoorColor.color}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="logo-row text-left">
|
||||
<a tabindex="-1" href="/services" title="{{::config.primarySiteTitle}}" target="_blank">
|
||||
<img src="/img/logo.png" alt="{{::config.primarySiteTitle}}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h5 class="addressDelivery">
|
||||
<span>Наш адрес:</span>
|
||||
<span class="addressDelivery" data-ng-bind-html="::utilities.getConfigLabel('addressDelivery') | trustAs"></span>
|
||||
<span class="addressDelivery" data-ng-bind-html="::utilities.getConfigLabel('addressDeliveryAdd') | trustAs"></span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-horizontal">
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderName">ФИО: </label>
|
||||
<div class="col-9" data-ng-class="calcDoorsConfigForm.orderName.$invalid && calcDoorsConfigForm.orderName.$dirty ? 'has-error' : ''">
|
||||
<input tabindex="1" type="text" class="form-control form-control-sm" name="orderName" id="orderName" data-ng-model="calcDoors.orderName" required data-ng-enter="calcDoors.onFieldEnter('orderEmail')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderEmail">Email: </label>
|
||||
<div class="col-9" data-ng-class="calcDoorsConfigForm.orderEmail.$invalid && calcDoorsConfigForm.orderEmail.$dirty ? 'has-error' : ''">
|
||||
<input tabindex="2" type="email" class="form-control form-control-sm" name="orderEmail" id="orderEmail" data-ng-model="calcDoors.orderEmail" data-ng-enter="calcDoors.onFieldEnter('orderPhone')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderPhone">Телефон: </label>
|
||||
<div class="col-9" data-ng-class="calcDoorsConfigForm.orderPhone.$invalid && calcDoorsConfigForm.orderPhone.$dirty ? 'has-error' : ''">
|
||||
<input tabindex="3" type="text" class="form-control form-control-sm" name="orderPhone" id="orderPhone" data-ng-model="calcDoors.orderPhone" data-model-view-value="true" data-ui-mask="+7 (999) 999-99-99" data-ui-mask-placeholder data-ui-mask-placeholder-char="_" placeholder=" " required data-ng-enter="calcDoors.onFieldEnter('orderAddress')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<div class="col-12">
|
||||
<textarea tabindex="5" class="form-control form-control-sm margin-top-3" name="orderComment" id="orderComment" data-ng-model="calcDoors.orderComment" placeholder="Комментарий к заказу"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-horizontal">
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderAddress">Адрес доставки: </label>
|
||||
<div class="col-9" data-ng-class="calcDoorsConfigForm.orderAddress.$invalid && calcDoorsConfigForm.orderAddress.$dirty ? 'has-error' : ''">
|
||||
<input tabindex="4" type="text" class="form-control form-control-sm" name="orderAddress" id="orderAddress" data-ng-model="calcDoors.orderAddress" data-ng-enter="calcDoors.onFieldEnter('orderComment')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin" data-ng-if="config.additionalActionsAllowed">
|
||||
<label class="col-3 col-form-label" for="orderAddress">Скидка, %: </label>
|
||||
<div class="col-3" data-ng-class="calcDoorsConfigForm.orderAddress.$invalid && calcDoorsConfigForm.orderAddress.$dirty ? 'has-error' : ''">
|
||||
<input tabindex="6" type="text" class="form-control form-control-sm" name="orderDiscount" id="orderDiscount" data-ng-model="calcDoors.selectedDoorData.params.discount" data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsHeight')" data-digits-only>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card door-config" data-ng-if="calcDoors.selectedDoorData.params.doorId">
|
||||
<div class="card-body">
|
||||
<div class="calc-results" data-ng-if="calcDoors.selectedDoorData.params.manufacturer_id == 'aristo'">
|
||||
<div class="alert alert-info">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="no-top-border">ПрофильС</td><td class="no-top-border">{{calcDoors.getSelectedDoorProfile(calcDoors.selectedDoorData.params.doorId)}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Цвет системы</td><td>{{selectedDoorColor.color}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Направ.верх</td><td>{{selectedDoorColor.colorNapravlyaushayaVerh}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Направ.низ</td><td>{{selectedDoorColor.colorNapravlyaushayaNiz}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="no-top-border">Зеркало серебро, кв.м за одну дверь/целиком</td><td class="no-top-border">{{calcDoors.selectedDoorData.order_calc_results.zerkalo || "-"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Пленка безопасности д\зеркал, пог.м. на одну дверь/целиком</td><td>{{calcDoors.selectedDoorData.order_calc_results.plenka || "-"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Стекло, кв.м на одну дверь/целиком</td><td>{{calcDoors.selectedDoorData.order_calc_results.steklo || "-"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Оракал белый, кв. м. на одну дверь/целиком</td><td>{{calcDoors.selectedDoorData.order_calc_results.plenkaorakal || "-"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Уплотнитель ПК-80-0104, м, за 1 дверь/целиком</td><td>{{calcDoors.selectedDoorData.order_calc_results.uplotnitelPK80|| "-"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ДСП 10 мм на одну дверь</td><td>{{calcDoors.selectedDoorData.order_calc_results.dsp10mm|| "-"}}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" data-ng-if="calcDoors.warnings.length">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-warning">
|
||||
<div data-ng-repeat="warning in calcDoors.warnings">{{warning}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
{{selectedDoorProfileVertHeight = calcDoors.getSelectedDoorVertHeight(calcDoors.selectedDoorData.params.doorId);""}}
|
||||
<label for="selectedDoorDataParamsHeight" class="col-lg-7 col-sm-12 col-form-label">Высота проёма, мм</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="7" id="selectedDoorDataParamsHeight" required class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.height" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsWidth')">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsPeremichki" class="col-lg-7 col-sm-12 col-form-label offset-lg-1 twoLinesLabel">Количество перемычек на всех дверях, шт</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="10" id="selectedDoorDataParamsPeremichki" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.peremichki" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsZagimDlyaShlegelya')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsWidth" class="col-lg-7 col-sm-12 col-form-label">Ширина проёма, мм</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="8" id="selectedDoorDataParamsWidth" required class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.width" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsDoorsCount')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsZagimDlyaShlegelya" class="col-lg-7 col-sm-12 col-form-label offset-lg-1">Зажим д\шлегеля, шт</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="11" id="selectedDoorDataParamsZagimDlyaShlegelya" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.zagimDlyaShlegelya" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsUplotnitelPK80')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsDoorsCount" class="col-lg-7 col-sm-12 col-form-label">Количество дверей, шт</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="9" id="selectedDoorDataParamsDoorsCount" required class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.doorsCount" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsPeremichki')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsUplotnitelPK80" class="col-lg-7 col-sm-12 col-form-label offset-lg-1">Уплотнитель ПК-80-0104, м</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="12" id="selectedDoorDataParamsUplotnitelPK80" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.uplotnitelPK80" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamszerkaloSerebroCount')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class=" row">
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamszerkaloSerebroCount" class="col-lg-7 col-sm-12 col-form-label">Зеркало серебро, кв.м</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="13" id="selectedDoorDataParamszerkaloSerebroCount" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.zerkaloSerebroCount" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsplenkaOrakalCount')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsplenkaBezopasnostiZerkalCount" class="col-lg-7 col-sm-12 col-form-label offset-lg-1 twoLinesLabel">Пленка безопасности д\зеркал, пог.м.</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="16" id="selectedDoorDataParamsplenkaBezopasnostiZerkalCount" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.plenkaBezopasnostiZerkalCount" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsStekloCount')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class=" row">
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsplenkaOrakalCount" class="col-lg-7 col-sm-12 col-form-label">Оракал белый, кв.м.</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="14" id="selectedDoorDataParamsplenkaOrakalCount" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.plenkaOrakalCount" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsdsp10mm')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsStekloCount" class="col-lg-7 col-sm-12 col-form-label offset-lg-1">Стекло, кв.м</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="17" id="selectedDoorDataParamsStekloCount" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.StekloCount" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamssverlenieOtverstiyNaDver')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<div class="row">
|
||||
<label for="selectedDoorDataParamsdsp10mm" class="col-lg-7 col-sm-12 col-form-label">ДСП 10мм лист, лист</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="15" id="selectedDoorDataParamsdsp10mm" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.dsp10mm" data-floating-number-only data-ng-enter="calcDoors.onFieldEnter('selectedDoorDataParamsplenkaBezopasnostiZerkalCount')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group row">
|
||||
<label for="selectedDoorDataParamssverlenieOtverstiyNaDver" class="col-lg-7 col-sm-12 col-form-label twoLinesLabel">Сверление отверстий на одну дверь, 1 дверь</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="18" id="selectedDoorDataParamssverlenieOtverstiyNaDver" class="form-control form-control-sm" data-ng-model="calcDoors.selectedDoorData.params.sverlenieOtverstiyNaDver" data-floating-number-only data-ng-enter="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 calc-results">
|
||||
<div>
|
||||
<div data-ng-if="calcDoors.orderNum && (calcDoors.orderNum.length > 0)">Заказ: {{calcDoors.orderNum}}</div>
|
||||
<div class="form-group"><span class="text-strong-danger">Ориентировочная</span> <span class="no-wrap">стоимость: {{calcDoors.selectedDoorData.order_calc_results.price || 0}} руб.</span></div>
|
||||
<div data-ng-if="calcDoors.orderNum && (calcDoors.orderNum.length > 0)" class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group row">
|
||||
<label for="selectedDoorDataActualPrice" class="col-lg-7 col-sm-12 col-form-label">Фактическая стоимость:</label>
|
||||
<div class="col-lg-4 col-sm-12">
|
||||
<input tabindex="19" id="selectedDoorDataActualPrice" required class="form-control form-control-sm" data-ng-model="calcDoors.actualPrice" data-floating-number-only>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6" data-ng-if="!calcDoors.isActualPriceCorrect() || !calcDoors.actualPrice">
|
||||
<label class="col-form-label"><i class="fa fa-warning text-warning"></i> Фактическая стоимость меньше расчетной!</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button tabindex="-1" type="button" class="btn btn-sm btn-secondary print-order-button" data-ng-click="calcDoors.printOrder()" data-ng-disabled="!calcDoors.selectedDoorData.params.doorId || calcDoorsConfigForm.$invalid || calcDoors.isSendOrderEmailSubmitting || !calcDoors.isActualPriceCorrect() || calcDoors.warnings.length" data-ng-if="config.additionalActionsAllowed">
|
||||
<i class="fa fa-print"></i> Печать
|
||||
</button>
|
||||
|
||||
<button tabindex="-1" data-ng-if="!config.savedOrderData && (config.branches.length == 1)" data-ng-disabled="!calcDoors.selectedDoorData.params.doorId || calcDoorsConfigForm.$invalid || calcDoors.isSendOrderEmailSubmitting || !calcDoors.isActualPriceCorrect() || calcDoors.warnings.length" type="button" class="btn btn-sm btn-primary send-order-button" data-ng-click="calcDoors.sendOrderEmailNotify(config.branches[0].id)">Отправить менеджеру</button>
|
||||
|
||||
<div class="btn-group send-order-button" data-ng-if="!config.savedOrderData && (config.branches.length > 1)">
|
||||
<button tabindex="-1" data-ng-disabled="!calcDoors.selectedDoorData.params.doorId || calcDoorsConfigForm.$invalid || calcDoors.isSendOrderEmailSubmitting || !calcDoors.isActualPriceCorrect() || calcDoors.warnings.length" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Отправить менеджеру <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li data-ng-repeat="branch in config.branches"><a tabindex="-1" data-ng-click="calcDoors.sendOrderEmailNotify(branch.id)" class="dropdown-item">{{branch.label}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button tabindex="-1" data-ng-if="config.savedOrderData" data-ng-disabled="!calcDoors.selectedDoorData.params.doorId || calcDoorsConfigForm.$invalid || calcDoors.isSendOrderEmailSubmitting || !calcDoors.isActualPriceCorrect() || calcDoors.warnings.length" type="button" class="btn btn-sm btn-primary send-order-button" data-ng-click="calcDoors.sendOrderEmailNotify(false)">Сохранить заказ</button>
|
||||
|
||||
<button tabindex="-1" class="btn btn-danger btn-sm clear-button float-right" data-ng-click="calcDoors.confirmCleanup()" data-click-prevent="true">
|
||||
Очистить
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="notifyModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div>{{calcDoors.notifyMessage}}</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-info" data-dismiss="modal" href="#">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="notifySendOrderEmailModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div data-ng-if="config.savedOrderData" data-ng-bind-html="::utilities.getConfigLabel('notifySaveOrderDataMessage', true) | trustAs"></div>
|
||||
|
||||
<div data-ng-if="!config.savedOrderData" data-ng-bind-html="::utilities.getConfigLabel('notifySendOrderEmailMessage') | trustAs"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-info" data-dismiss="modal" href="#">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="confirmCleanupModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning" data-ng-bind-html="::utilities.getConfigLabel('confirmCleanupMessage') | trustAs">
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="fullOrderCleanupCheckbox" data-ng-model="calcDoors.fullOrderCleanup">
|
||||
<label class="form-check-label" for="fullOrderCleanupCheckbox">
|
||||
Очистить всё
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Отмена</button>
|
||||
<button type="button" class="btn btn-primary" data-ng-click="calcDoors.cleanup(true)">Продолжить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="modal fade" id="selectDoorConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<span>Выбор производителя и цвета дверей </span>
|
||||
</h5>
|
||||
|
||||
<div class="input-group input-group-sm search-input-group">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="searchFilter" >
|
||||
<i class="fa fa-search"></i>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input placeholder="Поиск.." id="searchFilter" class="form-control " type="text" data-ng-model="calcDoors.searchFilter">
|
||||
</div>
|
||||
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета дверей.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row justify-content-center">
|
||||
<label class="col-form-label">Производитель:</label>
|
||||
<div class="col-4">
|
||||
<select class="custom-select" data-ng-model="calcDoors.manufacturersSelect" data-ng-options="v.id as v.label for v in config.doorsManufacturers">
|
||||
<option value="">Все</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectDoorId{{door.id}}" class="select-door-data col-4" data-ng-repeat="door in filteredDoors = (config.doors | filterData:calcDoors.searchFilter)" data-ng-show="!calcDoors.manufacturersSelect || (calcDoors.manufacturersSelect == door.manufacturer_id)">
|
||||
{{currentDoorImage = utilities.getDoorImageById(door.id);""}}
|
||||
|
||||
<div data-ng-click="calcDoors.selectDoorId(door)" data-ng-class="{'selected' : (calcDoors.selectDoorConfigModalData.params.doorId == door.id)}">
|
||||
<div data-ng-if="door.image" class="select-door-image img-thumbnail">
|
||||
<img data-src="{{currentDoorImage}}" class="img-lazy" >
|
||||
</div>
|
||||
|
||||
<div class="select-door-label">
|
||||
<span><b>{{door.color}}</b></span>
|
||||
<span>{{door.profile}} {{utilities.getDoorManufacturer(door.manufacturer_id)}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a data-ng-if="door.image" tabindex="-1" href="{{currentDoorImage}}" data-lightbox="door{{door.id}}LightBox" class="select-door-preview" data-ng-class="{'no-door-image' : !door.image}">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredDoors.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-disabled="!calcDoors.selectDoorConfigModalData.params.doorId"
|
||||
data-ng-click="calcDoors.confirmDoorSelection()">
|
||||
Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
@@ -0,0 +1,934 @@
|
||||
<div data-ng-controller="CutController" class="hidden-on-load">
|
||||
<div class="container apps-container">
|
||||
<form name="cutConfigForm">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="sheet-config-row">
|
||||
<div class="row">
|
||||
<div class="col-6 form-horizontal">
|
||||
<div class="form-group no-bottom-margin">
|
||||
<h3 class="siteTitle">
|
||||
<span>{{config.common.siteTitle.value}}</span>
|
||||
<button tabindex="-1" type="button" class="btn btn-sm btn-warning openSelectSheetConfigModal" data-ng-click="cut.openSelectSheetConfigModal()">Выбрать фактуру листа и кромки</button>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedSheetImage = utilities.getSheetImageById(cut.selectedSheetData.sheetId, 'image');""}}
|
||||
<label for="selectedSheetDimension" class="col-4 col-form-label">Фактура листа:<a tabindex="-1" data-ng-if="cut.selectedSheetData.sheetId && selectedSheetImage" href="{{selectedSheetImage}}" data-lightbox="sheetIdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label selected-sheet-dimension">
|
||||
{{cut.getSelectedSheetLabel(cut.selectedSheetData.sheetId)}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label for="selectedSheetDimension" class="col-4 col-form-label">Размер листа: </label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label selected-sheet-dimension">{{cut.getSelectedSheetFullDimensions()}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label class="col-4 col-form-label">Размер раскроя:<a class="popover-button cut-size-desc" tabindex="-1" role="button" data-ng-show="cut.selectedSheetData.sheetId" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{cut.faceDescriptionWithPrice | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a> </label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label selected-sheet-dimension">{{cut.getSelectedSheetDimensions()}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="row logo-row text-left">
|
||||
<div class="col-5">
|
||||
<a tabindex="-1" href="/services" title="{{::config.primarySiteTitle}}" target="_blank">
|
||||
<img src="/img/logo.png" alt="{{::config.primarySiteTitle}}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<h5 class="addressDelivery">
|
||||
<span>Наш адрес:</span>
|
||||
<span class="addressDelivery" data-ng-bind-html="::utilities.getConfigLabel('addressDelivery') | trustAs"></span>
|
||||
<span class="addressDelivery" data-ng-bind-html="::utilities.getConfigLabel('addressDeliveryAdd') | trustAs"></span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="detailWithBordersWarning text-danger">{{::utilities.getConfigLabel('detailWithBordersWarning')}}</h5>
|
||||
|
||||
<div class="headerInfoLabel">{{::utilities.getConfigLabel('headerInfoLabel') | trustAs}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-horizontal checkbox-group no-bottom-margin">
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label class="col-8 col-form-label" data-ng-click="cut.mergeSimilarDetailsToggle()">Объединение одинаковых деталей: </label>
|
||||
<div class="col-4" id="mergeSimilarDetails">
|
||||
<i class="fa fa-square-o" data-ng-if="!cut.mergeSimilarDetails" data-ng-click="cut.mergeSimilarDetailsToggle()"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="cut.mergeSimilarDetails" data-ng-click="cut.mergeSimilarDetailsToggle()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label class="col-6 col-form-label" data-ng-click="cut.packCuttingsToOrderToggle()">Вкладывать остатки в заказ: </label>
|
||||
<div class="col-4">
|
||||
<i class="fa fa-square-o" data-ng-if="!cut.packCuttingsToOrder" data-ng-click="cut.packCuttingsToOrderToggle()"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="cut.packCuttingsToOrder" data-ng-click="cut.packCuttingsToOrderToggle()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-horizontal">
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedBorder1Image = utilities.getBorderImageById(cut.selectedSheetData.border1Id);""}}
|
||||
<label class="col-3 col-form-label">
|
||||
Кромка №1:<a tabindex="-1" class="preview-button" data-ng-if="cut.selectedSheetData.border1Id && selectedBorder1Image" href="{{selectedBorder1Image}}" data-lightbox="border1IdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label selected-sheet-dimension">
|
||||
<span data-ng-bind-html="cut.getBorderLabel(cut.selectedSheetData.border1Id, cut.selectedSheetData.border1Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedBorder2Image = utilities.getBorderImageById(cut.selectedSheetData.border2Id);""}}
|
||||
<label class="col-3 col-form-label">
|
||||
Кромка №2:<a tabindex="-1" class="preview-button" data-ng-if="cut.selectedSheetData.border2Id && selectedBorder2Image" href="{{utilities.getBorderImageById(cut.selectedSheetData.border2Id)}}" data-lightbox="border2IdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label selected-sheet-dimension">
|
||||
<span data-ng-bind-html="cut.getBorderLabel(cut.selectedSheetData.border2Id, cut.selectedSheetData.border2Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-horizontal">
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderName">ФИО: <a class="popover-button" tabindex="-1" role="button" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{utilities.getConfigLabel('fioIsRequired', true) | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a></label>
|
||||
<div class="col-9" data-ng-class="cutConfigForm.orderName.$invalid && cutConfigForm.orderName.$dirty ? 'has-error' : ''">
|
||||
<input type="text" class="form-control form-control-sm" name="orderName" id="orderName" data-ng-model="cut.orderName" required data-ng-enter="cut.onFieldEnter('orderPhone')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderPhone">Телефон: <a class="popover-button" tabindex="-1" role="button" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{utilities.getConfigLabel('phoneIsRequired', true) | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a></label>
|
||||
<div class="col-9" data-ng-class="cutConfigForm.orderPhone.$invalid && cutConfigForm.orderPhone.$dirty ? 'has-error' : ''">
|
||||
<input type="text" class="form-control form-control-sm" name="orderPhone" id="orderPhone" data-ng-model="cut.orderPhone" data-model-view-value="true" data-digits-only placeholder=" " required data-ng-enter="cut.onFieldEnter('orderEmail')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderEmail">Email: <a class="popover-button" tabindex="-1" role="button" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{utilities.getConfigLabel('emailIsRequired', true) | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a></label>
|
||||
<div class="col-9" data-ng-class="cutConfigForm.orderEmail.$invalid && cutConfigForm.orderEmail.$dirty ? 'has-error' : ''">
|
||||
<input type="email" class="form-control form-control-sm" name="orderEmail" id="orderEmail" data-ng-model="cut.orderEmail" required data-ng-enter="cut.onFieldEnter('orderAddress')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderAddress">Адрес доставки: </label>
|
||||
<div class="col-9" data-ng-class="cutConfigForm.orderAddress.$invalid && cutConfigForm.orderAddress.$dirty ? 'has-error' : ''">
|
||||
<input type="text" class="form-control form-control-sm" name="orderAddress" id="orderAddress" data-ng-model="cut.orderAddress" data-ng-enter="cut.onFieldEnter('orderComment')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<div class="col-12">
|
||||
<textarea class="form-control form-control-sm margin-top-3" name="orderComment" id="orderComment" data-ng-model="cut.orderComment" placeholder="Комментарий к заказу"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card details-config">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-4 cut-results">
|
||||
<div class="print-left">
|
||||
<div data-ng-if="cut.orderNum && (cut.orderNum.length > 0)">Заказ: {{cut.orderNum}}</div>
|
||||
<div>Листов в раскрое: {{cut.sheets.length}}</div>
|
||||
|
||||
{{selectedSheetsInStock = utilities.getSelectedSheetsInStock(cut.selectedSheetData.sheetId);""}}
|
||||
<div data-ng-if="(selectedSheetsInStock != null) && (selectedSheetsInStock < cut.sheets.length)" class="text-warning">Листов на складе: {{selectedSheetsInStock}}</div>
|
||||
|
||||
<div>Всего деталей: {{cut.getDetailsCount()}}</div>
|
||||
<div>Площадь деталей: {{(cut.getDetailsArea()/1000000).toFixed(2).replace(".00", "")}}м<sup>2</sup></div>
|
||||
<div>Длина пропила: {{cut.notchCount}}м.</div>
|
||||
<div data-ng-if="cut.grooveCount.length > 0">Длина пропила пазов: {{cut.grooveCount}}м.</div>
|
||||
<div data-ng-if="cut.selectedSheetData.border1Id || cut.selectedSheetData.border2Id">Длина кромок:
|
||||
<ul>
|
||||
<li data-ng-repeat="borderId in [1, 2]" data-ng-if="cut.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
кромка №{{borderId}} - {{((cut.selectedSheetData["border" + borderId + "Count"] ? cut.selectedSheetData["border" + borderId + "Count"] : 0)/1000).toFixed(2).replace(".00", "")}}м.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div><span class="text-strong-danger">Ориентировочная</span> <span class="no-wrap">стоимость: {{cut.price}} руб.</span></div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="order-buttons">
|
||||
<div class="" data-ng-if="config.createdForManagerId">
|
||||
Если вы знаете менеджера,<br/> выберите его в поле ниже<br/>
|
||||
<div class="btn-group order-available-managers">
|
||||
<button tabindex="-1" data-ng-disabled="!cut.selectedSheetData.sheetId || cutConfigForm.$invalid || cut.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ utilities.getAvailableToOrderManagerNameById(cut.createdForManagerId) }} <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li data-ng-repeat="manager in config.availableToOrderManagers">
|
||||
<a tabindex="-1" data-ng-click="cut.setCreatedForManagerId(manager.id)" class="dropdown-item">{{manager.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="btn-group print-order-button" data-ng-if="config.additionalActionsAllowed">
|
||||
<button tabindex="-1" data-ng-disabled="!cut.selectedSheetData.sheetId || cutConfigForm.$invalid || cut.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-print"></i> Печать <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a tabindex="-1" data-ng-click="cut.printOrder('Spec')" class="dropdown-item">Печать спецификации</a></li>
|
||||
<li><a tabindex="-1" data-ng-click="cut.printOrder('Cut')" class="dropdown-item">Печать карт раскроя</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button tabindex="-1" data-ng-if="!config.savedOrderData && (config.branches.length == 1)" data-ng-disabled="!cut.selectedSheetData.sheetId || cutConfigForm.$invalid || cut.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary send-order-button" data-ng-click="cut.sendOrderEmailNotify(config.branches[0].id)">Отправить менеджеру</button>
|
||||
|
||||
<div class="btn-group send-order-button" data-ng-if="!config.savedOrderData && (config.branches.length > 1)">
|
||||
<button tabindex="-1" data-ng-disabled="!cut.selectedSheetData.sheetId || cutConfigForm.$invalid || cut.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Отправить менеджеру <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li data-ng-repeat="branch in config.branches"><a tabindex="-1" data-ng-click="cut.sendOrderEmailNotify(branch.id)" class="dropdown-item">{{branch.label}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button tabindex="-1" data-ng-if="config.savedOrderData" data-ng-disabled="!cut.selectedSheetData.sheetId || cutConfigForm.$invalid || cut.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary send-order-button" data-ng-click="cut.sendOrderEmailNotify(false)">Сохранить заказ</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-8 details-list">
|
||||
<h5 class="justify-content-between">
|
||||
<span>Параметры деталей, мм</span>
|
||||
</h5>
|
||||
|
||||
<div>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr data-ng-repeat="detail in cut.details">
|
||||
<td colspan="7">
|
||||
<div>
|
||||
<table class="table table-details-list table-no-borders">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="detail-number-label">№</th>
|
||||
<th>Длина</th>
|
||||
<th>Ширина</th>
|
||||
<th>Кол-во, шт</th>
|
||||
<th class="detail-borders"><span data-ng-if="cut.selectedSheetData.border1Id > 0">Кромка</span></th>
|
||||
<th class="detailCorners detailGrooves text-center">Доп.</th>
|
||||
<th class=""></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="detail-number-label">
|
||||
<span>{{$index+1}}</span>
|
||||
|
||||
<a tabindex="-1" href="#" data-ng-click="cut.openDetailLabelConfigModal(detail.id)" data-click-prevent="true" title="Наименование детали">
|
||||
<i class="fa fa-pencil" data-ng-class="{'text-success' : detail.label && (detail.label.length > 0) }"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<input id="detail{{detail.id}}width" class="form-control form-control-sm" type="text" data-ng-model="detail.width" data-digits-only data-ng-enter="cut.onDetailEnter(detail, 'width')" pattern="[0-9]*">
|
||||
</td>
|
||||
<td>
|
||||
<input id="detail{{detail.id}}height" class="form-control form-control-sm" type="text" data-ng-model="detail.height" data-digits-only data-ng-enter="cut.onDetailEnter(detail, 'height')" pattern="[0-9]*">
|
||||
</td>
|
||||
<td>
|
||||
<input id="detail{{detail.id}}count" class="form-control form-control-sm" type="text" data-ng-model="detail.count" data-digits-only data-ng-enter="cut.onDetailEnter(detail, 'count')" pattern="[0-9]*">
|
||||
</td>
|
||||
<td class="detail-borders">
|
||||
<span class="detail-color-box" style="background-color: {{detail.color}}" data-ng-if="!cut.selectedSheetData.border1Id"></span>
|
||||
|
||||
<div data-ng-if="cut.selectedSheetData.border1Id > 0" data-ng-class="{'single-border-config' : !cut.selectedSheetData.border2Id}">
|
||||
<div class="left-detail-border" >
|
||||
<div class="detail-border detail-border-{{borderId}} {{cut.detailsBorders[detail.id].left == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="cut.toggleDetailBorder(detail, 'left', borderId)" title="{{cut.detailsBorders[detail.id].left == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="cut.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-border-center">
|
||||
<div class="top-detail-border">
|
||||
<div class="detail-border detail-border-{{borderId}} {{cut.detailsBorders[detail.id].top == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="cut.toggleDetailBorder(detail, 'top', borderId)" title="{{cut.detailsBorders[detail.id].top == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="cut.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-borders {{cut.getDetailBordersClass(detail)}}" style="background-color: {{detail.color}}; border-color: {{detail.color}};"></div>
|
||||
|
||||
<div class="bottom-detail-border">
|
||||
<div class="detail-border detail-border-{{borderId}} {{cut.detailsBorders[detail.id].bottom == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="cut.toggleDetailBorder(detail, 'bottom', borderId)" title="{{cut.detailsBorders[detail.id].bottom == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="cut.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-detail-border">
|
||||
<div class="detail-border detail-border-{{borderId}} {{cut.detailsBorders[detail.id].right == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="cut.toggleDetailBorder(detail, 'right', borderId)" title="{{cut.detailsBorders[detail.id].right == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="cut.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="config-detailCorners-button">
|
||||
<a tabindex="-1" href="#" data-ng-click="cut.openDetailCornersConfigModal(detail, $index+1)" data-click-prevent="true" title="Скругление/срез/паз" data-ng-disabled="!cut.isDetailDimensionsFilled(detail)">
|
||||
<img src="/img/corners.png" alt="{{::config.siteTitle}}">
|
||||
</a>
|
||||
</td>
|
||||
<td class="remove-detail-button">
|
||||
<a tabindex="-1" href="#" class="text-danger remove-detail" data-ng-if="cut.details.length > 1" data-ng-click="cut.removeDetail(detail)" data-click-prevent="true">x</a>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div data-ng-bind-html="cut.getDetailCornersText(detail) | trustAs"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div data-ng-bind-html="cut.getDetailGroovesText(detail) | trustAs"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex justify-content-between">
|
||||
<button tabindex="-1" class="btn btn-sm btn-success" data-ng-click="cut.addDetail()" data-click-prevent="true">
|
||||
Добавить деталь
|
||||
</button>
|
||||
|
||||
<button tabindex="-1" class="btn btn-danger btn-sm clear-button" data-ng-click="cut.confirmCleanup()" data-click-prevent="true">
|
||||
Очистить
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="sheets-wrap" data-ng-if="(cut.selectedSheetData.sheetId) && cut.selectedSheetDimension">
|
||||
<div class="card" data-ng-repeat="sheet in cut.sheets">
|
||||
<div class="card-body">
|
||||
<div class="sheet" data-ng-class="cut.sheetClass" data-ng-style="cut.sheetStyle">
|
||||
<div class="info sheet-title">Лист {{sheet.id}}</div>
|
||||
<div class="info sheet-width">
|
||||
<span class="sheet-width-left">|‹</span>
|
||||
<span class="sheet-width-right">›|</span>
|
||||
{{cut.selectedSheetDimension.width}} мм
|
||||
</div>
|
||||
<div class="info sheet-height">
|
||||
<span class="sheet-height-top">›|</span>
|
||||
<span class="sheet-height-bottom">|‹</span>
|
||||
<span data-ng-style="cut.sheetHeightStyle">{{cut.selectedSheetDimension.height}} мм</span>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="detail in sheet.details" data-ng-style="cut.getDetailStyle(detail)" class="detail detail-with-entire-borders" data-ng-class="cut.getDetailClass(detail)" data-ng-click="cut.rotateDetail(detail)">
|
||||
<div class="detail-height">{{detail.height}}</div>
|
||||
<div class="detail-width">{{detail.width}}</div>
|
||||
|
||||
<div class=""></div>
|
||||
|
||||
<a class="detail-label-edit" tabindex="-1" href="#" data-ng-click="cut.openDetailLabelConfigModal(detail.detailId)" data-click-prevent="true" title="{{cut.getDetailLabel(detail.detailId)}}" data-ng-if="cut.getDetailLabel(detail.detailId).length > 0">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
|
||||
<div data-ng-repeat="borderPosition in config.borderPositions" class="entire-border {{borderPosition}}-border" data-ng-if="cut.detailsBorders[detail.detailId][borderPosition]"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="notifyModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div>{{cut.notifyMessage}}</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-info" data-dismiss="modal" href="#">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="notifySendOrderEmailModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div data-ng-if="config.savedOrderData" data-ng-bind-html="::utilities.getConfigLabel('notifySaveOrderDataMessage', true) | trustAs"></div>
|
||||
|
||||
<div data-ng-if="!config.savedOrderData" data-ng-bind-html="::utilities.getConfigLabel('notifySendOrderEmailMessage') | trustAs"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-info" data-dismiss="modal" href="#">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="confirmCleanupModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning" data-ng-bind-html="::utilities.getConfigLabel('confirmCleanupMessage') | trustAs">
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="fullOrderCleanupCheckbox" data-ng-model="cut.fullOrderCleanup">
|
||||
<label class="form-check-label" for="fullOrderCleanupCheckbox">
|
||||
Очистить всё
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Отмена</button>
|
||||
<button type="button" class="btn btn-primary" data-ng-click="cut.cleanup(true)">Продолжить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="modal fade" id="selectSheetConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<span data-ng-show="cut.activeSheetSelectStep == 1">Шаг 1/4: Выбор фактуры и размера листа</span>
|
||||
<span data-ng-show="cut.activeSheetSelectStep == 2">Шаг 2/4: Выбор цвета и толщины кромки №1</span>
|
||||
<span data-ng-show="cut.activeSheetSelectStep == 3">Шаг 3/4: Выбор цвета и толщины кромки №2</span>
|
||||
<span data-ng-show="cut.activeSheetSelectStep == 4">Шаг 4/4: Подтверждение выбранной конфигурации</span>
|
||||
</h5>
|
||||
|
||||
<div class="input-group input-group-sm search-input-group" data-ng-show="(cut.activeSheetSelectStep != 4)">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="searchFilter{{cut.activeSheetSelectStep}}" >
|
||||
<i class="fa fa-search"></i>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input placeholder="Поиск.." id="searchFilter{{cut.activeSheetSelectStep}}" class="form-control " type="text" data-ng-model="cut.searchFilters[cut.activeSheetSelectStep]">
|
||||
</div>
|
||||
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div data-ng-show="cut.activeSheetSelectStep == 1">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectSheetId{{sheet.id}}" class="select-sheet-data col-6 col-xl-4 col-lg-4 col-md-4 col-sm-6" data-ng-repeat="sheet in filteredSheets = (config.sheets | filterData:cut.searchFilters[1])" data-ng-if="sheet.is_active || config.savedOrderData && config.savedOrderData.sheet_data && (config.savedOrderData.sheet_data.sheetId == sheet.id)">
|
||||
<div data-ng-click="cut.selectSheetId(sheet)" data-ng-class="{'selected' : (cut.selectSheetConfigModalData.sheetId == sheet.id)}">
|
||||
<div class="select-sheet-image img-thumbnail" data-ng-if="cut.isSelectSheetConfigModalTriggered && sheet.thumb">
|
||||
<img data-ng-src="{{utilities.getSheetImageById(sheet.id, 'thumb')}}" class="img-lazy">
|
||||
</div>
|
||||
|
||||
<div class="select-sheet-label">
|
||||
<span><b>{{sheet.label}}</b></span>
|
||||
<span>Размеры:</> {{cut.getSheetFullDimensions(sheet.sheet_dimension_id)}}</span>
|
||||
<span>Цена: {{sheet.price}} руб. <span data-ng-if="sheet.sheetIdFor1C && (sheet.quantityIn1C != null)" class="sheet-1c-quantity" data-ng-class="{'text-danger': (sheet.quantityIn1C < 1)}">Ост. {{sheet.quantityIn1C > 0 ? sheet.quantityIn1C : 0}}л</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a tabindex="-1" href="{{utilities.getSheetImageById(sheet.id, 'image')}}" data-lightbox="sheet{{sheet.id}}LightBox" class="select-sheet-preview" data-ng-if="sheet.image" data-ng-class="{'no-sheet-thumb' : !sheet.thumb}">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredSheets.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-show="cut.activeSheetSelectStep == 2">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП. <br/>
|
||||
Выберите цвет и размер кромки №1 или нажмите "Пропустить", если в поклейке кромок нет необходимости.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectBorder1Id{{border.id}}" class="select-border-data col-12" data-ng-repeat="border in filteredBorders1 = (config.borders | filterData:cut.searchFilters[2])">
|
||||
<div data-ng-click="cut.selectBorderId(1, border)" data-ng-class="{'selected' : (cut.selectSheetConfigModalData.border1Id == border.id)}">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="select-border-image" data-ng-if="cut.isSelectSheetConfigModalTriggered && border.image">
|
||||
<img data-src="{{utilities.getBorderImageById(border.id)}}" class="img-thumbnail img-lazy">
|
||||
</div>
|
||||
<div class="">
|
||||
<span><b>{{border.label}} {{cut.checkIfBorderInSheetColor(cut.selectSheetConfigModalData.sheetId, border.id)}}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group" data-ng-if="cut.selectSheetConfigModalData.border1Id == border.id">
|
||||
<label for="border1HeightSelect">Толщина кромки:</label>
|
||||
<select class="custom-select" id="border1HeightSelect" data-ng-model="cut.selectSheetConfigModalData.border1Height" data-ng-options="v.cut_border_dimension.id as v.cut_border_dimension.label for v in border.available_dimensions" data-ng-disabled="!cut.selectSheetConfigModalData.border1Id">
|
||||
<option value="">Выберите толщину</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a tabindex="-1" href="{{utilities.getBorderImageById(border.id)}}" data-lightbox="border1{{border.id}}LightBox" class="select-border-preview" data-ng-if="border.image">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredBorders1.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-show="cut.activeSheetSelectStep == 3">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП. <br/>
|
||||
Выберите цвет и размер кромки №2 или нажмите "Пропустить", если в поклейке кромки №2 нет необходимости.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectBorder2Id{{border.id}}" class="select-border-data col-12" data-ng-repeat="border in filteredBorders2 = (config.borders | filterData:cut.searchFilters[3])">
|
||||
<div data-ng-click="cut.selectBorderId(2, border)" data-ng-class="{'selected' : (cut.selectSheetConfigModalData.border2Id == border.id)}">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="select-border-image" data-ng-if="cut.isSelectSheetConfigModalTriggered && border.image">
|
||||
<img data-src="{{utilities.getBorderImageById(border.id)}}" class="img-thumbnail img-lazy">
|
||||
</div>
|
||||
<div class="">
|
||||
<span><b>{{border.label}} {{cut.checkIfBorderInSheetColor(cut.selectSheetConfigModalData.sheetId, border.id)}}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group" data-ng-if="cut.selectSheetConfigModalData.border2Id == border.id">
|
||||
<label for="border2HeightSelect">Толщина кромки:</label>
|
||||
<select class="custom-select" id="border2HeightSelect" data-ng-model="cut.selectSheetConfigModalData.border2Height" data-ng-options="v.cut_border_dimension.id as v.cut_border_dimension.label for v in border.available_dimensions" data-ng-disabled="!cut.selectSheetConfigModalData.border2Id">
|
||||
<option value="">Выберите толщину</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a tabindex="-1" href="{{utilities.getBorderImageById(border.id)}}" data-lightbox="border2{{border.id}}LightBox" class="select-border-preview" data-ng-if="border.image">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredBorders2.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-show="cut.activeSheetSelectStep == 4">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП. <br/>
|
||||
Проверьте выбранную фактуру листа и конфигурацию кромок и нажмите "Сохранить".
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Фактура:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">{{cut.getSelectedSheetLabel(cut.selectSheetConfigModalData.sheetId)}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Размеры листа:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">{{cut.getSheetFullDimensionsBySheetId(cut.selectSheetConfigModalData.sheetId)}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Кромка 1:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">
|
||||
<span data-ng-bind-html="cut.getBorderLabel(cut.selectSheetConfigModalData.border1Id, cut.selectSheetConfigModalData.border1Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Кромка 2:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">
|
||||
<span data-ng-bind-html="cut.getBorderLabel(cut.selectSheetConfigModalData.border2Id, cut.selectSheetConfigModalData.border2Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="cut.activeSheetSelectStep == 1"
|
||||
data-ng-disabled="!cut.selectSheetConfigModalData.sheetId"
|
||||
data-ng-click="cut.discardBordersSelectFromStep1()">
|
||||
Пропустить выбор кромок
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="cut.activeSheetSelectStep == 1"
|
||||
data-ng-disabled="!cut.selectSheetConfigModalData.sheetId"
|
||||
data-ng-click="cut.setActiveSheetSelectStep(2)">
|
||||
Перейти к выбору кромок
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="cut.activeSheetSelectStep == 2"
|
||||
data-ng-click="cut.setActiveSheetSelectStep(1)">
|
||||
Вернуться к выбору фактуры
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-warning"
|
||||
data-ng-if="cut.activeSheetSelectStep == 2"
|
||||
data-ng-click="cut.discardBordersSelectFromStep2()">
|
||||
Пропустить
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="cut.activeSheetSelectStep == 2"
|
||||
data-ng-disabled="!cut.selectSheetConfigModalData.border1Id || !cut.selectSheetConfigModalData.border1Height"
|
||||
data-ng-click="cut.setActiveSheetSelectStep(3)">
|
||||
Перейти к выбору кромки №2
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="cut.activeSheetSelectStep == 3"
|
||||
data-ng-click="cut.setActiveSheetSelectStep(2)">
|
||||
Вернуться к выбору кромки №1
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-warning"
|
||||
data-ng-if="cut.activeSheetSelectStep == 3"
|
||||
data-ng-click="cut.discardBorder2SelectFromStep3()">
|
||||
Пропустить
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="cut.activeSheetSelectStep == 3"
|
||||
data-ng-disabled="!cut.selectSheetConfigModalData.border2Id || !cut.selectSheetConfigModalData.border2Height"
|
||||
data-ng-click="cut.setActiveSheetSelectStep(4)">
|
||||
Завершить настройку
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="cut.activeSheetSelectStep == 4"
|
||||
data-ng-click="cut.setActiveSheetSelectStep(1)">
|
||||
Вернуться к выбору фактуры
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="cut.activeSheetSelectStep == 4"
|
||||
data-ng-disabled="!cut.selectSheetConfigModalData.sheetId"
|
||||
data-ng-click="cut.confirmSheetSelection()">
|
||||
Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" id="detailCornersConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
Конфигурация детали №{{cut.detailCornersConfigModalData.uiOrderNum}}
|
||||
</h5>
|
||||
|
||||
<div>
|
||||
<button type="button" class="btn"
|
||||
data-ng-class="{true:'btn-info', false:'btn-light'}[cut.detailCornersConfigModalData.activeTab == cornersConfigButton.id]"
|
||||
data-ng-repeat="cornersConfigButton in config.cornersConfigButtons"
|
||||
data-ng-click="cut.setDetailCornersConfigActiveTab(cornersConfigButton.id)">
|
||||
{{cornersConfigButton.label}}
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row" data-ng-if="cut.detailCornersConfigModalData.activeTab == 'corners'">
|
||||
<div class="detailCornersCenter">
|
||||
<div class="detailCornersBox" data-ng-class="cut.getDetailCornersConfigClass()">
|
||||
<div class="detailCornersHorizontalDivider"></div>
|
||||
<div class="detailCornersVerticalDivider"></div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="cornerConfigRadiusLabel cornerConfigRadiusLabel-{{cornerPosition.id}}">
|
||||
<span>R={{cut.detailCornersConfigModalData.corners[cornerPosition.id].radius}}</span>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="cornerConfigCutLabel cornerConfigCutLabel-{{cornerPosition.id}}">
|
||||
<span class="cornerConfigCutXLabel">x={{cut.detailCornersConfigModalData.corners[cornerPosition.id].x}}</span>
|
||||
<span class="cornerConfigCutYLabel">y={{cut.detailCornersConfigModalData.corners[cornerPosition.id].y}}</span>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="cornerConfigCutLabel cornerConfigCutEdge-{{cornerPosition.id}}"></div>
|
||||
</div>
|
||||
|
||||
<div class="detailCornersWidth">{{cut.detailCornersConfigModalData.detail.width}} мм</div>
|
||||
<div class="detailCornersHeight">{{cut.detailCornersConfigModalData.detail.height}} мм</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="detailCorner detailCorner-{{cornerPosition.id}}">
|
||||
<label>{{cornerPosition.label}}</label>
|
||||
|
||||
<div class="">
|
||||
<button type="button" class="btn"
|
||||
data-ng-class="{true:'active btn-primary', false:'btn-light'}[cut.detailCornersConfigModalData.corners[cornerPosition.id].value == cornerValue.id]"
|
||||
data-ng-repeat="cornerValue in config.cornerValues"
|
||||
data-ng-disabled="cut.isDetailCornerConfigValueSelectDisabled(cornerPosition.id)"
|
||||
data-ng-click="cut.setDetailCornerConfigValue(cornerPosition.id, cornerValue.id)">
|
||||
{{cornerValue.label}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="detailCorner-config col-12">
|
||||
<div class="row" data-ng-if="cut.detailCornersConfigModalData.corners[cornerPosition.id].value == 'none'"></div>
|
||||
|
||||
<div class="row" data-ng-if="cut.detailCornersConfigModalData.corners[cornerPosition.id].value == 'radius'">
|
||||
<div class="input-group col-sm-12 col-lg-9">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailCornersConfigModalData{{cornerPosition.id}}Radius">Радиус, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailCornersConfigModalData{{cornerPosition.id}}Radius"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="cut.detailCornersConfigModalData.corners[cornerPosition.id].radius"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" data-ng-if="cut.detailCornersConfigModalData.corners[cornerPosition.id].value == 'cut'">
|
||||
<div class="input-group col-sm-12 col-lg-6 corners-config-left-group">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailCornersConfigModalData{{cornerPosition.id}}X">x, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailCornersConfigModalData{{cornerPosition.id}}X"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="cut.detailCornersConfigModalData.corners[cornerPosition.id].x"
|
||||
data-ng-disabled="cut.isDetailCornerConfigInputDisabled(cornerPosition.id)"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-12 col-lg-6 corners-config-right-group">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailCornersConfigModalData{{cornerPosition.id}}Y">y, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailCornersConfigModalData{{cornerPosition.id}}X" class="form-control form-control-sm" type="number"
|
||||
data-ng-model="cut.detailCornersConfigModalData.corners[cornerPosition.id].y"
|
||||
data-ng-disabled="cut.isDetailCornerConfigInputDisabled(cornerPosition.id)"
|
||||
data-digits-only pattern="[0-9]*" >
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-12 col-lg-12"
|
||||
data-ng-class="{'disabled': cut.isDetailCornerConfigDiagonalCheckboxDisabled(cornerPosition.id)}"
|
||||
data-ng-click="cut.onDetailCornersConfigDiagonalCutClick(cornerPosition.id)">
|
||||
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text with-checkbox">
|
||||
<i class="fa fa-square-o" data-ng-if="!cut.detailCornersConfigModalData.corners[cornerPosition.id].diagonalCut"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="cut.detailCornersConfigModalData.corners[cornerPosition.id].diagonalCut"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="col-form-label form-control">Диагональный срез</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" data-ng-if="cut.detailCornersConfigModalData.activeTab == 'grooves'" data-ng-class="cut.getDetailGroovesConfigClass()">
|
||||
<div class="detailGroovesCenter">
|
||||
<div class="detailGroovesBox" data-ng-class="cut.getDetailGroovesConfigClass()">
|
||||
<div data-ng-repeat="groovePosition in config.groovePositions" class="grooveConfigLabel grooveConfigLabel-{{groovePosition.id}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detailGroovesWidth">{{cut.detailCornersConfigModalData.detail.width}} мм</div>
|
||||
<div class="detailGroovesHeight">{{cut.detailCornersConfigModalData.detail.height}} мм</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="groovePosition in config.groovePositions" class="detailGroove detailGroove-{{groovePosition.id}}">
|
||||
<div class="detailGroove-config col-12">
|
||||
<div class="row">
|
||||
<div class="input-group"
|
||||
data-ng-class="[{true:'col-12', false:'offset-4 col-4'}[(groovePosition.id == 'left') || (groovePosition.id == 'right')], {'disabled': cut.isDetailGrooveConfigCheckboxDisabled(groovePosition.id)}]"
|
||||
data-ng-click="cut.onDetailGroovesConfigGrooveEnabledClick(groovePosition.id)">
|
||||
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text input-group-checkbox-text with-checkbox">
|
||||
<i class="fa fa-square-o" data-ng-if="!cut.detailCornersConfigModalData.grooves[groovePosition.id].enabled"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="cut.detailCornersConfigModalData.grooves[groovePosition.id].enabled"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="col-form-label form-control">{{groovePosition.label2}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-col-4 first-row-col-4" data-ng-if="cut.detailCornersConfigModalData.grooves[groovePosition.id].enabled">
|
||||
<div class="input-group col-12">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailGroovesConfigModalData{{groovePosition.id}}Offset">Отступ от края, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailGroovesConfigModalData{{groovePosition.id}}Offset"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="cut.detailCornersConfigModalData.grooves[groovePosition.id].offset"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-col-4 second-row-col-4" data-ng-if="cut.detailCornersConfigModalData.grooves[groovePosition.id].enabled">
|
||||
<div class="input-group col-12">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailGroovesConfigModalData{{groovePosition.id}}Depth">Глубина пропила, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailGroovesConfigModalData{{groovePosition.id}}Depth"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="cut.detailCornersConfigModalData.grooves[groovePosition.id].depth"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-col-4 third-row-col-4" data-ng-if="cut.detailCornersConfigModalData.grooves[groovePosition.id].enabled">
|
||||
<div class="input-group col-12">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailGroovesConfigModalData{{groovePosition.id}}Width">Ширина пропила, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailGroovesConfigModalData{{groovePosition.id}}Width"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="cut.detailCornersConfigModalData.grooves[groovePosition.id].width"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
|
||||
|
||||
<button class="btn btn-sm btn-success" data-ng-click="cut.saveDetailCornersConfig()">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="detailLabelConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-md">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
Наименование детали №{{cut.detailLabelConfigModalData.uiOrderNum}}
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<input class="form-control" type="text" data-ng-model="cut.detailLabelConfigModalData.label" maxlength="20">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
|
||||
|
||||
<button class="btn btn-sm btn-success" data-ng-click="cut.saveDetailLabelConfig()">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
Whitespace-only changes.
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
$class = 'message';
|
||||
if (!empty($params['class'])) {
|
||||
$class .= ' ' . $params['class'];
|
||||
}
|
||||
if (!isset($params['escape']) || $params['escape'] !== false) {
|
||||
$message = h($message);
|
||||
}
|
||||
?>
|
||||
<div class="<?= h($class) ?>" onclick="this.classList.add('hidden');"><?= $message ?></div>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div class="alert alert-danger alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p><?= $message ?></p>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
if (!isset($params['escape']) || $params['escape'] !== false) {
|
||||
$message = h($message);
|
||||
}
|
||||
?>
|
||||
<div class="message success" onclick="this.classList.add('hidden')"><?= $message ?></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php use Cake\Core\Configure;?>
|
||||
|
||||
<script type="text/javascript">
|
||||
supersamApp.factory('config', function() {
|
||||
return <?php echo json_encode(isset($jsConfig) ? $jsConfig : []); ?>;
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php use Cake\Core\Configure;?>
|
||||
|
||||
<script type="text/javascript">
|
||||
supersamApp.factory('config', function() {
|
||||
return <?php echo json_encode(isset($jsConfig) ? $jsConfig : []); ?>;
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script type="text/javascript">
|
||||
function getCookie(name) {
|
||||
var value = "; " + document.cookie;
|
||||
var parts = value.split("; " + name + "=");
|
||||
if (parts.length == 2) return parts.pop().split(";").shift();
|
||||
else return null;
|
||||
}
|
||||
|
||||
function setCookie(name,value,days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days*24*60*60*1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
}
|
||||
|
||||
(function($, document) {
|
||||
$(document).ready(function () {
|
||||
var cookieConsent = getCookie("cookie_consent");
|
||||
if (cookieConsent == null) {
|
||||
$("<div class=\"cookie-consent-container-wrap\"><div class=\"cookie-consent-container\"></div>"+
|
||||
"<div class=\"cookie-consent-content\">"+
|
||||
"<div><span>Мы используем файлы cookie, чтобы обеспечить максимальное удобство пользователям. Продолжая использовать этот сайт, вы даете согласие на использование файлов cookies.</span> <a href=\"https://supersamsev.ru/cookie-policy\" class=\"cookie-consent-more\" target=\"_blank\">Подробнее</a></div>"+
|
||||
"<a class=\"cookie-consent-ok\">Согласен</a>"+
|
||||
"</div>"+
|
||||
"</div>").appendTo('body');
|
||||
|
||||
|
||||
$(".cookie-consent-ok").on('click', function () {
|
||||
setCookie('cookie_consent', true, 1095);
|
||||
$(".cookie-consent-container-wrap").css({'opacity': '0', 'visibility': 'hidden'});
|
||||
});
|
||||
}
|
||||
})
|
||||
})(jQuery, document);
|
||||
</script>
|
||||
@@ -0,0 +1,264 @@
|
||||
<div id="result"></div>
|
||||
<div id="map"></div>
|
||||
|
||||
<a tabindex="-1" href="/services" title="{{::config.primarySiteTitle}}" target="_blank" class="delivery-logo-row">
|
||||
<img class="apps-logo" src="/img/logo-<?=$jsConfig['siteDomain'];?>.png" alt="{{::config.primarySiteTitle}}">
|
||||
</a>
|
||||
|
||||
<script type="text/javascript">
|
||||
function resultsClose() {
|
||||
$('#result').removeClass('active');
|
||||
}
|
||||
|
||||
function init() {
|
||||
var myMap = new ymaps.Map('map', {
|
||||
center: [<?=$delivery['location'];?>],
|
||||
zoom: 17,
|
||||
type: 'yandex#map',
|
||||
controls: []
|
||||
}),
|
||||
|
||||
searchFinishPoint = new ymaps.control.SearchControl({
|
||||
options: {
|
||||
useMapBounds: true,
|
||||
noCentering: true,
|
||||
noPopup: true,
|
||||
noPlacemark: true,
|
||||
placeholderContent: 'Адрес доставки',
|
||||
size: 'large',
|
||||
float: 'none',
|
||||
position: { left: 10, top: 44 }
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
calculator = new DeliveryCalculator(myMap, myMap.getCenter()) ;
|
||||
|
||||
searchFinishPoint.events.add('load', function (event) { $('#result').removeClass('active'); });
|
||||
searchFinishPoint.events.add('clear', function (event) { $('#result').removeClass('active'); });
|
||||
searchFinishPoint.events.add('submit', function (event) { $('#result').removeClass('active'); });
|
||||
|
||||
|
||||
myMap.controls.add(searchFinishPoint);
|
||||
calculator.setStartPoint([<?=$delivery['location'];?>]);
|
||||
|
||||
searchFinishPoint.events.add('resultselect', function (e) {
|
||||
var results = searchFinishPoint.getResultsArray(),
|
||||
selected = e.get('index'),
|
||||
point = results[selected].geometry.getCoordinates();
|
||||
|
||||
calculator.setFinishPoint(point);
|
||||
})
|
||||
.add('load', function (event) {
|
||||
if (!event.get('skip') && searchFinishPoint.getResultsCount()) {
|
||||
searchFinishPoint.showResult(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function DeliveryCalculator(map, finish) {
|
||||
this._map = map;
|
||||
this._start = null;
|
||||
this._route = null;
|
||||
this._startBalloon;
|
||||
this._finishBalloon;
|
||||
|
||||
map.events.add('click', this._onClick, this);
|
||||
}
|
||||
|
||||
var ptp = DeliveryCalculator.prototype;
|
||||
|
||||
ptp._onClick= function (e) {
|
||||
if (this._start) {
|
||||
this.setFinishPoint(e.get('coords'));
|
||||
} else {
|
||||
this.setStartPoint(e.get('coords'));
|
||||
}
|
||||
};
|
||||
|
||||
ptp._onStartDragEnd = function (e) {
|
||||
var coords = this._start.geometry.getCoordinates();
|
||||
this.geocode("start", coords);
|
||||
};
|
||||
|
||||
ptp._onFinishDragEnd = function (e) {
|
||||
var coords = this._finish.geometry.getCoordinates();
|
||||
this.geocode("finish", coords);
|
||||
};
|
||||
|
||||
ptp.getDirection = function () {
|
||||
if(this._route) {
|
||||
this._map.geoObjects.remove(this._route);
|
||||
}
|
||||
|
||||
if (this._start && this._finish) {
|
||||
var self = this,
|
||||
start = this._start.geometry.getCoordinates(),
|
||||
finish = this._finish.geometry.getCoordinates(),
|
||||
startBalloon = this._startBalloon,
|
||||
finishBalloon = this._finishBalloon;
|
||||
|
||||
ymaps.route([
|
||||
finish,
|
||||
start,
|
||||
], {multiRoute: true })
|
||||
.then(function (router) {
|
||||
var routes = router.getRoutes(), distanceWithTolls = 0, distanceWithoutTolls = 0, distance = 0,
|
||||
selectedRoute, selectedRouteWithTolls, selectedRouteWithoutTolls;
|
||||
|
||||
for (var i = 0, l = routes.getLength(); i < l; i++) {
|
||||
var route = routes.get(i);
|
||||
|
||||
if (!route.properties.get('blocked')) {
|
||||
distance = Math.ceil(route.properties.get('distance').value / 1000)
|
||||
if (route.properties.get('hasTolls')) {
|
||||
if ((distanceWithTolls == 0) || (distance < distanceWithTolls)) {
|
||||
selectedRouteWithTolls = route;
|
||||
distanceWithTolls = distance;
|
||||
}
|
||||
} else {
|
||||
if ((distanceWithoutTolls == 0) || (distance < distanceWithoutTolls)) {
|
||||
selectedRouteWithoutTolls = route;
|
||||
distanceWithoutTolls = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distanceWithoutTolls > 0) { //route without tolls exists
|
||||
selectedRoute = selectedRouteWithoutTolls;
|
||||
distance = distanceWithoutTolls;
|
||||
|
||||
self.drawSelectedRoute(router, selectedRoute, distance, startBalloon, finishBalloon, self);
|
||||
self._map.setBounds(self._map.geoObjects.getBounds())
|
||||
} else {
|
||||
var distanceWithTolls2 = 0, distanceWithoutTolls2 = 0, distance2 = 0;
|
||||
|
||||
if (distanceWithTolls > 6) {
|
||||
//возможно едем через паром, попытка построить роут в объезд
|
||||
ymaps.route([
|
||||
finish,
|
||||
{ type: 'wayPoint', point: 'Сапунгорская ул.' },
|
||||
start,
|
||||
], {multiRoute: true })
|
||||
.then(function (router2) {
|
||||
var routes2 = router2.getRoutes();
|
||||
|
||||
for (var i = 0, l = routes2.getLength(); i < l; i++) {
|
||||
var route2 = routes2.get(i);
|
||||
|
||||
if (!route2.properties.get('blocked')) {
|
||||
distance2 = Math.ceil(route2.properties.get('distance').value / 1000);
|
||||
|
||||
if (route2.properties.get('hasTolls')) {
|
||||
if ((distanceWithTolls2 == 0) || (distance2 < distanceWithTolls2)) {
|
||||
selectedRouteWithTolls2 = route2;
|
||||
distanceWithTolls2 = distance2;
|
||||
}
|
||||
} else {
|
||||
if ((distanceWithoutTolls2 == 0) || (distance2 < distanceWithoutTolls2)) {
|
||||
selectedRouteWithoutTolls2 = route2;
|
||||
distanceWithoutTolls2 = distance2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distanceWithoutTolls2 > 0) { //route without tolls exists
|
||||
selectedRoute2 = selectedRouteWithoutTolls2;
|
||||
distance2 = distanceWithoutTolls2;
|
||||
} else {
|
||||
selectedRoute2 = selectedRouteWithTolls;
|
||||
distance2 = distanceWithTolls;
|
||||
}
|
||||
|
||||
self.drawSelectedRoute(router2, selectedRoute2, distance2, startBalloon, finishBalloon, self);
|
||||
self._map.setBounds(self._map.geoObjects.getBounds())
|
||||
})
|
||||
} else {
|
||||
if (distanceWithoutTolls > 0) { //route without tolls exists
|
||||
selectedRoute = selectedRouteWithoutTolls;
|
||||
distance = distanceWithoutTolls;
|
||||
} else {
|
||||
selectedRoute = selectedRouteWithTolls;
|
||||
distance = distanceWithTolls;
|
||||
}
|
||||
|
||||
self.drawSelectedRoute(router, selectedRoute, distance2, startBalloon, finishBalloon, self);
|
||||
self._map.setBounds(self._map.geoObjects.getBounds())
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
ptp.drawSelectedRoute = function(router, selectedRoute, distance, startBalloon, finishBalloon, self) {
|
||||
router.setActiveRoute(selectedRoute);
|
||||
|
||||
var /*distance = Math.round(router.getLength() / 1000),*/
|
||||
distanceLabel = "",
|
||||
message = '<div class="resultInner"><span>Расстояние: ' + (distance < 1 ? 1 : distance) + 'км.</span><br/>' +
|
||||
'<span style="font-weight: bold; font-style: italic; ">Стоимость доставки: %sр.</span><span id="resultsClose" onClick="javascript:resultsClose();">×</span><div>'
|
||||
distanceLabel = self.calculate(distance);
|
||||
self._route = selectedRoute.getPaths();
|
||||
self._route.options.set({ strokeWidth: 5, strokeColor: '0000ffff', opacity: 0.5 });
|
||||
self._map.geoObjects.add(self._route);
|
||||
self._start.properties.set('balloonContentBody', startBalloon + message.replace('%s', distanceLabel));
|
||||
self._finish.properties.set('balloonContentBody', finishBalloon + message.replace('%s', distanceLabel));
|
||||
$('#result').html(finishBalloon + message.replace('%s', distanceLabel)).addClass('active');
|
||||
};
|
||||
|
||||
ptp.setStartPoint = function (position) {
|
||||
if(this._start) {
|
||||
this._start.geometry.setCoordinates(position);
|
||||
}
|
||||
else {
|
||||
this._start = new ymaps.Placemark(position, { iconContent: 'А', }, { draggable: false });
|
||||
this._start.events.add('dragend', this._onStartDragEnd, this);
|
||||
this._map.geoObjects.add(this._start);
|
||||
}
|
||||
this.geocode("start", position);
|
||||
};
|
||||
|
||||
ptp.setFinishPoint = function (position) {
|
||||
if(this._finish) {
|
||||
this._finish.geometry.setCoordinates(position);
|
||||
}
|
||||
else {
|
||||
this._finish = new ymaps.Placemark(position, { iconContent: 'Б' }, { draggable: true });
|
||||
this._finish.events.add('dragend', this._onFinishDragEnd, this);
|
||||
this._map.geoObjects.add(this._finish);
|
||||
}
|
||||
if (this._start) {
|
||||
this.geocode("finish", position);
|
||||
}
|
||||
};
|
||||
|
||||
ptp.geocode = function (str, point) {
|
||||
ymaps.geocode(point).then(function(geocode) {
|
||||
if (str == "start") {
|
||||
this._startBalloon = "<h3><?=$delivery['address'];?></h3><p>" + geocode.geoObjects.get(0).properties.get('description') + "</p>";
|
||||
this._start.properties.set('balloonContentBody', this._startBalloon);
|
||||
} else {
|
||||
this._finishBalloon = geocode.geoObjects.get(0) &&
|
||||
geocode.geoObjects.get(0).properties.get('balloonContentBody') || '';
|
||||
}
|
||||
this.getDirection();
|
||||
}, this);
|
||||
|
||||
}
|
||||
ptp.calculate = function (len) {
|
||||
// Константы.
|
||||
var DELIVERY_TARIF = <?=$delivery['costPerKm'];?>,
|
||||
MINIMUM_COST = <?=$delivery['minimalCost'];?>;
|
||||
if (len == 1) return (MINIMUM_COST);
|
||||
return Math.max((len - 1) * DELIVERY_TARIF + MINIMUM_COST, MINIMUM_COST);
|
||||
};
|
||||
|
||||
ymaps.ready(init);
|
||||
|
||||
</script>
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
@@ -0,0 +1,208 @@
|
||||
<div id="result"></div>
|
||||
<div id="map"></div>
|
||||
|
||||
<a tabindex="-1" href="/services" title="{{::config.primarySiteTitle}}" target="_blank" class="delivery-logo-row">
|
||||
<img class="apps-logo" src="/img/logo-<?=$jsConfig['siteDomain'];?>.png" alt="{{::config.primarySiteTitle}}">
|
||||
</a>
|
||||
|
||||
<script type="text/javascript">
|
||||
function resultsClose() {
|
||||
$('#result').removeClass('active');
|
||||
}
|
||||
|
||||
function init() {
|
||||
var myMap = new ymaps.Map('map', {
|
||||
center: [<?=$delivery['location'];?>],
|
||||
zoom: 17,
|
||||
type: 'yandex#map',
|
||||
controls: []
|
||||
}),
|
||||
|
||||
searchFinishPoint = new ymaps.control.SearchControl({
|
||||
options: {
|
||||
useMapBounds: true,
|
||||
noCentering: true,
|
||||
noPopup: true,
|
||||
noPlacemark: true,
|
||||
placeholderContent: 'Адрес доставки',
|
||||
size: 'large',
|
||||
float: 'none',
|
||||
position: { left: 10, top: 44 }
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
calculator = new DeliveryCalculator(myMap, myMap.getCenter()) ;
|
||||
|
||||
searchFinishPoint.events.add('load', function (event) { $('#result').removeClass('active'); });
|
||||
searchFinishPoint.events.add('clear', function (event) { $('#result').removeClass('active'); });
|
||||
searchFinishPoint.events.add('submit', function (event) { $('#result').removeClass('active'); });
|
||||
|
||||
|
||||
myMap.controls.add(searchFinishPoint);
|
||||
calculator.setStartPoint([<?=$delivery['location'];?>]);
|
||||
|
||||
searchFinishPoint.events.add('resultselect', function (e) {
|
||||
var results = searchFinishPoint.getResultsArray(),
|
||||
selected = e.get('index'),
|
||||
point = results[selected].geometry.getCoordinates();
|
||||
|
||||
calculator.setFinishPoint(point);
|
||||
})
|
||||
.add('load', function (event) {
|
||||
if (!event.get('skip') && searchFinishPoint.getResultsCount()) {
|
||||
searchFinishPoint.showResult(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function DeliveryCalculator(map, finish) {
|
||||
this._map = map;
|
||||
this._start = null;
|
||||
this._route = null;
|
||||
this._startBalloon;
|
||||
this._finishBalloon;
|
||||
|
||||
map.events.add('click', this._onClick, this);
|
||||
}
|
||||
|
||||
var ptp = DeliveryCalculator.prototype;
|
||||
|
||||
ptp._onClick= function (e) {
|
||||
if (this._start) {
|
||||
this.setFinishPoint(e.get('coords'));
|
||||
} else {
|
||||
this.setStartPoint(e.get('coords'));
|
||||
}
|
||||
};
|
||||
|
||||
ptp._onStartDragEnd = function (e) {
|
||||
var coords = this._start.geometry.getCoordinates();
|
||||
this.geocode("start", coords);
|
||||
};
|
||||
|
||||
ptp._onFinishDragEnd = function (e) {
|
||||
var coords = this._finish.geometry.getCoordinates();
|
||||
this.geocode("finish", coords);
|
||||
};
|
||||
|
||||
ptp.getDirection = function () {
|
||||
if(this._route) {
|
||||
this._map.geoObjects.remove(this._route);
|
||||
}
|
||||
|
||||
if (this._start && this._finish) {
|
||||
var self = this,
|
||||
start = this._start.geometry.getCoordinates(),
|
||||
finish = this._finish.geometry.getCoordinates(),
|
||||
startBalloon = this._startBalloon,
|
||||
finishBalloon = this._finishBalloon;
|
||||
|
||||
ymaps.route([
|
||||
finish,
|
||||
start,
|
||||
], {multiRoute: true})
|
||||
.then(function (router) {
|
||||
//self._map.geoObjects.add(router);
|
||||
|
||||
var routes = router.getRoutes(), distanceWithTolls = 0, distanceWithoutTolls = 0, distance = 0,
|
||||
selectedRoute, selectedRouteWithTolls, selectedRouteWithoutTolls;
|
||||
for (var i = 0, l = routes.getLength(); i < l; i++) {
|
||||
var route = routes.get(i);
|
||||
|
||||
if (!route.properties.get('blocked')) {
|
||||
distance = Math.ceil(route.properties.get('distance').value / 1000)
|
||||
if (route.properties.get('hasTolls')) {
|
||||
if ((distanceWithTolls == 0) || (distance < distanceWithTolls)) {
|
||||
selectedRouteWithTolls = route;
|
||||
distanceWithTolls = distance;
|
||||
}
|
||||
} else {
|
||||
if ((distanceWithoutTolls == 0) || (distance < distanceWithoutTolls)) {
|
||||
selectedRouteWithoutTolls = route;
|
||||
distanceWithoutTolls = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distanceWithoutTolls > 0) { //route without tolls exists
|
||||
selectedRoute = selectedRouteWithoutTolls;
|
||||
distance = distanceWithoutTolls;
|
||||
} else {
|
||||
selectedRoute = selectedRouteWithTolls;
|
||||
distance = distanceWithTolls;
|
||||
}
|
||||
|
||||
|
||||
router.setActiveRoute(selectedRoute);
|
||||
|
||||
var /*distance = Math.round(router.getLength() / 1000),*/
|
||||
distanceLabel = "",
|
||||
message = '<div class="resultInner"><span>Расстояние: ' + (distance < 1 ? 1 : distance) + 'км.</span><br/>' +
|
||||
'<span style="font-weight: bold; font-style: italic; ">Стоимость доставки: %sр.</span><span id="resultsClose" onClick="javascript:resultsClose();">×</span><div>'
|
||||
distanceLabel = self.calculate(distance);
|
||||
self._route = selectedRoute.getPaths();
|
||||
self._route.options.set({ strokeWidth: 5, strokeColor: '0000ffff', opacity: 0.5 });
|
||||
self._map.geoObjects.add(self._route);
|
||||
self._start.properties.set('balloonContentBody', startBalloon + message.replace('%s', distanceLabel));
|
||||
self._finish.properties.set('balloonContentBody', finishBalloon + message.replace('%s', distanceLabel));
|
||||
$('#result').html(finishBalloon + message.replace('%s', distanceLabel)).addClass('active');
|
||||
});
|
||||
|
||||
self._map.setBounds(self._map.geoObjects.getBounds())
|
||||
}
|
||||
};
|
||||
|
||||
ptp.setStartPoint = function (position) {
|
||||
if(this._start) {
|
||||
this._start.geometry.setCoordinates(position);
|
||||
}
|
||||
else {
|
||||
this._start = new ymaps.Placemark(position, { iconContent: 'А', }, { draggable: false });
|
||||
this._start.events.add('dragend', this._onStartDragEnd, this);
|
||||
this._map.geoObjects.add(this._start);
|
||||
}
|
||||
this.geocode("start", position);
|
||||
};
|
||||
|
||||
ptp.setFinishPoint = function (position) {
|
||||
if(this._finish) {
|
||||
this._finish.geometry.setCoordinates(position);
|
||||
}
|
||||
else {
|
||||
this._finish = new ymaps.Placemark(position, { iconContent: 'Б' }, { draggable: true });
|
||||
this._finish.events.add('dragend', this._onFinishDragEnd, this);
|
||||
this._map.geoObjects.add(this._finish);
|
||||
}
|
||||
if (this._start) {
|
||||
this.geocode("finish", position);
|
||||
}
|
||||
};
|
||||
|
||||
ptp.geocode = function (str, point) {
|
||||
ymaps.geocode(point).then(function(geocode) {
|
||||
if (str == "start") {
|
||||
this._startBalloon = "<h3><?=$delivery['address'];?></h3><p>" + geocode.geoObjects.get(0).properties.get('description') + "</p>";
|
||||
this._start.properties.set('balloonContentBody', this._startBalloon);
|
||||
} else {
|
||||
this._finishBalloon = geocode.geoObjects.get(0) &&
|
||||
geocode.geoObjects.get(0).properties.get('balloonContentBody') || '';
|
||||
}
|
||||
this.getDirection();
|
||||
}, this);
|
||||
|
||||
}
|
||||
ptp.calculate = function (len) {
|
||||
// Константы.
|
||||
var DELIVERY_TARIF = <?=$delivery['costPerKm'];?>,
|
||||
MINIMUM_COST = <?=$delivery['minimalCost'];?>;
|
||||
if (len == 1) return (MINIMUM_COST);
|
||||
return Math.max((len - 1) * DELIVERY_TARIF + MINIMUM_COST, MINIMUM_COST);
|
||||
};
|
||||
|
||||
ymaps.ready(init);
|
||||
|
||||
</script>
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
@@ -0,0 +1,8 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon/favicon_32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon_16.png">
|
||||
|
||||
<link rel="shortcut icon" type="image/png" href="/img/favicon/favicon_16.png" />
|
||||
<?php foreach(['57', '60', '76', '114', '120', '128', '144', '152', '167', '180', '192'] as $s) {
|
||||
echo '<link rel="apple-touch-icon-precomposed" sizes="' . $s . 'x' . $s . '" href="/img/favicon/apple-touch-icon-' . $s . '-precomposed.png" />' . "\n";
|
||||
} ?>
|
||||
<link rel="apple-touch-icon-precomposed" href="/img/favicon/apple-touch-icon-57-precomposed.png" />
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo json_encode($result);
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php if (!empty($isAuthorized)) { ?>
|
||||
<nav class="navbar sticky-top navbar-expand-lg navbar-light bg-light" data-ng-controller="NavController" >
|
||||
<div class="container">
|
||||
<ul class="navbar-nav">
|
||||
<li class="dropdown navbar-current-app">
|
||||
<?php
|
||||
foreach($jsConfig['appsList'] as $app) {
|
||||
if (!empty($currentApp) && ($currentApp == $app['id']) && !empty($authUserAvailableApps) && in_array($app['id'], $authUserAvailableApps)) {
|
||||
echo '<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">'.$app['label'].'</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="dropdown-menu">
|
||||
<?php
|
||||
foreach($jsConfig['appsList'] as $app) {
|
||||
if (!empty($authUserAvailableApps) && in_array($app['id'], $authUserAvailableApps)) {
|
||||
echo '<a href="' . $app['adminUrl'] . '" class="dropdown-item">' . $app['label'] . '</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<button class="navbar-toggler pull-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse justify-content-between" id="navbarNavDropdown">
|
||||
<ul class="navbar-nav">
|
||||
|
||||
|
||||
<?php if (!empty($currentApp)) {
|
||||
if ($currentApp == "cut") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "CutOrders" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Заказы", ['controller' => 'CutOrders', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<li class="<?php echo($this->request->getParam('controller') == "CutSettings" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Настройки", ['controller' => 'CutSettings', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<li class="<?php echo($this->request->getParam('controller') == "CutStatistics" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Статистика", ['controller' => 'CutStatistics', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
if ($currentApp == "calcDoors") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "CalcDoorsOrders" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Заказы", ['controller' => 'CalcDoorsOrders', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<li class="<?php echo($this->request->getParam('controller') == "CalcDoorsSettings" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Настройки", ['controller' => 'CalcDoorsSettings', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<li class="<?php echo($this->request->getParam('controller') == "CalcDoorsStatistics" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Статистика", ['controller' => 'CalcDoorsStatistics', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php }
|
||||
|
||||
if ($currentApp == "fasad") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "FasadOrders" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Заказы", ['controller' => 'FasadOrders', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<li class="<?php echo($this->request->getParam('controller') == "FasadSettings" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Настройки", ['controller' => 'FasadSettings', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<li class="<?php echo($this->request->getParam('controller') == "FasadStatistics" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Статистика", ['controller' => 'FasadStatistics', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
if ($currentApp == "smsSubscribes") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "SmsSubscribes" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Список рассылок", ['controller' => 'SmsSubscribes', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php }
|
||||
|
||||
if ($currentApp == "smsOrdersReady") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "SmsOrdersReady" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Поиск", ['controller' => 'SmsOrdersReady', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php }
|
||||
|
||||
if ($currentApp == "emailSubscribes") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "EmailSubscribes" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Список рассылок", ['controller' => 'EmailSubscribes', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php }
|
||||
|
||||
if ($currentApp == "deliveryJournal") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "DeliveryJournal" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Журнал", ['controller' => 'DeliveryJournal', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
<?php }
|
||||
|
||||
if ($currentApp == "ordersInfo") { ?>
|
||||
<li class="<?php echo($this->request->getParam('controller') == "OrdersInfo" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Счета", ['controller' => 'OrdersInfo', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>
|
||||
|
||||
<!--<li class="<?php echo($this->request->getParam('controller') == "OrdersInfoSettings" ? "active" : "") ?>">
|
||||
<?php echo $this->Html->link("Настройки", ['controller' => 'OrdersInfoSettings', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "nav-link"), null); ?>
|
||||
</li>-->
|
||||
<?php }
|
||||
}?>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
<li class="dropdown">
|
||||
<?php echo $this->Html->link('<i class="fa fa-user"></i> ' . $authUserName, '#', array("escape" => false, "class" => "nav-link dropdown-toggle", "data-toggle" => "dropdown"), null); ?>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<?php
|
||||
if (in_array("cut", $authUserAvailableApps) && ($currentApp == "cut")) {
|
||||
echo '<span class="dropdown-item select-file-button cursor-pointer" ngf-select data-ng-model="nav.convertAstraToBazisFile" name="convertAstraToBazisFile" ngf-accept="\'.xml\'" ngf-max-size="20MB" data-ng-change="nav.convertAstraToBazis()">Астра<i class="fa fa-arrow-right"></i>Базис конвертер</span>';
|
||||
}
|
||||
|
||||
if (in_array("cut", $authUserAvailableApps) || in_array("calcDoors", $authUserAvailableApps)) {
|
||||
echo $this->Html->link("Настройки", ['controller' => 'Settings', 'action' => 'index', 'prefix' => 'manager'], array("escape" => false, "class" => "dropdown-item"), null);
|
||||
}
|
||||
|
||||
if ($authUserRole == "admin") {
|
||||
echo $this->Html->link("Пользователи", ['controller' => 'Users', 'action' => 'users_list' , 'prefix' => 'manager'], array("escape" => false, "class" => "dropdown-item"), null);
|
||||
}
|
||||
|
||||
if ($authUserRole != "kassir") {
|
||||
echo '<div class="dropdown-divider"></div>';
|
||||
}
|
||||
|
||||
echo $this->Html->link("Выход", ['controller' => 'Users', 'action' => 'logout' , 'prefix' => 'manager' ], array("escape" => false, "class" => "dropdown-item", 'confirm' => "Вы уверены?"));
|
||||
?>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="current-time nav-link"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<?php } ?>
|
||||
@@ -0,0 +1,15 @@
|
||||
<div class="page-404">
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<a href="<?=$jsConfig['primarySiteUrl'];?>" title="<?=$jsConfig['primarySiteTitle'];?>"><img class="apps-logo" src="/img/logo-<?=$jsConfig['siteDomain'];?>.png"></a><br/><br/>
|
||||
|
||||
<?= $this->element("services");?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
<div>
|
||||
<a href="https://supersam24.ru" class="services-link btn btn-primary">Магазин фурнитуры</a>
|
||||
<a href="https://supersamsev.ru" class="services-link btn btn-primary">Магазин ДСП</a>
|
||||
<a href="https://prometeysev.ru" class="services-link btn btn-primary">Все для кухни, ремонта и дома</a>
|
||||
|
||||
<div class="services-social-links">
|
||||
<a class="vk" href="https://vk.com/supersam_aristo" target="_blank">
|
||||
<img src="/img/social/vk-h.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<br/><br/></div>
|
||||
|
||||
<b>Также вы можете воспользоваться нашими сервисами:</b><br/>
|
||||
<div>
|
||||
<?php
|
||||
foreach ($jsConfig["appsList"] as $app) {
|
||||
if (!empty($app['url'])) {
|
||||
echo '<a href="' . $app['url'] . '" class="services-link btn btn-info">' . (!empty($app['site_label']) ? $app['site_label'] : $app['label_long']) . '</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<div>
|
||||
<?php
|
||||
foreach ($jsConfig["delivery"] as $delivery) {
|
||||
if (empty($delivery['is_deleted'])) {
|
||||
echo '<a href="/delivery/' . $delivery['slug'] . '" class="services-link btn btn-info">' . $delivery['label404'] . '</a>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
$content = explode("\n", $content);
|
||||
|
||||
foreach ($content as $line) :
|
||||
echo '<p> ' . $line . "</p>\n";
|
||||
endforeach;
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
echo $content;
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
$this->layout = 'error';
|
||||
|
||||
if (Configure::read('debug')) :
|
||||
$this->layout = 'dev_error';
|
||||
|
||||
$this->assign('title', $message);
|
||||
$this->assign('templateName', 'error400.ctp');
|
||||
|
||||
$this->start('file');
|
||||
?>
|
||||
<?php if (!empty($error->queryString)) : ?>
|
||||
<p class="notice">
|
||||
<strong>SQL Query: </strong>
|
||||
<?= h($error->queryString) ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($error->params)) : ?>
|
||||
<strong>SQL Query Params: </strong>
|
||||
<?php Debugger::dump($error->params) ?>
|
||||
<?php endif; ?>
|
||||
<?= $this->element('auto_table_warning') ?>
|
||||
<?php
|
||||
if (extension_loaded('xdebug')) :
|
||||
xdebug_print_function_stack();
|
||||
endif;
|
||||
|
||||
$this->end();
|
||||
endif;
|
||||
?>
|
||||
<?= $this->element("page404");?>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Error\Debugger;
|
||||
|
||||
$this->layout = 'error';
|
||||
|
||||
if (Configure::read('debug')) :
|
||||
$this->layout = 'dev_error';
|
||||
|
||||
$this->assign('title', $message);
|
||||
$this->assign('templateName', 'error500.ctp');
|
||||
|
||||
$this->start('file');
|
||||
?>
|
||||
<?php if (!empty($error->queryString)) : ?>
|
||||
<p class="notice">
|
||||
<strong>SQL Query: </strong>
|
||||
<?= h($error->queryString) ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($error->params)) : ?>
|
||||
<strong>SQL Query Params: </strong>
|
||||
<?php Debugger::dump($error->params) ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($error instanceof Error) : ?>
|
||||
<strong>Error in: </strong>
|
||||
<?= sprintf('%s, line %s', str_replace(ROOT, 'ROOT', $error->getFile()), $error->getLine()) ?>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
echo $this->element('auto_table_warning');
|
||||
|
||||
if (extension_loaded('xdebug')) :
|
||||
xdebug_print_function_stack();
|
||||
endif;
|
||||
|
||||
$this->end();
|
||||
endif;
|
||||
?>
|
||||
<?= $this->element("page404");?>
|
||||
@@ -0,0 +1,934 @@
|
||||
<div data-ng-controller="FasadController" class="hidden-on-load">
|
||||
<div class="container apps-container">
|
||||
<form name="fasadConfigForm">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="sheet-config-row">
|
||||
<div class="row">
|
||||
<div class="col-6 form-horizontal">
|
||||
<div class="form-group no-bottom-margin">
|
||||
<h3 class="siteTitle">
|
||||
<span>{{config.common.siteTitle.value}}</span>
|
||||
<button tabindex="-1" type="button" class="btn btn-sm btn-warning openSelectSheetConfigModal" data-ng-click="fasad.openSelectSheetConfigModal()">Выбрать фактуру листа и кромки</button>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedSheetImage = utilities.getFasadSheetImageById(fasad.selectedSheetData.sheetId, 'image');""}}
|
||||
<label for="selectedSheetDimension" class="col-4 col-form-label">Фактура листа:<a tabindex="-1" data-ng-if="fasad.selectedSheetData.sheetId && selectedSheetImage" href="{{selectedSheetImage}}" data-lightbox="sheetIdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label selected-sheet-dimension">
|
||||
{{fasad.getSelectedSheetLabel(fasad.selectedSheetData.sheetId)}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label for="selectedSheetDimension" class="col-4 col-form-label">Размер листа: </label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label selected-sheet-dimension">{{fasad.getSelectedSheetFullDimensions()}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label class="col-4 col-form-label">Размер распила:<a class="popover-button cut-size-desc" tabindex="-1" role="button" data-ng-show="fasad.selectedSheetData.sheetId" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{fasad.faceDescriptionWithPrice | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a> </label>
|
||||
<div class="col-8">
|
||||
<label class="col-form-label selected-sheet-dimension">{{fasad.getSelectedSheetDimensions()}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="row logo-row text-left">
|
||||
<div class="col-5">
|
||||
<a tabindex="-1" href="/services" title="{{::config.primarySiteTitle}}" target="_blank">
|
||||
<img src="/img/logo.png" alt="{{::config.primarySiteTitle}}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<h5 class="addressDelivery">
|
||||
<span>Наш адрес:</span>
|
||||
<span class="addressDelivery" data-ng-bind-html="::utilities.getConfigLabel('addressDelivery') | trustAs"></span>
|
||||
<span class="addressDelivery" data-ng-bind-html="::utilities.getConfigLabel('addressDeliveryAdd') | trustAs"></span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="detailWithBordersWarning text-danger">{{::utilities.getConfigLabel('detailWithBordersWarning')}}</h5>
|
||||
|
||||
<div class="headerInfoLabel">{{::utilities.getConfigLabel('headerInfoLabel') | trustAs}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-horizontal checkbox-group no-bottom-margin">
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label class="col-8 col-form-label" data-ng-click="fasad.mergeSimilarDetailsToggle()">Объединение одинаковых деталей: </label>
|
||||
<div class="col-4" id="mergeSimilarDetails">
|
||||
<i class="fa fa-square-o" data-ng-if="!fasad.mergeSimilarDetails" data-ng-click="fasad.mergeSimilarDetailsToggle()"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="fasad.mergeSimilarDetails" data-ng-click="fasad.mergeSimilarDetailsToggle()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
<label class="col-6 col-form-label" data-ng-click="fasad.packCuttingsToOrderToggle()">Вкладывать остатки в заказ: </label>
|
||||
<div class="col-4">
|
||||
<i class="fa fa-square-o" data-ng-if="!fasad.packCuttingsToOrder" data-ng-click="fasad.packCuttingsToOrderToggle()"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="fasad.packCuttingsToOrder" data-ng-click="fasad.packCuttingsToOrderToggle()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-horizontal">
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedBorder1Image = utilities.getFasadBorderImageById(fasad.selectedSheetData.border1Id);""}}
|
||||
<label class="col-3 col-form-label">
|
||||
Кромка №1:<a tabindex="-1" class="preview-button" data-ng-if="fasad.selectedSheetData.border1Id && selectedBorder1Image" href="{{selectedBorder1Image}}" data-lightbox="border1IdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label selected-sheet-dimension">
|
||||
<span data-ng-bind-html="fasad.getBorderLabel(fasad.selectedSheetData.border1Id, fasad.selectedSheetData.border1Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row no-bottom-margin">
|
||||
{{selectedBorder2Image = utilities.getFasadBorderImageById(fasad.selectedSheetData.border2Id);""}}
|
||||
<label class="col-3 col-form-label">
|
||||
Кромка №2:<a tabindex="-1" class="preview-button" data-ng-if="fasad.selectedSheetData.border2Id && selectedBorder2Image" href="{{utilities.getFasadBorderImageById(fasad.selectedSheetData.border2Id)}}" data-lightbox="border2IdLightBox"><i class="fa fa-question-circle"></i></a>
|
||||
</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label selected-sheet-dimension">
|
||||
<span data-ng-bind-html="fasad.getBorderLabel(fasad.selectedSheetData.border2Id, fasad.selectedSheetData.border2Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-horizontal">
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderName">ФИО: <a class="popover-button" tabindex="-1" role="button" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{utilities.getConfigLabel('fioIsRequired', true) | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a></label>
|
||||
<div class="col-9" data-ng-class="fasadConfigForm.orderName.$invalid && fasadConfigForm.orderName.$dirty ? 'has-error' : ''">
|
||||
<input type="text" class="form-control form-control-sm" name="orderName" id="orderName" data-ng-model="fasad.orderName" required data-ng-enter="fasad.onFieldEnter('orderPhone')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderPhone">Телефон: <a class="popover-button" tabindex="-1" role="button" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{utilities.getConfigLabel('phoneIsRequired', true) | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a></label>
|
||||
<div class="col-9" data-ng-class="fasadConfigForm.orderPhone.$invalid && fasadConfigForm.orderPhone.$dirty ? 'has-error' : ''">
|
||||
<input type="text" class="form-control form-control-sm" name="orderPhone" id="orderPhone" data-ng-model="fasad.orderPhone" data-model-view-value="true" data-digits-only placeholder=" " required data-ng-enter="fasad.onFieldEnter('orderEmail')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderEmail">Email: <a class="popover-button" tabindex="-1" role="button" data-container="body" data-toggle="popover" data-trigger="focus" data-placement="right" data-content="{{utilities.getConfigLabel('emailIsRequired', true) | trustAs}}" data-html="true"><i class="fa fa-question-circle"></i></a></label>
|
||||
<div class="col-9" data-ng-class="fasadConfigForm.orderEmail.$invalid && fasadConfigForm.orderEmail.$dirty ? 'has-error' : ''">
|
||||
<input type="email" class="form-control form-control-sm" name="orderEmail" id="orderEmail" data-ng-model="fasad.orderEmail" required data-ng-enter="fasad.onFieldEnter('orderAddress')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<label class="col-3 col-form-label" for="orderAddress">Адрес доставки: </label>
|
||||
<div class="col-9" data-ng-class="fasadConfigForm.orderAddress.$invalid && fasadConfigForm.orderAddress.$dirty ? 'has-error' : ''">
|
||||
<input type="text" class="form-control form-control-sm" name="orderAddress" id="orderAddress" data-ng-model="fasad.orderAddress" data-ng-enter="fasad.onFieldEnter('orderComment')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group row margin-top-3 no-bottom-margin">
|
||||
<div class="col-12">
|
||||
<textarea class="form-control form-control-sm margin-top-3" name="orderComment" id="orderComment" data-ng-model="fasad.orderComment" placeholder="Комментарий к заказу"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card details-config">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-4 cut-results">
|
||||
<div class="print-left">
|
||||
<div data-ng-if="fasad.orderNum && (fasad.orderNum.length > 0)">Заказ: {{fasad.orderNum}}</div>
|
||||
<div>Листов в распиле: {{fasad.sheets.length}}</div>
|
||||
|
||||
{{selectedSheetsInStock = utilities.getSelectedSheetsInStock(fasad.selectedSheetData.sheetId);""}}
|
||||
<div data-ng-if="(selectedSheetsInStock != null) && (selectedSheetsInStock < fasad.sheets.length)" class="text-warning">Листов на складе: {{selectedSheetsInStock}}</div>
|
||||
|
||||
<div>Всего деталей: {{fasad.getDetailsCount()}}</div>
|
||||
<div>Площадь деталей: {{(fasad.getDetailsArea()/1000000).toFixed(2).replace(".00", "")}}м<sup>2</sup></div>
|
||||
<div>Длина пропила: {{fasad.notchCount}}м.</div>
|
||||
<div data-ng-if="fasad.grooveCount.length > 0">Длина пропила пазов: {{fasad.grooveCount}}м.</div>
|
||||
<div data-ng-if="fasad.selectedSheetData.border1Id || fasad.selectedSheetData.border2Id">Длина кромок:
|
||||
<ul>
|
||||
<li data-ng-repeat="borderId in [1, 2]" data-ng-if="fasad.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
кромка №{{borderId}} - {{((fasad.selectedSheetData["border" + borderId + "Count"] ? fasad.selectedSheetData["border" + borderId + "Count"] : 0)/1000).toFixed(2).replace(".00", "")}}м.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div><span class="text-strong-danger">Ориентировочная</span> <span class="no-wrap">стоимость: {{fasad.price}} руб.</span></div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="order-buttons">
|
||||
<div class="" data-ng-if="config.createdForManagerId">
|
||||
Если вы знаете менеджера,<br/> выберите его в поле ниже<br/>
|
||||
<div class="btn-group order-available-managers">
|
||||
<button tabindex="-1" data-ng-disabled="!fasad.selectedSheetData.sheetId || fasadConfigForm.$invalid || fasad.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ utilities.getAvailableToOrderManagerNameById(fasad.createdForManagerId) }} <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li data-ng-repeat="manager in config.availableToOrderManagers">
|
||||
<a tabindex="-1" data-ng-click="fasad.setCreatedForManagerId(manager.id)" class="dropdown-item">{{manager.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="btn-group print-order-button" data-ng-if="config.additionalActionsAllowed">
|
||||
<button tabindex="-1" data-ng-disabled="!fasad.selectedSheetData.sheetId || fasadConfigForm.$invalid || fasad.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-print"></i> Печать <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a tabindex="-1" data-ng-click="fasad.printOrder('Spec')" class="dropdown-item">Печать спецификации</a></li>
|
||||
<li><a tabindex="-1" data-ng-click="fasad.printOrder('Fasad')" class="dropdown-item">Печать карт распила</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button tabindex="-1" data-ng-if="!config.savedOrderData && (config.branches.length == 1)" data-ng-disabled="!fasad.selectedSheetData.sheetId || fasadConfigForm.$invalid || fasad.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary send-order-button" data-ng-click="fasad.sendOrderEmailNotify(config.branches[0].id)">Отправить менеджеру</button>
|
||||
|
||||
<div class="btn-group send-order-button" data-ng-if="!config.savedOrderData && (config.branches.length > 1)">
|
||||
<button tabindex="-1" data-ng-disabled="!fasad.selectedSheetData.sheetId || fasadConfigForm.$invalid || fasad.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Отправить менеджеру <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li data-ng-repeat="branch in config.branches"><a tabindex="-1" data-ng-click="fasad.sendOrderEmailNotify(branch.id)" class="dropdown-item">{{branch.label}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button tabindex="-1" data-ng-if="config.savedOrderData" data-ng-disabled="!fasad.selectedSheetData.sheetId || fasadConfigForm.$invalid || fasad.isSendOrderEmailSubmitting" type="button" class="btn btn-sm btn-primary send-order-button" data-ng-click="fasad.sendOrderEmailNotify(false)">Сохранить заказ</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-8 details-list">
|
||||
<h5 class="justify-content-between">
|
||||
<span>Параметры деталей, мм</span>
|
||||
</h5>
|
||||
|
||||
<div>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr data-ng-repeat="detail in fasad.details">
|
||||
<td colspan="7">
|
||||
<div>
|
||||
<table class="table table-details-list table-no-borders">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="detail-number-label">№</th>
|
||||
<th>Длина</th>
|
||||
<th>Ширина</th>
|
||||
<th>Кол-во, шт</th>
|
||||
<th class="detail-borders"><span data-ng-if="fasad.selectedSheetData.border1Id > 0">Кромка</span></th>
|
||||
<th class="detailCorners detailGrooves text-center">Доп.</th>
|
||||
<th class=""></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="detail-number-label">
|
||||
<span>{{$index+1}}</span>
|
||||
|
||||
<a tabindex="-1" href="#" data-ng-click="fasad.openDetailLabelConfigModal(detail.id)" data-click-prevent="true" title="Наименование детали">
|
||||
<i class="fa fa-pencil" data-ng-class="{'text-success' : detail.label && (detail.label.length > 0) }"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<input id="detail{{detail.id}}width" class="form-control form-control-sm" type="text" data-ng-model="detail.width" data-digits-only data-ng-enter="fasad.onDetailEnter(detail, 'width')" pattern="[0-9]*">
|
||||
</td>
|
||||
<td>
|
||||
<input id="detail{{detail.id}}height" class="form-control form-control-sm" type="text" data-ng-model="detail.height" data-digits-only data-ng-enter="fasad.onDetailEnter(detail, 'height')" pattern="[0-9]*">
|
||||
</td>
|
||||
<td>
|
||||
<input id="detail{{detail.id}}count" class="form-control form-control-sm" type="text" data-ng-model="detail.count" data-digits-only data-ng-enter="fasad.onDetailEnter(detail, 'count')" pattern="[0-9]*">
|
||||
</td>
|
||||
<td class="detail-borders">
|
||||
<span class="detail-color-box" style="background-color: {{detail.color}}" data-ng-if="!fasad.selectedSheetData.border1Id"></span>
|
||||
|
||||
<div data-ng-if="fasad.selectedSheetData.border1Id > 0" data-ng-class="{'single-border-config' : !fasad.selectedSheetData.border2Id}">
|
||||
<div class="left-detail-border" >
|
||||
<div class="detail-border detail-border-{{borderId}} {{fasad.detailsBorders[detail.id].left == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="fasad.toggleDetailBorder(detail, 'left', borderId)" title="{{fasad.detailsBorders[detail.id].left == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="fasad.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-border-center">
|
||||
<div class="top-detail-border">
|
||||
<div class="detail-border detail-border-{{borderId}} {{fasad.detailsBorders[detail.id].top == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="fasad.toggleDetailBorder(detail, 'top', borderId)" title="{{fasad.detailsBorders[detail.id].top == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="fasad.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-borders {{fasad.getDetailBordersClass(detail)}}" style="background-color: {{detail.color}}; border-color: {{detail.color}};"></div>
|
||||
|
||||
<div class="bottom-detail-border">
|
||||
<div class="detail-border detail-border-{{borderId}} {{fasad.detailsBorders[detail.id].bottom == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="fasad.toggleDetailBorder(detail, 'bottom', borderId)" title="{{fasad.detailsBorders[detail.id].bottom == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="fasad.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-detail-border">
|
||||
<div class="detail-border detail-border-{{borderId}} {{fasad.detailsBorders[detail.id].right == borderId ? 'active' : ''}}" data-ng-repeat="borderId in [1, 2]" data-ng-click="fasad.toggleDetailBorder(detail, 'right', borderId)" title="{{fasad.detailsBorders[detail.id].right == borderId ? 'Удалить кромку' : 'Добавить кромку'}}" data-ng-if="fasad.selectedSheetData['border'+borderId+'Id'] > 0">
|
||||
{{borderId}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="config-detailCorners-button">
|
||||
<a tabindex="-1" href="#" data-ng-click="fasad.openDetailCornersConfigModal(detail, $index+1)" data-click-prevent="true" title="Скругление/срез/паз" data-ng-disabled="!fasad.isDetailDimensionsFilled(detail)">
|
||||
<img src="/img/corners.png" alt="{{::config.siteTitle}}">
|
||||
</a>
|
||||
</td>
|
||||
<td class="remove-detail-button">
|
||||
<a tabindex="-1" href="#" class="text-danger remove-detail" data-ng-if="fasad.details.length > 1" data-ng-click="fasad.removeDetail(detail)" data-click-prevent="true">x</a>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div data-ng-bind-html="fasad.getDetailCornersText(detail) | trustAs"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div data-ng-bind-html="fasad.getDetailGroovesText(detail) | trustAs"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex justify-content-between">
|
||||
<button tabindex="-1" class="btn btn-sm btn-success" data-ng-click="fasad.addDetail()" data-click-prevent="true">
|
||||
Добавить деталь
|
||||
</button>
|
||||
|
||||
<button tabindex="-1" class="btn btn-danger btn-sm clear-button" data-ng-click="fasad.confirmCleanup()" data-click-prevent="true">
|
||||
Очистить
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="sheets-wrap" data-ng-if="(fasad.selectedSheetData.sheetId) && fasad.selectedSheetDimension">
|
||||
<div class="card" data-ng-repeat="sheet in fasad.sheets">
|
||||
<div class="card-body">
|
||||
<div class="sheet" data-ng-class="fasad.sheetClass" data-ng-style="fasad.sheetStyle">
|
||||
<div class="info sheet-title">Лист {{sheet.id}}</div>
|
||||
<div class="info sheet-width">
|
||||
<span class="sheet-width-left">|‹</span>
|
||||
<span class="sheet-width-right">›|</span>
|
||||
{{fasad.selectedSheetDimension.width}} мм
|
||||
</div>
|
||||
<div class="info sheet-height">
|
||||
<span class="sheet-height-top">›|</span>
|
||||
<span class="sheet-height-bottom">|‹</span>
|
||||
<span data-ng-style="fasad.sheetHeightStyle">{{fasad.selectedSheetDimension.height}} мм</span>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="detail in sheet.details" data-ng-style="fasad.getDetailStyle(detail)" class="detail detail-with-entire-borders" data-ng-class="fasad.getDetailClass(detail)" data-ng-click="fasad.rotateDetail(detail)">
|
||||
<div class="detail-height">{{detail.height}}</div>
|
||||
<div class="detail-width">{{detail.width}}</div>
|
||||
|
||||
<div class=""></div>
|
||||
|
||||
<a class="detail-label-edit" tabindex="-1" href="#" data-ng-click="fasad.openDetailLabelConfigModal(detail.detailId)" data-click-prevent="true" title="{{fasad.getDetailLabel(detail.detailId)}}" data-ng-if="fasad.getDetailLabel(detail.detailId).length > 0">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
|
||||
<div data-ng-repeat="borderPosition in config.borderPositions" class="entire-border {{borderPosition}}-border" data-ng-if="fasad.detailsBorders[detail.detailId][borderPosition]"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="notifyModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div>{{fasad.notifyMessage}}</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-info" data-dismiss="modal" href="#">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="notifySendOrderEmailModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div data-ng-if="config.savedOrderData" data-ng-bind-html="::utilities.getConfigLabel('notifySaveOrderDataMessage', true) | trustAs"></div>
|
||||
|
||||
<div data-ng-if="!config.savedOrderData" data-ng-bind-html="::utilities.getConfigLabel('notifySendOrderEmailMessage') | trustAs"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-info" data-dismiss="modal" href="#">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="confirmCleanupModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning" data-ng-bind-html="::utilities.getConfigLabel('confirmCleanupMessage') | trustAs">
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="fullOrderCleanupCheckbox" data-ng-model="fasad.fullOrderCleanup">
|
||||
<label class="form-check-label" for="fullOrderCleanupCheckbox">
|
||||
Очистить всё
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Отмена</button>
|
||||
<button type="button" class="btn btn-primary" data-ng-click="fasad.cleanup(true)">Продолжить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="modal fade" id="selectSheetConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<span data-ng-show="fasad.activeSheetSelectStep == 1">Шаг 1/4: Выбор фактуры и размера листа</span>
|
||||
<span data-ng-show="fasad.activeSheetSelectStep == 2">Шаг 2/4: Выбор цвета и толщины кромки №1</span>
|
||||
<span data-ng-show="fasad.activeSheetSelectStep == 3">Шаг 3/4: Выбор цвета и толщины кромки №2</span>
|
||||
<span data-ng-show="fasad.activeSheetSelectStep == 4">Шаг 4/4: Подтверждение выбранной конфигурации</span>
|
||||
</h5>
|
||||
|
||||
<div class="input-group input-group-sm search-input-group" data-ng-show="(fasad.activeSheetSelectStep != 4)">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="searchFilter{{fasad.activeSheetSelectStep}}" >
|
||||
<i class="fa fa-search"></i>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input placeholder="Поиск.." id="searchFilter{{fasad.activeSheetSelectStep}}" class="form-control " type="text" data-ng-model="fasad.searchFilters[fasad.activeSheetSelectStep]">
|
||||
</div>
|
||||
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div data-ng-show="fasad.activeSheetSelectStep == 1">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectSheetId{{sheet.id}}" class="select-sheet-data col-6 col-xl-4 col-lg-4 col-md-4 col-sm-6" data-ng-repeat="sheet in filteredSheets = (config.sheets | filterData:fasad.searchFilters[1])" data-ng-if="sheet.is_active || config.savedOrderData && config.savedOrderData.sheet_data && (config.savedOrderData.sheet_data.sheetId == sheet.id)">
|
||||
<div data-ng-click="fasad.selectSheetId(sheet)" data-ng-class="{'selected' : (fasad.selectSheetConfigModalData.sheetId == sheet.id)}">
|
||||
<div class="select-sheet-image img-thumbnail" data-ng-if="fasad.isSelectSheetConfigModalTriggered && sheet.thumb">
|
||||
<img data-ng-src="{{utilities.getFasadSheetImageById(sheet.id, 'thumb')}}" class="img-lazy">
|
||||
</div>
|
||||
|
||||
<div class="select-sheet-label">
|
||||
<span><b>{{sheet.label}}</b></span>
|
||||
<span>Размеры:</> {{fasad.getSheetFullDimensions(sheet.sheet_dimension_id)}}</span>
|
||||
<span>Цена: {{sheet.price}} руб. <span data-ng-if="sheet.sheetIdFor1C && (sheet.quantityIn1C != null)" class="sheet-1c-quantity" data-ng-class="{'text-danger': (sheet.quantityIn1C < 1)}">Ост. {{sheet.quantityIn1C > 0 ? sheet.quantityIn1C : 0}}л</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a tabindex="-1" href="{{utilities.getFasadSheetImageById(sheet.id, 'image')}}" data-lightbox="sheet{{sheet.id}}LightBox" class="select-sheet-preview" data-ng-if="sheet.image" data-ng-class="{'no-sheet-thumb' : !sheet.thumb}">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredSheets.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-show="fasad.activeSheetSelectStep == 2">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП. <br/>
|
||||
Выберите цвет и размер кромки №1 или нажмите "Пропустить", если в поклейке кромок нет необходимости.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectBorder1Id{{border.id}}" class="select-border-data col-12" data-ng-repeat="border in filteredBorders1 = (config.borders | filterData:fasad.searchFilters[2])">
|
||||
<div data-ng-click="fasad.selectBorderId(1, border)" data-ng-class="{'selected' : (fasad.selectSheetConfigModalData.border1Id == border.id)}">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="select-border-image" data-ng-if="fasad.isSelectSheetConfigModalTriggered && border.image">
|
||||
<img data-src="{{utilities.getFasadBorderImageById(border.id)}}" class="img-thumbnail img-lazy">
|
||||
</div>
|
||||
<div class="">
|
||||
<span><b>{{border.label}} {{fasad.checkIfBorderInSheetColor(fasad.selectSheetConfigModalData.sheetId, border.id)}}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group" data-ng-if="fasad.selectSheetConfigModalData.border1Id == border.id">
|
||||
<label for="border1HeightSelect">Толщина кромки:</label>
|
||||
<select class="custom-select" id="border1HeightSelect" data-ng-model="fasad.selectSheetConfigModalData.border1Height" data-ng-options="v.fasad_border_dimension.id as v.fasad_border_dimension.label for v in border.available_dimensions" data-ng-disabled="!fasad.selectSheetConfigModalData.border1Id">
|
||||
<option value="">Выберите толщину</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a tabindex="-1" href="{{utilities.getFasadBorderImageById(border.id)}}" data-lightbox="border1{{border.id}}LightBox" class="select-border-preview" data-ng-if="border.image">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredBorders1.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-show="fasad.activeSheetSelectStep == 3">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП. <br/>
|
||||
Выберите цвет и размер кромки №2 или нажмите "Пропустить", если в поклейке кромки №2 нет необходимости.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div id="selectBorder2Id{{border.id}}" class="select-border-data col-12" data-ng-repeat="border in filteredBorders2 = (config.borders | filterData:fasad.searchFilters[3])">
|
||||
<div data-ng-click="fasad.selectBorderId(2, border)" data-ng-class="{'selected' : (fasad.selectSheetConfigModalData.border2Id == border.id)}">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="select-border-image" data-ng-if="fasad.isSelectSheetConfigModalTriggered && border.image">
|
||||
<img data-src="{{utilities.getFasadBorderImageById(border.id)}}" class="img-thumbnail img-lazy">
|
||||
</div>
|
||||
<div class="">
|
||||
<span><b>{{border.label}} {{fasad.checkIfBorderInSheetColor(fasad.selectSheetConfigModalData.sheetId, border.id)}}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group" data-ng-if="fasad.selectSheetConfigModalData.border2Id == border.id">
|
||||
<label for="border2HeightSelect">Толщина кромки:</label>
|
||||
<select class="custom-select" id="border2HeightSelect" data-ng-model="fasad.selectSheetConfigModalData.border2Height" data-ng-options="v.fasad_border_dimension.id as v.fasad_border_dimension.label for v in border.available_dimensions" data-ng-disabled="!fasad.selectSheetConfigModalData.border2Id">
|
||||
<option value="">Выберите толщину</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a tabindex="-1" href="{{utilities.getFasadBorderImageById(border.id)}}" data-lightbox="border2{{border.id}}LightBox" class="select-border-preview" data-ng-if="border.image">
|
||||
<img src="/img/lightbox/zoom-in.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div data-ng-if="!filteredBorders2.length" class="col-12">Не найдено результатов по вашему запросу.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-show="fasad.activeSheetSelectStep == 4">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
Внимание! Цвет на мониторе может отличаться от реального цвета ДСП. <br/>
|
||||
Проверьте выбранную фактуру листа и конфигурацию кромок и нажмите "Сохранить".
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Фактура:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">{{fasad.getSelectedSheetLabel(fasad.selectSheetConfigModalData.sheetId)}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Размеры листа:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">{{fasad.getSheetFullDimensionsBySheetId(fasad.selectSheetConfigModalData.sheetId)}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Кромка 1:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">
|
||||
<span data-ng-bind-html="fasad.getBorderLabel(fasad.selectSheetConfigModalData.border1Id, fasad.selectSheetConfigModalData.border1Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-form-label col-3">Кромка 2:</label>
|
||||
<div class="col-9">
|
||||
<label class="col-form-label">
|
||||
<span data-ng-bind-html="fasad.getBorderLabel(fasad.selectSheetConfigModalData.border2Id, fasad.selectSheetConfigModalData.border2Height) | trustAs"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 1"
|
||||
data-ng-disabled="!fasad.selectSheetConfigModalData.sheetId"
|
||||
data-ng-click="fasad.discardBordersSelectFromStep1()">
|
||||
Пропустить выбор кромок
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 1"
|
||||
data-ng-disabled="!fasad.selectSheetConfigModalData.sheetId"
|
||||
data-ng-click="fasad.setActiveSheetSelectStep(2)">
|
||||
Перейти к выбору кромок
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 2"
|
||||
data-ng-click="fasad.setActiveSheetSelectStep(1)">
|
||||
Вернуться к выбору фактуры
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-warning"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 2"
|
||||
data-ng-click="fasad.discardBordersSelectFromStep2()">
|
||||
Пропустить
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 2"
|
||||
data-ng-disabled="!fasad.selectSheetConfigModalData.border1Id || !fasad.selectSheetConfigModalData.border1Height"
|
||||
data-ng-click="fasad.setActiveSheetSelectStep(3)">
|
||||
Перейти к выбору кромки №2
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 3"
|
||||
data-ng-click="fasad.setActiveSheetSelectStep(2)">
|
||||
Вернуться к выбору кромки №1
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-warning"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 3"
|
||||
data-ng-click="fasad.discardBorder2SelectFromStep3()">
|
||||
Пропустить
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 3"
|
||||
data-ng-disabled="!fasad.selectSheetConfigModalData.border2Id || !fasad.selectSheetConfigModalData.border2Height"
|
||||
data-ng-click="fasad.setActiveSheetSelectStep(4)">
|
||||
Завершить настройку
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-secondary"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 4"
|
||||
data-ng-click="fasad.setActiveSheetSelectStep(1)">
|
||||
Вернуться к выбору фактуры
|
||||
</button>
|
||||
|
||||
<button class="btn btn-sm btn-success"
|
||||
data-ng-if="fasad.activeSheetSelectStep == 4"
|
||||
data-ng-disabled="!fasad.selectSheetConfigModalData.sheetId"
|
||||
data-ng-click="fasad.confirmSheetSelection()">
|
||||
Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" id="detailCornersConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
Конфигурация детали №{{fasad.detailCornersConfigModalData.uiOrderNum}}
|
||||
</h5>
|
||||
|
||||
<div>
|
||||
<button type="button" class="btn"
|
||||
data-ng-class="{true:'btn-info', false:'btn-light'}[fasad.detailCornersConfigModalData.activeTab == cornersConfigButton.id]"
|
||||
data-ng-repeat="cornersConfigButton in config.cornersConfigButtons"
|
||||
data-ng-click="fasad.setDetailCornersConfigActiveTab(cornersConfigButton.id)">
|
||||
{{cornersConfigButton.label}}
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row" data-ng-if="fasad.detailCornersConfigModalData.activeTab == 'corners'">
|
||||
<div class="detailCornersCenter">
|
||||
<div class="detailCornersBox" data-ng-class="fasad.getDetailCornersConfigClass()">
|
||||
<div class="detailCornersHorizontalDivider"></div>
|
||||
<div class="detailCornersVerticalDivider"></div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="cornerConfigRadiusLabel cornerConfigRadiusLabel-{{cornerPosition.id}}">
|
||||
<span>R={{fasad.detailCornersConfigModalData.corners[cornerPosition.id].radius}}</span>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="cornerConfigCutLabel cornerConfigCutLabel-{{cornerPosition.id}}">
|
||||
<span class="cornerConfigCutXLabel">x={{fasad.detailCornersConfigModalData.corners[cornerPosition.id].x}}</span>
|
||||
<span class="cornerConfigCutYLabel">y={{fasad.detailCornersConfigModalData.corners[cornerPosition.id].y}}</span>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="cornerConfigCutLabel cornerConfigCutEdge-{{cornerPosition.id}}"></div>
|
||||
</div>
|
||||
|
||||
<div class="detailCornersWidth">{{fasad.detailCornersConfigModalData.detail.width}} мм</div>
|
||||
<div class="detailCornersHeight">{{fasad.detailCornersConfigModalData.detail.height}} мм</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="cornerPosition in config.cornerPositions" class="detailCorner detailCorner-{{cornerPosition.id}}">
|
||||
<label>{{cornerPosition.label}}</label>
|
||||
|
||||
<div class="">
|
||||
<button type="button" class="btn"
|
||||
data-ng-class="{true:'active btn-primary', false:'btn-light'}[fasad.detailCornersConfigModalData.corners[cornerPosition.id].value == cornerValue.id]"
|
||||
data-ng-repeat="cornerValue in config.cornerValues"
|
||||
data-ng-disabled="fasad.isDetailCornerConfigValueSelectDisabled(cornerPosition.id)"
|
||||
data-ng-click="fasad.setDetailCornerConfigValue(cornerPosition.id, cornerValue.id)">
|
||||
{{cornerValue.label}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="detailCorner-config col-12">
|
||||
<div class="row" data-ng-if="fasad.detailCornersConfigModalData.corners[cornerPosition.id].value == 'none'"></div>
|
||||
|
||||
<div class="row" data-ng-if="fasad.detailCornersConfigModalData.corners[cornerPosition.id].value == 'radius'">
|
||||
<div class="input-group col-sm-12 col-lg-9">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailCornersConfigModalData{{cornerPosition.id}}Radius">Радиус, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailCornersConfigModalData{{cornerPosition.id}}Radius"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="fasad.detailCornersConfigModalData.corners[cornerPosition.id].radius"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" data-ng-if="fasad.detailCornersConfigModalData.corners[cornerPosition.id].value == 'cut'">
|
||||
<div class="input-group col-sm-12 col-lg-6 corners-config-left-group">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailCornersConfigModalData{{cornerPosition.id}}X">x, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailCornersConfigModalData{{cornerPosition.id}}X"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="fasad.detailCornersConfigModalData.corners[cornerPosition.id].x"
|
||||
data-ng-disabled="fasad.isDetailCornerConfigInputDisabled(cornerPosition.id)"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-12 col-lg-6 corners-config-right-group">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailCornersConfigModalData{{cornerPosition.id}}Y">y, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailCornersConfigModalData{{cornerPosition.id}}X" class="form-control form-control-sm" type="number"
|
||||
data-ng-model="fasad.detailCornersConfigModalData.corners[cornerPosition.id].y"
|
||||
data-ng-disabled="fasad.isDetailCornerConfigInputDisabled(cornerPosition.id)"
|
||||
data-digits-only pattern="[0-9]*" >
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-12 col-lg-12"
|
||||
data-ng-class="{'disabled': fasad.isDetailCornerConfigDiagonalCheckboxDisabled(cornerPosition.id)}"
|
||||
data-ng-click="fasad.onDetailCornersConfigDiagonalCutClick(cornerPosition.id)">
|
||||
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text with-checkbox">
|
||||
<i class="fa fa-square-o" data-ng-if="!fasad.detailCornersConfigModalData.corners[cornerPosition.id].diagonalCut"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="fasad.detailCornersConfigModalData.corners[cornerPosition.id].diagonalCut"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="col-form-label form-control">Диагональный срез</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" data-ng-if="fasad.detailCornersConfigModalData.activeTab == 'grooves'" data-ng-class="fasad.getDetailGroovesConfigClass()">
|
||||
<div class="detailGroovesCenter">
|
||||
<div class="detailGroovesBox" data-ng-class="fasad.getDetailGroovesConfigClass()">
|
||||
<div data-ng-repeat="groovePosition in config.groovePositions" class="grooveConfigLabel grooveConfigLabel-{{groovePosition.id}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detailGroovesWidth">{{fasad.detailCornersConfigModalData.detail.width}} мм</div>
|
||||
<div class="detailGroovesHeight">{{fasad.detailCornersConfigModalData.detail.height}} мм</div>
|
||||
</div>
|
||||
|
||||
<div data-ng-repeat="groovePosition in config.groovePositions" class="detailGroove detailGroove-{{groovePosition.id}}">
|
||||
<div class="detailGroove-config col-12">
|
||||
<div class="row">
|
||||
<div class="input-group"
|
||||
data-ng-class="[{true:'col-12', false:'offset-4 col-4'}[(groovePosition.id == 'left') || (groovePosition.id == 'right')], {'disabled': fasad.isDetailGrooveConfigCheckboxDisabled(groovePosition.id)}]"
|
||||
data-ng-click="fasad.onDetailGroovesConfigGrooveEnabledClick(groovePosition.id)">
|
||||
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text input-group-checkbox-text with-checkbox">
|
||||
<i class="fa fa-square-o" data-ng-if="!fasad.detailCornersConfigModalData.grooves[groovePosition.id].enabled"></i>
|
||||
<i class="fa fa-check-square-o" data-ng-if="fasad.detailCornersConfigModalData.grooves[groovePosition.id].enabled"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="col-form-label form-control">{{groovePosition.label2}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-col-4 first-row-col-4" data-ng-if="fasad.detailCornersConfigModalData.grooves[groovePosition.id].enabled">
|
||||
<div class="input-group col-12">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailGroovesConfigModalData{{groovePosition.id}}Offset">Отступ от края, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailGroovesConfigModalData{{groovePosition.id}}Offset"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="fasad.detailCornersConfigModalData.grooves[groovePosition.id].offset"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-col-4 second-row-col-4" data-ng-if="fasad.detailCornersConfigModalData.grooves[groovePosition.id].enabled">
|
||||
<div class="input-group col-12">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailGroovesConfigModalData{{groovePosition.id}}Depth">Глубина пропила, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailGroovesConfigModalData{{groovePosition.id}}Depth"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="fasad.detailCornersConfigModalData.grooves[groovePosition.id].depth"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-col-4 third-row-col-4" data-ng-if="fasad.detailCornersConfigModalData.grooves[groovePosition.id].enabled">
|
||||
<div class="input-group col-12">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="detailGroovesConfigModalData{{groovePosition.id}}Width">Ширина пропила, мм</label>
|
||||
</div>
|
||||
|
||||
<input id="detailGroovesConfigModalData{{groovePosition.id}}Width"
|
||||
class="form-control form-control-sm" type="number"
|
||||
data-ng-model="fasad.detailCornersConfigModalData.grooves[groovePosition.id].width"
|
||||
data-digits-only pattern="[0-9]*">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
|
||||
|
||||
<button class="btn btn-sm btn-success" data-ng-click="fasad.saveDetailCornersConfig()">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="detailLabelConfigModal" data-backdrop="static">
|
||||
<div class="modal-dialog modal-md">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
Наименование детали №{{fasad.detailLabelConfigModalData.uiOrderNum}}
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<input class="form-control" type="text" data-ng-model="fasad.detailLabelConfigModalData.label" maxlength="20">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button>
|
||||
|
||||
<button class="btn btn-sm btn-success" data-ng-click="fasad.saveDetailLabelConfig()">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $this->Assign('title', $siteTitle);?>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title><?= $this->fetch('title') ?></title>
|
||||
</head>
|
||||
<body>
|
||||
<?= $this->fetch('content') ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
echo $this->fetch('content');
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 0.10.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
echo $this->fetch('content');
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php use Cake\Core\Configure; ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html class="horizontal-only">
|
||||
<head>
|
||||
<?= $this->Html->charset() ?>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title><?= $this->fetch('title');?></title>
|
||||
<?php echo $this->element("favicon"); ?>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$release = "?v".Configure::read('Release');
|
||||
|
||||
$cssList = [
|
||||
"bootstrap.min.css",
|
||||
"lightbox.min.css",
|
||||
"fontawesome.custom.css",
|
||||
"styles.css",
|
||||
];
|
||||
|
||||
foreach ($cssList as $key => $css) {
|
||||
$cssList[$key] = $css.$release;
|
||||
}
|
||||
echo $this->Html->css($cssList);
|
||||
} else {
|
||||
echo $this->Html->css('jquery.reject');
|
||||
} ?>
|
||||
|
||||
<?= $this->fetch('meta'); ?>
|
||||
<?= $this->fetch('css'); ?>
|
||||
<?= $this->fetch('script'); ?>
|
||||
|
||||
<base href="/">
|
||||
</head>
|
||||
|
||||
<body data-ng-app="supersamApp">
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
echo $this->fetch('content');
|
||||
|
||||
$scripts = [
|
||||
"jquery.min.js",
|
||||
"popper.min.js",
|
||||
"bootstrap.min.js",
|
||||
"angular.min.js",
|
||||
"angular-local-storage.min.js",
|
||||
"angular-mask.min.js",
|
||||
"jquery.scrollTo.min.js",
|
||||
"lightbox.min.js",
|
||||
"lozad.min.js",
|
||||
|
||||
"custom.js",
|
||||
"config.js",
|
||||
"directives.js",
|
||||
"calcDoorsController.js"
|
||||
];
|
||||
|
||||
foreach ($scripts as $key => $script) {
|
||||
$scripts[$key] = $script.$release;
|
||||
}
|
||||
echo $this->Html->script($scripts);
|
||||
|
||||
echo $this->element('common_data');
|
||||
echo $this->element('cookie_consent');
|
||||
} else {
|
||||
echo $this->Html->script("jquery-1.min.js");
|
||||
echo $this->Html->script("jquery.reject.js");
|
||||
echo $this->Html->script("jquery.reject-config.js");
|
||||
}
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php use Cake\Core\Configure; ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html class="horizontal-only">
|
||||
<head>
|
||||
<?= $this->Html->charset() ?>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title><?= $this->fetch('title');?></title>
|
||||
<?php echo $this->element("favicon"); ?>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$release = "?v".Configure::read('Release');
|
||||
|
||||
$cssList = [
|
||||
"bootstrap.min.css",
|
||||
"lightbox.min.css",
|
||||
"fontawesome.custom.css",
|
||||
"styles.css",
|
||||
];
|
||||
|
||||
foreach ($cssList as $key => $css) {
|
||||
$cssList[$key] = $css.$release;
|
||||
}
|
||||
echo $this->Html->css($cssList);
|
||||
} else {
|
||||
echo $this->Html->css('jquery.reject');
|
||||
} ?>
|
||||
|
||||
<?= $this->fetch('meta'); ?>
|
||||
<?= $this->fetch('css'); ?>
|
||||
<?= $this->fetch('script'); ?>
|
||||
|
||||
<base href="/">
|
||||
</head>
|
||||
|
||||
<body data-ng-app="supersamApp">
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
echo $this->fetch('content');
|
||||
|
||||
$scripts = [
|
||||
"jquery.min.js",
|
||||
"popper.min.js",
|
||||
"bootstrap.min.js",
|
||||
"angular.min.js",
|
||||
"angular-local-storage.min.js",
|
||||
"angular-mask.js",
|
||||
"jquery.scrollTo.min.js",
|
||||
"lightbox.min.js",
|
||||
"lozad.min.js",
|
||||
|
||||
"custom.js",
|
||||
"config.js",
|
||||
"directives.js",
|
||||
"cutController.js"
|
||||
];
|
||||
|
||||
foreach ($scripts as $key => $script) {
|
||||
$scripts[$key] = $script.$release;
|
||||
}
|
||||
echo $this->Html->script($scripts);
|
||||
|
||||
echo $this->element('common_data');
|
||||
echo $this->element('cookie_consent');
|
||||
} else {
|
||||
echo $this->Html->script("jquery-1.min.js");
|
||||
echo $this->Html->script("jquery.reject.js");
|
||||
echo $this->Html->script("jquery.reject-config.js");
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php use Cake\Core\Configure; ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<?= $this->Html->charset() ?>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title><?= $this->fetch('title');?></title>
|
||||
<?php echo $this->element("favicon"); ?>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$release = "?v".Configure::read('Release');
|
||||
|
||||
$cssList = [
|
||||
"delivery.css",
|
||||
];
|
||||
|
||||
foreach ($cssList as $key => $css) {
|
||||
$cssList[$key] = $css.$release;
|
||||
}
|
||||
echo $this->Html->css($cssList);
|
||||
} else {
|
||||
echo $this->Html->css('jquery.reject');
|
||||
} ?>
|
||||
|
||||
<?= $this->fetch('meta'); ?>
|
||||
<?= $this->fetch('css'); ?>
|
||||
<?= $this->fetch('script'); ?>
|
||||
|
||||
<base href="/">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$scripts = [
|
||||
"jquery.min.js",
|
||||
];
|
||||
|
||||
foreach ($scripts as $key => $script) {
|
||||
$scripts[$key] = $script.$release;
|
||||
}
|
||||
$scripts[] = "https://api-maps.yandex.ru/2.1/?apikey=".$apiKey."&lang=ru_RU";
|
||||
|
||||
echo $this->Html->script($scripts);
|
||||
|
||||
echo $this->element('delivery_'.$delivery['slug']);
|
||||
|
||||
echo $this->fetch('content');
|
||||
echo $this->element('cookie_consent');
|
||||
} else {
|
||||
echo $this->Html->script("jquery-1.min.js");
|
||||
echo $this->Html->script("jquery.reject.js");
|
||||
echo $this->Html->script("jquery.reject-config.js");
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php use Cake\Core\Configure; ?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<?= $this->Html->charset() ?>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>СуперСам</title>
|
||||
<?php echo $this->element("favicon"); ?>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$release = "?v".Configure::read('Release');
|
||||
|
||||
$cssList = [
|
||||
"bootstrap.min.css",
|
||||
"styles.css",
|
||||
];
|
||||
|
||||
foreach ($cssList as $key => $css) {
|
||||
$cssList[$key] = $css.$release;
|
||||
}
|
||||
echo $this->Html->css($cssList);
|
||||
} else {
|
||||
echo $this->Html->css('jquery.reject');
|
||||
} ?>
|
||||
|
||||
<?= $this->fetch('meta'); ?>
|
||||
<?= $this->fetch('css'); ?>
|
||||
<?= $this->fetch('script'); ?>
|
||||
|
||||
<base href="/">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php if (empty($isRejectedBrowser)) {
|
||||
$scripts = [
|
||||
"jquery.min.js",
|
||||
];
|
||||
|
||||
foreach ($scripts as $key => $script) {
|
||||
$scripts[$key] = $script.$release;
|
||||
}
|
||||
|
||||
echo $this->Html->script($scripts);
|
||||
echo $this->fetch('content');
|
||||
echo $this->element('cookie_consent');
|
||||
} else {
|
||||
echo $this->Html->script("jquery-1.min.js");
|
||||
echo $this->Html->script("jquery.reject.js");
|
||||
echo $this->Html->script("jquery.reject-config.js");
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
Loaded 100 of 17284 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user