├── .docker ├── nginx │ ├── .gitignore │ └── dev │ │ └── app.conf ├── php │ └── dev │ │ └── xdebug.ini ├── roadrunner │ ├── Dockerfile │ ├── DockerfileProd │ ├── DockerfileSource │ ├── config │ │ ├── rr.prod.yaml │ │ └── rr.yaml │ ├── docker-build.me │ ├── docker-healthcheck.sh │ └── status.sh └── temporal │ ├── Dockerfile │ └── dynamicconfig │ └── development.yaml ├── .dockerignore ├── .env.example ├── .env.testing ├── .env.testing.example ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .jshintrc ├── LICENSE ├── Readme.md ├── SECURITY.md ├── app ├── Admin.php ├── Catalog.php ├── Console │ ├── Commands │ │ └── SalesReportCommand.php │ └── Kernel.php ├── DTO │ ├── CategoriesDTO.php │ ├── FilterNumberDTO.php │ └── FilterSelectorDTO.php ├── Dispatch.php ├── Domain │ └── Reports │ │ └── DailySalesReport.php ├── Enums │ └── AdminPaymentMethodStatuses.php ├── Events │ ├── Event.php │ ├── OrderCreated.php │ └── PaymentCreated.php ├── Exceptions │ ├── FondyPaymentException.php │ ├── Handler.php │ ├── PaymentException.php │ └── PsrInvalidArgumentException.php ├── Http │ ├── Controllers │ │ ├── AdminCategoriesController.php │ │ ├── AdminController.php │ │ ├── AdminOrdersController.php │ │ ├── AdminPaymentMethodsController.php │ │ ├── AdminProductsController.php │ │ ├── AdminPropertiesController.php │ │ ├── AdminShippingMethodsController.php │ │ ├── AdminUsersController.php │ │ ├── Auth │ │ │ ├── AdminForgotPasswordController.php │ │ │ ├── AdminLoginController.php │ │ │ ├── AdminResetPasswordController.php │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ ├── RegisterController.php │ │ │ └── ResetPasswordController.php │ │ ├── CartController.php │ │ ├── CheckoutController.php │ │ ├── Controller.php │ │ ├── FilterController.php │ │ ├── HomeController.php │ │ ├── OrderController.php │ │ ├── SearchController.php │ │ ├── ShopController.php │ │ ├── StubController.php │ │ └── TestController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── EncryptCookies.php │ │ ├── ForceLogout.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ └── VerifyCsrfToken.php │ ├── Requests │ │ ├── CartAddRelatedRequest.php │ │ ├── CartAddRequest.php │ │ ├── CartChangePaymentRequest.php │ │ ├── CartChangeShippingRequest.php │ │ ├── CartRemoveItemRequest.php │ │ ├── CheckoutRequest.php │ │ └── OrderActionRequest.php │ └── Resources │ │ ├── CartPostResource.php │ │ ├── CategoriesResource.php │ │ ├── Dispatch.php │ │ ├── OrderCollection.php │ │ ├── OrderData.php │ │ ├── OrderDetailResource.php │ │ ├── OrderResource.php │ │ ├── Payment.php │ │ ├── ProductCollection.php │ │ ├── ProductResource.php │ │ └── PropertiesResource.php ├── Library │ └── Services │ │ ├── Ipsp │ │ ├── Api.php │ │ ├── Client.php │ │ ├── Curl.php │ │ ├── Error.php │ │ ├── Request.php │ │ ├── Resource.php │ │ ├── Resource │ │ │ ├── Capture.php │ │ │ ├── Checkout.php │ │ │ ├── P2pcredit.php │ │ │ ├── Pcidss.php │ │ │ ├── PcidssConfirm.php │ │ │ ├── Recurring.php │ │ │ ├── Reports.php │ │ │ ├── Result.php │ │ │ ├── Reverse.php │ │ │ ├── Status.php │ │ │ ├── TransactionList.php │ │ │ └── Verification.php │ │ ├── Response.php │ │ └── XmlData.php │ │ ├── IpspPaymentService.php │ │ ├── PaymentResponseInterface.php │ │ └── PaymentServiceInterface.php ├── Listeners │ ├── EventListener.php │ ├── LogSuccessfulLogin.php │ ├── OrderSubscriber.php │ └── PaymentStatusSubscriber.php ├── Notifications │ └── AdminResetPasswordNotification.php ├── Order.php ├── OrderData.php ├── Payment.php ├── PaymentMethod.php ├── Product.php ├── Property.php ├── PropertyValue.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── ErpServiceProvider.php │ ├── EventServiceProvider.php │ ├── PaymentServiceProvider.php │ └── RouteServiceProvider.php ├── RelatedProduct.php ├── Repositories │ ├── OrderRepository.php │ ├── PaymentMethodRepository.php │ ├── PaymentRepository.php │ ├── ProductRepository.php │ └── PropertyRepository.php ├── Services │ ├── Cart │ │ ├── CartPostActions.php │ │ ├── CartPostDTO.php │ │ └── CartService.php │ ├── Erp │ │ ├── DTO │ │ │ └── ErpOrderDTO.php │ │ ├── ErpServiceInterface.php │ │ └── ErpServiceStub.php │ ├── Order │ │ ├── OrderActions.php │ │ └── OrderStatuses.php │ ├── Payment │ │ ├── FondyPayment.php │ │ ├── PayPalHttpClient.php │ │ ├── PaymentMethodInterface.php │ │ ├── PaymentMethodManager.php │ │ ├── PaymentResponse.php │ │ └── PaypalPayment.php │ ├── Recommended │ │ └── Recommended.php │ ├── Shipping │ │ ├── FixRateShippingMethod.php │ │ ├── FreeShippingMethod.php │ │ └── ShippingMethodImplementation.php │ ├── Warehouse │ │ ├── DTO │ │ │ └── WarehouseOrderDTO.php │ │ ├── ValueObject │ │ │ └── WarehouseOrderStatus.php │ │ ├── WarehouseServiceInterface.php │ │ └── WarehouseServiceStub.php │ └── WorkflowService.php ├── ShippingMethod.php ├── Temporal │ ├── Cron │ │ ├── SalesReportActivity.php │ │ ├── SalesReportActivityInterface.php │ │ ├── SalesReportWorkflow.php │ │ └── SalesReportWorkflowInterface.php │ ├── ErpActivity.php │ ├── ErpActivityInterface.php │ ├── Locator.php │ ├── OrderCompletedWorkflow.php │ ├── OrderCompletedWorkflowInterface.php │ ├── PaymentActivity.php │ ├── PaymentActivityInterface.php │ ├── PaymentWorkflow.php │ ├── PaymentWorkflowInterface.php │ ├── WarehouseActivity.php │ └── WarehouseActivityInterface.php ├── Unit.php └── User.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── compose.yaml ├── composer.json ├── composer.lock ├── composer.phar ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── database.php ├── filesystems.php ├── flare.php ├── ignition.php ├── logging.php ├── mail.php ├── octane.php ├── payments.php ├── queue.php ├── sentry.php ├── services.php ├── session.php ├── tinker.php └── view.php ├── database ├── .gitignore ├── factories │ ├── CatalogFactory.php │ ├── DispatchFactory.php │ ├── OrderDataFactory.php │ ├── OrderFactory.php │ ├── PaymentFactory.php │ ├── ProductFactory.php │ ├── PropertyFactory.php │ ├── PropertyValueFactory.php │ ├── RelatedProductFactory.php │ ├── ShippingMethodFactory.php │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2017_10_08_113015_create_products_table.php │ ├── 2017_10_08_114109_create_orders_table.php │ ├── 2017_10_08_114503_create_related_products_table.php │ ├── 2017_10_08_115559_create_order_data_table.php │ ├── 2017_10_24_071139_add_cart_to_users.php │ ├── 2017_11_05_070115_create_catalogs_table.php │ ├── 2017_11_05_071437_add_catalog_to_product.php │ ├── 2017_11_08_134904_create_units_table.php │ ├── 2017_11_08_175930_create_properties_table.php │ ├── 2017_11_09_073633_create_product_property_table.php │ ├── 2017_11_12_152737_add_priority_to_properties_table.php │ ├── 2017_11_12_174417_add_type_to_properties_table.php │ ├── 2017_11_13_071534_create_property_values_table.php │ ├── 2017_11_13_072524_alter_first_properties_table.php │ ├── 2017_11_15_211208_change_propidcol_product_properties_table.php │ ├── 2017_12_02_202911_create_admins_table.php │ ├── 2017_12_21_200452_add_force_logout_users_table.php │ ├── 2017_12_22_074807_add_user_id_orders_table.php │ ├── 2017_12_22_112834_create_shipping_methods_table.php │ ├── 2018_01_02_074253_create_products_related_products_table.php │ ├── 2018_01_02_075043_remove_columns_from_related_products_table.php │ ├── 2018_01_05_100641_alter_status_orders_table.php │ ├── 2019_02_04_175305_alter_users_table_change_type_column_cart.php │ ├── 2022_04_10_130734_create_payment_methods_table.php │ ├── 2022_04_22_124253_create_dispatches_table.php │ ├── 2022_04_22_124353_create_payments_table.php │ ├── 2022_05_15_100734_add_payment_methods.php │ └── 2024_07_28_125305_alter_users_table_change_type_column_cart_nullable.php └── seeders │ ├── AdminsTableSeeder.php │ ├── CatalogsTableSeeder.php │ ├── DatabaseSeeder.php │ ├── ProductPropertiesTableSeeder.php │ ├── ProductsRelatedProductsTableSeeder.php │ ├── ProductsTableSeeder.php │ ├── PropertiesTableSeeder.php │ ├── PropertyValuesTableSeeder.php │ ├── RelatedProductsTableSeeder.php │ ├── ShippingMethodsTableSeeder.php │ └── UnitsTableSeeder.php ├── docker-compose.yml ├── package-lock.json ├── package.json ├── phpstan.neon ├── phpunit.xml ├── public ├── .htaccess ├── css │ └── app.css ├── desktop.ini ├── favicon.ico ├── fonts │ └── vendor │ │ └── bootstrap-sass │ │ └── bootstrap │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 ├── images │ ├── cart-icon.png │ ├── categories │ │ └── cat_1512673520.jpg │ ├── loading.gif │ ├── prod1.jpg │ ├── prod2.jpg │ ├── prod3.jpg │ ├── prod4.jpg │ ├── prod5.jpg │ ├── prod6.jpg │ └── products │ │ ├── .empty │ │ └── .gitignore ├── index.php ├── js │ ├── admin_script.js │ ├── app.js │ ├── app.js.LICENSE.txt │ ├── bootstrap-confirmation.min.js │ ├── jquery.easing.1.3.min.js │ └── my_script.js ├── mix-manifest.json ├── php_errors.log ├── rel1.jpg ├── robots.txt ├── service-worker.js └── web.config ├── resources ├── assets │ ├── js │ │ ├── app.js │ │ ├── bootstrap.js │ │ ├── components │ │ │ ├── Cart.vue │ │ │ ├── Categories.vue │ │ │ ├── ModalWrapper.vue │ │ │ ├── NavCart.vue │ │ │ ├── NavSearch.vue │ │ │ ├── OrderInfo.vue │ │ │ ├── OrdersList.vue │ │ │ ├── Product.vue │ │ │ ├── ProductFilter.vue │ │ │ ├── ProductFilters.vue │ │ │ ├── ProductList.vue │ │ │ └── SingleItem.vue │ │ └── models │ │ │ └── Order.js │ └── sass │ │ ├── _variables.scss │ │ └── app.scss ├── lang │ └── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php └── views │ ├── admin │ ├── admin-left-column.blade.php │ ├── admin.blade.php │ ├── categories.blade.php │ ├── dashboard.blade.php │ ├── edit-category.blade.php │ ├── edit-product.blade.php │ ├── edit-user.blade.php │ ├── nav.blade.php │ ├── new-property-modal.blade.php │ ├── orders-load.blade.php │ ├── orders.blade.php │ ├── payment-methods.blade.php │ ├── product-properties.blade.php │ ├── products-load.blade.php │ ├── products.blade.php │ ├── property-modal.blade.php │ ├── property-values.blade.php │ ├── shipping-methods-load.blade.php │ ├── shipping-methods.blade.php │ ├── users-load.blade.php │ └── users.blade.php │ ├── app.blade.php │ ├── auth │ ├── admin-login.blade.php │ ├── login.blade.php │ ├── passwords │ │ ├── email-admin.blade.php │ │ ├── email.blade.php │ │ ├── reset-admin.blade.php │ │ └── reset.blade.php │ └── register.blade.php │ ├── cart.blade.php │ ├── empty-cart.blade.php │ ├── errors │ ├── 401.blade.php │ ├── 402.blade.php │ ├── 403.blade.php │ ├── 404.blade.php │ ├── 419.blade.php │ ├── 429.blade.php │ ├── 500.blade.php │ ├── 503.blade.php │ ├── layout.blade.php │ └── minimal.blade.php │ ├── home.blade.php │ ├── layouts │ ├── auth.blade.php │ ├── categories.blade.php │ ├── error.blade.php │ ├── modal.blade.php │ ├── nav.blade.php │ └── product-not-found.blade.php │ ├── paywithpaypal.blade.php │ ├── product.blade.php │ ├── shop.blade.php │ ├── shop │ ├── order-success.blade.php │ ├── order.blade.php │ ├── orders.blade.php │ ├── search-product.blade.php │ ├── single.blade.php │ └── test.blade.php │ └── test.blade.php ├── routes ├── api.php ├── channels.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── temporal └── roadrunner-worker ├── tests ├── CreatesApplication.php ├── Feature │ ├── CartControllerTest.php │ ├── HttpGetShopTest.php │ ├── OrderControllerTest.php │ ├── RelatedProductRepositoryTest.php │ └── Repositories │ │ └── ProductRepositoryTest.php ├── TestCase.php ├── Unit │ ├── CatalogTest.php │ ├── OrderTest.php │ └── RecommendedTest.php └── js │ ├── Cart.spec.js │ ├── NavCart.spec.js │ ├── NavSearch.spec.js │ ├── Product.spec.js │ ├── ProductFilter.spec.js │ ├── SingleItem.spec.js │ ├── flush-promises.js │ ├── setup.js │ └── webpack.config.js └── webpack.mix.js /.docker/nginx/.gitignore: -------------------------------------------------------------------------------- 1 | *.crt 2 | *.key 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /.docker/php/dev/xdebug.ini: -------------------------------------------------------------------------------- 1 | zend_extension=/opt/bitnami/php/lib/php/extensions/xdebug.so 2 | xdebug.idekey=PHPSTORM 3 | xdebug.client_host=host.docker.internal 4 | xdebug.mode=develop,debug 5 | xdebug.start_with_request=yes 6 | -------------------------------------------------------------------------------- /.docker/roadrunner/DockerfileProd: -------------------------------------------------------------------------------- 1 | ARG RR_VERSION 2 | ARG RR_IMAGE=ghcr.io/roadrunner-server/roadrunner:${RR_VERSION} 3 | 4 | FROM ${RR_IMAGE} as rr 5 | FROM gaintvlad/lara_shop_roadrunner:latest 6 | 7 | ARG XDEBUG_VERSION=3.2.1 8 | ARG WWWUSER=1000 9 | ARG WWWGROUP=1000 10 | 11 | RUN addgroup -g $WWWGROUP octane \ 12 | && adduser -D -s /bin/bash -G octane -u $WWWUSER octane \ 13 | 14 | RUN set -eux; \ 15 | apk add --no-cache --virtual .build-deps $PHPIZE_DEPS; \ 16 | pecl install xdebug-$XDEBUG_VERSION; \ 17 | docker-php-ext-enable xdebug; \ 18 | apk del .build-deps 19 | 20 | 21 | # Copy Composer 22 | COPY --from=composer:2 /usr/bin/composer /usr/bin/composer 23 | 24 | # Copy RoadRunner 25 | COPY --from=rr /usr/bin/rr /usr/bin/rr 26 | 27 | # Copy RoadRunner config 28 | COPY ./.docker/roadrunner/config/rr.prod.yaml /etc/.rr.yaml 29 | 30 | WORKDIR /app 31 | 32 | COPY .docker/roadrunner/docker-healthcheck.sh /usr/local/bin/docker-healthcheck 33 | 34 | COPY ./ /app 35 | 36 | RUN composer install \ 37 | --no-dev \ 38 | --no-interaction \ 39 | --prefer-dist \ 40 | --no-scripts \ 41 | --ignore-platform-reqs \ 42 | --optimize-autoloader \ 43 | --apcu-autoloader \ 44 | --ansi 45 | 46 | RUN composer dumpautoload 47 | 48 | RUN chmod +x /usr/local/bin/docker-healthcheck 49 | 50 | EXPOSE 80 51 | 52 | HEALTHCHECK --interval=1s --timeout=10s --retries=30 CMD ["docker-healthcheck"] 53 | 54 | CMD ["/usr/bin/rr", "serve", "-d", "-c", "/etc/.rr.yaml"] 55 | -------------------------------------------------------------------------------- /.docker/roadrunner/config/rr.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | rpc: 4 | listen: tcp://127.0.0.1:6001 5 | 6 | server: 7 | command: "/app/temporal/roadrunner-worker" 8 | env: 9 | - XDEBUG_SESSION: 1 10 | 11 | http: 12 | address: :80 13 | #max_request_size: 256 14 | middleware: [ "static", "headers", "gzip" ] 15 | uploads: 16 | dir: /tmp 17 | forbid: [ ".php", ".exe", ".bat", ".sh" ] 18 | headers: 19 | response: 20 | X-Powered-By: RoadRunner 21 | ssl: 22 | address: :443 23 | key: "/app/ssl/localhost-key.pem" 24 | cert: "/app/ssl/localhost.pem" 25 | root_ca: "/app/ssl/localhost.pem" 26 | #client_auth_type: require_and_verify_client_cert 27 | static: 28 | dir: "/app/public" 29 | forbid: [".htaccess", ".php", ".sql", ".config", "php_errors.log"] 30 | calculate_etag: false 31 | weak: false 32 | allow: [ "" ] 33 | request: 34 | input: "custom-header" 35 | response: 36 | output: "output-header" 37 | pool: 38 | num_workers: 2 39 | allocate_timeout: 30s 40 | max_jobs: 64 41 | debug: false 42 | 43 | temporal: 44 | address: temporal:7233 45 | activities: 46 | num_workers: 6 47 | 48 | reload: 49 | interval: 1s 50 | patterns: [".php", ".yaml"] 51 | services: 52 | http: 53 | recursive: true 54 | dirs: [ "/app/app" ] 55 | temporal: 56 | recursive: true 57 | dirs: [ "/app/app" ] 58 | 59 | status: 60 | address: roadrunner:2114 61 | -------------------------------------------------------------------------------- /.docker/roadrunner/docker-build.me: -------------------------------------------------------------------------------- 1 | docker build -f DockerfileSource --build-arg RR_VERSION=2024.2.0 --build-arg PHP_IMAGE_VERSION=8.3-cli-alpine -t lara_shop_roadrunner . 2 | 3 | docker image tag lara_shop_roadrunner gaintvlad/lara_shop_roadrunner:latest 4 | 5 | docker image tag lara_shop_roadrunner gaintvlad/lara_shop_roadrunner:8.3-2024.2 6 | 7 | docker image push gaintvlad/lara_shop_roadrunner:latest 8 | -------------------------------------------------------------------------------- /.docker/roadrunner/docker-healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | url=roadrunner:2114/health?plugin=http 4 | 5 | status_code=$(curl --write-out %{http_code} --silent --output /dev/null ${url}) 6 | 7 | echo ${status_code} 8 | 9 | if [[ "$status_code" -ne 200 ]] ; then 10 | exit 1 11 | else 12 | exit 0 13 | fi 14 | -------------------------------------------------------------------------------- /.docker/roadrunner/status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exit 0 4 | -------------------------------------------------------------------------------- /.docker/temporal/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM temporalio/auto-setup:latest 2 | 3 | COPY ./.docker/temporal/dynamicconfig /etc/temporal/config/dynamicconfig 4 | -------------------------------------------------------------------------------- /.docker/temporal/dynamicconfig/development.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/.docker/temporal/dynamicconfig/development.yaml -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.local_data/ 2 | **/*.log 3 | **/*.md 4 | **/._* 5 | **/.dockerignore 6 | **/.DS_Store 7 | **/.git/ 8 | **/.gitattributes 9 | **/.gitignore 10 | **/.gitmodules 11 | **/docker-compose.*.yaml 12 | **/docker-compose.*.yml 13 | **/docker-compose.yaml 14 | **/docker-compose.yml 15 | **/Dockerfile 16 | **/Thumbs.db 17 | .editorconfig 18 | .env.*.local 19 | .env.local 20 | .env 21 | .env.prod 22 | build/ 23 | node_modules/ 24 | -------------------------------------------------------------------------------- /.env.testing: -------------------------------------------------------------------------------- 1 | APP_KEY=base64:zEPImOeK5vgeO/jtFAAprVGAh+ZW8XLkfAuS3bZDX4w= 2 | APP_URL=http://localhost 3 | APP_NAME=Laravel 4 | APP_ENV=testing 5 | APP_DEBUG=false 6 | APP_LOG_LEVEL=debug 7 | 8 | APP_ORDERS_PREFIX=ule 9 | 10 | DB_CONNECTION=mysql 11 | DB_HOST=mariadb_test 12 | DB_PORT=3306 13 | DB_DATABASE=shop 14 | DB_USERNAME=admin 15 | DB_PASSWORD=secret 16 | DB_CHARSET=utf8 17 | DB_COLLATION=utf8_unicode_ci 18 | 19 | BROADCAST_DRIVER=log 20 | CACHE_DRIVER=redis 21 | SESSION_DRIVER=file 22 | QUEUE_DRIVER=sync 23 | 24 | RR_VERSION=2023.1.4 25 | PHP_IMAGE_VERSION=8.0.14-cli-alpine3.17 26 | -------------------------------------------------------------------------------- /.env.testing.example: -------------------------------------------------------------------------------- 1 | APP_KEY= your app key from .env 2 | APP_URL=http://localhost 3 | 4 | DB_CONNECTION=sqlite 5 | DB_HOST=127.0.0.1 6 | DB_PORT=3306 7 | DB_DATABASE=:memory: 8 | DB_USERNAME=root 9 | DB_PASSWORD= 10 | 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | public/hot 3 | public/storage 4 | public/.well-known/* 5 | storage/*.key 6 | vendor 7 | .idea 8 | .vagrant 9 | Homestead.json 10 | Homestead.yaml 11 | npm-debug.log 12 | yarn-error.log 13 | .env 14 | .env.prod 15 | .env.testing 16 | *.log 17 | 18 | /Vagrantfile 19 | /.phpunit.result.cache 20 | .local_data/ 21 | 22 | ssl/* 23 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "camelcase" : true, 3 | "indent": 2, 4 | "undef": true, 5 | "quotmark": false, 6 | "maxlen": 120, 7 | "trailing": true, 8 | "curly": true, 9 | "strict": false, 10 | "browser": true, 11 | "devel": true, 12 | "jquery": true, 13 | "esversion": 6, 14 | "node": true, 15 | "asi": true 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Uladimir Sadkou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 1.x | :white_check_mark: | 8 | 9 | 10 | ## Reporting a Vulnerability 11 | sadkoff@tut.by 12 | -------------------------------------------------------------------------------- /app/Admin.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | protected $fillable = [ 20 | 'name', 'email', 'password', 'job_title' 21 | ]; 22 | 23 | /** 24 | * The attributes that should be hidden for arrays. 25 | * 26 | * @var array 27 | */ 28 | protected $hidden = [ 29 | 'password', 'remember_token', 30 | ]; 31 | 32 | /** 33 | * @param string $token 34 | */ 35 | public function sendPasswordResetNotification($token): void 36 | { 37 | $this->notify(new AdminResetPasswordNotification($token)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Catalog.php: -------------------------------------------------------------------------------- 1 | hasMany('App\Product', 'catalog_id', 'id'); 23 | } 24 | 25 | /** 26 | * @param int $id 27 | * @return array 28 | */ 29 | public function getCatalogIdsTree(int $id): array 30 | { 31 | $child_ids = [$id]; 32 | $catalog_ids = []; 33 | do { 34 | $catalog_ids = array_merge($catalog_ids, $child_ids); 35 | $child_ids = $this::whereIn('parent_id', $child_ids)->pluck('id')->toArray(); 36 | } 37 | while ($child_ids); 38 | 39 | return $catalog_ids; 40 | } 41 | 42 | /** 43 | * @return Collection 44 | */ 45 | public function parentsNode(): Collection 46 | { 47 | return $this->where('parent_id', NULL)->get(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | 31 | /** 32 | * Register the commands for the application. 33 | * 34 | * @return void 35 | */ 36 | protected function commands() 37 | { 38 | $this->load(__DIR__.'/Commands'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/DTO/CategoriesDTO.php: -------------------------------------------------------------------------------- 1 | catalogs = $catalogs; 15 | $this->parentCatalogs = $parentCatalogs; 16 | } 17 | 18 | public function getCatalogs(): BaseCollection 19 | { 20 | return $this->catalogs; 21 | } 22 | 23 | public function setCatalogs(BaseCollection $catalogs): self 24 | { 25 | $this->catalogs = $catalogs; 26 | 27 | return $this; 28 | } 29 | 30 | public function getParentCatalogs(): BaseCollection 31 | { 32 | return $this->parentCatalogs; 33 | } 34 | 35 | public function setParentCatalogs(BaseCollection $parentCatalogs): self 36 | { 37 | $this->parentCatalogs = $parentCatalogs; 38 | 39 | return $this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/DTO/FilterNumberDTO.php: -------------------------------------------------------------------------------- 1 | minValue; 16 | } 17 | 18 | public function getMaxValue(): float 19 | { 20 | return $this->maxValue; 21 | } 22 | 23 | public function getId(): int 24 | { 25 | return $this->id; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/DTO/FilterSelectorDTO.php: -------------------------------------------------------------------------------- 1 | values; 15 | } 16 | 17 | public function getId(): int 18 | { 19 | return $this->id; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Dispatch.php: -------------------------------------------------------------------------------- 1 | belongsTo(ShippingMethod::class, 'shipping_method_id', 'id'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Domain/Reports/DailySalesReport.php: -------------------------------------------------------------------------------- 1 | subDay(); 23 | } 24 | 25 | $orders = $this->orderRepository->getDailyOrders($day); 26 | 27 | $this->erpService->sendDailySalesReport($orders); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Enums/AdminPaymentMethodStatuses.php: -------------------------------------------------------------------------------- 1 | 'Disabled', 14 | 1 => 'Enabled', 15 | 2 => 'Missing from the config', 16 | 3 => 'Missing from the DB' 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /app/Events/Event.php: -------------------------------------------------------------------------------- 1 | order = $order; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Events/PaymentCreated.php: -------------------------------------------------------------------------------- 1 | payment = $payment; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Exceptions/FondyPaymentException.php: -------------------------------------------------------------------------------- 1 | middleware('auth:admin'); 12 | } 13 | 14 | /** 15 | * @return View 16 | */ 17 | public function index(): View 18 | { 19 | return view('admin.dashboard'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | propertyRepository->getFilteredProducts()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Http/Controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | json(['status' => 'confirmed']); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Http/Controllers/TestController.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/ForceLogout.php: -------------------------------------------------------------------------------- 1 | force_logout)) { 25 | // Not for the next time! 26 | // Maybe a `unmarkForLogout()` method is appropriate here. 27 | $user->force_logout = false; 28 | $user->save(); 29 | 30 | // Log her out 31 | Auth::guard('web')->logout(); 32 | 33 | return redirect()->route('login'); 34 | } 35 | 36 | return $next($request); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 21 | if ($guard === 'admin') { 22 | return redirect('admin'); 23 | } 24 | return redirect('shop'); 25 | } 26 | return $next($request); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'password', 16 | 'password_confirmation', 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Requests/CartAddRelatedRequest.php: -------------------------------------------------------------------------------- 1 | 'required|integer|exists:related_products,id', 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Requests/CartAddRequest.php: -------------------------------------------------------------------------------- 1 | 'required|integer|min:1|max:99999', 30 | 'productQty' => 'required|integer|min:1|max:99', 31 | ]; 32 | } 33 | 34 | /** 35 | * @return string[] 36 | */ 37 | public function messages(): array 38 | { 39 | return [ 40 | 'productQty.required' => 'The Quantity field can not be blank.', 41 | 'productQty.integer' => 'Quantity must be integer.', 42 | 'productQty.min' => 'Minimum of Quantity is 1 psc.', 43 | 'productQty.max' => 'Maximum of Quantity is 99 psc.' 44 | ]; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/Http/Requests/CartChangePaymentRequest.php: -------------------------------------------------------------------------------- 1 | 'required|integer|exists:payment_methods,id,enabled,1', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/CartChangeShippingRequest.php: -------------------------------------------------------------------------------- 1 | 'required|numeric|min:0', 28 | 'shippingMethodId' => 'required|integer|exists:shipping_methods,id,enable,1', 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Http/Requests/CartRemoveItemRequest.php: -------------------------------------------------------------------------------- 1 | 'required|integer|exists:products,id', 30 | 'subtotal' => 'required|numeric|min:0', 31 | 'isRelated' => 'required|boolean', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Requests/OrderActionRequest.php: -------------------------------------------------------------------------------- 1 | 'required|exists:orders,id,user_id,' . $this->user()->id, 30 | 'action' => ['required', Rule::in(OrderActions::getActions())], 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Resources/CartPostResource.php: -------------------------------------------------------------------------------- 1 | resource; 23 | return [ 24 | 'items' => $cardPostDto->getCountItems(), 25 | 'total' => $cardPostDto->getTotal(), 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Resources/CategoriesResource.php: -------------------------------------------------------------------------------- 1 | resource; 14 | return [ 15 | 'catalogs' => $categoriesDto->getCatalogs(), 16 | 'parentCatalogs' => $categoriesDto->getParentCatalogs(), 17 | ]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Http/Resources/Dispatch.php: -------------------------------------------------------------------------------- 1 | $this->id, 23 | 'label' => ShippingMethod::getLabel($this->whenLoaded('method')?->class_name), 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/OrderCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Resources/OrderData.php: -------------------------------------------------------------------------------- 1 | $this->id, 28 | 'label' => $this->order_label, 29 | 'total' => $this->total, 30 | 'createdAt' => $this->created_at->toDateTimeString(), 31 | 'status' => $this->status, 32 | 'orderData' => OrderData::collection($this->whenLoaded('orderData')), 33 | 'payments' => Payment::collection($this->whenLoaded('payments')), 34 | 'dispatches' => Dispatch::collection($this->whenLoaded('dispatches')), 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Http/Resources/OrderResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 28 | 'label' => $this->order_label, 29 | 'total' => $this->total, 30 | 'created_at' => $this->created_at->toDateTimeString(), 31 | 'status' => $this->status, 32 | 'uri' => route('order', ['id' => $this->id]) 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Resources/Payment.php: -------------------------------------------------------------------------------- 1 | $this->collection, 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Resources/ProductResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 32 | 'catalog_id' => $this->catalog_id, 33 | 'image' => $this->image, 34 | 'name' => $this->name, 35 | 'description' => $this->description, 36 | 'price' => $this->price, 37 | 'created_at' => $this->created_at->toDateTimeString(), 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Http/Resources/PropertiesResource.php: -------------------------------------------------------------------------------- 1 | $this->collection]; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Client.php: -------------------------------------------------------------------------------- 1 | id = $id; 17 | $this->password = $password; 18 | $this->url = sprintf('https://%s/api',$domain); 19 | } 20 | /** 21 | * @return int 22 | */ 23 | public function getId(){ 24 | return $this->id; 25 | } 26 | /** 27 | * @return String 28 | */ 29 | public function getPassword(){ 30 | return $this->password; 31 | } 32 | /** 33 | * @return String 34 | */ 35 | public function getUrl(){ 36 | return $this->url; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Error.php: -------------------------------------------------------------------------------- 1 | array( 14 | 'type' => 'string', 15 | 'required'=>TRUE 16 | ), 17 | 'order_id'=>array( 18 | 'type' => 'string', 19 | 'required'=>TRUE 20 | ), 21 | 'currency' => array( 22 | 'type' => 'string', 23 | 'required'=>TRUE 24 | ), 25 | 'amount' => array( 26 | 'type' => 'integer', 27 | 'required'=>TRUE 28 | ), 29 | 'signature' => array( 30 | 'type' => 'string', 31 | 'required'=>TRUE 32 | ) 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Checkout.php: -------------------------------------------------------------------------------- 1 | array( 14 | 'type' => 'string', 15 | 'required'=>TRUE 16 | ), 17 | 'order_id'=>array( 18 | 'type' => 'string', 19 | 'required'=>TRUE 20 | ), 21 | 'order_desc'=>array( 22 | 'type' => 'string', 23 | 'required'=>TRUE 24 | ), 25 | 'currency' => array( 26 | 'type' => 'string', 27 | 'required'=>TRUE 28 | ), 29 | 'amount' => array( 30 | 'type' => 'integer', 31 | 'required'=>TRUE 32 | ), 33 | 'signature' => array( 34 | 'type' => 'string', 35 | 'required'=>TRUE 36 | ) 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/P2pcredit.php: -------------------------------------------------------------------------------- 1 | array( 17 | 'type' => 'string', 18 | 'required'=>TRUE 19 | ), 20 | 'order_id'=>array( 21 | 'type' => 'string', 22 | 'required'=>TRUE 23 | ), 24 | 'order_desc'=>array( 25 | 'type' => 'string', 26 | 'required'=>TRUE 27 | ), 28 | 'currency' => array( 29 | 'type' => 'string', 30 | 'required'=>TRUE 31 | ), 32 | 'amount' => array( 33 | 'type' => 'integer', 34 | 'required'=>TRUE 35 | ), 36 | 'receiver_card_number'=>array( 37 | 'type' => 'string', 38 | 'required'=>FALSE 39 | ), 40 | 'receiver_rectoken'=>array( 41 | 'type' => 'string', 42 | 'required'=>FALSE 43 | ), 44 | 'signature' => array( 45 | 'type' => 'string', 46 | 'required'=>TRUE 47 | ), 48 | 'version' => array( 49 | 'type' => 'string', 50 | 'required'=>FALSE 51 | ) 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/PcidssConfirm.php: -------------------------------------------------------------------------------- 1 | array( 14 | 'type' => 'string', 15 | 'required' => TRUE 16 | ), 17 | 'merchant_id' => array( 18 | 'type' => 'string', 19 | 'required' => TRUE 20 | ), 21 | 'pares' => array( 22 | 'type' => 'string', 23 | 'required' => TRUE 24 | ), 25 | 'md' => array( 26 | 'type' => 'string', 27 | 'required' => TRUE 28 | ), 29 | 'version' => array( 30 | 'type' => 'cvv', 31 | 'required' => FALSE 32 | ), 33 | 'signature' => array( 34 | 'type' => 'string', 35 | 'required' => TRUE 36 | ) 37 | ); 38 | } -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Recurring.php: -------------------------------------------------------------------------------- 1 | array( 17 | 'type' => 'string', 18 | 'required'=>TRUE 19 | ), 20 | 'order_id'=>array( 21 | 'type' => 'string', 22 | 'required'=>TRUE 23 | ), 24 | 'currency' => array( 25 | 'type' => 'string', 26 | 'required'=>TRUE 27 | ), 28 | 'amount' => array( 29 | 'type' => 'integer', 30 | 'required'=>TRUE 31 | ), 32 | 'signature' => array( 33 | 'type' => 'string', 34 | 'required'=>TRUE 35 | ), 36 | 'rectoken' => array( 37 | 'type' => 'string', 38 | 'required'=>TRUE 39 | ), 40 | 'version' => array( 41 | 'type' => 'string', 42 | 'required'=>FALSE 43 | ) 44 | ); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Reports.php: -------------------------------------------------------------------------------- 1 | array( 14 | 'type' => 'string', 15 | 'required'=> TRUE 16 | ), 17 | 'date_from'=>array( 18 | 'type' => 'string', 19 | 'format' => '', 20 | 'required' => TRUE 21 | ), 22 | 'date_to' => array( 23 | 'type' => 'string', 24 | 'format' => '' , 25 | 'required'=> TRUE 26 | ), 27 | 'signature' => array( 28 | 'type' => 'string', 29 | 'required'=>TRUE 30 | ), 31 | 'version' => array( 32 | 'type' => 'string', 33 | 'required'=>FALSE 34 | ) 35 | ); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Result.php: -------------------------------------------------------------------------------- 1 | parseResponseData(); 15 | } else{ 16 | $this->setResponse($data); 17 | } 18 | return $this; 19 | } 20 | private function parseResponseData(){ 21 | $body = file_get_contents('php://input'); 22 | $types = $this->request->getContentTypes(); 23 | $types = array_flip($types); 24 | $type = explode(';',$_SERVER['CONTENT_TYPE']); 25 | $type = trim($type[0]); 26 | if(isset($types[$type])){ 27 | $this->format = $types[$type]; 28 | $data = $this->parseRespose($body); 29 | $this->setResponse($data); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Reverse.php: -------------------------------------------------------------------------------- 1 | array( 16 | 'type' => 'string', 17 | 'required'=>TRUE 18 | ), 19 | 'order_id'=>array( 20 | 'type' => 'string', 21 | 'required'=>TRUE 22 | ), 23 | 'currency' => array( 24 | 'type' => 'string', 25 | 'required'=>TRUE 26 | ), 27 | 'amount' => array( 28 | 'type' => 'integer', 29 | 'required'=>TRUE 30 | ), 31 | 'signature' => array( 32 | 'type' => 'string', 33 | 'required'=>TRUE 34 | ), 35 | 'version' => array( 36 | 'type' => 'string', 37 | 'required'=>FALSE 38 | ) 39 | ); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Status.php: -------------------------------------------------------------------------------- 1 | array( 14 | 'type' => 'string', 15 | 'required'=>TRUE 16 | ), 17 | 'merchant_id'=>array( 18 | 'type' => 'string', 19 | 'required'=>TRUE 20 | ), 21 | 'signature' => array( 22 | 'type' => 'string', 23 | 'required'=>TRUE 24 | ), 25 | 'version' => array( 26 | 'type' => 'string', 27 | 'required'=>FALSE 28 | ) 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/TransactionList.php: -------------------------------------------------------------------------------- 1 | array( 15 | 'type' => 'string', 16 | 'required' => TRUE 17 | ), 18 | 'merchant_id' => array( 19 | 'type' => 'int', 20 | 'required' => TRUE 21 | ), 22 | 'signature' => array( 23 | 'type' => 'string', 24 | 'required' => TRUE 25 | ) 26 | ); 27 | } -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/Resource/Verification.php: -------------------------------------------------------------------------------- 1 | 'y', 14 | 'verification_type'=>'code' 15 | ); 16 | protected $fields = array( 17 | 'merchant_id'=>array( 18 | 'type' => 'string', 19 | 'required'=>TRUE 20 | ), 21 | 'order_id'=>array( 22 | 'type' => 'string', 23 | 'required'=>TRUE 24 | ), 25 | 'currency' => array( 26 | 'type' => 'string', 27 | 'required'=>TRUE 28 | ), 29 | 'amount' => array( 30 | 'type' => 'integer', 31 | 'required'=>TRUE 32 | ), 33 | 'verification'=>array( 34 | 'type' => 'string', 35 | 'equal'=> 'y' 36 | ), 37 | 'verification_type'=>array( 38 | 'type' => 'string', 39 | 'equal'=> 'y', 40 | 'required'=>TRUE 41 | ), 42 | 'signature' => array( 43 | 'type' => 'string', 44 | 'required'=>TRUE 45 | ), 46 | 'version' => array( 47 | 'type' => 'string', 48 | 'required'=>FALSE 49 | ) 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /app/Library/Services/Ipsp/XmlData.php: -------------------------------------------------------------------------------- 1 | $val) { 13 | if(is_numeric($key)) continue; 14 | if( is_array($val) ) { 15 | $this->addChild($key); 16 | $this->arrayToXml($val); 17 | } else { 18 | $this->addChild($key,$val); 19 | } 20 | } 21 | } 22 | 23 | /** 24 | * @return array 25 | */ 26 | public function xmlToArray(): array 27 | { 28 | $result = []; 29 | $children = $this->children(); 30 | foreach($children as $item){ 31 | if($item->count()>0) 32 | $result[$item->getName()] = $item->xmlToArray(); 33 | else 34 | $result[$item->getName()] = (string)$item; 35 | } 36 | 37 | return $result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Library/Services/IpspPaymentService.php: -------------------------------------------------------------------------------- 1 | api = $api; 14 | } 15 | 16 | public function checkStatus(array $requestData) 17 | { 18 | $requestData['currency'] = constant(get_class($this->api) . '::' . $requestData['currency']); 19 | return $this->api->call('status', $requestData)->getResponse(); 20 | } 21 | 22 | public function pay(array $requestData) 23 | { 24 | $requestData['currency'] = constant(get_class($this->api) . '::' . $requestData['currency']); 25 | return $this->api->call('checkout', $requestData)->getResponse(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Library/Services/PaymentResponseInterface.php: -------------------------------------------------------------------------------- 1 | 'handleOrderCreated', 23 | ]; 24 | } 25 | 26 | public function handleOrderCreated(OrderCreated $event): void 27 | { 28 | $this->workflowService->sendOrderToWarehouse($event->order->id); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Listeners/PaymentStatusSubscriber.php: -------------------------------------------------------------------------------- 1 | 'handlePaymentCreated', 22 | ]; 23 | } 24 | 25 | public function handlePaymentCreated(PaymentCreated $event): void 26 | { 27 | $this->paymentRepository->updateById( 28 | $event->payment->getPaymentId(), 29 | [ 30 | 'external_id' => $event->payment->getExternalId(), 31 | 'status' => Payment::STATUS_CREATED, 32 | ], 33 | ); 34 | $this->checkPayment($event->payment->getPaymentId()); 35 | } 36 | 37 | private function checkPayment(int $getPaymentId): void 38 | { 39 | $this->workflowService->checkPayment($getPaymentId); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/OrderData.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Product', 'product_id','id'); 34 | } 35 | 36 | /** 37 | * @param Builder $query 38 | * @param int $orderId 39 | * @return Builder 40 | */ 41 | public function scopeByOrderId(Builder $query, int $orderId): Builder 42 | { 43 | return $query->where('order_id', $orderId); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Payment.php: -------------------------------------------------------------------------------- 1 | belongsTo(PaymentMethod::class, 'payment_method_id', 'id'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/PaymentMethod.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | protected $fillable = ['class_name', 'priority', 'config_key', 'enabled', 'label']; 35 | } 36 | -------------------------------------------------------------------------------- /app/Property.php: -------------------------------------------------------------------------------- 1 | $selectProperties 20 | */ 21 | class Property extends Model 22 | { 23 | use HasFactory; 24 | 25 | public const TYPE_SELECTOR = 'selector'; 26 | public const TYPE_NUMBER = 'number'; 27 | 28 | protected $fillable = array('name', 'prop_group_id', 'priority', 'type'); 29 | 30 | /** 31 | * @return string[] 32 | */ 33 | public static function getTypes(): array 34 | { 35 | return [ 36 | self::TYPE_NUMBER, 37 | self::TYPE_SELECTOR, 38 | ]; 39 | } 40 | 41 | /** 42 | * @return HasMany 43 | */ 44 | public function propertyValues(): HasMany 45 | { 46 | return $this->hasMany('App\PropertyValue', 'property_id', 'id'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/PropertyValue.php: -------------------------------------------------------------------------------- 1 | belongsToMany('App\Product', 'product_property', 'property_value_id','product_id' )->withTimestamps(); 32 | } 33 | 34 | /** 35 | * @return BelongsTo 36 | */ 37 | public function properties(): BelongsTo 38 | { 39 | return $this->belongsTo('App\Property', 'property_id','id'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->get('request')->server->set('HTTPS', 'on'); 26 | URL::forceScheme('https'); 27 | } catch (\Throwable $e) { 28 | } 29 | 30 | } 31 | } 32 | 33 | /** 34 | * Register any application services. 35 | * 36 | * @return void 37 | */ 38 | public function register () 39 | { 40 | $this->app->singleton( 41 | WorkflowClientInterface::class, 42 | fn () => WorkflowClient::create( 43 | ServiceClient::create('temporal:7233') 44 | ) 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $policies = []; 15 | 16 | /** 17 | * Register any authentication / authorization services. 18 | * 19 | * @return void 20 | */ 21 | public function boot() 22 | { 23 | $this->registerPolicies(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | > 15 | */ 16 | protected $listen = [ 17 | 'App\Events\Event' => [ 18 | 'App\Listeners\EventListener', 19 | ], 20 | 'Illuminate\Auth\Events\Login' => [ 21 | 'App\Listeners\LogSuccessfulLogin', 22 | ], 23 | ]; 24 | 25 | /** 26 | * @var string[] 27 | */ 28 | protected $subscribe = [ 29 | PaymentStatusSubscriber::class, 30 | OrderSubscriber::class, 31 | ]; 32 | 33 | /** 34 | * Register any events for your application. 35 | * 36 | * @return void 37 | */ 38 | public function boot() 39 | { 40 | parent::boot(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Providers/PaymentServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind(PaymentServiceInterface::class, fn () => new IpspPaymentService(new IspsApi())); 34 | $this->app->singleton(PaymentActivityInterface::class, PaymentActivity::class); 35 | $this->app->singleton(PaymentWorkflowInterface::class, PaymentWorkflow::class); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/RelatedProduct.php: -------------------------------------------------------------------------------- 1 | belongsToMany( 26 | 'App\Product', 27 | 'products_related_products', 28 | 'product_id', 29 | 'related_product_id' 30 | )->withTimestamps(); 31 | } 32 | 33 | /** 34 | * @param array $productsInCart 35 | * @return Product|null 36 | */ 37 | public function getRelatedProduct(array $productsInCart): ?Product 38 | { 39 | return Product::whereHas('relatedProducts', function ($query) use ($productsInCart) { 40 | $query->whereIn('product_id', $productsInCart); 41 | }) 42 | ->whereNotIn('products.id', $productsInCart) 43 | ->join('related_products', 'products.id', '=', 'related_products.id') 44 | ->orderBy('points', 'desc') 45 | ->first(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/Repositories/PaymentRepository.php: -------------------------------------------------------------------------------- 1 | mPayment->findOrFail($id); 18 | $payment->update($fieldsValues); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Repositories/PropertyRepository.php: -------------------------------------------------------------------------------- 1 | mProperty->newQuery() 17 | ->with('propertyValues') 18 | ->orderBy('priority') 19 | ->get(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Services/Cart/CartPostActions.php: -------------------------------------------------------------------------------- 1 | countItems = $countItems; 15 | $this->total = $total; 16 | } 17 | 18 | /** 19 | * @return int 20 | */ 21 | public function getCountItems(): int 22 | { 23 | return $this->countItems; 24 | } 25 | 26 | /** 27 | * @return float 28 | */ 29 | public function getTotal(): float 30 | { 31 | return $this->total; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Services/Erp/DTO/ErpOrderDTO.php: -------------------------------------------------------------------------------- 1 | orderId = $orderId; 14 | $this->payload = $payload; 15 | } 16 | 17 | public function getOrderId(): int 18 | { 19 | return $this->orderId; 20 | } 21 | 22 | public function setOrderId(int $orderId): self 23 | { 24 | $this->orderId = $orderId; 25 | 26 | return $this; 27 | } 28 | 29 | public function getPayload(): string 30 | { 31 | return $this->payload; 32 | } 33 | 34 | public function setPayload(string $payload): self 35 | { 36 | $this->payload = $payload; 37 | 38 | return $this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Services/Erp/ErpServiceInterface.php: -------------------------------------------------------------------------------- 1 | ipspPaymentService->pay($paymentRequestData); 25 | 26 | $data = $response->getData(); 27 | 28 | if (($data['response_status'] ?? '') === self::STATUS_SUCCESS) { 29 | return new PaymentResponse($data, $data['payment_id'], $data['checkout_url']); 30 | } 31 | 32 | throw new FondyPaymentException($data['error_message'] ?? "Sorry, Fondy doesn't work."); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Services/Payment/PayPalHttpClient.php: -------------------------------------------------------------------------------- 1 | refreshToken = $refreshToken; 23 | $this->authInjector = new AuthorizationInjector($this, $environment, $this->refreshToken); 24 | $this->addInjector($this->authInjector); 25 | $this->addInjector(new GzipInjector()); 26 | } 27 | 28 | public function userAgent() 29 | { 30 | return UserAgent::getValue(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Services/Payment/PaymentMethodInterface.php: -------------------------------------------------------------------------------- 1 | data; 18 | } 19 | 20 | public function getCheckoutUrl(): ?string 21 | { 22 | return $this->checkoutUrl; 23 | } 24 | 25 | public function getExternalId(): ?string 26 | { 27 | return $this->externalId; 28 | } 29 | 30 | public function getPaymentId(): ?int 31 | { 32 | return $this->paymentId; 33 | } 34 | 35 | public function setPaymentId(int $paymentId): self 36 | { 37 | $this->paymentId = $paymentId; 38 | 39 | return $this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Services/Recommended/Recommended.php: -------------------------------------------------------------------------------- 1 | relatedProduct->where('id', $relatedProductId)->increment('points', $value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Services/Shipping/FixRateShippingMethod.php: -------------------------------------------------------------------------------- 1 | orderId = $orderId; 14 | $this->payload = $payload; 15 | } 16 | 17 | public function getOrderId(): int 18 | { 19 | return $this->orderId; 20 | } 21 | 22 | public function setOrderId(int $orderId): self 23 | { 24 | $this->orderId = $orderId; 25 | 26 | return $this; 27 | } 28 | 29 | public function getPayload(): string 30 | { 31 | return $this->payload; 32 | } 33 | 34 | public function setPayload(string $payload): self 35 | { 36 | $this->payload = $payload; 37 | 38 | return $this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Services/Warehouse/ValueObject/WarehouseOrderStatus.php: -------------------------------------------------------------------------------- 1 | workflowClient->newWorkflowStub( 19 | PaymentWorkflowInterface::class, 20 | WorkflowOptions::new() 21 | ->withWorkflowTaskTimeout(60) 22 | ); 23 | 24 | $this->workflowClient->start($workflow, $paymentId); 25 | } 26 | 27 | public function sendOrderToWarehouse(int $orderId): void 28 | { 29 | $workflow = $this->workflowClient->newWorkflowStub( 30 | OrderCompletedWorkflowInterface::class, 31 | WorkflowOptions::new() 32 | ->withWorkflowTaskTimeout(60) 33 | ); 34 | 35 | $this->workflowClient->start($workflow, $orderId); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Temporal/Cron/SalesReportActivity.php: -------------------------------------------------------------------------------- 1 | report->createReport(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Temporal/Cron/SalesReportActivityInterface.php: -------------------------------------------------------------------------------- 1 | salesReportActivity = Workflow::newActivityStub( 19 | SalesReportActivityInterface::class, 20 | ActivityOptions::new() 21 | ->withScheduleToCloseTimeout(CarbonInterval::seconds(30)) 22 | ); 23 | } 24 | 25 | public function create(): \Generator 26 | { 27 | return yield $this->salesReportActivity->composeCreating(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Temporal/Cron/SalesReportWorkflowInterface.php: -------------------------------------------------------------------------------- 1 | []])); 19 | 20 | return $this->erpService->placeNewOrder($orderDto); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Temporal/ErpActivityInterface.php: -------------------------------------------------------------------------------- 1 | withStartToCloseTimeout(10) 17 | ); 18 | 19 | $erpActivity = Workflow::newActivityStub( 20 | ErpActivityInterface::class, 21 | ActivityOptions::new()->withStartToCloseTimeout(10) 22 | ); 23 | 24 | $promises = []; 25 | $promises[] = yield $warehouseActivity->sendOrder($orderId); 26 | $promises[] = yield $erpActivity->sendOrder($orderId); 27 | 28 | return Promise::all($promises); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Temporal/OrderCompletedWorkflowInterface.php: -------------------------------------------------------------------------------- 1 | ok()) { 21 | $this->paymentRepository->updateById($paymentId, ['status' => Payment::STATUS_CONFIRMED]); 22 | 23 | return true; 24 | } 25 | 26 | return false; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Temporal/PaymentActivityInterface.php: -------------------------------------------------------------------------------- 1 | withStartToCloseTimeout(10) 16 | ); 17 | 18 | return yield $activity->checkStatus($id); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Temporal/PaymentWorkflowInterface.php: -------------------------------------------------------------------------------- 1 | []])); 19 | $this->warehouseService->createNewOrder($orderDto); 20 | 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Temporal/WarehouseActivityInterface.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | protected $fillable = [ 26 | 'name', 'email', 'password', 'cart', 27 | ]; 28 | 29 | /** 30 | * The attributes that should be hidden for arrays. 31 | * 32 | * @var array 33 | */ 34 | protected $hidden = [ 35 | 'password', 'remember_token', 36 | ]; 37 | 38 | /** 39 | * @return HasMany 40 | */ 41 | public function orders(): HasMany 42 | { 43 | return $this->hasMany(Order::class, 'user_id', 'id'); 44 | } 45 | 46 | /** 47 | * @param int $userId 48 | * @return int 49 | */ 50 | public function markForLogoutById(int $userId): int 51 | { 52 | return $this->where('id', $userId) 53 | ->update(['cart' => '', 'force_logout' => true]); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /composer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/composer.phar -------------------------------------------------------------------------------- /config/payments.php: -------------------------------------------------------------------------------- 1 | 'paypal', 5 | 'methods' => [ 6 | 'paypal' => [ 7 | 'label' => 'PayPal', 8 | 'class_name' => 'App\\Services\\Payment\\PaypalPayment', 9 | 'client_id' => env('PAYPAL_CLIENT_ID', '0000'), 10 | 'secret' => env('PAYPAL_CLIENT_SECRET', 'secret'), 11 | 'settings' => [ 12 | 'mode' => 'sandbox', // live, sandbox 13 | 'http.ConnectionTimeOut' => 1000, 14 | 'log.LogEnabled' => true, 15 | 'log.FileName' => storage_path() . '/logs/paypal.log', 16 | 'log.LogLevel' => 'FINE', 17 | ], 18 | ], 19 | 'fondy' => [ 20 | 'label' => 'Fondy', 21 | 'class_name' => 'App\\Services\\Payment\\FondyPayment', 22 | ], 23 | ], 24 | ]; 25 | -------------------------------------------------------------------------------- /config/sentry.php: -------------------------------------------------------------------------------- 1 | env('SENTRY_LARAVEL_DSN', env('SENTRY_DSN')), 6 | 7 | // capture release as git sha 8 | // 'release' => trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')), 9 | 10 | // When left empty or `null` the Laravel environment will be used 11 | 'environment' => env('SENTRY_ENVIRONMENT'), 12 | 13 | 'breadcrumbs' => [ 14 | // Capture Laravel logs in breadcrumbs 15 | 'logs' => true, 16 | 17 | // Capture SQL queries in breadcrumbs 18 | 'sql_queries' => true, 19 | 20 | // Capture bindings on SQL queries logged in breadcrumbs 21 | 'sql_bindings' => true, 22 | 23 | // Capture queue job information in breadcrumbs 24 | 'queue_info' => true, 25 | 26 | // Capture command information in breadcrumbs 27 | 'command_info' => true, 28 | ], 29 | 30 | // @see: https://docs.sentry.io/platforms/php/configuration/options/#send-default-pii 31 | 'send_default_pii' => false, 32 | 33 | 'traces_sample_rate' => (float)(env('SENTRY_TRACES_SAMPLE_RATE', 0.0)), 34 | 35 | 'controllers_base_namespace' => env('SENTRY_CONTROLLERS_BASE_NAMESPACE', 'App\\Http\\Controllers'), 36 | 37 | ]; 38 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | ], 21 | 22 | 'ses' => [ 23 | 'key' => env('SES_KEY'), 24 | 'secret' => env('SES_SECRET'), 25 | 'region' => 'us-east-1', 26 | ], 27 | 28 | 'sparkpost' => [ 29 | 'secret' => env('SPARKPOST_SECRET'), 30 | ], 31 | 32 | 'stripe' => [ 33 | 'model' => App\User::class, 34 | 'key' => env('STRIPE_KEY'), 35 | 'secret' => env('STRIPE_SECRET'), 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => realpath(storage_path('framework/views')), 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /database/factories/CatalogFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = Catalog::class; 19 | 20 | public function definition(): array 21 | { 22 | return [ 23 | 'name' => $this->faker->words(15, true), 24 | 'description' => $this->faker->sentence, 25 | 'parent_id' => null, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/factories/DispatchFactory.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | protected $model = Dispatch::class; 18 | 19 | /** 20 | * Define the model's default state. 21 | * 22 | * @return array 23 | */ 24 | public function definition(): array 25 | { 26 | return [ 27 | 'shipping_method_id' => $this->faker->unique()->numberBetween(1, 9), 28 | 'order_id' => $this->faker->numberBetween(1, 99999), 29 | 'code' => $this->faker->numberBetween(1, 99), 30 | 'details' => $this->faker->text(), 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/factories/OrderDataFactory.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | protected $model = OrderData::class; 20 | 21 | /** 22 | * Define the model's default state. 23 | * 24 | * @return array 25 | */ 26 | public function definition(): array 27 | { 28 | return [ 29 | 'order_id' => fn () => (int) (Order::factory()->create()?->id ?? 0), 30 | 'product_id' => fn () => (int) (Product::factory()->create()?->id ?? 0), 31 | 'is_related_product' => $this->faker->boolean(), 32 | 'price' => $this->faker->randomFloat(2, 0.05, 999999), 33 | 'qty' => $this->faker->numberBetween(1, 100), 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/factories/OrderFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = Order::class; 19 | 20 | /** 21 | * Define the model's default state. 22 | * 23 | * @return array 24 | */ 25 | public function definition(): array 26 | { 27 | return [ 28 | 'order_label' => 'prfx_' . $this->faker->unique()->ean8(), 29 | 'commentary' => $this->faker->text(), 30 | 'status' => $this->faker->randomElement(['pending payment', 'process', 'completed', 'deleted']), 31 | 'total' => $this->faker->randomFloat(2, 0.05, 999999), 32 | 'user_id' => fn () => (int) (User::factory()->create()?->id ?? 0), 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/factories/PaymentFactory.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | protected $model = Payment::class; 18 | 19 | /** 20 | * Define the model's default state. 21 | * 22 | * @return array 23 | */ 24 | public function definition(): array 25 | { 26 | return [ 27 | 'payment_method_id' => $this->faker->unique()->numberBetween(1, 9), 28 | 'order_id' => $this->faker->numberBetween(1, 99999), 29 | 'status' => $this->faker->randomElement([Payment::STATUS_CREATED, Payment::STATUS_INITIALIZED, Payment::STATUS_PAID]), 30 | 'external_id' => $this->faker->uuid(), 31 | 'details' => $this->faker->text(), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/ProductFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = Product::class; 19 | 20 | /** 21 | * Define the model's default state. 22 | * 23 | * @return array 24 | * @throws Exception 25 | */ 26 | public function definition() 27 | { 28 | return [ 29 | 'name' => $this->faker->name, 30 | 'catalog_id' => random_int(1, 10), 31 | 'description' => $this->faker->sentence, 32 | 'price' => $this->faker->randomFloat(2, 0.02, 999999.99), 33 | 'image' => 'product_img.jpg' 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/factories/PropertyFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = Property::class; 19 | 20 | /** 21 | * Define the model's default state. 22 | * 23 | * @return array 24 | * @throws Exception 25 | */ 26 | public function definition() 27 | { 28 | return [ 29 | 'name' => $this->faker->sentence, 30 | 'prop_group_id' => random_int(1, 100), 31 | 'priority' => $this->faker->numberBetween(1, 50), 32 | 'type' => $this->faker->randomElement(Property::getTypes()), 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/factories/PropertyValueFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = PropertyValue::class; 19 | 20 | /** 21 | * Define the model's default state. 22 | * 23 | * @return array 24 | * @throws Exception 25 | */ 26 | public function definition() 27 | { 28 | return [ 29 | 'property_id' => $this->faker->numberBetween(1, 100), 30 | 'value' => $this->faker->text(30), 31 | 'unit_id' => $this->faker->numberBetween(1, 20), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/RelatedProductFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = RelatedProduct::class; 19 | 20 | /** 21 | * Define the model's default state. 22 | * 23 | * @return array 24 | */ 25 | public function definition(): array 26 | { 27 | return [ 28 | 'points' => $this->faker->numberBetween(0, 1000), 29 | 'impressions' => $this->faker->numberBetween(0, 10000), 30 | 'choices' => $this->faker->numberBetween(0, 10000), 31 | 'deleting' => $this->faker->numberBetween(0, 10000), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/ShippingMethodFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $model = ShippingMethod::class; 19 | 20 | /** 21 | * Define the model's default state. 22 | * 23 | * @return array 24 | * @throws Exception 25 | */ 26 | public function definition() 27 | { 28 | return [ 29 | 'class_name' => $this->faker->word, 30 | 'priority' => $this->faker->numberBetween(1, 50), 31 | 'enable' => $this->faker->boolean(), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | protected $model = User::class; 18 | 19 | /** 20 | * Define the model's default state. 21 | * 22 | * @return array 23 | */ 24 | public function definition() 25 | { 26 | static $password; 27 | 28 | return [ 29 | 'name' => $this->faker->name, 30 | 'email' => $this->faker->unique()->safeEmail, 31 | 'password' => $password ?: $password = bcrypt('secret'), 32 | 'remember_token' => str_random(10), 33 | 'cart' => null, 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->string('password'); 21 | $table->rememberToken(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('users'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_10_08_113015_create_products_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('description'); 20 | $table->float('price', 2); 21 | $table->string('image'); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('products'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_10_08_114109_create_orders_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('commentary'); 19 | $table->float('total', 2); 20 | $table->enum('status', ['process', 'completed', 'deleted']); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('orders'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_10_08_114503_create_related_products_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('product_id'); 19 | $table->integer('related_product_id'); 20 | $table->integer('points'); 21 | $table->integer('impressions'); 22 | $table->integer('choices'); 23 | $table->integer('deleting'); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('related_products'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2017_10_08_115559_create_order_data_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('order_id'); 19 | $table->integer('product_id'); 20 | $table->integer('is_related_product'); 21 | $table->float('price', 2); 22 | $table->integer('qty'); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('order_data'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_10_24_071139_add_cart_to_users.php: -------------------------------------------------------------------------------- 1 | string('cart')->nullable(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('users', function(Blueprint $table) { 29 | $table->dropColumn('cart'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_11_05_070115_create_catalogs_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->unique(); 19 | $table->string('description')->nullable(); 20 | $table->integer('parent_id')->nullable(); 21 | $table->string('image')->nullable(); 22 | $table->integer('priority')->nullable(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('catalogs'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_11_05_071437_add_catalog_to_product.php: -------------------------------------------------------------------------------- 1 | integer('catalog_id')->default(0); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('products', function (Blueprint $table) { 29 | $table->dropColumn('catalog_id'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_11_08_134904_create_units_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->char('name', 15)->unique(); 19 | $table->char('code', 5)->nullable(); 20 | $table->string('full_name')->nullable(); 21 | $table->integer('decimal_place')->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('units'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_11_08_175930_create_properties_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('property_name_id')->default(0); 19 | $table->string('name', 100); 20 | $table->string('value'); 21 | $table->integer('prop_group_id')->nullable(); 22 | $table->integer('unit_id')->nullable(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('properties'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_11_09_073633_create_product_property_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('property_id'); 19 | $table->integer('product_id'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('product_property'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2017_11_12_152737_add_priority_to_properties_table.php: -------------------------------------------------------------------------------- 1 | string('priority')->nullable(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('properties', function (Blueprint $table) { 29 | $table->dropColumn('priority'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_11_12_174417_add_type_to_properties_table.php: -------------------------------------------------------------------------------- 1 | enum('type', ['number', 'selector'])->default('number'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('properties', function (Blueprint $table) { 29 | $table->dropColumn('type'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_11_13_071534_create_property_values_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('property_id')->default(0); 19 | $table->string('value'); 20 | $table->integer('unit_id')->nullable(); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('property_values'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_11_13_072524_alter_first_properties_table.php: -------------------------------------------------------------------------------- 1 | dropColumn('value', 'property_name_id', 'unit_id'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('properties', function (Blueprint $table) { 29 | $table->integer('property_name_id')->default(0); 30 | $table->string('value')->default(''); 31 | $table->integer('unit_id')->nullable(); 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_11_15_211208_change_propidcol_product_properties_table.php: -------------------------------------------------------------------------------- 1 | renameColumn('property_id', 'property_value_id'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('product_property', function (Blueprint $table) { 29 | $table->renameColumn('property_value_id', 'property_id'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_12_02_202911_create_admins_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('job_title'); 20 | $table->string('email')->unique(); 21 | $table->string('password'); 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('admins'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_12_21_200452_add_force_logout_users_table.php: -------------------------------------------------------------------------------- 1 | boolean('force_logout')->default(false); 18 | }); 19 | } 20 | 21 | /**b 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down(): void 27 | { 28 | Schema::table('users', function(Blueprint $table) { 29 | $table->dropColumn('force_logout'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_12_22_074807_add_user_id_orders_table.php: -------------------------------------------------------------------------------- 1 | integer('user_id')->default(1); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('orders', function(Blueprint $table) { 29 | $table->dropColumn('user_id'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_12_22_112834_create_shipping_methods_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('class_name'); 19 | $table->integer('priority'); 20 | $table->boolean('enable')->default(true); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('shipping_methods'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2018_01_02_074253_create_products_related_products_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('related_product_id'); 19 | $table->integer('product_id'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('products_related_products'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2018_01_02_075043_remove_columns_from_related_products_table.php: -------------------------------------------------------------------------------- 1 | dropColumn('product_id', 'related_product_id'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('related_products', function (Blueprint $table) { 29 | $table->integer('product_id')->default(0); 30 | $table->integer('related_product_id')->default(0); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2018_01_05_100641_alter_status_orders_table.php: -------------------------------------------------------------------------------- 1 | dropColumn('status'); 18 | }); 19 | Schema::table('orders', function (Blueprint $table) { 20 | $table->enum('status', ['pending payment', 'process', 'completed', 'deleted'])->default('pending payment'); 21 | $table->string('order_label')->default(''); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::table('orders', function (Blueprint $table) { 33 | $table->dropColumn('status'); 34 | }); 35 | Schema::table('orders', function (Blueprint $table) { 36 | $table->enum('status', ['process', 'completed', 'deleted'])->default('process'); 37 | $table->dropColumn('order_label'); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2019_02_04_175305_alter_users_table_change_type_column_cart.php: -------------------------------------------------------------------------------- 1 | text('cart')->change(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('users', function(Blueprint $table) { 29 | $table->string('cart')->change(); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2022_04_10_130734_create_payment_methods_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('label', 150); 19 | $table->string('config_key', 50)->unique(); 20 | $table->string('class_name'); 21 | $table->integer('priority'); 22 | $table->boolean('enabled')->default(true); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('payment_methods'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2022_04_22_124253_create_dispatches_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->unsignedInteger('shipping_method_id'); 19 | $table->unsignedBigInteger('order_id'); 20 | $table->longText('details')->nullable(); 21 | $table->string('code', 20)->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('dispatches'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2022_04_22_124353_create_payments_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 19 | $table->unsignedInteger('payment_method_id'); 20 | $table->unsignedBigInteger('order_id'); 21 | $table->unsignedInteger('status')->default(Payment::STATUS_INITIALIZED); 22 | $table->string('external_id', 100)->nullable(); 23 | $table->longText('details')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('payments'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2022_05_15_100734_add_payment_methods.php: -------------------------------------------------------------------------------- 1 | delete(); 17 | 18 | $paymentMethod = new PaymentMethod(); 19 | $paymentMethod->class_name = 'App\\Services\\Payment\\PaypalPayment'; 20 | $paymentMethod->label = 'PayPal'; 21 | $paymentMethod->config_key = 'paypal'; 22 | $paymentMethod->priority = 1; 23 | $paymentMethod->enabled = true; 24 | $paymentMethod->save(); 25 | 26 | $paymentMethod = new PaymentMethod(); 27 | $paymentMethod->class_name = 'App\\Services\\Payment\\FondyPayment'; 28 | $paymentMethod->label = 'Fondy'; 29 | $paymentMethod->config_key = 'fondy'; 30 | $paymentMethod->priority = 2; 31 | $paymentMethod->enabled = true; 32 | $paymentMethod->save(); 33 | } 34 | 35 | /**O 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down(): void 41 | { 42 | DB::table('payment_methods')->truncate(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /database/migrations/2024_07_28_125305_alter_users_table_change_type_column_cart_nullable.php: -------------------------------------------------------------------------------- 1 | text('cart')->nullable()->change(); 18 | }); 19 | } 20 | 21 | public function down(): void 22 | { 23 | Schema::table('users', function(Blueprint $table) { 24 | $table->text('cart')->change(); 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/seeders/AdminsTableSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 20 | DB::table('admins')->insert( 21 | [ 'name' => 'Admin', 22 | 'job_title' => 'Administrator', 23 | 'email' => 'admin@admin.dev', 24 | 'password' => Hash::make('password'), 25 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 26 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 27 | ] 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call( 17 | [ 18 | CatalogsTableSeeder::class, 19 | UnitsTableSeeder::class, 20 | ProductsTableSeeder::class, 21 | RelatedProductsTableSeeder::class, 22 | ProductsRelatedProductsTableSeeder::class, 23 | PropertiesTableSeeder::class, 24 | PropertyValuesTableSeeder::class, 25 | ProductPropertiesTableSeeder::class, 26 | AdminsTableSeeder::class, 27 | ShippingMethodsTableSeeder::class, 28 | ] 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/seeders/ProductPropertiesTableSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 20 | $faker = Faker::create(); 21 | $data_array = []; 22 | for ($i = 1; $i < 100; $i++) { 23 | $data_array[] = [ 24 | 'property_value_id' => $faker->numberBetween(1, 12), 25 | 'product_id' => $i, 26 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 27 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 28 | ]; 29 | } 30 | DB::table('product_property')->insert($data_array); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/seeders/ProductsRelatedProductsTableSeeder.php: -------------------------------------------------------------------------------- 1 | numberBetween(1,200); 24 | if ($related_product_id != $i) { 25 | $related_products[] = 26 | [ 27 | 'product_id' => $i, 28 | 'related_product_id' => $related_product_id, 29 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 30 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 31 | ]; 32 | } 33 | } 34 | } 35 | DB::table('products_related_products')->truncate(); 36 | DB::table('products_related_products')->insert($related_products); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/seeders/ProductsTableSeeder.php: -------------------------------------------------------------------------------- 1 | $faker->sentence, 24 | 'image' => 'prod'.$faker->numberBetween(1,6).'.jpg', 25 | 'description' => $faker->paragraph(2, true), 26 | 'price' => $faker->numberBetween(100,100000)/100, 27 | 'catalog_id' => $faker->numberBetween(1,16), 28 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 29 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 30 | ]; 31 | } 32 | DB::table('products')->truncate(); 33 | DB::table('products')->insert($productsArray); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/seeders/PropertiesTableSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 19 | DB::table('properties')->insert([ 20 | [ 21 | 'name' => 'manufacturer', 22 | 'priority' => 0, 23 | 'type' => 'selector', 24 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 25 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 26 | ], 27 | [ 28 | 'name' => 'weight', 29 | 'priority' => 1, 30 | 'type' => 'number', 31 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 32 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 33 | ] 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/seeders/RelatedProductsTableSeeder.php: -------------------------------------------------------------------------------- 1 | 1000, 27 | 'impressions' => 0, 28 | 'choices' => 0, 29 | 'deleting' => 0, 30 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 31 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 32 | ]; 33 | 34 | } 35 | DB::table('related_products')->truncate(); 36 | DB::table('related_products')->insert($related_products); 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /database/seeders/ShippingMethodsTableSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 19 | DB::table('shipping_methods')->insert([ 20 | [ 21 | 'class_name' => 'FreeShippingMethod', 22 | 'priority' => 1, 23 | 'enable' => true, 24 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 25 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 26 | ], 27 | [ 28 | 'class_name' => 'FixRateShippingMethod', 29 | 'priority' => 0, 30 | 'enable' => true, 31 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 32 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s') 33 | ], 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | includes: 2 | - ./vendor/nunomaduro/larastan/extension.neon 3 | 4 | parameters: 5 | paths: 6 | - app 7 | # The level 9 is the highest level 8 | level: 7 9 | ignoreErrors: 10 | - '#Unsafe usage of new static#' 11 | - '#PHPDoc tag @throws with type .*?Psr\\SimpleCache\\InvalidArgumentException.*? is not subtype of Throwable#' 12 | excludePaths: 13 | - ./*/*/FileToBeExcluded.php 14 | - ./vendor/** 15 | - ./app/Library/Services/** 16 | - ./app/Temporal/** 17 | - ./tests/** 18 | - ./storage/** 19 | - ./bootstrap/cache/** 20 | checkMissingIterableValueType: false 21 | reportUnmatchedIgnoredErrors: false 22 | checkGenericClassInNonGenericObjectType: false 23 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/Feature 6 | 7 | 8 | ./tests/Unit 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ./app 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteCond %{REQUEST_URI} (.+)/$ 11 | RewriteRule ^ %1 [L,R=301] 12 | 13 | # Handle Front Controller... 14 | RewriteCond %{REQUEST_FILENAME} !-d 15 | RewriteCond %{REQUEST_FILENAME} !-f 16 | RewriteRule ^ index.php [L] 17 | 18 | # Handle Authorization Header 19 | RewriteCond %{HTTP:Authorization} . 20 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 21 | 22 | -------------------------------------------------------------------------------- /public/desktop.ini: -------------------------------------------------------------------------------- 1 | [ViewState] 2 | Mode= 3 | Vid= 4 | FolderType=Generic 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/favicon.ico -------------------------------------------------------------------------------- /public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /public/images/cart-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/cart-icon.png -------------------------------------------------------------------------------- /public/images/categories/cat_1512673520.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/categories/cat_1512673520.jpg -------------------------------------------------------------------------------- /public/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/loading.gif -------------------------------------------------------------------------------- /public/images/prod1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/prod1.jpg -------------------------------------------------------------------------------- /public/images/prod2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/prod2.jpg -------------------------------------------------------------------------------- /public/images/prod3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/prod3.jpg -------------------------------------------------------------------------------- /public/images/prod4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/prod4.jpg -------------------------------------------------------------------------------- /public/images/prod5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/prod5.jpg -------------------------------------------------------------------------------- /public/images/prod6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/prod6.jpg -------------------------------------------------------------------------------- /public/images/products/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/images/products/.empty -------------------------------------------------------------------------------- /public/images/products/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.empty 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /public/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/app.js": "/js/app.js", 3 | "/css/app.css": "/css/app.css" 4 | } 5 | -------------------------------------------------------------------------------- /public/rel1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/rel1.jpg -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/service-worker.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiantVlad/laravel_shop_cart/7a1ebbca52272f1a40b7d30303d05830d907ee7b/public/service-worker.js -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /resources/assets/js/components/ModalWrapper.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | 29 | 32 | -------------------------------------------------------------------------------- /resources/assets/js/components/NavCart.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 44 | 45 | 48 | -------------------------------------------------------------------------------- /resources/assets/js/components/NavSearch.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 47 | 48 | 50 | -------------------------------------------------------------------------------- /resources/assets/js/components/ProductFilters.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 48 | 49 | 51 | -------------------------------------------------------------------------------- /resources/assets/js/models/Order.js: -------------------------------------------------------------------------------- 1 | export default (data) => ({ 2 | id: data ? data.id : null, 3 | createdAt: data ? data.createdAt : null, 4 | total: data ? data.total : 0, 5 | status: data ? data.total : null, 6 | orderData: data ? data.orderData : [], 7 | dispatches: data ? data.dispatches : [], 8 | payments: data ? data.payments : [], 9 | }) 10 | -------------------------------------------------------------------------------- /resources/assets/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // Body 3 | $body-bg: #f5f8fa; 4 | 5 | // Borders 6 | $laravel-border-color: darken($body-bg, 10%); 7 | $list-group-border: $laravel-border-color; 8 | $navbar-default-border: $laravel-border-color; 9 | $panel-default-border: $laravel-border-color; 10 | $panel-inner-border: $laravel-border-color; 11 | 12 | // Brands 13 | $brand-primary: #3097D1; 14 | $brand-info: #8eb4cb; 15 | $brand-success: #2ab27b; 16 | $brand-warning: #cbb956; 17 | $brand-danger: #bf5329; 18 | 19 | // Typography 20 | $icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/"; 21 | $font-family-sans-serif: "Raleway", sans-serif; 22 | $font-size-base: 14px; 23 | $line-height-base: 1.6; 24 | $text-color: #636b6f; 25 | 26 | // Navbar 27 | $navbar-default-bg: #fff; 28 | 29 | // Buttons 30 | $btn-default-color: $text-color; 31 | 32 | // Inputs 33 | $input-border: lighten($text-color, 40%); 34 | $input-border-focus: lighten($brand-primary, 25%); 35 | $input-color-placeholder: lighten($text-color, 30%); 36 | 37 | // Panels 38 | $panel-default-heading-bg: #fff; 39 | -------------------------------------------------------------------------------- /resources/assets/sass/app.scss: -------------------------------------------------------------------------------- 1 | // Fonts 2 | @import url("https://fonts.googleapis.com/css?family=Roboto:300,400,600"); 3 | // Variables 4 | @import "variables"; 5 | // Bootstrap 6 | @import "~bootstrap-sass/assets/stylesheets/bootstrap"; 7 | @import "~bootstrap-select/dist/css/bootstrap-select.css"; 8 | 9 | body.general-body { 10 | padding-top: 60px; 11 | div.general-nav-col { 12 | padding: 0px 4px; 13 | .navbar-form{ 14 | padding: 0px 3px; 15 | } 16 | } 17 | ul.general-nav li a { 18 | padding: 7px; 19 | } 20 | .jumbotron { 21 | padding-bottom: 30px; 22 | padding-top: 30px; 23 | } 24 | } 25 | 26 | div.nav-search { 27 | padding-top: 7px; 28 | padding-bottom: 7px; 29 | } 30 | 31 | .product-list { 32 | 33 | } 34 | 35 | .form-group.required .control-label:after { 36 | color: #d00; 37 | content: "*"; 38 | position: absolute; 39 | margin-left: 8px; 40 | top:7px; 41 | } 42 | 43 | .footer { 44 | background-color: #eeeeee; 45 | } 46 | 47 | @media (max-width: 767px) { 48 | body.general-body { 49 | padding-top: 110px; 50 | } 51 | } 52 | //xs-sm-md 53 | @media (min-width: 768px) and (max-width: 1199px) { 54 | body.general-body { 55 | padding-top: 80px; 56 | } 57 | ul.general-nav{ 58 | li { 59 | width: 100%; 60 | a { 61 | float: right; 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least six characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have e-mailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/views/admin/admin-left-column.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('left-column') 4 |
5 |
Categories
6 |
Products
7 |
Users
8 |
Orders
9 |
Payment methods
10 |
Shipping
11 |
Settings
12 |
13 | 14 | @stop 15 | -------------------------------------------------------------------------------- /resources/views/admin/admin.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Admin WG-Shop 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | @if (Auth::guard('admin')->check()) 19 | @include('admin.nav') 20 | @endif 21 | 22 |
23 |
24 |
25 | @yield('left-column') 26 |
27 |
28 | @include('layouts.error') 29 | @yield('content') 30 |
31 |
32 |
33 | 34 |
35 |
36 |

Created by Uladzimir Sadkou hofirma@gmail.com

37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /resources/views/admin/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('left-column') 4 | @include('admin.admin-left-column') 5 | @stop 6 | @section('content') 7 | 8 |
9 |
10 |

DASHBOARD

11 |
12 |
13 |
14 |

Hello

15 |
16 | @stop -------------------------------------------------------------------------------- /resources/views/admin/orders-load.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
ID
3 |
Created
4 |
User/E-mail
5 |
Total
6 |
Status
7 |
8 | @if (!empty($orders)) 9 | @foreach ($orders as $order) 10 |
11 |
{{$order->order_label}}
12 |
{{$order->created_at->format('Y-M-d h:i')}}
13 |
{{$order->user->name}}
{{$order->user->email}}
14 |
{{$order->total}}
15 |
{{$order->status}}
16 | 17 | 18 | 19 |
20 | @endforeach 21 |
22 | {{ $orders->links() }} 23 |
24 | @endif 25 | -------------------------------------------------------------------------------- /resources/views/admin/orders.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('left-column') 4 | @include('admin.admin-left-column') 5 | @stop 6 | 7 | @section('content') 8 |
9 |
10 |

Orders

11 |
12 |
13 |
14 |
15 |
16 | {{ csrf_field() }} 17 |
18 | 19 |
20 | 23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 | @include('admin.orders-load') 31 |
32 | @stop -------------------------------------------------------------------------------- /resources/views/admin/products-load.blade.php: -------------------------------------------------------------------------------- 1 | @php $i=0; @endphp 2 | @foreach ($products as $product) 3 | @php $i++; @endphp 4 |
5 |
{{$i}}
6 |
7 | image 8 |
9 |
{{$product->name}}
10 |
{{$product->description}}
11 |
{{$product->price}}
12 |
{{$product->catalogs->name}}
13 | 14 |
15 |
16 | 17 | {{ method_field('DELETE') }} 18 | {{ csrf_field() }} 19 | 22 |
23 |
24 |
25 | @endforeach 26 |
27 | {{ $products->links() }} 28 |
29 | -------------------------------------------------------------------------------- /resources/views/admin/property-modal.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/admin/property-values.blade.php: -------------------------------------------------------------------------------- 1 | @if (is_array($propertyValues)) 2 | 4 | 5 | @else 6 | @if ($propertyValues->first()->properties->type === 'selector') 7 | 15 | @else 16 | 18 | @endif 19 | @endif -------------------------------------------------------------------------------- /resources/views/admin/shipping-methods-load.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
Label
3 |
priority
4 |
Status
5 |
6 |
7 |
8 | @if (!empty($shippingMethods)) 9 | @foreach ($shippingMethods as $shippingMethod) 10 |
11 |
{{$shippingMethod->label}}
12 |
{{$shippingMethod->priority}}
13 |
{{$shippingMethod->enable ? 'enable' : 'disable'}}
14 | 15 |
16 | 18 | 19 |
20 |
21 | @endforeach 22 | @endif 23 | -------------------------------------------------------------------------------- /resources/views/admin/shipping-methods.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('left-column') 4 | @include('admin.admin-left-column') 5 | @stop 6 | 7 | @section('content') 8 |
9 |
10 |

Shipping Methods

11 |
12 |
13 | 14 |
15 | @include('admin.shipping-methods-load') 16 |
17 | @stop -------------------------------------------------------------------------------- /resources/views/admin/users-load.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
ID
3 |
Name
4 |
E-mail
5 |
6 | @foreach ($users as $user) 7 |
8 |
{{$user->id}}
9 |
{{$user->name}}
10 |
{{$user->email}}
11 | 12 | 13 |
14 |
15 | {{ csrf_field() }} 16 | 17 | 18 | 21 |
22 |
23 |
24 | @endforeach 25 |
26 | {{ $users->links() }} 27 |
28 | -------------------------------------------------------------------------------- /resources/views/admin/users.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('left-column') 4 | @include('admin.admin-left-column') 5 | @stop 6 | 7 | @section('content') 8 |
9 |
10 |

Users

11 |
12 |
13 |
14 |
15 |
16 | {{ csrf_field() }} 17 |
18 | 19 |
20 | 23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 | @include('admin.users-load') 31 |
32 | @stop -------------------------------------------------------------------------------- /resources/views/app.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ config('app.name', 'Laravel') }} 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | @include('layouts.nav') 17 | @yield('categories') 18 | @include('layouts.modal') 19 | 20 |
21 |
22 |
23 | @yield('left-column') 24 |
25 |
26 | @include('layouts.error') 27 | @yield('content') 28 |
29 |
30 |
31 | 32 |
33 |
34 |

Created by Uladzimir Sadkou hofirma@gmail.com

35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /resources/views/cart.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | 3 | @section('content') 4 |
5 |

Product Cart

6 |
7 | 8 |
9 |
10 | @include('layouts.error') 11 | 12 | @if(!empty($products)) 13 | 23 | 24 | @endif 25 | 26 |
27 |
28 | @stop 29 | -------------------------------------------------------------------------------- /resources/views/empty-cart.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | 3 | @section('content') 4 |
5 |
6 |

Your CART is empty

7 |
8 |
9 | @stop 10 | -------------------------------------------------------------------------------- /resources/views/errors/401.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Unauthorized')) 4 | @section('code', '401') 5 | @section('message', __('Unauthorized')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/402.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Payment Required')) 4 | @section('code', '402') 5 | @section('message', __('Payment Required')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/403.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Forbidden')) 4 | @section('code', '403') 5 | @section('message', __($exception->getMessage() ?: 'Forbidden')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/404.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Not Found')) 4 | @section('code', '404') 5 | @section('message', __('Not Found')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/419.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Page Expired')) 4 | @section('code', '419') 5 | @section('message', __('Page Expired')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/429.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Too Many Requests')) 4 | @section('code', '429') 5 | @section('message', __('Too Many Requests')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/500.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Server Error')) 4 | @section('code', '500') 5 | @section('message', __('Server Error')) 6 | -------------------------------------------------------------------------------- /resources/views/errors/503.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors::minimal') 2 | 3 | @section('title', __('Service Unavailable')) 4 | @section('code', '503') 5 | @section('message', __('Service Unavailable')) 6 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
Dashboard
9 | 10 |
11 | @if (session('status')) 12 |
13 | {{ session('status') }} 14 |
15 | @endif 16 | 17 | You are logged in! 18 |
19 |
20 |
21 |
22 |
23 | @endsection 24 | -------------------------------------------------------------------------------- /resources/views/layouts/categories.blade.php: -------------------------------------------------------------------------------- 1 | @if (isset($parent_catalogs)) 2 |
3 |
4 |
5 | Shop 6 | @php $last_elem_flag = count($parent_catalogs); @endphp 7 | @foreach( $parent_catalogs as $parent_catalog ) 8 | @php --$last_elem_flag; @endphp 9 |   10 |   11 | {{$parent_catalog['name']}} 15 | @endforeach 16 |
17 |
18 |
19 | @endif 20 | 21 |
22 |
23 | @foreach($catalogs as $catalog) 24 |
25 | {{$catalog->name}} 26 |
27 | @endforeach 28 |
29 |
30 | -------------------------------------------------------------------------------- /resources/views/layouts/error.blade.php: -------------------------------------------------------------------------------- 1 | @if ($errors->any()) 2 |
3 |
    4 | @foreach ($errors->all() as $error) 5 |
  • {{ $error }}
  • 6 | @endforeach 7 |
8 |
9 | @endif 10 | @if(session()->has('message')) 11 |
12 | {{ session()->get('message') }} 13 |
14 | @endif 15 | -------------------------------------------------------------------------------- /resources/views/layouts/modal.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 20 |
-------------------------------------------------------------------------------- /resources/views/layouts/product-not-found.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Products not found

5 |
6 |
-------------------------------------------------------------------------------- /resources/views/shop.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | @section('categories') 3 | 4 | @stop 5 | 6 | @section('left-column') 7 | 8 | @stop 9 | 10 | @section('content') 11 |
12 |
13 |

Shop

14 |
15 |
16 |
17 | 18 |
19 | @stop 20 | -------------------------------------------------------------------------------- /resources/views/shop/order-success.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @extends('app') 4 | 5 | @section('content') 6 |
7 | 11 |
12 | @stop -------------------------------------------------------------------------------- /resources/views/shop/order.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | 3 | @section('content') 4 | 5 | 6 | @stop 7 | -------------------------------------------------------------------------------- /resources/views/shop/orders.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | 3 | @section('content') 4 | 6 | 7 | @stop 8 | -------------------------------------------------------------------------------- /resources/views/shop/search-product.blade.php: -------------------------------------------------------------------------------- 1 | @if (isset($products)) 2 |
3 | @foreach ($products as $product) 4 |
5 |
{{$product->name}}
6 | product id {{ $product->id }} 9 | 10 |

Price: {{$product->price}}

11 |
12 | @if($loop->iteration % 2 == 0) 13 |
14 | @endif 15 | @endforeach 16 |
17 | @endif 18 | -------------------------------------------------------------------------------- /resources/views/shop/single.blade.php: -------------------------------------------------------------------------------- 1 | @extends('app') 2 | 3 | @section('content') 4 |
5 |
6 |

{{ $product->name }}

7 |
8 |
9 | 10 |
11 | 12 |
13 | @stop -------------------------------------------------------------------------------- /resources/views/shop/test.blade.php: -------------------------------------------------------------------------------- 1 |

hello

-------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 17 | return $request->user(); 18 | }); 19 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 16 | }); 17 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | 12 | $uri = urldecode( 13 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?: '' 14 | ); 15 | 16 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 17 | // built-in PHP web server. This provides a convenient way to test a Laravel 18 | // application without having installed a "real" web server software here. 19 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 20 | return false; 21 | } 22 | 23 | require_once __DIR__.'/public/index.php'; 24 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Feature/RelatedProductRepositoryTest.php: -------------------------------------------------------------------------------- 1 | create([ 17 | 'points' => 300, 18 | ]); 19 | RelatedProduct::where('id', $related->id)->increment('points', -5); 20 | $related->refresh(); 21 | $this->assertEquals(295, $related->points); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | relatedProduct = $this->createMock(RelatedProduct::class); 20 | } 21 | 22 | public function testIncrementRate(): void 23 | { 24 | $builder = $this->createMock(Builder::class); 25 | $builder->expects($this->once())->method('increment')->with('points', -3); 26 | 27 | $this->relatedProduct->expects($this->once()) 28 | ->method('__call') 29 | ->with('where', ['id', 123]) 30 | ->willReturn($builder); 31 | 32 | $recommended = new Recommended($this->relatedProduct); 33 | $recommended->incrementRate(123, -3); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/js/NavSearch.spec.js: -------------------------------------------------------------------------------- 1 | import {createWrapper, shallowMount} from '@vue/test-utils' 2 | import NavSearch from '../../resources/assets/js/components/NavSearch.vue' 3 | import { flushPromises } from './flush-promises' 4 | import chai from 'chai' 5 | 6 | describe('NavSearch.vue', () => { 7 | let wrapper; 8 | const expect = chai.expect 9 | beforeEach(() => { 10 | wrapper = shallowMount(NavSearch, { 11 | propsData: { 12 | searchUrl: '/search' 13 | } 14 | }); 15 | }); 16 | 17 | it('finds button with id nav-search-btn', () => { 18 | expect(wrapper.find('#nav-search-btn').exists()).to.be.true 19 | }); 20 | 21 | it('clicks on search', (done) => { 22 | const rootWrapper = createWrapper(wrapper.vm.$root) 23 | const textInput = wrapper.find('input#nav-search') 24 | textInput.setValue('some value') 25 | delete global.window.location 26 | global.window.location = {pathname: '/shop'} 27 | wrapper.find('button#nav-search-btn').trigger('click') 28 | flushPromises().then(() => { 29 | expect(rootWrapper.emitted().product_search[0][0]).to.be.eq({keyword: 'some value'}) 30 | }).finally(() => (done())) 31 | }) 32 | }); 33 | -------------------------------------------------------------------------------- /tests/js/flush-promises.js: -------------------------------------------------------------------------------- 1 | export const flushPromises = () => new Promise(resolve => setTimeout(resolve)); 2 | -------------------------------------------------------------------------------- /tests/js/setup.js: -------------------------------------------------------------------------------- 1 | require('jsdom-global')(undefined, { 2 | url: 'https://my-site.com' 3 | }); 4 | 5 | window.Date = Date; 6 | 7 | let meta = window.document.createElement('meta'); 8 | meta.name = 'csrf-token'; 9 | meta.content = '123456'; 10 | window.document.getElementsByTagName('head')[0].appendChild(meta) 11 | 12 | global.document = window.document; 13 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | mix.webpackConfig({ 14 | resolve: { 15 | alias: { 16 | 'bootstrap-confirmation': 'bootstrap-confirmation2/bootstrap-confirmation.js' // relative to node_modules 17 | }, 18 | //extensions: [ '.tsx', '.ts', '.js', '.vue' ], 19 | } 20 | }); 21 | mix.js('resources/assets/js/app.js', 'public/js').vue() 22 | .sass('resources/assets/sass/app.scss', 'public/css'); 23 | --------------------------------------------------------------------------------