diff --git a/.do/deploy.template.yaml b/.do/deploy.template.yaml new file mode 100644 index 000000000..76d313a45 --- /dev/null +++ b/.do/deploy.template.yaml @@ -0,0 +1,20 @@ +spec: + name: nexopos + databases: + - name: nexopos + engine: MYSQL + production: true + cluster_name: ns + services: + - environment_slug: php + name: nexopos + git: + repo_clone_url: https://github.com/blair2004/NexoPOS-4x + branch: master + build_command: + npm install + composer install + cp .env.example .env + php artisan key:generate + php artisan storage:link + run_command: heroku-php-apache2 public/ diff --git a/README.md b/README.md index 58434c094..62dbb8776 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ [![Latest Stable Version](https://poser.pugx.org/blair2004/nexopos/v)](//packagist.org/packages/blair2004/nexopos) [![Total Downloads](https://poser.pugx.org/blair2004/nexopos/downloads)](//packagist.org/packages/blair2004/nexopos) [![Latest Unstable Version](https://poser.pugx.org/blair2004/nexopos/v/unstable)](//packagist.org/packages/blair2004/nexopos) [![License](https://poser.pugx.org/blair2004/nexopos/license)](//packagist.org/packages/blair2004/nexopos) +[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/blair2004/NexoPOS-4x/tree/v4.5.x&refcode=ebdb80cb0ec7) + # About NexoPOS 4.x NexoPOS 4 is a free point of sale system build using Laravel, TailwindCSS, Vue and other open-source resources. This POS System focuses on utilities and functionalities to offer for most businesses all the tools they need to manage better their store. NexoPOS 4.x include a responsive and beautiful dashboard that ease the interaction either on a smartphone, tables or desktops. diff --git a/app/Console/Commands/GenerateModuleCommand.php b/app/Console/Commands/GenerateModuleCommand.php index 482ac6f61..30eaa39b8 100755 --- a/app/Console/Commands/GenerateModuleCommand.php +++ b/app/Console/Commands/GenerateModuleCommand.php @@ -29,7 +29,7 @@ class GenerateModuleCommand extends Command * * @var string */ - protected $description = 'Create a new Tendoo module'; + protected $description = 'Create a new NexoPOS 4.x module'; /** * Create a new command instance. @@ -52,7 +52,7 @@ public function handle() if ( ns()->installed() ) { $this->askInformations(); } else { - $this->info( 'Tendoo is not yet installed.' ); + $this->info( 'NexoPOS 4.x is not yet installed.' ); } } diff --git a/app/Crud/CustomerCrud.php b/app/Crud/CustomerCrud.php index 511f40ca4..5fd448d87 100755 --- a/app/Crud/CustomerCrud.php +++ b/app/Crud/CustomerCrud.php @@ -16,6 +16,7 @@ use App\Models\CustomerBillingAddress; use App\Models\CustomerGroup; use App\Models\CustomerShippingAddress; +use App\Services\Users; use Exception; use TorMorten\Eventy\Facades\Events as Hook; @@ -565,7 +566,7 @@ public function bulkAction( Request $request ) * Deleting licence is only allowed for admin * and supervisor. */ - $user = app()->make( 'Tendoo\Core\Services\Users' ); + $user = app()->make( Users::class ); if ( ! $user->is([ 'admin', 'supervisor' ]) ) { return response()->json([ 'status' => 'failed', diff --git a/app/Crud/ProductCategoryCrud.php b/app/Crud/ProductCategoryCrud.php index de32c794f..656956d40 100755 --- a/app/Crud/ProductCategoryCrud.php +++ b/app/Crud/ProductCategoryCrud.php @@ -393,6 +393,7 @@ public function bulkAction( Request $request ) * and supervisor. */ $user = app()->make( Users::class ); + if ( ! $user->is([ 'admin', 'supervisor' ]) ) { return response()->json([ 'status' => 'failed', diff --git a/app/Http/Controllers/Dashboard/CrudController.php b/app/Http/Controllers/Dashboard/CrudController.php index c52edd399..9dc622fad 100755 --- a/app/Http/Controllers/Dashboard/CrudController.php +++ b/app/Http/Controllers/Dashboard/CrudController.php @@ -382,7 +382,7 @@ public function crudBulkActions( String $namespace, Request $request ) * assuming we're bulk deleting * but the action might be different later */ - $response = $resource->bulkAction( $request ); + $response = Hook::filter( get_class( $resource ) . '@bulkAction', $resource->bulkAction( $request ), $request ); return [ 'status' => 'success', @@ -462,9 +462,9 @@ public function getConfig( string $namespace ) get_class( $resource ) . '@getColumns', $resource->getColumns() ), - 'labels' => $resource->getLabels(), - 'links' => $resource->getLinks() ?? [], - 'bulkActions' => $resource->getBulkActions(), + 'labels' => Hook::filter( get_class( $resource ) . '@getLabels', $resource->getLabels() ), + 'links' => Hook::filter( get_class( $resource ) . '@getLinks', $resource->getLinks() ?? [] ), + 'bulkActions' => Hook::filter( get_class( $resource ) . '@getBulkActions', $resource->getBulkActions() ), 'namespace' => $namespace, ]; } @@ -499,8 +499,8 @@ public function getFormConfig( string $namespace, $id = null ) $form = Hook::filter( get_class( $resource )::method( 'getForm' ), $resource->getForm( $model ), compact( 'model' ) ); $config = [ 'form' => $form, - 'labels' => $resource->getLabels(), - 'links' => @$resource->getLinks(), + 'labels' => Hook::filter( get_class( $resource ) . '@getLabels', $resource->getLabels() ), + 'links' => Hook::filter( get_class( $resource ) . '@getLinks', $resource->getLinks() ), 'namespace' => $namespace, ]; diff --git a/app/Http/Controllers/Dashboard/CustomersController.php b/app/Http/Controllers/Dashboard/CustomersController.php index 6b0ff2bb8..8f82d9387 100755 --- a/app/Http/Controllers/Dashboard/CustomersController.php +++ b/app/Http/Controllers/Dashboard/CustomersController.php @@ -268,7 +268,7 @@ public function getCustomersRewards( Customer $customer ) public function editCustomerReward( Customer $customer, CustomerReward $reward ) { return CustomerRewardCrud::form( $reward, [ - 'returnUrl' => ns()->route( 'ns.dashboard.customers-rewards', [ 'customer' => $customer->id ]), + 'returnUrl' => ns()->route( 'ns.dashboard.customers-rewards-list', [ 'customer' => $customer->id ]), 'queryParams' => [ 'customer_id' => $customer->id ] diff --git a/app/Services/AuthService.php b/app/Services/AuthService.php index a070db449..c9fb2a5fc 100755 --- a/app/Services/AuthService.php +++ b/app/Services/AuthService.php @@ -510,6 +510,7 @@ public function lostPasswordUnsecured( $fields ) /** * Check recaptcha using predefined * values as POST data + * @deprecated * @return void */ public function checkReCaptcha( $data = []) diff --git a/app/Services/CoreService.php b/app/Services/CoreService.php index decedd4de..9118e2aeb 100755 --- a/app/Services/CoreService.php +++ b/app/Services/CoreService.php @@ -125,6 +125,18 @@ public function url( $url ) return url( Hook::filter( 'ns-url', $url ) ); } + /** + * Returns a filtred URL to which + * apply the filter "ns-url" hook. + * + * @param string $url + * @return string $url + */ + public function asset( $url ) + { + return url( Hook::filter( 'ns-asset', $url ) ); + } + /** * check if a use is allowed to * access a page or trigger an error. This should not be used diff --git a/app/Services/OrdersService.php b/app/Services/OrdersService.php index dd97f2204..36223922f 100755 --- a/app/Services/OrdersService.php +++ b/app/Services/OrdersService.php @@ -637,10 +637,7 @@ public function __checkDiscountVality( $fields ) })->sum(); if ( $fields['discount'] > $productsTotal ) { - throw new NotAllowedException([ - 'status' => 'failed', - 'message' => __('A discount cannot exceed the sub total value of an order.') - ]); + throw new NotAllowedException( __('A discount cannot exceed the sub total value of an order.') ); } } } diff --git a/config/nexopos.php b/config/nexopos.php index 36bd06b59..1d0bdca39 100755 --- a/config/nexopos.php +++ b/config/nexopos.php @@ -1,6 +1,6 @@ '4.5.2', + 'version' => '4.5.3', 'languages' => [ 'en' => 'English', 'fr' => 'Français', diff --git a/package.json b/package.json index 7f6632097..722a6e55e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,8 @@ { "private": true, + "engines": { + "node": "14.x" + }, "scripts": { "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", diff --git a/resources/ts/components/ns-crud.ts b/resources/ts/components/ns-crud.ts index 31b8c8767..c1156fb93 100755 --- a/resources/ts/components/ns-crud.ts +++ b/resources/ts/components/ns-crud.ts @@ -226,18 +226,20 @@ const nsCrud = Vue.component( 'ns-crud', { bulkDo() { if ( this.bulkAction ) { if ( this.selectedEntries.length > 0 ) { - console.log( this.getSelectedAction ); - if ( confirm( this.getSelectedAction.confirm || this.$slots[ 'error-bulk-confirmation' ] || __( 'No bulk confirmation message provided on the CRUD class.' ) ) ) { + if ( confirm( this.getSelectedAction.confirm || this.$slots[ 'error-bulk-confirmation' ] || __( 'Would you like to perform the selected bulk action on the selected entries ?' ) ) ) { return nsHttpClient.post( `${this.src}/bulk-actions`, { action: this.bulkAction, entries: this.selectedEntries.map( r => r.$id ) - }).subscribe( (result: HttpStatusResponse ) => { - nsSnackBar.info( result.message ).subscribe(); - this.selectedEntries = []; - this.refresh(); - }, ( error ) => { - nsSnackBar.error( error.message ) - .subscribe(); + }).subscribe({ + next: (result: HttpStatusResponse ) => { + nsSnackBar.info( result.message ).subscribe(); + this.selectedEntries = []; + this.refresh(); + }, + error: ( error ) => { + nsSnackBar.error( error.message ) + .subscribe(); + } }) } } else { diff --git a/resources/views/pages/dashboard/products/print-labels.blade.php b/resources/views/pages/dashboard/products/print-labels.blade.php index b6e6a6a4b..fa74c28e5 100755 --- a/resources/views/pages/dashboard/products/print-labels.blade.php +++ b/resources/views/pages/dashboard/products/print-labels.blade.php @@ -304,7 +304,7 @@ @{{ item.selectedUnitQuantity.sale_price | currency }}
- +
@{{ item.selectedUnitQuantity.barcode }}
diff --git a/routes/web/customers.php b/routes/web/customers.php index 2bd51a3c9..4af6aafba 100644 --- a/routes/web/customers.php +++ b/routes/web/customers.php @@ -5,22 +5,22 @@ use App\Http\Controllers\Dashboard\RewardsSystemController; use Illuminate\Support\Facades\Route; -Route::get( '/customers', [ CustomersController::class, 'listCustomers' ]); -Route::get( '/customers/create', [ CustomersController::class, 'createCustomer' ]); -Route::get( '/customers/edit/{customer}', [ CustomersController::class, 'editCustomer' ]); -Route::get( '/customers/{customer}/rewards', [ CustomersController::class, 'getCustomersRewards' ])->name( ns()->routeName( 'ns.dashboard.customers-rewards' ) ); -Route::get( '/customers/{customer}/rewards/edit/{reward}', [ CustomersController::class, 'editCustomerReward' ]); -Route::get( '/customers/{customer}/orders', [ CustomersController::class, 'getCustomersOrders' ]); -Route::get( '/customers/{customer}/coupons', [ CustomersController::class, 'getCustomersCoupons' ]); -Route::get( '/customers/{customer}/account-history', [ CustomersController::class, 'getCustomerAccountHistory' ]); -Route::get( '/customers/{customer}/account-history/create', [ CustomersController::class, 'createCustomerAccountHistory' ]); -Route::get( '/customers/{customer}/account-history/edit/{customerAccountHistory}', [ CustomersController::class, 'editCustomerAccountHistory' ]); -Route::get( '/customers/groups', [ CustomersGroupsController::class, 'listCustomersGroups' ]); -Route::get( '/customers/groups/create', [ CustomersGroupsController::class, 'createCustomerGroup' ]); -Route::get( '/customers/groups/edit/{group}', [ CustomersGroupsController::class, 'editCustomerGroup' ]); -Route::get( '/customers/rewards-system', [ RewardsSystemController::class, 'list' ]); -Route::get( '/customers/rewards-system/create', [ RewardsSystemController::class, 'create' ]); +Route::get( '/customers', [ CustomersController::class, 'listCustomers' ])->name( ns()->routeName( 'ns.dashboard.customers-list' ) ); +Route::get( '/customers/create', [ CustomersController::class, 'createCustomer' ])->name( ns()->routeName( 'ns.dashboard.customers-create' ) ); +Route::get( '/customers/edit/{customer}', [ CustomersController::class, 'editCustomer' ])->name( ns()->routeName( 'ns.dashboard.customers-edit' ) ); +Route::get( '/customers/{customer}/rewards', [ CustomersController::class, 'getCustomersRewards' ])->name( ns()->routeName( 'ns.dashboard.customers-rewards-list' ) ); +Route::get( '/customers/{customer}/rewards/edit/{reward}', [ CustomersController::class, 'editCustomerReward' ])->name( ns()->routeName( 'ns.dashboard.customers-rewards-edit' ) ); +Route::get( '/customers/{customer}/orders', [ CustomersController::class, 'getCustomersOrders' ])->name( ns()->routeName( 'ns.dashboard.customers-orders-list' ) ); +Route::get( '/customers/{customer}/coupons', [ CustomersController::class, 'getCustomersCoupons' ])->name( ns()->routeName( 'ns.dashboard.customers-coupons-list' ) ); +Route::get( '/customers/{customer}/account-history', [ CustomersController::class, 'getCustomerAccountHistory' ])->name( ns()->routeName( 'ns.dashboard.customers-account-history-list' ) ); +Route::get( '/customers/{customer}/account-history/create', [ CustomersController::class, 'createCustomerAccountHistory' ])->name( ns()->routeName( 'ns.dashboard.customers-account-history-create' ) ); +Route::get( '/customers/{customer}/account-history/edit/{customerAccountHistory}', [ CustomersController::class, 'editCustomerAccountHistory' ])->name( ns()->routeName( 'ns.dashboard.customers-account-history-edit' ) ); +Route::get( '/customers/groups', [ CustomersGroupsController::class, 'listCustomersGroups' ])->name( ns()->routeName( 'ns.dashboard.customersgroups-list' ) ); +Route::get( '/customers/groups/create', [ CustomersGroupsController::class, 'createCustomerGroup' ])->name( ns()->routeName( 'ns.dashboard.customersgroups-create' ) ); +Route::get( '/customers/groups/edit/{group}', [ CustomersGroupsController::class, 'editCustomerGroup' ])->name( ns()->routeName( 'ns.dashboard.customersgroups-edit' ) ); +Route::get( '/customers/rewards-system', [ RewardsSystemController::class, 'list' ])->name( ns()->routeName( 'ns.dashboard.rewards-list' ) ); +Route::get( '/customers/rewards-system/create', [ RewardsSystemController::class, 'create' ])->name( ns()->routeName( 'ns.dashboard.rewards-create' ) ); Route::get( '/customers/rewards-system/edit/{reward}', [ RewardsSystemController::class, 'edit' ])->name( ns()->routeName( 'ns.dashboard.rewards-edit' ) ); -Route::get( '/customers/coupons', [ CustomersController::class, 'listCoupons' ]); -Route::get( '/customers/coupons/create', [ CustomersController::class, 'createCoupon' ]); -Route::get( '/customers/coupons/edit/{coupon}', [ CustomersController::class, 'editCoupon' ]); \ No newline at end of file +Route::get( '/customers/coupons', [ CustomersController::class, 'listCoupons' ])->name( ns()->routeName( 'ns.dashboard.customers-coupons-list' ) ); +Route::get( '/customers/coupons/create', [ CustomersController::class, 'createCoupon' ])->name( ns()->routeName( 'ns.dashboard.customers-coupons-create' ) ); +Route::get( '/customers/coupons/edit/{coupon}', [ CustomersController::class, 'editCoupon' ])->name( ns()->routeName( 'ns.dashboard.customers-coupons-edit' ) ); \ No newline at end of file diff --git a/tests/Feature/CreateOrderTest.php b/tests/Feature/CreateOrderTest.php index c5a6161b4..0ee4f225f 100755 --- a/tests/Feature/CreateOrderTest.php +++ b/tests/Feature/CreateOrderTest.php @@ -257,11 +257,13 @@ public function processOrders( $currentDate, $callback ) * Let's test wether the cash * flow has been created for this sale */ - $this->assertTrue( - CashFlow::where( 'order_id', $responseData[ 'data' ][ 'order' ][ 'id' ] )->first() - instanceof CashFlow, - __( 'No cash flow were created for this order.' ) - ); + if ( $responseData[ 'data' ][ 'order' ][ 'payment_status' ] !== 'unpaid' ) { + $this->assertTrue( + CashFlow::where( 'order_id', $responseData[ 'data' ][ 'order' ][ 'id' ] )->first() + instanceof CashFlow, + __( 'No cash flow were created for this order.' ) + ); + } /** * if a custom callback is provided