Разработка архитектуры, профиля, загрузки из Excel и 1C, много мелких изменений

This commit is contained in:
RedHood 2021-01-13 14:04:59 +10:00
parent 7d27736a02
commit fbd64ecb96
116 changed files with 3415 additions and 1098 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
vendor/
cache/
/vendor
/cache

View File

@ -21,7 +21,9 @@
"npm-asset/jquery": "^3.5",
"bower-asset/jquery": "^3.5",
"explosivebit/arangodb": "^2.0",
"triagens/arangodb": "^3.6"
"triagens/arangodb": "^3.6",
"moonlandsoft/yii2-phpexcel": "^2.0",
"carono/yii2-1c-exchange": "^0.3.1"
},
"require-dev": {
"codeception/codeception": ">=4.1",

783
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d83ed7a25bd848237d6ae45b945471f6",
"content-hash": "88957d501cd6111bfb6987bd71d90524",
"packages": [
{
"name": "bower-asset/bootstrap",
@ -32,7 +32,7 @@
"version": "3.3.11",
"source": {
"type": "git",
"url": "git@github.com:RobinHerbots/Inputmask.git",
"url": "https://github.com/RobinHerbots/Inputmask.git",
"reference": "5e670ad62f50c738388d4dcec78d2888505ad77b"
},
"dist": {
@ -53,7 +53,7 @@
"version": "3.5.1",
"source": {
"type": "git",
"url": "https://github.com/jquery/jquery-dist.git",
"url": "git@github.com:jquery/jquery-dist.git",
"reference": "4c0e4becb8263bb5b3e6dadc448d8e7305ef8215"
},
"dist": {
@ -71,7 +71,7 @@
"version": "v1.3.2",
"source": {
"type": "git",
"url": "git@github.com:bestiejs/punycode.js.git",
"url": "https://github.com/bestiejs/punycode.js.git",
"reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3"
},
"dist": {
@ -102,6 +102,102 @@
"MIT"
]
},
{
"name": "carono/commerceml",
"version": "0.2.5",
"source": {
"type": "git",
"url": "https://github.com/carono/php-commerceml.git",
"reference": "9d357db9912ab680bc3932ba7c77a6dbb53c8e42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/carono/php-commerceml/zipball/9d357db9912ab680bc3932ba7c77a6dbb53c8e42",
"reference": "9d357db9912ab680bc3932ba7c77a6dbb53c8e42",
"shasum": ""
},
"require": {
"ext-simplexml": "*"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Zenwalker\\CommerceML\\": "src/",
"Zenwalker\\CommerceML\\Tests\\": "tests/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxim Poletaev",
"email": "zenwalker2@gmail.com",
"homepage": "http://zenwalker.ru"
},
{
"name": "Aleksandr Kasyanov",
"email": "info@carono.ru",
"homepage": "http://carono.ru"
}
],
"description": "Library for parsing CommerceML files",
"homepage": "https://github.com/zenwalker/php-commerceml",
"keywords": [
"1c",
"commerceml"
],
"time": "2019-06-24T13:49:20+00:00"
},
{
"name": "carono/yii2-1c-exchange",
"version": "0.3.1",
"source": {
"type": "git",
"url": "https://github.com/carono/yii2-1c-exchange.git",
"reference": "dce5af59ba5d6e6b86e33d824621dce2df77e056"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/carono/yii2-1c-exchange/zipball/dce5af59ba5d6e6b86e33d824621dce2df77e056",
"reference": "dce5af59ba5d6e6b86e33d824621dce2df77e056",
"shasum": ""
},
"require": {
"carono/commerceml": "^0.2.3",
"php": ">=5.6",
"yiisoft/yii2": "^2.0"
},
"require-dev": {
"yiidoc/yii2-redactor": "^2.0"
},
"type": "yii2-extension",
"extra": {
"bootstrap": "carono\\exchange1c\\Bootstrap"
},
"autoload": {
"psr-4": {
"carono\\exchange1c\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aleksandr Kasyanov",
"email": "info@carono.ru",
"homepage": "http://carono.ru"
}
],
"description": "Yii2 module for the exchange of goods and documents from 1C",
"time": "2020-09-08T12:58:28+00:00"
},
{
"name": "cebe/markdown",
"version": "1.2.1",
@ -362,6 +458,339 @@
],
"time": "2020-06-29T00:56:53+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58",
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58",
"shasum": ""
},
"require": {
"myclabs/php-enum": "^1.5",
"php": ">= 7.1",
"psr/http-message": "^1.0",
"symfony/polyfill-mbstring": "^1.0"
},
"require-dev": {
"ext-zip": "*",
"guzzlehttp/guzzle": ">= 6.3",
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": ">= 7.5"
},
"type": "library",
"autoload": {
"psr-4": {
"ZipStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Duncan",
"email": "pabs@pablotron.org"
},
{
"name": "Jonatan Männchen",
"email": "jonatan@maennchen.ch"
},
{
"name": "Jesse Donat",
"email": "donatj@gmail.com"
},
{
"name": "András Kolesár",
"email": "kolesar@kolesar.hu"
}
],
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
"keywords": [
"stream",
"zip"
],
"funding": [
{
"url": "https://opencollective.com/zipstream",
"type": "open_collective"
}
],
"time": "2020-05-30T13:11:16+00:00"
},
{
"name": "markbaker/complex",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "9999f1432fae467bc93c53f357105b4c31bb994c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/9999f1432fae467bc93c53f357105b4c31bb994c",
"reference": "9999f1432fae467bc93c53f357105b4c31bb994c",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
},
"files": [
"classes/src/functions/abs.php",
"classes/src/functions/acos.php",
"classes/src/functions/acosh.php",
"classes/src/functions/acot.php",
"classes/src/functions/acoth.php",
"classes/src/functions/acsc.php",
"classes/src/functions/acsch.php",
"classes/src/functions/argument.php",
"classes/src/functions/asec.php",
"classes/src/functions/asech.php",
"classes/src/functions/asin.php",
"classes/src/functions/asinh.php",
"classes/src/functions/atan.php",
"classes/src/functions/atanh.php",
"classes/src/functions/conjugate.php",
"classes/src/functions/cos.php",
"classes/src/functions/cosh.php",
"classes/src/functions/cot.php",
"classes/src/functions/coth.php",
"classes/src/functions/csc.php",
"classes/src/functions/csch.php",
"classes/src/functions/exp.php",
"classes/src/functions/inverse.php",
"classes/src/functions/ln.php",
"classes/src/functions/log2.php",
"classes/src/functions/log10.php",
"classes/src/functions/negative.php",
"classes/src/functions/pow.php",
"classes/src/functions/rho.php",
"classes/src/functions/sec.php",
"classes/src/functions/sech.php",
"classes/src/functions/sin.php",
"classes/src/functions/sinh.php",
"classes/src/functions/sqrt.php",
"classes/src/functions/tan.php",
"classes/src/functions/tanh.php",
"classes/src/functions/theta.php",
"classes/src/operations/add.php",
"classes/src/operations/subtract.php",
"classes/src/operations/multiply.php",
"classes/src/operations/divideby.php",
"classes/src/operations/divideinto.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"time": "2020-08-26T10:42:07+00:00"
},
{
"name": "markbaker/matrix",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
"reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
},
"files": [
"classes/src/functions/adjoint.php",
"classes/src/functions/antidiagonal.php",
"classes/src/functions/cofactors.php",
"classes/src/functions/determinant.php",
"classes/src/functions/diagonal.php",
"classes/src/functions/identity.php",
"classes/src/functions/inverse.php",
"classes/src/functions/minors.php",
"classes/src/functions/trace.php",
"classes/src/functions/transpose.php",
"classes/src/operations/add.php",
"classes/src/operations/directsum.php",
"classes/src/operations/subtract.php",
"classes/src/operations/multiply.php",
"classes/src/operations/divideby.php",
"classes/src/operations/divideinto.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@demon-angel.eu"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"time": "2020-08-28T17:11:00+00:00"
},
{
"name": "moonlandsoft/yii2-phpexcel",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/moonlandsoft/yii2-phpexcel.git",
"reference": "e0614787a41a9e7e1c9ab3b707ce54c256461d7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/moonlandsoft/yii2-phpexcel/zipball/e0614787a41a9e7e1c9ab3b707ce54c256461d7f",
"reference": "e0614787a41a9e7e1c9ab3b707ce54c256461d7f",
"shasum": ""
},
"require": {
"phpoffice/phpspreadsheet": "*",
"yiisoft/yii2": "*"
},
"type": "yii2-extension",
"autoload": {
"psr-4": {
"moonland\\phpexcel\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Moh Khoirul Anam",
"email": "moh.khoirul.anaam@gmail.com"
}
],
"description": "Exporting PHP to Excel or Importing Excel to PHP",
"keywords": [
"excel",
"export",
"extension",
"import",
"xls",
"yii2"
],
"time": "2018-10-27T03:52:57+00:00"
},
{
"name": "myclabs/php-enum",
"version": "1.7.7",
"source": {
"type": "git",
"url": "https://github.com/myclabs/php-enum.git",
"reference": "d178027d1e679832db9f38248fcc7200647dc2b7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/d178027d1e679832db9f38248fcc7200647dc2b7",
"reference": "d178027d1e679832db9f38248fcc7200647dc2b7",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "^7",
"squizlabs/php_codesniffer": "1.*",
"vimeo/psalm": "^3.8"
},
"type": "library",
"autoload": {
"psr-4": {
"MyCLabs\\Enum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP Enum contributors",
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
}
],
"description": "PHP Enum implementation",
"homepage": "http://github.com/myclabs/php-enum",
"keywords": [
"enum"
],
"funding": [
{
"url": "https://github.com/mnapoli",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
"type": "tidelift"
}
],
"time": "2020-11-14T18:14:52+00:00"
},
{
"name": "npm-asset/jquery",
"version": "3.5.1",
@ -374,6 +803,302 @@
"MIT"
]
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.16.1",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "76d4323b85129d0c368149c831a07a3e258b2b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/76d4323b85129d0c368149c831a07a3e258b2b50",
"reference": "76d4323b85129d0c368149c831a07a3e258b2b50",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.13",
"maennchen/zipstream-php": "^2.1",
"markbaker/complex": "^1.5||^2.0",
"markbaker/matrix": "^1.2||^2.0",
"php": "^7.2||^8.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"dompdf/dompdf": "^0.8.5",
"friendsofphp/php-cs-fixer": "^2.16",
"jpgraph/jpgraph": "^4.0",
"mpdf/mpdf": "^8.0",
"phpcompatibility/php-compatibility": "^9.3",
"phpunit/phpunit": "^8.5||^9.3",
"squizlabs/php_codesniffer": "^3.5",
"tecnickcom/tcpdf": "^6.3"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
"jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"time": "2020-12-31T18:03:49+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"time": "2020-06-29T06:28:15+00:00"
},
{
"name": "psr/http-factory",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"time": "2019-04-30T12:38:16+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/simple-cache",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v6.2.4",
@ -3146,56 +3871,6 @@
],
"time": "2019-01-08T18:20:26+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",

View File

@ -0,0 +1 @@
/import

View File

@ -27,7 +27,6 @@ class AppAsset extends AssetBundle
'css/header.css',
'css/info_panel.css',
'css/categories_blocks_panel.css',
'css/ticker.css',
'css/footer.css'
];
public $js = [
@ -36,8 +35,9 @@ class AppAsset extends AssetBundle
'js/bootstrap/popper.min.js',
'js/bootstrap/bootstrap.min.js',
'https://cdn.jsdelivr.net/bxslider/4.1.1/jquery.bxslider.min.js',
'https://unpkg.com/cookielib/src/cookie.min.js',
'js/menu.js',
'js/account.js',
'js/ticker.js',
'js/reinitialization.js'
];
public $depends = [

View File

@ -4,7 +4,7 @@
* Application configuration shared by all test types
*/
return [
'id' => 'basic-tests',
'id' => 'skillparts-tests',
'basePath' => dirname(__DIR__),
'aliases' => [
'@bower' => '@vendor/bower-asset',

View File

@ -1,7 +1,7 @@
<?php
$config = [
'id' => 'basic',
'id' => 'skillparts',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'aliases' => [
@ -21,7 +21,8 @@ $config = [
],
'user' => [
'identityClass' => 'app\models\Account',
'enableAutoLogin' => true,
'loginUrl' => ['/authentication'],
'enableAutoLogin' => true
],
// 'session' => [
// 'class' => 'yii\web\Session',
@ -30,7 +31,7 @@ $config = [
// 'useCookies' => true,
// ],
'errorHandler' => [
'errorAction' => 'site/error',
'errorAction' => 'error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
@ -53,12 +54,29 @@ $config = [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'site'],
'<action>' => 'site/<action>'
[
'class' => 'yii\rest\UrlRule',
'controller' => 'main'
],
'product/<id:\d+>' => 'product/index'
],
],
],
'modules' => [
'exchange' => [
'class' => 'carono\exchange1c\ExchangeModule',
'groupClass' => 'app\models\SupplyGroup',
'productClass' => 'app\models\Supply',
'offerClass' => 'app\models\Product',
'partnerClass' => 'app\models\Account',
'documentClass' => 'app\models\Purchase',
'auth' => function ($mail, $pswd) {
// Необходимо уничтожить AccountForm
return (new \app\models\AccountForm())->authentication($mail, $pswd);
}
]
],
'params' => require __DIR__ . '/params.php',
];
@ -70,16 +88,7 @@ if (YII_ENV_DEV) {
'ArangoDB' => [
'class' => 'explosivebit\arangodb\panels\arangodb\ArangoDbPanel'
]
],
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
]
];
}

View File

@ -0,0 +1,93 @@
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\AccessControl;
use app\models\AccountForm;
class AuthenticationController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['?'],
]
],
]
];
}
public function actionIndex()
{
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
// Инициализация
$model = new AccountForm(Yii::$app->request->post('AccountForm'));
$model->scenario = $model::SCENARIO_AUTHENTICATION;
Yii::$app->response->format = Response::FORMAT_JSON;
if (!Yii::$app->user->isGuest || $model->authentication()) {
// Аккаунт аутентифицирован
// Запись ответа
$return = [
'nav' => (new AccountForm())->deauthenticationGenHtml(),
'_csrf' => Yii::$app->request->getCsrfToken()
];
if (($cookies = Yii::$app->request->cookies)->has('redirect')) {
// Найдено cookie с переадресацией
// Запись ответа
$return['redirect'] = '/' . $cookies['redirect'];
$return['main'] = $this->renderPartial($return['redirect'] . '/index');
// Очистка cookie
unset(Yii::$app->response->cookies['redirect']);
} else {
// Не найдено cookie с переадресацией
if (Yii::$app->request->pathInfo === 'authentication' || Yii::$app->request->pathInfo === 'registration') {
// Если клиент на промежуточном URI
// Запись ответа
$return['redirect'] = '/';
$return['main'] = $this->renderPartial('/index');
}
}
return $return;
} else {
// Аккаунт не аутентифицирован
Yii::$app->response->statusCode = 400;
return [
'main' => $this->renderPartial('/account', compact('model')),
'redirect' => '/authentication',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
}
if (!Yii::$app->user->isGuest) {
Yii::$app->response->redirect('/');
} else {
return $this->render('/account');
}
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use app\models\AccountForm;
class DeauthenticationController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@'],
]
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'index' => ['post'],
],
]
];
}
public function actionIndex()
{
Yii::$app->response->format = Response::FORMAT_JSON;
// Выход из аккаунта
Yii::$app->user->logout();
// Инициализация
$model = new AccountForm(Yii::$app->request->post('AccountForm') ?? Yii::$app->request->get('AccountForm') ?? null);
// Ответа
return [
'nav' => $model->authenticationGenHtml($this->renderPartial('/account', compact('model'))),
'main' => $this->renderPartial('/index'),
'redirect' => '/',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\ErrorAction;
use yii\web\Response;
class ErrorController extends Controller
{
public function actionIndex()
{
$exception = Yii::$app->errorHandler->exception;
if ($exception !== null) {
// Исключение не выброшено
// Запись кода ошибки
$statusCode = $exception->statusCode;
// Запись названия ошибки
$name = match ($exception->statusCode) {
404 => '404 (Не найдено)',
default => $exception->getName()
};
// Запись сообщения об ошибке
$message = match ($exception->statusCode) {
404 => 'Страница не найдена',
default => $exception->getMessage()
};
return $this->render('/error', compact('exception', 'statusCode', 'name', 'message'));
}
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\Response;
use app\models\AccountForm;
class IdentificationController extends Controller
{
public function actionIndex()
{
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
if (Yii::$app->user->isGuest) {
// Аккаунт не аутентифицирован
// Инициализация
$model = new AccountForm(Yii::$app->request->post('AccountForm') ?? Yii::$app->request->get('AccountForm') ?? null);
// Запись ответа
$return = [
'nav' => $model->authenticationGenHtml($this->renderPartial('/account', compact('model'))),
'_csrf' => Yii::$app->request->getCsrfToken()
];
} else {
// Аккаунт аутентифицирован
// Инициализация
$model = Yii::$app->user;
// Запись ответа
$return = [
'nav' => (new AccountForm())->deauthenticationGenHtml(),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
if (($cookies = Yii::$app->request->cookies)->has('redirect')) {
// Найдено cookie с переадресацией
// Запись ответа
$return['redirect'] = '/' . $cookies['redirect'];
// Очистка cookie
unset(Yii::$app->response->cookies['redirect']);
}
return $return;
}
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\Response;
class MainController extends Controller
{
/**
* {@inheritdoc}
*/
public function actions()
{
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
/**
* Displays homepage.
*
* @return string
*/
public function actionIndex()
{
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
return [
'main' => $this->renderPartial('/index'),
'redirect' => '/',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('/index');
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use app\models\Product;
use yii\web\HttpException;
class ProductController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['add'],
'rules' => [
[
'allow' => false,
'roles' => ['?']
]
]
]
];
}
public function actionIndex(int $id)
{
if ($model = Product::readById($id)) {
// Товар найден
// Инициализация
$model = $model->getAttributes();
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
return [
'main' => $this->renderPartial('index', compact('model')),
'redirect' => '/product/' . $id,
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('index', compact('model'));
} else {
throw new HttpException(404);
}
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use yii\web\Cookie;
use yii\web\UploadedFile;
use app\models\Supply;
use app\models\SupplyGroup;
class ProfileController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@']
],
[
'allow' => false,
'roles' => ['?'],
'verbs' => ['POST'],
'denyCallback' => [$this, 'accessDenied']
]
]
]
];
}
public function accessDenied()
{
$cookies = Yii::$app->response->cookies;
$cookies->add(new Cookie([
'name' => 'redirect',
'value' => Yii::$app->request->pathInfo
]));
Yii::$app->response->format = Response::FORMAT_JSON;
// Проверить переадресацию на уровне сервера
Yii::$app->response->content = json_encode([
'main' => $this->renderPartial('/account'),
'redirect' => '/authentication',
'_csrf' => Yii::$app->request->getCsrfToken()
]);
}
public function actionIndex()
{
// Инициализация
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
return [
'main' => $this->renderPartial('index'),
'redirect' => '/profile',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('index', compact('model'));
}
public function actionImport()
{
// Инициализация
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
$model->scenario = $model::SCENARIO_IMPORT;
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
$model->file = UploadedFile::getInstances($model, 'file');
if (!$test = $model->import()) {
Yii::$app->response->statusCode = 409;
}
return [
'main' => $this->renderPartial('index', compact('model')),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('index', compact('model'));
}
public static function readGroups()
{
// Инициализация
$groups = [];
foreach (SupplyGroup::readAll() as $group) {
// Перебор всех групп
// Генерация [КЛЮЧ => ИМЯ]
$groups[$group->_key] = $group->name;
}
return $groups;
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use app\models\AccountForm;
class RegistrationController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['?'],
]
],
]
];
}
public function actionIndex()
{
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
// Инициализация
$model = new AccountForm(Yii::$app->request->post('AccountForm'));
$model->scenario = $model::SCENARIO_REGISTRATION;
Yii::$app->response->format = Response::FORMAT_JSON;
if (!Yii::$app->user->isGuest || $model->registration()) {
// Данные прошли проверку и аккаунт был создан
// Аутентификация
$model->scenario = $model::SCENARIO_AUTHENTICATION;
$model->authentication();
// Запись ответа
$return = [
'nav' => (new AccountForm())->deauthenticationGenHtml(),
'_csrf' => Yii::$app->request->getCsrfToken()
];
if (($cookies = Yii::$app->response->cookies)->has('redirect')) {
// Найдено cookie с переадресацией
// Запись ответа
$return['redirect'] = '/' . $cookies['redirect'];
$return['main'] = $this->renderPartial($return['redirect'] . '/index');
// Очистка cookie
unset(Yii::$app->response->cookies['redirect']);
} else {
// Не найдено cookie с переадресацией
if (Yii::$app->request->pathInfo === 'authentication' || Yii::$app->request->pathInfo === 'registration') {
// Если клиент на промежуточном URI
// Запись ответа
$return['redirect'] = '/';
$return['main'] = $this->renderPartial('/index');
}
}
return $return;
} else {
// Данные не прошли проверку
Yii::$app->response->statusCode = 400;
return [
'main' => $this->renderPartial('/account', compact('model')),
'redirect' => '/registration',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
}
if (!Yii::$app->user->isGuest) {
Yii::$app->response->redirect('/');
} else {
return $this->render('/account', compact('model'));
}
}
}

View File

@ -1,285 +0,0 @@
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\VerbFilter;
use app\models\AccountForm;
use app\models\ContactForm;
class SiteController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* {@inheritdoc}
*/
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
/**
* Displays homepage.
*
* @return string
*/
public function actionIndex()
{
return $this->render('index');
}
/**
* Identification action.
*
* @return Response
*/
public function actionIdentification()
{
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = Response::FORMAT_JSON;
if (Yii::$app->user->isGuest) {
return [
'menu' => '<a onclick="authentication()">Вход</a>',
'_csrf' => Yii::$app->request->getCsrfToken()
];
} else {
$mail = Yii::$app->user->identity->mail;
return [
'menu' => <<<HTML
<p class="m-0">
<a class="text-dark" href="/cart"><i class="fas fa-shopping-cart mr-4"></i></a>
<a class="text-dark" href="/orders"><i class="fas fa-list mr-4"></i></a>
<a class="text-dark" onclick="deauthentication()">Выход ($mail)</a>
</p>
HTML,
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
}
}
/**
* Login action.
*
* @return Response|string
*/
public function actionAuthentication()
{
$model = new AccountForm(Yii::$app->request->post()['AccountForm'] ?? Yii::$app->request->get()['AccountForm'] ?? null);
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
if (!Yii::$app->user->isGuest) {
// Аккаунт уже аутентифицирован
Yii::$app->response->statusCode = 403;
return [
'form' => $this->renderPartial('index'),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
if ($model->authentication()) {
// Данные прошли проверку
return [
'menu' => <<<HTML
<p class="m-0">
<a class="text-dark" href="/cart"><i class="fas fa-shopping-cart mr-4"></i></a>
<a class="text-dark" href="/orders"><i class="fas fa-list mr-4"></i></a>
<a class="text-dark" onclick="deauthentication()">Выход ($model->mail)</a>
</p>
HTML,
'form' => $this->renderPartial('index'),
'_csrf' => Yii::$app->request->getCsrfToken()
];
} else {
// Данные не прошли проверку
Yii::$app->response->statusCode = 400;
return [
'form' => $this->renderPartial('account', compact('model')),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
} else if (Yii::$app->request->isPost) {
// POST-запрос
} else {
// GET-запрос и прочие
if (!Yii::$app->user->isGuest) {
// Аккаунт уже аутентифицирован
Yii::$app->response->redirect('/');
}
}
return $this->render('authentication', compact('model'));
}
/**
* Logout action.
*
* @return Response
*/
public function actionDeauthentication()
{
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
Yii::$app->user->logout();
return [
'menu' => '<a onclick="authentication()">Вход</a>',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
Yii::$app->response->redirect('/');
}
/**
* Login action.
*
* @return Response|string
*/
public function actionRegistration()
{
$model = new AccountForm(Yii::$app->request->post()['AccountForm'] ?? Yii::$app->request->get()['AccountForm'] ?? null);
$model->type = 0;
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
if (!Yii::$app->user->isGuest) {
// Аккаунт уже аутентифицирован
Yii::$app->response->statusCode = 302;
return [
'form' => $this->renderPartial('index'),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
if ($model->registration()) {
// Данные прошли проверку и аккаунт был создан
return [
'menu' => <<<HTML
<p class="m-0">
<a class="text-dark" href="/cart"><i class="fas fa-shopping-cart mr-4"></i></a>
<a class="text-dark" href="/orders"><i class="fas fa-list mr-4"></i></a>
<a class="text-dark" onclick="deauthentication()">Выход ($model->mail)</a>
</p>
HTML,
'form' => $this->renderPartial('index'),
'_csrf' => Yii::$app->request->getCsrfToken()
];
} else {
// Данные не прошли проверку
Yii::$app->response->statusCode = 400;
return [
'form' => $this->renderPartial('account', compact('model')),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
} else if (Yii::$app->request->isPost) {
// POST-запрос
return;
} else {
// GET-запрос и прочие
if (!Yii::$app->user->isGuest) {
// Аккаунт уже аутентифицирован
Yii::$app->response->redirect('/');
}
}
return $this->render('registration', compact('model'));
}
/**
* Displays профиль
*
* @return Response|string
*/
public function actionProfile()
{
$model = new Account();
return $this->render('profile', compact('model'));
}
/**
* Displays contact page.
*
* @return Response|string
*/
public function actionContact()
{
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted');
return $this->refresh();
}
return $this->render('contact', [
'model' => $model,
]);
}
/**
* Displays about page.
*
* @return string
*/
public function actionAbout()
{
return $this->render('about');
}
}

View File

@ -11,10 +11,6 @@ class m201219_074926_create_account_collection extends Migration
public function down()
{
// $this->delete('accounts', 'mail');
// $this->delete('accounts', 'name');
// $this->delete('accounts', 'pswd');
$this->dropCollection('account');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210101_092505_create_product_collection extends Migration
{
public function up()
{
$this->createCollection('product');
}
public function down()
{
$this->dropCollection('product');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210107_163448_create_supply_collection extends Migration
{
public function up()
{
$this->createCollection('supply');
}
public function down()
{
$this->dropCollection('supply');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210108_014505_create_account_edge_supply_collection extends Migration
{
public function up()
{
$this->createCollection('account_edge_supply', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('account_edge_supply');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210108_212826_create_product_group_collection extends Migration
{
public function up()
{
$this->createCollection('product_group');
}
public function down()
{
$this->dropCollection('product_group');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210108_221446_create_product_edge_product_group_collection extends Migration
{
public function up()
{
$this->createCollection('product_edge_product_group', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('product_edge_product_group');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210108_222132_create_supply_edge_product_collection extends Migration
{
public function up()
{
$this->createCollection('supply_edge_product', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('supply_edge_product');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210108_222740_create_product_edge_product_collection extends Migration
{
public function up()
{
$this->createCollection('product_edge_product', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('product_edge_product');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210109_214817_create_supply_group_collection extends Migration
{
public function up()
{
$this->createCollection('supply_group');
}
public function down()
{
$this->dropCollection('supply_group');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210109_214833_create_supply_edge_supply_group_collection extends Migration
{
public function up()
{
$this->createCollection('supply_edge_supply_group', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('supply_edge_supply_group');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210111_044635_create_supply_edge_supply_collection extends Migration
{
public function up()
{
$this->createCollection('supply_edge_supply', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('supply_edge_supply');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210112_010347_create_product_group_edge_product_group_collection extends Migration
{
public function up()
{
$this->createCollection('product_group_edge_product_group', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('product_group_edge_product_group');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210112_010411_create_supply_group_edge_supply_group_collection extends Migration
{
public function up()
{
$this->createCollection('supply_group_edge_supply_group', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('supply_group_edge_supply_group');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210112_034135_create_requisite_collection extends Migration
{
public function up()
{
$this->createCollection('requisite');
}
public function down()
{
$this->dropCollection('requisite');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210112_034232_create_supply_edge_requisite_collection extends Migration
{
public function up()
{
$this->createCollection('supply_edge_requisite', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('supply_edge_requisite');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210113_021800_create_purchase_collection extends Migration
{
public function up()
{
$this->createCollection('purchase');
}
public function down()
{
$this->dropCollection('purchase');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210113_021905_create_account_edge_purchase_collection extends Migration
{
public function up()
{
$this->createCollection('account_edge_purchase', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('account_edge_purchase');
}
}

View File

@ -0,0 +1,16 @@
<?php
use explosivebit\arangodb\Migration;
class m210113_021917_create_purchase_edge_supply_collection extends Migration
{
public function up()
{
$this->createCollection('purchase_edge_supply', ['Type' => 3]);
}
public function down()
{
$this->dropCollection('purchase_edge_supply');
}
}

View File

@ -4,91 +4,106 @@ namespace app\models;
use Yii;
use yii\web\IdentityInterface;
use explosivebit\arangodb\ActiveRecord;
use carono\exchange1c\interfaces\PartnerInterface;
class Account extends ActiveRecord implements IdentityInterface
class Account extends Document implements IdentityInterface, PartnerInterface
{
public $_mail;
public $_pswd;
public $_name;
public $_simc;
public $_sity;
public $_comp;
public $_taxn;
public $_auth;
/**
* @return string the name of the index associated with this ActiveRecord class.
*/
public static function collectionName()
{
return 'account';
}
/**
* @return array list of attribute names.
*/
public function attributes()
{
return ['mail', 'pswd', 'auth', 'name' => 'sex', 'simc', 'sity', 'comp', 'taxn', 'auth'];
return array_merge(
parent::attributes(),
['mail', 'pswd', 'name', 'simc', 'sity', 'comp', 'taxn', 'auth']
);
}
public function rules()
{
return array_merge(
parent::rules(),
[
[['mail', 'pswd'], 'required', 'message' => 'Заполните поле'],
['mail', 'email'],
[['mail', 'comp', 'simc'], 'unique', 'message' => '2']
]
);
}
public function attributeLabels()
{
return array_merge(
parent::attributeLabels(),
[
'mail' => 'Почта',
'pswd' => 'Пароль',
'name' => 'Имя',
'simc' => 'Номер',
'sity' => 'Город',
'comp' => 'Компания',
'taxn' => 'ИНН',
'auth' => 'Аутентификационный хеш'
]
);
}
public function beforeSave($data)
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {
$this->auth = Yii::$app->security->generateRandomString();
}
return true;
}
return false;
}
public function getExportFields1c($context = null)
{
return [
'Ид' => 'id',
'Наименование' => 'username',
'ПолноеНаименование' => 'full_name',
'Фамилия' => 'surname',
'Имя' => 'name',
];
}
/**
* @return int|string current user ID
*/
public function getId()
{
return $this->mail;
return $this->_key;
}
/**
* @return string current user auth key
*/
public function getAuthKey()
{
return $this->auth;
}
/**
* Finds an identity by the given ID.
*
* @param string|int $id the ID to be looked for
* @return IdentityInterface|null the identity object that matches the given ID.
*/
public static function findIdentity($mail)
public static function findIdentity($_key)
{
return static::findByMail($mail);
return static::findByKey($_key);
}
/**
* Finds an identity by the given token.
*
* @param string $token the token to be looked for
* @return IdentityInterface|null the identity object that matches the given token.
*/
public static function findIdentityByAccessToken($pass, $type = null)
{
return static::findOne(['pass' => $pass]);
}
/**
* Finds user by mail
*
* @param string $mail
* @return static|null
*/
public static function findByMail($mail)
{
return static::findOne(['mail' => $mail]);
}
/**
* Validates mail
*
* @param string $pswd password to validate
* @return bool if password provided is valid for current user
*/
public function validateMail($mail)
public static function findByKey($_key)
{
return static::findOne(['_key' => $_key]);
}
public static function validateMail($mail)
{
if (static::findByMail($mail)) {
// Почта найдена в базе данных
@ -99,34 +114,13 @@ class Account extends ActiveRecord implements IdentityInterface
return true;
}
/**
* Validates password
*
* @param string $pswd password to validate
* @return bool if password provided is valid for current user
*/
public function validatePassword($pswd)
{
return Yii::$app->security->validatePassword($pswd, $this->pswd);
}
/**
* @param string $auth
* @return bool if auth key is valid for current user
*/
public function validateAuthKey($auth)
{
return $this->getAuthKey() === $auth;
}
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if ($this->isNewRecord) {
$this->auth = Yii::$app->security->generateRandomString();
}
return true;
}
return false;
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class AccountEdgePurchase extends Edge
{
public static function collectionName()
{
return 'account_edge_purchase';
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class AccountEdgeSupply extends Edge
{
public static function collectionName()
{
return 'account_edge_supply';
}
}

View File

@ -14,37 +14,29 @@ use app\models\Account;
*/
class AccountForm extends Model
{
const SCENARIO_REGISTRATION = 'registration';
const SCENARIO_REGISTRATION_END = 'registration_end';
const SCENARIO_AUTHENTICATION = 'authentication';
public $mail;
public $pswd;
public $auto = true;
/**
* Тип обработки
*
* Регистрация: 0
* Аутентификация: 1
*
* @var integer
*/
public $type = 1;
private $account = false;
/**
* @return array the validation rules.
*/
public function rules()
{
return [
// Обязательные поля
[['mail', 'pswd'], 'required', 'message' => 'Заполните поле'],
// Функция "Запомнить меня"
['auto', 'boolean'],
// Проверка почты
['mail', 'validateMail', 'message'=>'Неправильная почта'],
['auto', 'boolean', 'on' => self::SCENARIO_AUTHENTICATION],
// Проверка почты,
['mail', 'email', 'message' => 'Проверьте почту'],
['mail', 'validateMail', 'on' => self::SCENARIO_REGISTRATION],
// Проверка пароля
['pswd', 'validatePassword', 'message'=>'Неправильный пароль'],
['pswd', 'validatePassword', 'on' => self::SCENARIO_AUTHENTICATION]
];
}
@ -53,38 +45,28 @@ class AccountForm extends Model
return [
'mail' => 'Почта',
'pswd' => 'Пароль',
'auto' => 'Запомнить'
'auto' => '<i class="fas fa-lock"></i>'
];
}
/**
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
*/
public function validateMail($attribute, $params)
{
if (!$this->hasErrors() && $this->type === 0) {
if (!$this->hasErrors()) {
// Проблем нет, обрабатывается событие регистрации
$account = $this->getAccount();
if (!$account || !$account->validateMail($this->mail)) {
// Проверка не пройдена
$this->addError($attribute, 'Почта уже привязана к другому аккаунту');
$this->addError($attribute, 'Почта уже привязана');
}
}
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors() && $this->type === 1) {
if (!$this->hasErrors()) {
// Проблем нет, обрабатывается событие аутентификации
$account = $this->getAccount();
@ -92,7 +74,7 @@ class AccountForm extends Model
if (!$account || !$account->validatePassword($this->pswd)) {
// Проверка не пройдена
$this->addError($attribute, 'Проверьте входные данные');
$this->addError($attribute, 'Проверьте пароль');
}
}
}
@ -101,8 +83,13 @@ class AccountForm extends Model
* Logs in a account using the provided accountname and password.
* @return bool whether the account is logged in successfully
*/
public function authentication()
public function authentication(string $mail = null, string $pswd = null)
{
if (isset($mail, $pswd)) {
$this->mail = $mail;
$this->pswd = $pswd;
}
if (isset($this->mail, $this->pswd) && $this->validate()) {
// Проверка пройдена
@ -148,4 +135,38 @@ class AccountForm extends Model
return $this->account;
}
public function authenticationGenHtml(string $dropdown): string
{
return <<<HTML
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
<div class="btn-group">
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
<div class="dropdown-menu dropdown-menu-long dropdown-menu-right p-3" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
<h5 class="mb-3 text-center">Аутентификация</h5>
$dropdown
<!-- <a class="dropdown-item-text text-center px-0 py-2" href="#"><small>Восстановление пароля</small></a> -->
</div>
</div>
HTML;
}
public function deauthenticationGenHtml(): string
{
$mail = Yii::$app->user->identity->mail;
return <<<HTML
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
<div class="btn-group">
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
<div class="dropdown-menu dropdown-menu-right py-1" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
<a class="dropdown-item button_white text-dark" onclick="deauthentication()">Выход ($mail)</a>
</div>
</div>
HTML;
}
}

View File

@ -1,65 +0,0 @@
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* ContactForm is the model behind the contact form.
*/
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
public $verifyCode;
/**
* @return array the validation rules.
*/
public function rules()
{
return [
// name, email, subject and body are required
[['name', 'email', 'subject', 'body'], 'required'],
// email has to be a valid email address
['email', 'email'],
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}
/**
* @return array customized attribute labels
*/
public function attributeLabels()
{
return [
'verifyCode' => 'Verification Code',
];
}
/**
* Sends an email to the specified email address using the information collected by this model.
* @param string $email the target email address
* @return bool whether the model passes validation
*/
public function contact($email)
{
if ($this->validate()) {
Yii::$app->mailer->compose()
->setTo($email)
->setFrom([Yii::$app->params['senderEmail'] => Yii::$app->params['senderName']])
->setReplyTo([$this->email => $this->name])
->setSubject($this->subject)
->setTextBody($this->body)
->send();
return true;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace app\models;
use explosivebit\arangodb\ActiveRecord;
abstract class Document extends ActiveRecord
{
public function attributes()
{
return ['_key', 'date'];
}
public function rules()
{
return [
// [
// 'date',
// 'required',
// 'message' => 'Заполните поле: {attribute}'
// ]
];
}
public function attributeLabels()
{
return [
'date' => 'Дата'
];
}
public function beforeSave($data)
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {
$this->date = time();
}
return true;
}
return false;
}
public static function readAmount()
{
return static::find()->count();
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace app\models;
use explosivebit\arangodb\ActiveRecord;
abstract class Edge extends ActiveRecord
{
public function attributes()
{
return ['_key', '_from', '_to', 'date', 'type', 'account'];
}
public function rules()
{
return [
[
['_from', '_to', 'date', 'type', 'account'],
'required',
'message' => 'Заполните поле: {attribute}'
],
[
'date',
'integer'
],
[
'type',
'string'
],
[
'account',
'string'
// Надо добавить проверку существования аккаунта
]
];
}
public function attributeLabels()
{
return [
'date' => 'Дата',
'type' => 'Тип',
'account' => 'Аккаунт'
];
}
public function beforeSave($data)
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {
$this->date = time();
}
return true;
}
return false;
}
}

View File

@ -0,0 +1,352 @@
<?php
namespace app\models;
use moonland\phpexcel\Excel;
use carono\exchange1c\interfaces\ProductInterface;
use Zenwalker\CommerceML\Model\Product as Product1c;
class Product extends Document implements ProductInterface
{
const SCENARIO_IMPORT = 'import';
public $file;
public $group;
public static function collectionName()
{
return 'product';
}
public function attributes()
{
return array_merge(
parent::attributes(),
['name', 'catn', 'oemn', 'data', 'cost', 'time']
);
}
public function rules()
{
return array_merge(
parent::rules(),
[
[
['name', 'catn'],
'required',
'message' => 'Заполните поля: {attribute}',
'except' => self::SCENARIO_IMPORT
],
[
'file',
'required',
'message' => 'Заполните поля: {attribute}',
'on' => self::SCENARIO_IMPORT
],
['catn', 'integer', 'message' => '{attribute} должен быть числом'],
// ['oemn', 'integer'], Нужна своя проверка на массив
[
'file',
'file',
'skipOnEmpty' => false,
'extensions' => 'xlsx',
'checkExtensionByMimeType' => false,
'maxFiles' => 5,
'maxSize' => 1024 * 1024 * 30,
'wrongExtension' => 'Разрешены только документы в формате: ".xlsx"',
'message' => 'Проблема при чтении документа',
'on' => self::SCENARIO_IMPORT
]
]
);
}
public function attributeLabels()
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)',
'catn' => 'Каталожный номер (catn)',
'oemn' => 'OEM номера (oemn)',
'data' => 'Данные товара (data)',
'cost' => 'Цены (cost)',
'time' => 'Сроки доставки (time)',
'file' => 'Документ',
'group' => 'Группа',
]
);
}
public function beforeSave($data)
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {
// Надо избавиться от unset();
unset($this->_key);
}
return true;
}
return false;
}
public function import()
{
// Инициализация массива данных
$data = [];
if ($this->validate()) {
foreach ($this->file as $file) {
// Перебор файлов
// Сохранение на диск
if (!file_exists('../assets/import/excel/')) {
mkdir('../assets/import/excel/', 0775, true);
}
$file->saveAs($path = '../assets/import/excel/' . $file->baseName . '.' . $file->extension);
// Проверка файла пройдена
$data[] = Excel::import($path, [
'setFirstRecordAsKeys' => true,
'setIndexSheetByName' => true,
]);
}
foreach ($data[0] as $doc) {
// Перебор полученных документов
// Сохранение в базе данных
$product = new static($doc);
if ($product->validate()) {
// Проверка пройдена
// Запись документа
$product->save();
// Запись группы
$group = static::class . 'Group';
(new $group())->writeMember($product, $this->group);
} else {
// Проверка не пройдена
foreach ($product->errors as $attribute => $error) {
$this->addError($attribute, $error);
}
}
}
return true;
}
return false;
}
/**
* Установка реквизитов для продукта
*/
// public function setRequisite1c(string $name, string $value): bool
public function setRequisite1c($name, $value): bool
{
if (!$requisite = Requisite::readByName($name)) {
// Реквизиты не найдены
// Инициализация
$requisite = new Requisite();
$requisite->name = $name;
$requisite->value = $value;
// Запись
return $requisite->save();
}
return false;
}
/**
* Установка группы, где находится продукт
*/
// public function setGroup1c(ProductGroup $group): bool
public function setGroup1c($group): bool
{
// Чтение группы
$group = SupplyGroup::readByOnecName($group->id)[0];
// Запись ребра: ПОСТАВКА => ГРУППА ПОСТАВОК
return static::writeEdgeBetweenGroup(static::collectionName() . '/' . $this->_key, $group->collectionName() . '/' . $group->_key);
}
/**
* Запись всех параметров. Вызывается 1 раз при импорте
*/
public static function createProperties1c($properties): void
{
// Это нам не нужно, кажется, надо будет тестить
/**
* @var \Zenwalker\CommerceML\Model\Property $property
*/
// foreach ($properties as $property) {
// $propertyModel = Property::createByMl($property);
// foreach ($property->getAvailableValues() as $value) {
// if (!$propertyValue = PropertyValue::findOne(['onec_name' => $value->id])) {
// $propertyValue = new PropertyValue();
// $propertyValue->name = (string)$value->Значение;
// $propertyValue->property_id = $propertyModel->id;
// $propertyValue->onec_name = (string)$value->ИдЗначения;
// $propertyValue->save();
// unset($propertyValue);
// }
// }
// }
}
/**
* $property - Свойство товара (import.xml > Классификатор > Свойства > Свойство)
* $property->value - Разыменованное значение (string) (import.xml > Классификатор > Свойства > Свойство > Значение)
* $property->getValueModel() - Данные по значению, Ид значения, и т.д (import.xml > Классификатор > Свойства > Свойство > ВариантыЗначений > Справочник)
*
* @param MlProperty $property
* @return void
*/
public function setProperty1c($property): void
{
// Это тоже нам не нужно
// $propertyModel = Property::findOne(['onec_name' => $property->id]);
// $propertyValue = $property->getValueModel();
// if ($propertyAccountingId = (string)$propertyValue->ИдЗначения) {
// $value = PropertyValue::findOne(['onec_name' => $propertyAccountingId]);
// $attributes = ['property_value_id' => $value->id];
// } else {
// $attributes = ['value' => $propertyValue->value];
// }
// $this->addPivot($propertyModel, PvProductProperty::class, $attributes);
}
/**
* В этой фукнции мы получаем абсолютный путь до картинки и название изрбражения (для alt аттрибута)
*
* @param string $path
* @param string $caption
* @return mixed
*/
public function addImage1c($path, $caption): bool
{
// if (!$this->getImages()->andWhere(['md5' => md5_file($path)])->exists()) {
// $this->addPivot(FileUpload::startUpload($path)->process(), PvProductImage::class, ['caption' => $caption]);
// }
return false;
}
/**
* В эту фукнцию отправляется xml данные предложения из файла
*/
// public function getOffer1c(Supply $offer): Supply
public function getOffer1c($offer): Supply
{
$supply = Supply::createByMl($offer);
$supply->product_id = $this->id;
if ($supply->getDirtyAttributes()) {
$supply->save();
}
return $supply;
}
/**
* @param MlOffer $offer
*/
public static function createByMl($offer): Supply
{
if (!$model = static::readByOnecName($offer->id)) {
// Нет записей в базе данных
// Инициализация
$model = new static;
$model->name = (string) $offer->name;
$model->onec_name = (string) $offer->id;
}
$model->remnant = (string) $offer->Количество;
return $model;
}
/**
* @param $product
* @return self
*/
public static function createModel1c($product): static
{
if (!$model = static::findOne(['onec_name' => $product->id])) {
$model = new static();
$model->onec_name = $product->id;
}
$model->name = $product->name;
$model->description = (string) $product->Описание;
$model->article = (string) $product->Артикул;
$model->save();
return $model;
}
public function setRaw1cData($cml, $object)
{
}
/**
* Название поля в котором хранится ID из 1C
*/
public static function getIdFieldName1c(): string
{
return 'onec_name';
}
private static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenRequisite(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeRequisite();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
public static function readById(string $_key): ?Product
{
return Product::findOne(['_key' => $_key]);
}
public function getGroup1c(): ProductGroup
{
return $this->group;
}
public static function readByOnecName(string $name): ?Product
{
return static::findOne([static::getIdFieldName1c() => $name]);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class ProductEdgeProduct extends Edge
{
public static function collectionName()
{
return 'product_edge_product';
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class ProductEdgeProductGroup extends Edge
{
public static function collectionName()
{
return 'product_edge_product_group';
}
}

View File

@ -0,0 +1,175 @@
<?php
namespace app\models;
use carono\exchange1c\interfaces\GroupInterface;
use Zenwalker\CommerceML\Model\Group;
class ProductGroup extends Document implements GroupInterface
{
public static function collectionName()
{
return 'product_group';
}
public function attributes()
{
return array_merge(
parent::attributes(),
['name', 'onec_name', 'onec_prnt_name']
);
}
public function rules()
{
return array_merge(
parent::rules(),
[
// [
// 'name',
// 'required',
// 'message' => 'Заполните поле: {attribute}'
// ]
]
);
}
public function attributeLabels()
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)',
'onec_name' => 'Название 1C (onec_name)',
'onec_prnt_name' => 'Название родителя 1C (onec_prnt_name)',
]
);
}
public function writeMember(Document $member, string $group)
{
if (isset($member->_key)) {
return static::writeEdgeBetweenMember($member->collectionName() . '/' . $member->_key, $this->collectionName() . '/' . $group);
}
return false;
}
/**
* Создание дерева групп
* в параметр передаётся массив всех групп (import.xml > Классификатор > Группы)
* $groups[0]->parent - родительская группа
* $groups[0]->children - дочерние группы
*
* @param Group[] $groups
*/
public static function createTree1c($groups): Document|null
{
foreach ($groups as $group) {
// Перебор групп
// Создание
$parent = static::createByML($group);
if ($children = $group->getChildren()) {
// Найден потомок
// Вход в рекурсию
$children = static::createTree1c($children);
// Запись рёбер с родителем
static::writeEdgeBetweenGroup($parent::collectionName() . '/' . $parent->_key, $children::collectionName() . '/' . $children->_key);
return $children;
}
return $parent;
}
}
/**
* Создаём группу по модели группы CommerceML
* проверяем все дерево родителей группы, если родителя нет в базе - создаём
*
* @param Group $group
*/
public static function createByML(Group $group): static|array|null
{
if (!$model = static::readByOnecName($group->id)) {
// Группа не найдена
// Инициализация
$model = new static;
$model->onec_name = $group->id;
}
$model->name = $group->name;
if ($parent = $group->getParent()) {
// Найден родитель
// Инициализация (рекурсия)
$parentModel = static::createByML($parent);
$model->onec_prnt_name = $parentModel->id;
unset($parentModel);
} else {
$model->onec_prnt_name = null;
}
$model->save();
return $model;
}
private static function writeEdgeBetweenMember(string $from, string $to): bool
{
// Инициализация
$edge = new ProductEdgeProductGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация
$edge = new ProductGroupEdgeProductGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
public static function readAll()
{
return static::find()->all();
}
public static function readByName(string $name)
{
return static::findOne(['name' => $name]);
}
/**
* Название поля в котором хранится ID из 1C
*/
public static function getIdFieldName1c(): string
{
return 'onec_name';
}
public static function readByOnecName(string $name): ?Product
{
return static::findOne([static::getIdFieldName1c() => $name]);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class ProductGroupEdgeProductGroup extends Edge
{
public static function collectionName()
{
return 'product_group_edge_product_group';
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace app\models;
use carono\exchange1c\interfaces\DocumentInterface;
class Purchase extends Document implements DocumentInterface
{
public static function collectionName()
{
return 'requisite';
}
/**
* @return DocumentInterface[]
*/
public static function findDocuments1c()
{
return self::find()->andWhere(['status_id' => 2])->all();
}
/**
* @return OfferInterface[]
*/
public function getOffers1c()
{
return $this->offers;
}
public function getRequisites1c()
{
}
/**
* Получаем контрагента у документа
*
* @return PartnerInterface
*/
public function getPartner1c()
{
return $this->user;
}
public function getExportFields1c($context = null)
{
return [
'Ид' => 'id',
'Наименование' => 'login',
'ПолноеНаименование' => 'full_name',
'Фамилия' => 'surname',
'Имя' => 'name',
'Контакты' => [
[
'@name' => 'Контакт',
'Тип' => 'Почта',
'Значение' => $this->email,
],
[
'@name' => 'Контакт',
'Тип' => 'ТелефонРабочий',
'Значение' => $this->phone,
],
],
];
}
/**
* Возвращаем имя поля в базе данных, в котором хранится ID из 1с
*
* @return string
*/
public static function getIdFieldName1c()
{
return 'accounting_id';
}
public function setRaw1cData($cml, $object)
{
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class PurchaseEdgeSupply extends Edge
{
public static function collectionName()
{
return 'purchase_edge_supply';
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace app\models;
class Requisite extends Document
{
public static function collectionName()
{
return 'requisite';
}
public function attributes()
{
return array_merge(
parent::attributes(),
['name', 'value']
);
}
public function rules()
{
return array_merge(
parent::rules(),
[
[
['name', 'value'],
'required',
'message' => 'Заполните поле: {attribute}'
]
]
);
}
public function attributeLabels()
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название',
'value' => 'Значение'
]
);
}
public static function readByName(string $name)
{
return static::findOne(['name' => $name]);
}
}

View File

@ -0,0 +1,158 @@
<?php
namespace app\models;
use Yii;
use app\models\Account;
use app\models\Product;
use app\models\SupplyEdgeProduct;
use carono\exchange1c\interfaces\OfferInterface;
class Supply extends Product implements OfferInterface
{
public static function collectionName()
{
return 'supply';
}
public function afterSave($data, $vars)
{
if (is_null($product = self::readByCatn($this->catn))) {
// Товар не найден
// Инициализация
$product = (new Product(array_intersect_key($this->getAttributes(), (new Product)->getAttributes())));
// Запись
if (!$product->save()) {
return false;
}
}
// Запись рёбер: АККАУНТ => ПОСТАВКА => ТОВАР, и проверка на то, что оба созданы
static::writeEdgeBetweenAccount(Account::collectionName() . '/' . Yii::$app->user->identity->_key, static::collectionName() . '/' . $this->_key);
static::writeEdgeBetweenProduct(static::collectionName() . '/' . $this->_key, Product::collectionName() . '/' . $product->_key);
}
/**
* В этом методе необходимо создать все типы цен, фукнция вызывается один раз
*/
public static function createPriceTypes1c($types): void
{
foreach ($types as $type) {
// PriceType::createByMl($type);
}
}
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > Цены
*
* Цена товара,
* К $price можно обратиться как к массиву, чтобы получить список цен (Цены > Цена)
* $price->type - тип цены (offers.xml > ПакетПредложений > ТипыЦен > ТипЦены)
*
* @param \Zenwalker\CommerceML\Model\Price $price
*/
public function setPrice1c($price): void
{
// $priceType = PriceType::findOne(['accounting_id' => $price->getType()->id]);
// $priceModel = Price::createByMl($price, $this, $priceType);
// $this->addPivot($priceModel, PvOfferPrice::class);
}
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > ХарактеристикиТовара > ХарактеристикаТовара
*
* Характеристики товара
* $name - Наименование
* $value - Значение
*
* @param \Zenwalker\CommerceML\Model\Simple $specification
* @return void
*/
public function setSpecification1c($specification)
{
// $specificationModel = Specification::createByMl($specification);
// $this->addPivot($specificationModel, PvOfferSpecification::class, ['value' => (string)$specification->Значение]);
}
public function getExportFields1c($context = null)
{
return [
'Ид' => 'id',
'Наименование' => 'login',
'ПолноеНаименование' => 'full_name',
'Фамилия' => 'surname',
'Имя' => 'name',
'Контакты' => [
[
'@name' => 'Контакт',
'Тип' => 'Почта',
'Значение' => $this->email,
],
[
'@name' => 'Контакт',
'Тип' => 'ТелефонРабочий',
'Значение' => $this->phone,
],
],
];
}
public static function writeEdgeBetweenAccount(string $from, string $to): bool
{
// Инициализация
$edge = new AccountEdgeSupply();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenProduct(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeProduct();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenRequisite(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeRequisite();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
public static function readByCatn(string $catn): ?Product
{
return Product::findOne(['catn' => $catn]);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class SupplyEdgeProduct extends Edge
{
public static function collectionName()
{
return 'supply_edge_product';
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class SupplyEdgeRequisite extends Edge
{
public static function collectionName()
{
return 'supply_edge_requisite';
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class SupplyEdgeSupply extends ProductEdgeProduct
{
public static function collectionName()
{
return 'supply_edge_supply';
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class SupplyEdgeSupplyGroup extends ProductEdgeProductGroup
{
public static function collectionName()
{
return 'supply_edge_supply_group';
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace app\models;
class SupplyGroup extends ProductGroup
{
public static function collectionName()
{
return 'supply_group';
}
protected static function writeEdgeBetweenMember(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
protected static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyGroupEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
public static function readByOnecName(string $onec_name): ?Product
{
return static::findOne(['onec_name' => $onec_name]);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace app\models;
class SupplyGroupEdgeSupplyGroup extends Edge
{
public static function collectionName()
{
return 'supply_group_edge_supply_group';
}
}

View File

@ -1,104 +0,0 @@
<?php
namespace app\models;
class User extends \yii\base\BaseObject implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
/**
* {@inheritdoc}
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* {@inheritdoc}
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* @param string $username
* @return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* {@inheritdoc}
*/
public function getId()
{
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* {@inheritdoc}
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* @param string $password password to validate
* @return bool if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}

View File

@ -0,0 +1,43 @@
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use app\models\AccountForm;
?>
<div class="container d-flex flex-column h-100">
<div class="row my-auto">
<div class="mx-auto">
<?php
$form = ActiveForm::begin([
'id' => 'form_account',
'action' => false,
'fieldConfig' => [
'template' => '{label}{input}{error}',
'options' => ['class' => '']
],
'options' => [
'class' => '',
'onsubmit' => 'return false;'
]
]);
$model = $model ?? new AccountForm;
?>
<?= $form->field($model, 'mail', ['enableLabel' => false])->textInput(['autofocus' => true, 'placeholder' => $model->getAttributeLabel('mail')]) ?>
<?= $form->field($model, 'pswd', ['enableLabel' => false])->passwordInput(['placeholder' => $model->getAttributeLabel('pswd')]) ?>
<div class="d-flex mb-2 mt-3">
<?= Html::submitButton('Войти', ['name' => 'submitAuthentication', 'onclick' => 'authentication(this.parentElement.parentElement);', 'class' => 'flex-grow-1 mr-2 btn btn-primary button_clean']) ?>
<?= $form->field($model, 'auto', ['checkboxTemplate' => '<div class="checkbox button_clean">{beginLabel}' .
Html::submitButton('{labelTitle}', ['name' => 'submit', 'data-toggle' => 'button', 'class' => 'w-100 btn btn-primary button_clean', 'aria-pressed' => 'false']) .
'{endLabel}</div>'])->checkbox()->label($model->getAttributeLabel('auto'), ['class' => 'w-100 m-0']) ?>
</div>
<?= Html::submitButton('Регистрация', ['name' => 'submitRegistration', 'onclick' => 'registration(this.parentElement);', 'class' => 'col-12 ml-auto btn btn-success btn-sm button_clean']) ?>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,16 @@
<?php
use yii\helpers\Html;
$this->title = $name;
?>
<div id="page_error" class="container py-3">
<h1><?= Html::encode($this->title) ?></h1>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>
</div>

View File

@ -0,0 +1,86 @@
<?php
/* @var $this yii\web\View */
$this->title = 'SkillParts';
?>
<link href="/css/ticker.css" rel="stylesheet">
<div id="page_index">
<div class="info_panel mb-4">
<div class="container h-100 d-flex flex-column justify-content-center">
<p class="mb-4 gilroy">Проблема с подбором запчастей?</p>
<p class="d-flex">
<span class="p-2 px-3 button_call_icon"><i class="fas fa-phone-alt text-white"></i></span>
<a class="btn text-white button_clean button_blue button_call" href="/call" role="button">Связаться с менеджером</a>
</p>
</div>
<div class="h-100 d-flex flex-column justify-content-end">
<img class="img-fluid" src="/img/photos/compressed/963K_cutted.webp" alt="Связаться с менеджером">
</div>
</div>
<div class="h-100 d-flex ticker">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/cummins.png" alt="Cummins">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/iveco.png" alt="Iveco">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/komatsu.png" alt="Komatsu">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/case.png" alt="Case">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/isuzu.png" alt="Isuzu">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/new_holland.svg" alt="New Holland">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/perkins.png" alt="Perkins">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/john_deere.png" alt="John Deere">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/caterpillar.png" alt="Caterpillar">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/shantui.png" alt="Shantui">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/xcmg.png" alt="XCMG">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/kobelco.png" alt="Kobelco">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/shehwa.png" alt="SHEHWA">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/bomag.png" alt="BOMAG">
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/hitachi.png" alt="Hitachi">
</div>
<div class="container mb-4">
<!-- <div class="row mb-3">
<h4 class="col gilroy categories_blocks_panel_title">Сопутствующие товары</h4>
</div> -->
<div class="row mb-5 mb-md-0 px-3 px-md-0">
<div class="col-12 col-md-6 col-lg-4 mb-4 mb-lg-0 py-0 d-flex flex-column">
<div class="px-3 px-xl-4 pt-3 d-inline-block category_block_title">
<h4 class="m-0">Масла, смазки</h4>
</div>
<div class="p-3 px-md-4 category_block">
<dl class="mb-0">
<dd>Масла моторные</dd>
<dd>Масла трансмиссионные</dd>
<dd>Масла гидравлические</dd>
<dd>Смазки</dd>
</dl>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4 mb-4 mb-lg-0 py-0 d-flex flex-column">
<div class="px-3 px-xl-4 pt-3 d-inline-block category_block_title">
<h4 class="m-0">Электрооборудование</h4>
</div>
<div class="p-3 px-md-4 category_block">
<dl class="mb-0">
<dd>Фары и свет</dd>
</dl>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4 mb-4 mb-lg-0 py-0 d-flex flex-column">
<div class="px-3 px-xl-4 pt-3 d-inline-block category_block_title">
<h4 class="m-0">Инструмент</h4>
</div>
<div class="p-3 px-md-4 category_block">
<dl class="mb-0">
<dd>Шприцы для смазки </dd>
<dd>Ключи, съёмники</dd>
<dd>Наборы инструментов</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
<script src="/js/ticker.js" defer></script>

View File

@ -7,8 +7,11 @@ use yii\helpers\Html;
use app\assets\AppAsset;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
@ -24,33 +27,26 @@ AppAsset::register($this);
<body>
<?php $this->beginBody() ?>
<header>
<div class="container">
<div class="row mt-3 mt-sm-0 pt-3">
<div class="col-3 col-sm-4 col-md-2 d-flex flex-column justify-content-end logotype">
<a href="/"><img class="img-fluid" src="/img/logos/skillparts.png" alt="SkillParts"></a>
</div>
<div class="col ml-auto text-right d-flex flex-column justify-content-end">
<div class="row">
<nav id="nav" class="col"></nav>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col">
<div class="h-divider d-flex">
<div class="col-1 ml-auto p-0 h-divider-title-left"></div>
<div class="col-5 col-lg-4 h-divider-title d-flex flex-column justify-content-center">
<header class="container pt-2 mt-1 mb-4">
<div class="row h-100">
<a class="col-3 h-100 py-2" title="SkillParts" href="/" role="button" onclick="return page_main();">
<img class="h-100" src="/img/logos/skillparts.svg" alt="SkillParts">
</a>
<div class="col-6 px-0 mt-auto d-flex">
<div class="ml-auto p-0 h-divider-title-left"></div>
<div class="px-4 d-flex flex-column justify-content-center h-divider-title">
<h6 class="text-center text-white my-0"><b>Запчасти для спецтехники</b></h6>
</div>
<div class="col-1 mr-auto p-0 h-divider-title-right"></div>
</div>
<div class="mr-auto p-0 h-divider-title-right"></div>
</div>
<nav class="col-3 mt-auto d-flex justify-content-end"></nav>
</div>
<div class="h-divider"></div>
</header>
<div class="row mb-4">
<div class="col-lg-3 pr-0 pr-lg-3 d-flex flex-column align-center justify-content-end dropdownMenuButton_column">
<aside class="container mb-4">
<div class="row">
<div class="col-lg-3 d-flex flex-column align-center justify-content-end dropdownMenuButton_column">
<button id="dropdownMenuButton" class="btn form-control d-flex align-items-center button_clean catalog_button" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bars col-auto text-left p-0 mr-auto h-100 d-flex flex-column justify-content-center"></i>
<p class="col-10 m-0 p-0">Каталог товаров</p>
@ -75,15 +71,13 @@ AppAsset::register($this);
</form>
</div>
</div>
</div>
</header>
</aside>
<main>
<main class="col p-0">
<?= $content ?>
</main>
<footer class="py-4">
<div class="container">
<footer class="container py-4">
<div class="row px-3">
<div class="col-12 col-md-auto mr-md-5">
<h5 class="row mb-2"><b>Контакты</b></h5>
@ -99,11 +93,11 @@ AppAsset::register($this);
<small class="row mb-1"><a>Партнерская сеть</a></small>
</div>
</div>
</div>
</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

View File

@ -0,0 +1,18 @@
<?php
?>
<div id="page_product" class="h-100">
<div class="container h-100">
<div class="row h-100 py-3">
<div class="col-12">
<div class="block_main h-100 p-3 rounded">
<h4 class="ml-4"><?php echo $model['name'] ?></h4>
<div class="dropdown-divider"></div>
<p class="ml-4">Дата создания: <?php echo date('d.m.Y H:i', $model['date']) ?></p>
<pre class="ml-4"><?php var_dump($model) ?></pre>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,61 @@
<?php
use yii\bootstrap\ActiveForm;
use app\controllers\ProfileController;
use app\models\Product;
use app\models\Supply;
?>
<div id="page_profile" class="h-100">
<div class="container h-100">
<div class="row h-100 py-3">
<div class="col-3">
<div class="block_sidebar h-100 p-3 rounded">
<div class="d-flex">
<p>Почта: </p>
<p class="ml-auto"><?php echo Yii::$app->user->identity->mail ?></p>
</div>
</div>
</div>
<div class="col-9">
<div class="block_main h-100 p-3 rounded">
<h4 class="ml-4">Личный кабинет</h4>
<div class="dropdown-divider"></div>
<p>Не знаю что сюда пока добавить</p>
<?php
$form = ActiveForm::begin([
'id' => 'form_product_import_excel',
'action' => false,
'fieldConfig' => [
'template' => '{label}{input}',
'options' => ['class' => '']
],
'options' => [
'class' => 'mb-3',
'onsubmit' => 'return false;'
]
]);
$model = $model ?? new Supply;
$groups = ProfileController::readGroups();
?>
<?= $form->field($model, 'group', ['options' => ['class' => "mb-3"]])->dropDownList($groups ?? ['Нет данных']); ?>
<?= $form->field($model, 'file', ['enableLabel' => false])->fileInput(['multiple' => true, 'onChange' => 'supply_import(this.parentElement.parentElement)']) ?>
<?= $form->errorSummary($model, ['header' => 'В документе были допущены ошибки:' /*, 'footer' => 'Исправьте их и попробуйте снова'*/]); ?>
<?php ActiveForm::end(); ?>
<p>Всего товаров: <?php echo Product::readAmount() ?></p>
<p>Всего поставок: <?php echo Supply::readAmount() ?></p>
</div>
</div>
</div>
</div>
</div>
<script src="/js/profile.js" defer></script>

View File

@ -1,18 +0,0 @@
<?php
/* @var $this yii\web\View */
use yii\helpers\Html;
$this->title = 'About';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-about">
<h1><?= Html::encode($this->title) ?></h1>
<p>
This is the About page. You may modify the following file to customize its content:
</p>
<code><?= __FILE__ ?></code>
</div>

View File

@ -1,34 +0,0 @@
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use app\models\RegistrationForm;
?>
<div class="container d-flex flex-column">
<div class="row my-auto">
<div class="col-lg-4 mx-auto">
<?php $form = ActiveForm::begin([
'id' => 'form_account',
'action' => false,
'fieldConfig' => [
'template' => "{label}\n<div>{input}</div>\n<div>{error}</div>"
],
'options' => [
'onsubmit' => 'return false;'
]
]); ?>
<?= $form->field($model, 'mail')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'pswd')->passwordInput() ?>
<?= $form->field($model, 'auto')->checkbox() ?>
<div class="d-flex">
<?= Html::submitButton('Войти', ['name' => 'submit', 'onclick' => 'authentication(this.parentElement.parentElement);', 'class' => 'btn btn-primary col-4']) ?>
<?= Html::submitButton('Регистрация', ['name' => 'submit', 'onclick' => 'registration(this.parentElement.parentElement);', 'class' => 'btn btn-success col-7 ml-auto']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -1,68 +0,0 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model app\models\ContactForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
$this->title = 'Contact';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-contact">
<h1><?= Html::encode($this->title) ?></h1>
<?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?>
<div class="alert alert-success">
Thank you for contacting us. We will respond to you as soon as possible.
</div>
<p>
Note that if you turn on the Yii debugger, you should be able
to view the mail message on the mail panel of the debugger.
<?php if (Yii::$app->mailer->useFileTransport): ?>
Because the application is in development mode, the email is not sent but saved as
a file under <code><?= Yii::getAlias(Yii::$app->mailer->fileTransportPath) ?></code>.
Please configure the <code>useFileTransport</code> property of the <code>mail</code>
application component to be false to enable email sending.
<?php endif; ?>
</p>
<?php else: ?>
<p>
If you have business inquiries or other questions, please fill out the following form to contact us.
Thank you.
</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
<?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'subject') ?>
<?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
]) ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
<?php endif; ?>
</div>

View File

@ -1,27 +0,0 @@
<?php
/* @var $this yii\web\View */
/* @var $name string */
/* @var $message string */
/* @var $exception Exception */
use yii\helpers\Html;
$this->title = $name;
?>
<div class="site-error">
<h1><?= Html::encode($this->title) ?></h1>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>
<p>
The above error occurred while the Web server was processing your request.
</p>
<p>
Please contact us if you think this is a server error. Thank you.
</p>
</div>

View File

@ -1,77 +0,0 @@
<?php
/* @var $this yii\web\View */
$this->title = 'SkillParts';
?>
<div class="info_panel mb-4">
<div class="container h-100 d-flex flex-column justify-content-center">
<p class="col-lg-8 mb-4 gilroy">Проблема с подбором запчастей?</p>
<a class="text-white btn button_clean button_call" href="/call">Связаться с менеджером</a>
</div>
<div class="h-100 d-flex flex-column justify-content-end">
<img class="img-fluid" src="/img/photos/963K_cutted.webp" alt="Связаться с менеджером">
</div>
</div>
<div class="h-100 d-flex ticker">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/cummins.png" alt="Cummins">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/iveco.png" alt="Iveco">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/komatsu.png" alt="Komatsu">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/case.png" alt="Case">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/isuzu.png" alt="Isuzu">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/new_holland.png" alt="New Holland">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/perkins.png" alt="Perkins">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/john_deere.png" alt="John Deere">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/caterpillar.png" alt="Caterpillar">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/shantui.png" alt="Shantui">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/xcmg.png" alt="XCMG">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/kobelco.png" alt="Kobelco">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/shehwa.png" alt="SHEHWA">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/bomag.png" alt="BOMAG">
<img class="w-auto h-75 mr-3 my-auto" src="/img/logos/hitachi.png" alt="Hitachi">
</div>
<div class="container mb-4">
<!-- <div class="row mb-3">
<h4 class="col gilroy categories_blocks_panel_title">Сопутствующие товары</h4>
</div> -->
<div class="row mb-5 mb-md-0 px-3 px-md-0">
<div class="col-12 col-md-6 col-lg-4 mb-4 mb-lg-0 py-0 d-flex flex-column">
<div class="px-3 px-xl-4 pt-3 d-inline-block category_block_title">
<h4 class="m-0">Масла, смазки</h4>
</div>
<div class="p-3 px-md-4 category_block">
<dl class="mb-0">
<dd>Масла моторные</dd>
<dd>Масла трансмиссионные</dd>
<dd>Масла гидравлические</dd>
<dd>Смазки</dd>
</dl>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4 mb-4 mb-lg-0 py-0 d-flex flex-column">
<div class="px-3 px-xl-4 pt-3 d-inline-block category_block_title">
<h4 class="m-0">Электрооборудование</h4>
</div>
<div class="p-3 px-md-4 category_block">
<dl class="mb-0">
<dd>Фары и свет</dd>
</dl>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4 mb-4 mb-lg-0 py-0 d-flex flex-column">
<div class="px-3 px-xl-4 pt-3 d-inline-block category_block_title">
<h4 class="m-0">Инструмент</h4>
</div>
<div class="p-3 px-md-4 category_block">
<dl class="mb-0">
<dd>Шприцы для смазки </dd>
<dd>Ключи, съёмники</dd>
<dd>Наборы инструментов</dd>
</dl>
</div>
</div>
</div>
</div>

View File

@ -1,63 +0,0 @@
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-contact">
<h1><?= Html::encode($this->title) ?></h1>
<?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?>
<div class="alert alert-success">
Thank you for contacting us. We will respond to you as soon as possible.
</div>
<p>
Note that if you turn on the Yii debugger, you should be able
to view the mail message on the mail panel of the debugger.
<?php if (Yii::$app->mailer->useFileTransport): ?>
Because the application is in development mode, the email is not sent but saved as
a file under <code><?= Yii::getAlias(Yii::$app->mailer->fileTransportPath) ?></code>.
Please configure the <code>useFileTransport</code> property of the <code>mail</code>
application component to be false to enable email sending.
<?php endif; ?>
</p>
<?php else: ?>
<p>
If you have business inquiries or other questions, please fill out the following form to contact us.
Thank you.
</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
<?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'subject') ?>
<?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
]) ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
<?php endif; ?>
</div>

View File

@ -1,11 +1,21 @@
header {
height: 4rem;
background-color: #fff;
}
nav {
height: max-content;
}
#profile_button+.dropdown-menu-long {
width: 250px;
}
#profile_button+.dropdown-menu #form_account .help-block-error {
margin-bottom: .5rem;
}
.h-divider {
margin-top: -20px;
position: relative;
pointer-events: none;
border-bottom: 4px solid #123EAB;
}

View File

@ -27,17 +27,14 @@
}
.info_panel .button_call {
width: 350px;
margin-left: 2vw;
background-color: #123EAB;
width: max-content;
border-radius: 0px 5px 5px 0px;
}
.info_panel .button_call:hover {
background-color: #1b4bc4;
}
.info_panel .button_call:active {
background-color: #402d82;
.info_panel .button_call_icon {
font-size: 1rem;
border-radius: 5px 0px 0px 5px;
background-color: #132f77;
}
@media (max-width: 400px) {}

View File

@ -12,6 +12,10 @@ a {
cursor: pointer;
}
a:hover {
text-decoration: none;
}
button {
transition: 0s !important;
}
@ -25,19 +29,54 @@ body {
main {
flex-grow: 1;
display: grid;
background-color: #f0eefb;
}
.block_sidebar {
background-color: #fff;
}
.block_main {
background-color: #fff;
}
.button_clean, .button_clean:hover, .button_clean:focus, .button_clean:active {
outline: none !important;
box-shadow: none !important;
}
.button_blue {
background-color: #123EAB;
}
.button_blue:hover {
background-color: #1b4bc4;
}
.button_blue:active {
background-color: #402d82;
}
.button_white {
background-color: #fff;
}
.button_white:hover {
background-color: #eaebee;
}
.button_white:active {
background-color: #cfd3dd;
}
.d-inline-block {
display: inline-block;
}
.form-group:last-child {
padding: 0;
}
.gilroy {
font-family: 'Gilroy';
}

View File

@ -1,3 +1,7 @@
.ticker img {
object-fit: contain;
}
.bx-wrapper {
margin-bottom: 1.5rem !important;
width: 100vw;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Some files were not shown because too many files have changed in this diff Show More