├── public ├── favicon.ico ├── robots.txt ├── img │ ├── invextry-ss1.png │ ├── invextry-ss2.png │ ├── invextry-ss3.png │ ├── placeholder.png │ ├── invextry-logo.png │ └── invextry-social.png ├── .htaccess └── index.php ├── A2ZTRACK ├── problems-solutions.txt ├── modules.txt └── module-checklist.txt ├── database ├── .gitignore ├── seeders │ ├── CreateApp.php │ ├── TaxSeeder.php │ ├── WarehouseSeeder.php │ ├── SuperAdminSeeder.php │ ├── AccountSeeder.php │ ├── UnitSeeder.php │ ├── BrandSeeder.php │ └── ProductCategorySeeder.php ├── migrations │ ├── 2023_07_1_141608_create_invextry_meta_table.php │ ├── 2023_08_05_182000_create_payment_methods_table.php │ ├── 2023_07_28_152756_create_brands_table.php │ ├── 2023_07_26_124157_create_taxes_table.php │ ├── 2014_10_12_100000_create_password_reset_tokens_table.php │ ├── 2023_07_31_124517_create_product_categories_table.php │ ├── 2023_07_19_141527_create_currencies_table.php │ ├── 2023_08_05_136533_create_account_adjustments_table.php │ ├── 2023_07_26_182430_create_warehouses_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2023_08_05_136435_create_accounts_table.php │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2023_07_23_134907_create_units_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ ├── 2023_08_02_155740_create_product_stocks_table.php │ ├── 2023_08_05_181011_create_invoice_items_table.php │ ├── 2023_08_05_183542_create_payments_table.php │ ├── 2020_10_12_000000_add_variants_to_media.php │ └── 2023_08_05_135214_create_parties_table.php └── factories │ └── UserFactory.php ├── bootstrap ├── cache │ └── .gitignore └── app.php ├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore ├── debugbar │ └── .gitignore ├── framework │ ├── testing │ │ └── .gitignore │ ├── views │ │ └── .gitignore │ ├── cache │ │ ├── data │ │ │ └── .gitignore │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── .gitignore └── demo │ ├── brands │ ├── hp.jpg │ ├── mi.jpg │ ├── rfl.jpg │ ├── ssg.png │ ├── arong.jpg │ ├── asus.jpg │ ├── bata.jpg │ ├── casio.jpg │ ├── dano.jpg │ ├── dell.jpg │ ├── eset.jpg │ ├── fresh.jpg │ ├── lotto.jpg │ ├── nido.jpg │ ├── panda.jpg │ ├── pran.jpg │ ├── regal.jpg │ ├── titan.jpg │ ├── yamah.jpg │ ├── oriant.jpg │ ├── philip.jpg │ ├── samsung.png │ ├── vision.jpg │ ├── walton.jpg │ └── pepsodent.jpg │ ├── products │ ├── Jeans.jpg │ ├── dates.jpg │ ├── fanta.jpg │ ├── iphone.jpg │ ├── kitkat.jpg │ ├── mango.webp │ ├── mi-tv.jpg │ ├── mojo.webp │ ├── oreo.jpg │ ├── pepsi.jpg │ ├── pepsi.webp │ ├── polo.png │ ├── sauce.webp │ ├── shirt.jpg │ ├── toy.webp │ ├── chicken.webp │ ├── coconut.webp │ ├── dettol.webp │ ├── hand-beg.jpg │ ├── heater.webp │ ├── hilsha.webp │ ├── noodles.webp │ ├── sony-tv.jpg │ ├── asus-laptop.jpg │ ├── casual-shoe.jpg │ ├── cloth-beg.jpg │ ├── dairy-milk.jpg │ ├── handwash.webp │ ├── loafer-shoe.jpg │ ├── rupchanda.webp │ ├── vision-tv.jpg │ ├── vivo-phone.jpg │ ├── apex-slipper.jpg │ ├── cc-tv-camera.jpg │ ├── infinix-phone.jpg │ ├── leather-shoe.jpg │ ├── nikkon-camera.jpg │ ├── sneakers-shoe.jpg │ ├── sports-camera.jpg │ ├── step-out-beg.png │ ├── macbook-laptop.jpg │ └── bangladesh-jersey.webp │ └── product-categories │ ├── beg.jpg │ ├── oil.png │ ├── toy.jpg │ ├── tv.jpg │ ├── camera.jpg │ ├── drinks.jpg │ ├── glass.jpg │ ├── laptop.png │ ├── shoe.jpg │ ├── tablet.jpg │ ├── watch.jpg │ ├── fruits.webp │ ├── t-shirt.jpg │ ├── chocolate.jpg │ ├── furniture.jpg │ ├── headphone.jpg │ ├── milk-powder.jpg │ └── smart-phone.jpg ├── resources ├── admin-resources │ ├── modules │ │ └── user │ │ │ └── userStore.js │ ├── assets │ │ ├── css │ │ │ └── main.css │ │ ├── img │ │ │ └── invextry-logo.png │ │ └── icons │ │ │ ├── menu-svg-icon.vue │ │ │ ├── filter-svg-icon.vue │ │ │ ├── square-svg-icon.vue │ │ │ ├── booklet-svg-icon.vue │ │ │ ├── box-svg-icon.vue │ │ │ ├── cross-svg-icon.vue │ │ │ ├── bin-svg-icon.vue │ │ │ ├── qrcode-svg-icon.vue │ │ │ ├── edit-svg-icon.vue │ │ │ ├── plus-svg-icon.vue │ │ │ ├── wallet-svg-icon.vue │ │ │ ├── logout-svg-icon.vue │ │ │ ├── more-svg-icon.vue │ │ │ ├── customer-svg-icon.vue │ │ │ ├── supplier-svg-icon.vue │ │ │ ├── sort-svg-icon.vue │ │ │ ├── beg-svg-icon.vue │ │ │ ├── cart-svg-icon.vue │ │ │ ├── view-svg-icon.vue │ │ │ ├── twentyfour-svg-icon.vue │ │ │ ├── user-svg-icon.vue │ │ │ ├── coin-1-svg-icon.vue │ │ │ ├── dashboard-svg-icon.vue │ │ │ ├── globe-svg-icon.vue │ │ │ ├── setting-svg-icon.vue │ │ │ └── hand-love-svg-icon.vue │ ├── views │ │ ├── App.vue │ │ └── Admin.vue │ ├── utils │ │ ├── format-validation-errors.js │ │ └── file.js │ ├── components │ │ ├── buttons │ │ │ ├── AddNewButton.vue │ │ │ ├── FilterButton.vue │ │ │ └── BulkDeleteButton.vue │ │ ├── img │ │ │ └── ImagesBox.vue │ │ └── shared │ │ │ ├── notification │ │ │ ├── notificationStore.js │ │ │ ├── notications-container.vue │ │ │ └── notification.vue │ │ │ ├── confirm-alert │ │ │ ├── confirmStore.js │ │ │ └── confirm-box.vue │ │ │ └── loader │ │ │ └── Loader.vue │ ├── stores │ │ ├── sidebar.js │ │ └── authStore.js │ ├── main.js │ └── plugins │ │ └── axios-settings.js └── views │ └── admin │ └── app.blade.php ├── routes ├── api.php ├── channels.php └── console.php ├── tests ├── TestCase.php ├── Unit │ └── ExampleTest.php ├── Feature │ └── ExampleTest.php └── CreatesApplication.php ├── .gitattributes ├── app ├── Models │ ├── Invoice │ │ ├── InvoiceItem.php │ │ └── Invoice.php │ ├── Setting │ │ ├── Tax.php │ │ ├── Currency.php │ │ └── Warehouse.php │ ├── Product │ │ ├── Brand.php │ │ ├── ProductCategory.php │ │ ├── Unit.php │ │ └── Product.php │ ├── Party.php │ ├── Accounting │ │ ├── Account.php │ │ └── AccountAdjustment.php │ ├── Payment.php │ └── User.php ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ ├── Api │ │ │ ├── User │ │ │ │ └── UserController.php │ │ │ ├── Payment │ │ │ │ └── PaymentController.php │ │ │ ├── Dashboard │ │ │ │ └── DashboardController.php │ │ │ ├── Invoice │ │ │ │ ├── SaleInvoiceController.php │ │ │ │ └── PurchaseInvoiceController.php │ │ │ └── Upload │ │ │ │ └── UploadController.php │ │ └── Auth │ │ │ ├── RegisterController.php │ │ │ └── LoginController.php │ ├── Middleware │ │ ├── EncryptCookies.php │ │ ├── VerifyCsrfToken.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── Authenticate.php │ │ ├── ValidateSignature.php │ │ ├── ViewOnly.php │ │ ├── PreventXSS.php │ │ ├── TrustProxies.php │ │ └── RedirectIfAuthenticated.php │ ├── Resources │ │ ├── Tax │ │ │ ├── TaxCollection.php │ │ │ └── TaxResource.php │ │ ├── Unit │ │ │ ├── UnitCollection.php │ │ │ └── UnitResource.php │ │ ├── Brand │ │ │ ├── BrandCollection.php │ │ │ └── BrandResource.php │ │ ├── Party │ │ │ ├── CustomerListCollection.php │ │ │ ├── SupplierListCollection.php │ │ │ ├── CustomerListResource.php │ │ │ ├── SupplierListResource.php │ │ │ ├── CustomerDetailsRerource.php │ │ │ └── SupplierDetailsRerource.php │ │ ├── Product │ │ │ ├── ProductListCollection.php │ │ │ ├── ProductCategoryCollection.php │ │ │ ├── ProductCategoryResource.php │ │ │ ├── ProductListResource.php │ │ │ └── SingleProductResource.php │ │ ├── Warehouse │ │ │ ├── WarehouseCollection.php │ │ │ └── WarehouseResource.php │ │ ├── Currency │ │ │ ├── CurrencyCollection.php │ │ │ └── CurrencyResource.php │ │ ├── Accounting │ │ │ ├── AdjustmentResource.php │ │ │ └── AccountResource.php │ │ └── Invoice │ │ │ ├── SaleListResource.php │ │ │ └── PurchaseListResource.php │ └── Requests │ │ ├── Tax │ │ ├── CreateTaxRequest.php │ │ └── UpdateTaxRequest.php │ │ ├── Currency │ │ ├── CreateCurrencyRequest.php │ │ └── UpdateCurrencyRequest.php │ │ ├── Warehouse │ │ ├── CreateWarehouseRequest.php │ │ └── UpdateWarehouseRequest.php │ │ ├── Brand │ │ ├── CreateBrandRequest.php │ │ └── UpdateBrandRequest.php │ │ ├── Product │ │ ├── CreateProductCategoryRequest.php │ │ ├── UpdateProductCategoryRequest.php │ │ ├── CreateProductRequest.php │ │ └── UpdateProductRequest.php │ │ ├── Unit │ │ ├── CreateUnitRequest.php │ │ └── UpdateUnitRequest.php │ │ ├── Accounting │ │ ├── CreateAdjustmentRequest.php │ │ ├── UpdateAdjustmentRequest.php │ │ ├── CreateAccountRequest.php │ │ └── UpdateAccountRequest.php │ │ ├── Payment │ │ └── CreatePaymentRequest.php │ │ └── Party │ │ ├── CreateCustomerRequest.php │ │ ├── CreateSupplierRequest.php │ │ ├── UpdateCustomerRequest.php │ │ └── UpdateSupplierRequest.php ├── Providers │ ├── BroadcastServiceProvider.php │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php ├── Console │ └── Kernel.php ├── Services │ ├── AccountAdjustmentService.php │ └── StockService.php └── Exceptions │ └── Handler.php ├── .editorconfig ├── .gitignore ├── vite.config.js ├── package.json ├── config ├── cors.php ├── services.php ├── view.php └── hashing.php ├── phpunit.xml ├── .env.example ├── License.txt └── artisan /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /A2ZTRACK/problems-solutions.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/admin-resources/modules/user/userStore.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/debugbar/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import './bootstrap.css'; 2 | @import './app.css'; -------------------------------------------------------------------------------- /public/img/invextry-ss1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/public/img/invextry-ss1.png -------------------------------------------------------------------------------- /public/img/invextry-ss2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/public/img/invextry-ss2.png -------------------------------------------------------------------------------- /public/img/invextry-ss3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/public/img/invextry-ss3.png -------------------------------------------------------------------------------- /public/img/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/public/img/placeholder.png -------------------------------------------------------------------------------- /storage/demo/brands/hp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/hp.jpg -------------------------------------------------------------------------------- /storage/demo/brands/mi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/mi.jpg -------------------------------------------------------------------------------- /storage/demo/brands/rfl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/rfl.jpg -------------------------------------------------------------------------------- /storage/demo/brands/ssg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/ssg.png -------------------------------------------------------------------------------- /public/img/invextry-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/public/img/invextry-logo.png -------------------------------------------------------------------------------- /storage/demo/brands/arong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/arong.jpg -------------------------------------------------------------------------------- /storage/demo/brands/asus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/asus.jpg -------------------------------------------------------------------------------- /storage/demo/brands/bata.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/bata.jpg -------------------------------------------------------------------------------- /storage/demo/brands/casio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/casio.jpg -------------------------------------------------------------------------------- /storage/demo/brands/dano.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/dano.jpg -------------------------------------------------------------------------------- /storage/demo/brands/dell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/dell.jpg -------------------------------------------------------------------------------- /storage/demo/brands/eset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/eset.jpg -------------------------------------------------------------------------------- /storage/demo/brands/fresh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/fresh.jpg -------------------------------------------------------------------------------- /storage/demo/brands/lotto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/lotto.jpg -------------------------------------------------------------------------------- /storage/demo/brands/nido.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/nido.jpg -------------------------------------------------------------------------------- /storage/demo/brands/panda.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/panda.jpg -------------------------------------------------------------------------------- /storage/demo/brands/pran.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/pran.jpg -------------------------------------------------------------------------------- /storage/demo/brands/regal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/regal.jpg -------------------------------------------------------------------------------- /storage/demo/brands/titan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/titan.jpg -------------------------------------------------------------------------------- /storage/demo/brands/yamah.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/yamah.jpg -------------------------------------------------------------------------------- /public/img/invextry-social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/public/img/invextry-social.png -------------------------------------------------------------------------------- /storage/demo/brands/oriant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/oriant.jpg -------------------------------------------------------------------------------- /storage/demo/brands/philip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/philip.jpg -------------------------------------------------------------------------------- /storage/demo/brands/samsung.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/samsung.png -------------------------------------------------------------------------------- /storage/demo/brands/vision.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/vision.jpg -------------------------------------------------------------------------------- /storage/demo/brands/walton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/walton.jpg -------------------------------------------------------------------------------- /storage/demo/products/Jeans.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/Jeans.jpg -------------------------------------------------------------------------------- /storage/demo/products/dates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/dates.jpg -------------------------------------------------------------------------------- /storage/demo/products/fanta.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/fanta.jpg -------------------------------------------------------------------------------- /storage/demo/products/iphone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/iphone.jpg -------------------------------------------------------------------------------- /storage/demo/products/kitkat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/kitkat.jpg -------------------------------------------------------------------------------- /storage/demo/products/mango.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/mango.webp -------------------------------------------------------------------------------- /storage/demo/products/mi-tv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/mi-tv.jpg -------------------------------------------------------------------------------- /storage/demo/products/mojo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/mojo.webp -------------------------------------------------------------------------------- /storage/demo/products/oreo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/oreo.jpg -------------------------------------------------------------------------------- /storage/demo/products/pepsi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/pepsi.jpg -------------------------------------------------------------------------------- /storage/demo/products/pepsi.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/pepsi.webp -------------------------------------------------------------------------------- /storage/demo/products/polo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/polo.png -------------------------------------------------------------------------------- /storage/demo/products/sauce.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/sauce.webp -------------------------------------------------------------------------------- /storage/demo/products/shirt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/shirt.jpg -------------------------------------------------------------------------------- /storage/demo/products/toy.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/toy.webp -------------------------------------------------------------------------------- /storage/demo/brands/pepsodent.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/brands/pepsodent.jpg -------------------------------------------------------------------------------- /storage/demo/products/chicken.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/chicken.webp -------------------------------------------------------------------------------- /storage/demo/products/coconut.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/coconut.webp -------------------------------------------------------------------------------- /storage/demo/products/dettol.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/dettol.webp -------------------------------------------------------------------------------- /storage/demo/products/hand-beg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/hand-beg.jpg -------------------------------------------------------------------------------- /storage/demo/products/heater.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/heater.webp -------------------------------------------------------------------------------- /storage/demo/products/hilsha.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/hilsha.webp -------------------------------------------------------------------------------- /storage/demo/products/noodles.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/noodles.webp -------------------------------------------------------------------------------- /storage/demo/products/sony-tv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/sony-tv.jpg -------------------------------------------------------------------------------- /resources/admin-resources/views/App.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /storage/demo/products/asus-laptop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/asus-laptop.jpg -------------------------------------------------------------------------------- /storage/demo/products/casual-shoe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/casual-shoe.jpg -------------------------------------------------------------------------------- /storage/demo/products/cloth-beg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/cloth-beg.jpg -------------------------------------------------------------------------------- /storage/demo/products/dairy-milk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/dairy-milk.jpg -------------------------------------------------------------------------------- /storage/demo/products/handwash.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/handwash.webp -------------------------------------------------------------------------------- /storage/demo/products/loafer-shoe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/loafer-shoe.jpg -------------------------------------------------------------------------------- /storage/demo/products/rupchanda.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/rupchanda.webp -------------------------------------------------------------------------------- /storage/demo/products/vision-tv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/vision-tv.jpg -------------------------------------------------------------------------------- /storage/demo/products/vivo-phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/vivo-phone.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/beg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/beg.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/oil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/oil.png -------------------------------------------------------------------------------- /storage/demo/product-categories/toy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/toy.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/tv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/tv.jpg -------------------------------------------------------------------------------- /storage/demo/products/apex-slipper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/apex-slipper.jpg -------------------------------------------------------------------------------- /storage/demo/products/cc-tv-camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/cc-tv-camera.jpg -------------------------------------------------------------------------------- /storage/demo/products/infinix-phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/infinix-phone.jpg -------------------------------------------------------------------------------- /storage/demo/products/leather-shoe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/leather-shoe.jpg -------------------------------------------------------------------------------- /storage/demo/products/nikkon-camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/nikkon-camera.jpg -------------------------------------------------------------------------------- /storage/demo/products/sneakers-shoe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/sneakers-shoe.jpg -------------------------------------------------------------------------------- /storage/demo/products/sports-camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/sports-camera.jpg -------------------------------------------------------------------------------- /storage/demo/products/step-out-beg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/step-out-beg.png -------------------------------------------------------------------------------- /storage/demo/product-categories/camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/camera.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/drinks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/drinks.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/glass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/glass.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/laptop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/laptop.png -------------------------------------------------------------------------------- /storage/demo/product-categories/shoe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/shoe.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/tablet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/tablet.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/watch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/watch.jpg -------------------------------------------------------------------------------- /storage/demo/products/macbook-laptop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/macbook-laptop.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/fruits.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/fruits.webp -------------------------------------------------------------------------------- /storage/demo/product-categories/t-shirt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/t-shirt.jpg -------------------------------------------------------------------------------- /storage/demo/products/bangladesh-jersey.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/products/bangladesh-jersey.webp -------------------------------------------------------------------------------- /storage/demo/product-categories/chocolate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/chocolate.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/furniture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/furniture.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/headphone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/headphone.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/milk-powder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/milk-powder.jpg -------------------------------------------------------------------------------- /storage/demo/product-categories/smart-phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/storage/demo/product-categories/smart-phone.jpg -------------------------------------------------------------------------------- /resources/admin-resources/assets/img/invextry-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efthakhar/invextry/HEAD/resources/admin-resources/assets/img/invextry-logo.png -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | compiled.php 2 | config.php 3 | down 4 | events.scanned.php 5 | maintenance.php 6 | routes.php 7 | routes.scanned.php 8 | schedule-* 9 | services.json 10 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 7 | return $request->user(); 8 | }); 9 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | { 3 | erros[key] = erros[key].toString(); 4 | }); 5 | 6 | return erros; 7 | } 8 | -------------------------------------------------------------------------------- /app/Models/Invoice/InvoiceItem.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Models/Setting/Tax.php: -------------------------------------------------------------------------------- 1 | 2 | import PlusSvg from "../../assets/icons/plus-svg-icon.vue"; 3 | 4 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/media 5 | /public/uploads 6 | /public/hot 7 | /public/storage 8 | /storage/*.key 9 | /vendor 10 | .env 11 | .env.backup 12 | .env.production 13 | .phpunit.result.cache 14 | Homestead.json 15 | Homestead.yaml 16 | auth.json 17 | npm-debug.log 18 | yarn-error.log 19 | /.fleet 20 | /.idea 21 | /.vscode -------------------------------------------------------------------------------- /resources/admin-resources/components/buttons/FilterButton.vue: -------------------------------------------------------------------------------- 1 | 4 | 10 | -------------------------------------------------------------------------------- /resources/admin-resources/components/buttons/BulkDeleteButton.vue: -------------------------------------------------------------------------------- 1 | 4 | 10 | -------------------------------------------------------------------------------- /app/Models/Setting/Currency.php: -------------------------------------------------------------------------------- 1 | Customers/Suppliers/Users -- users_meta_table 12 | 10. Purchases 13 | 11. Sales 14 | 12. Payment methods 15 | 13. Payment 16 | 14. POS SYSTEM 17 | 15. Account 18 | 16. Deposit 19 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | Create migration file 5 | 6 | > Create Model file 7 | 8 | > Create Seeder file and define permissions 9 | 10 | > Create Requests file 11 | 12 | > Create Resource and Collections file 13 | 14 | > Create necessary routes and controllers methods 15 | 16 | > Create pinia store file 17 | 18 | > Create vuejs others files 19 | -------------------------------------------------------------------------------- /app/Models/Product/Brand.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Resources/Tax/TaxCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /resources/admin-resources/stores/sidebar.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | 3 | export const useSidebar = defineStore("sidebar", { 4 | state: () => ({ 5 | open: true, 6 | }), 7 | 8 | getters: { 9 | getSidebarStatus: (state) => state.open, 10 | }, 11 | 12 | actions: { 13 | toggle() { 14 | this.open = !this.open; 15 | }, 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /app/Http/Resources/Unit/UnitCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Models/Product/ProductCategory.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /database/seeders/CreateApp.php: -------------------------------------------------------------------------------- 1 | call([ 16 | RolePermissionSeeder::class, 17 | SuperAdminSeeder::class, 18 | ]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Models/Party.php: -------------------------------------------------------------------------------- 1 | 0, 14 | 'sale_return_due' => 0, 15 | 'purchase_due' => 0, 16 | 'purchase_return_due' => 0, 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /app/Models/Product/Unit.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Resources/Party/SupplierListCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Resources/Product/ProductListCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Resources/Warehouse/WarehouseCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Resources/Product/ProductCategoryCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection, 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /resources/admin-resources/utils/file.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | export default async function deleteUploadedFile(fileIDs) { 4 | return new Promise((resolve, reject) => { 5 | axios 6 | .delete(`/api/upload/${fileIDs}`) 7 | .then((response) => { 8 | resolve(fileIDs); 9 | }) 10 | .catch((error) => { 11 | reject(error); 12 | }); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import laravel from "laravel-vite-plugin"; 3 | import vue from "@vitejs/plugin-vue"; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | vue(), 8 | laravel({ 9 | input: [ 10 | // invextry backend admin assets 11 | "resources/admin-resources/main.js", 12 | ], 13 | refresh: true, 14 | }), 15 | ], 16 | }); 17 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 16 | 17 | $response->assertStatus(200); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Http/Resources/Tax/TaxResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'name' => $this->name, 16 | 'rate' => $this->rate, 17 | ]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Invextry 9 | 10 | 11 |
12 | @vite('resources/admin-resources/main.js') 13 | 14 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventRequestsDuringMaintenance.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Models/Accounting/Account.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'current_password', 16 | 'password', 17 | 'password_confirmation', 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /resources/admin-resources/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import { createPinia } from "pinia"; 3 | import "./plugins/axios-settings.js"; 4 | import router from "./router"; 5 | import "./assets/css/main.css"; 6 | 7 | import App from "./views/App.vue"; 8 | 9 | const app = createApp(App); 10 | const store = createPinia(); 11 | 12 | app.use(store); 13 | app.use(router); 14 | 15 | app.config.globalProperties.$demoIMG = '/img/placeholder.png' 16 | 17 | app.mount("#invextry-admin"); 18 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 18 | 19 | return $app; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustHosts.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function hosts(): array 15 | { 16 | return [ 17 | $this->allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | expectsJson() ? null : route('login'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/menu-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /app/Models/Accounting/AccountAdjustment.php: -------------------------------------------------------------------------------- 1 | belongsTo(Account::class, 'account_id'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/filter-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /app/Http/Resources/Currency/CurrencyCollection.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function toArray(Request $request): array 16 | { 17 | return [ 18 | 'data' => $this->collection, 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Resources/Warehouse/WarehouseResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'name' => $this->name, 16 | 'email' => $this->email, 17 | 'phone' => $this->phone, 18 | 'address' => $this->address, 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/ValidateSignature.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 'fbclid', 16 | // 'utm_campaign', 17 | // 'utm_content', 18 | // 'utm_medium', 19 | // 'utm_source', 20 | // 'utm_term', 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /resources/admin-resources/components/img/ImagesBox.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | 18 | 28 | -------------------------------------------------------------------------------- /app/Http/Requests/Tax/CreateTaxRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('taxes')], 20 | 'rate' => ['required', 'numeric'], 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "type": "module", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build" 7 | }, 8 | "devDependencies": { 9 | "axios": "^1.4.0", 10 | "laravel-vite-plugin": "^0.7.5", 11 | "vite": "^4.0.0" 12 | }, 13 | "dependencies": { 14 | "@vitejs/plugin-vue": "^4.2.3", 15 | "apexcharts": "^3.41.1", 16 | "pinia": "^2.1.4", 17 | "vue": "^3.2.36", 18 | "vue-apexcharts": "^1.6.2", 19 | "vue-loader": "^17.0.1", 20 | "vue-router": "^4.2.4", 21 | "vue3-apexcharts": "^1.4.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /app/Http/Resources/Unit/UnitResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'name' => $this->name, 16 | 'short_name' => $this->short_name, 17 | 'base_unit_id' => $this->base_unit_id, 18 | 'operator' => $this->operator, 19 | 'operation_value' => $this->operation_value, 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Currency/CreateCurrencyRequest.php: -------------------------------------------------------------------------------- 1 | 'required|max:30|unique:currencies', 19 | 'code' => 'required|max:10|unique:currencies', 20 | 'symbol' => 'required|max:5', 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Resources/Currency/CurrencyResource.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function toArray(Request $request): array 16 | { 17 | 18 | return [ 19 | 'id' => $this->id, 20 | 'name' => $this->name, 21 | 'code' => $this->code, 22 | 'symbol' => $this->symbol, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected $policies = [ 16 | // 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | */ 22 | public function boot(): void 23 | { 24 | // 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/square-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/ViewOnly.php: -------------------------------------------------------------------------------- 1 | method(); 14 | 15 | if ($http_method == 'POST' || $http_method == 'PUT' || $http_method == 'DELETE') { 16 | return response()->json([ 17 | 'message' => 'no permision to create, update and delete', 18 | ], 403); 19 | } 20 | 21 | return $next($request); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Resources/Accounting/AdjustmentResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 14 | 'account_id' => $this->account_id, 15 | 'account' => $this->account, 16 | 'amount' => $this->amount, 17 | 'type' => $this->type, 18 | 'date' => $this->date, 19 | 'note' => $this->note, 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/booklet-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/box-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /app/Http/Resources/Party/CustomerListResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'name' => $this->name, 16 | 'phone' => $this->phone, 17 | 'email' => $this->email, 18 | 'status' => $this->status, 19 | 'sale_due' => $this->sale_due, 20 | 'sale_return_due' => $this->sale_return_due, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /database/migrations/2023_07_1_141608_create_invextry_meta_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->string('meta_key'); 14 | $table->text('meta_value'); 15 | $table->timestamps(); 16 | }); 17 | } 18 | 19 | public function down(): void 20 | { 21 | Schema::dropIfExists('invextry_meta'); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 16 | } 17 | 18 | /** 19 | * Register the commands for the application. 20 | */ 21 | protected function commands(): void 22 | { 23 | $this->load(__DIR__.'/Commands'); 24 | 25 | require base_path('routes/console.php'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Requests/Tax/UpdateTaxRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 22 | 23 | return [ 24 | 'name' => ['required', 'string', Rule::unique('taxes')->ignore($tax_id)], 25 | 'rate' => ['required', 'numeric'], 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Resources/Party/SupplierListResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'name' => $this->name, 16 | 'phone' => $this->phone, 17 | 'email' => $this->email, 18 | 'status' => $this->status, 19 | 'purchase_due' => $this->purchase_due, 20 | 'purchase_return_due' => $this->purchase_return_due, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /database/seeders/TaxSeeder.php: -------------------------------------------------------------------------------- 1 | 1, 'name' => '1%vat', 'rate' => '1'], 12 | ['id' => 2, 'name' => '2.55%tax', 'rate' => '2.55'], 13 | ['id' => 3, 'name' => '14.5%localTax', 'rate' => '14.5'], 14 | ['id' => 4, 'name' => 'vat@5%', 'rate' => '5'], 15 | ['id' => 5, 'name' => '4% transit tax', 'rate' => '4.00'], 16 | ]; 17 | 18 | public function run(): void 19 | { 20 | foreach ($this->taxes as $tax) { 21 | Tax::create($tax); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Resources/Accounting/AccountResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 14 | 'name' => $this->name, 15 | 'bank_name' => $this->bank_name, 16 | 'branch_name' => $this->branch_name, 17 | 'account_number' => $this->account_number, 18 | 'balance' => $this->balance, 19 | 'details' => $this->details, 20 | 'status' => $this->status, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventXSS.php: -------------------------------------------------------------------------------- 1 | all(); 19 | 20 | array_walk_recursive($input, function (&$input) { 21 | $input = strip_tags($input); 22 | }); 23 | $request->merge($input); 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/cross-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /database/seeders/WarehouseSeeder.php: -------------------------------------------------------------------------------- 1 | 1, 'name' => 'warehouse 1', 'email' => 'warehouse1@invextry.com', 'phone' => '01900000000', 'address' => 'Road no 10, sector 5, F block'], 12 | ['id' => 2, 'name' => 'warehouse 2', 'email' => 'warehouse2@invextry.com', 'phone' => '01800000000', 'address' => 'Road no 40, sector 10, K block'], 13 | ]; 14 | 15 | public function run(): void 16 | { 17 | foreach ($this->warehouses as $warehouse) { 18 | Warehouse::create($warehouse); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/bin-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /app/Services/AccountAdjustmentService.php: -------------------------------------------------------------------------------- 1 | increment('balance', $adjustment['amount']); 22 | } elseif ($adjustment['type'] == 'subtract') { 23 | $account->decrement('balance', $adjustment['amount']); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2023_08_05_182000_create_payment_methods_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name', 100)->unique(); 17 | $table->timestamps(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down(): void 25 | { 26 | Schema::dropIfExists('payment_methods'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected $dontFlash = [ 16 | 'current_password', 17 | 'password', 18 | 'password_confirmation', 19 | ]; 20 | 21 | /** 22 | * Register the exception handling callbacks for the application. 23 | */ 24 | public function register(): void 25 | { 26 | $this->reportable(function (Throwable $e) { 27 | // 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | |string|null 14 | */ 15 | protected $proxies; 16 | 17 | /** 18 | * The headers that should be used to detect proxies. 19 | * 20 | * @var int 21 | */ 22 | protected $headers = 23 | Request::HEADER_X_FORWARDED_FOR | 24 | Request::HEADER_X_FORWARDED_HOST | 25 | Request::HEADER_X_FORWARDED_PORT | 26 | Request::HEADER_X_FORWARDED_PROTO | 27 | Request::HEADER_X_FORWARDED_AWS_ELB; 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2023_07_28_152756_create_brands_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name')->unique(); 17 | $table->string('slug')->unique(); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | */ 25 | public function down(): void 26 | { 27 | Schema::dropIfExists('brands'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/qrcode-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /resources/admin-resources/components/shared/notification/notificationStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | 3 | export const useNotificationStore = defineStore("notification", { 4 | state: () => ({ 5 | notifications: [], 6 | }), 7 | 8 | getters: { 9 | getNotifications: (state) => state.notifications, 10 | }, 11 | 12 | actions: { 13 | async pushNotification(data) { 14 | data.id = data.id || Date.now() + Math.random(1, 9); 15 | data.time = data.time || 3000; 16 | this.notifications.push(data); 17 | }, 18 | 19 | async hideNotification(data) { 20 | let index = this.notifications.indexOf(data); 21 | this.notifications.splice(index, 1); 22 | }, 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /app/Http/Resources/Brand/BrandResource.php: -------------------------------------------------------------------------------- 1 | media) { 16 | foreach ($this->media as $m) { 17 | $logo[] = [ 18 | 'id' => $m->id, 19 | 'url' => $m->getUrl(), 20 | ]; 21 | } 22 | } 23 | 24 | return [ 25 | 'id' => $this->id, 26 | 'name' => $this->name, 27 | 'slug' => $this->slug, 28 | 'logo' => $logo, 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2023_07_26_124157_create_taxes_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name')->unique(); 17 | $table->unsignedDouble('rate', 6, 3); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | */ 25 | public function down(): void 26 | { 27 | Schema::dropIfExists('taxes'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /app/Http/Requests/Warehouse/CreateWarehouseRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('warehouses')], 20 | 'email' => ['required', 'email', Rule::unique('warehouses')], 21 | 'phone' => ['required', 'string', Rule::unique('warehouses')], 22 | 'address' => ['nullable', 'string'], 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/edit-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Currency/UpdateCurrencyRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 'name' => ['required', 'max:30', Rule::unique('currencies')->ignore($currency_id)], 22 | 'code' => ['required', 'max:10', Rule::unique('currencies')->ignore($currency_id)], 23 | 'symbol' => ['required', 'max:5'], 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/plus-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php: -------------------------------------------------------------------------------- 1 | string('email')->primary(); 16 | $table->string('token'); 17 | $table->timestamp('created_at')->nullable(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down(): void 25 | { 26 | Schema::dropIfExists('password_reset_tokens'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/wallet-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Brand/CreateBrandRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('brands')], 21 | 'slug' => ['required', 'string', Rule::unique('brands')], 22 | ]; 23 | } 24 | 25 | protected function prepareForValidation(): void 26 | { 27 | $this->merge([ 28 | 'slug' => str()->slug($this->slug), 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2023_07_31_124517_create_product_categories_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name')->unique(); 17 | $table->string('slug')->unique(); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | */ 25 | public function down(): void 26 | { 27 | Schema::dropIfExists('product_categories'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/logout-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/more-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | -------------------------------------------------------------------------------- /database/migrations/2023_07_19_141527_create_currencies_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name', 50)->unique(); 17 | $table->string('code', 10)->unique(); 18 | $table->string('symbol', 10); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down(): void 27 | { 28 | Schema::dropIfExists('currencies'); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /app/Http/Resources/Product/ProductCategoryResource.php: -------------------------------------------------------------------------------- 1 | getMedia('thumbnail')) { 16 | foreach ($this->getMedia('thumbnail') as $m) { 17 | $thumbnail[] = [ 18 | 'id' => $m->id, 19 | 'url' => $m->getUrl(), 20 | ]; 21 | } 22 | } 23 | 24 | return [ 25 | 'id' => $this->id, 26 | 'name' => $this->name, 27 | 'slug' => $this->slug, 28 | 'thumbnail' => $thumbnail, 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2023_08_05_136533_create_account_adjustments_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->unsignedBigInteger('account_id'); 14 | $table->unsignedDouble('amount', 20, 4); 15 | $table->string('type', 20); // add/remove 16 | $table->date('date'); 17 | $table->text('note')->nullable(); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | public function down(): void 23 | { 24 | Schema::dropIfExists('account_adjustments'); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /app/Http/Requests/Product/CreateProductCategoryRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('product_categories')], 21 | 'slug' => ['required', 'string', Rule::unique('product_categories')], 22 | ]; 23 | } 24 | 25 | protected function prepareForValidation(): void 26 | { 27 | $this->merge([ 28 | 'slug' => str()->slug($this->slug), 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2023_07_26_182430_create_warehouses_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name')->unique(); 17 | $table->string('email')->unique(); 18 | $table->string('phone')->unique(); 19 | $table->text('address')->nullable(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down(): void 28 | { 29 | Schema::dropIfExists('warehouses'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 24 | return redirect(RouteServiceProvider::HOME); 25 | } 26 | } 27 | 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/customer-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/supplier-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Unit/CreateUnitRequest.php: -------------------------------------------------------------------------------- 1 | 'required|max:30|unique:units', 21 | 'short_name' => 'required|max:10|unique:units', 22 | 'base_unit_id' => ['nullable', 'numeric', 'required_with_all:operator,operation_value'], 23 | 'operator' => ['nullable', Rule::in(['divide', 'multiply']), 'required_with:base_unit_id'], 24 | 'operation_value' => ['nullable', 'numeric', 'required_with:base_unit_id'], 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Requests/Warehouse/UpdateWarehouseRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 'name' => ['required', 'string', Rule::unique('warehouses')->ignore($warehouse_id)], 22 | 'email' => ['required', 'email', Rule::unique('warehouses')->ignore($warehouse_id)], 23 | 'phone' => ['required', 'string', Rule::unique('warehouses')->ignore($warehouse_id)], 24 | 'address' => ['nullable', 'string'], 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/User/UserController.php: -------------------------------------------------------------------------------- 1 | getRoleNames(); 16 | $permissions = $user->getAllPermissions(); 17 | 18 | return response()->json([ 19 | 'id' => $user_id, 20 | 'user' => [ 21 | 'id' => $user->id, 22 | 'name' => $user->name, 23 | 'user_name' => $user->user_name, 24 | 'email' => $user->email, 25 | ], 26 | 'roles' => $roles, 27 | 'permissions' => $permissions->pluck('name'), 28 | ]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/Accounting/CreateAdjustmentRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 20 | 'amount' => ['numeric', 'required'], 21 | 'type' => ['required', 'in:add,subtract'], 22 | 'date' => ['required', 'date'], 23 | 'note' => ['nullable', 'string'], 24 | ]; 25 | } 26 | 27 | public function messages() 28 | { 29 | return [ 30 | 'account_id.required' => 'The Account field is required', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Accounting/UpdateAdjustmentRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 20 | 'amount' => ['numeric', 'required'], 21 | 'type' => ['required', 'in:add,subtract'], 22 | 'date' => ['required', 'date'], 23 | 'note' => ['nullable', 'string'], 24 | ]; 25 | } 26 | 27 | public function messages() 28 | { 29 | return [ 30 | 'account_id.required' => 'The Account field is required', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Brand/UpdateBrandRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 22 | 23 | return [ 24 | 'name' => ['required', 'string', Rule::unique('brands')->ignore($brand_id)], 25 | 'slug' => ['required', 'string', Rule::unique('brands')->ignore($brand_id)], 26 | ]; 27 | } 28 | 29 | protected function prepareForValidation(): void 30 | { 31 | $this->merge([ 32 | 'slug' => str()->slug($this->slug), 33 | ]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Models/Payment.php: -------------------------------------------------------------------------------- 1 | belongsTo(Invoice::class, 'invoice_id'); 28 | } 29 | 30 | public function party() 31 | { 32 | return $this->belongsTo(Party::class, 'party_id'); 33 | } 34 | 35 | public function account() 36 | { 37 | return $this->belongsTo(Account::class, 'account_id'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Requests/Accounting/CreateAccountRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('accounts')], 21 | 'bank_name' => ['string', 'required_with:branch_name'], 22 | 'branch_name' => ['string', 'nullable'], 23 | 'account_number' => ['required', 'string'], 24 | 'balance' => ['numeric'], 25 | 'details' => ['nullable', 'string'], 26 | 'status' => ['required', 'in:active,disabled'], 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/admin-resources/stores/authStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | import { ref } from "vue"; 3 | import axios from "axios"; 4 | 5 | export const useAuthStore = defineStore("auth", { 6 | state: () => ({ 7 | fetched: false, 8 | user: {}, 9 | role: {}, 10 | permissions: [], 11 | }), 12 | 13 | getters: {}, 14 | 15 | actions: { 16 | async getAuthUser() { 17 | await axios 18 | .get(`/api/users/authenticated-user`) 19 | .then((response) => { 20 | this.user = response.data.user; 21 | this.role = response.data.role; 22 | this.permissions = response.data.permissions; 23 | }) 24 | .catch((errors) => {}); 25 | }, 26 | 27 | userCan(ability) { 28 | return this.permissions.includes(ability); 29 | }, 30 | }, 31 | }); 32 | -------------------------------------------------------------------------------- /database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('uuid')->unique(); 17 | $table->text('connection'); 18 | $table->text('queue'); 19 | $table->longText('payload'); 20 | $table->longText('exception'); 21 | $table->timestamp('failed_at')->useCurrent(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('failed_jobs'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2023_08_05_136435_create_accounts_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->string('name'); 14 | $table->string('bank_name')->nullable(); 15 | $table->string('branch_name')->nullable(); 16 | $table->string('account_number'); 17 | $table->unsignedDouble('balance', 20, 4)->nullable(); 18 | $table->text('details')->nullable(); 19 | $table->string('status', 20); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | public function down(): void 25 | { 26 | Schema::dropIfExists('accounts'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /app/Http/Requests/Accounting/UpdateAccountRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 'name' => ['required', 'string', Rule::unique('accounts')->ignore($account_id)], 22 | 'bank_name' => ['string', 'required_with:branch_name'], 23 | 'branch_name' => ['string', 'nullable'], 24 | 'account_number' => ['required', 'string'], 25 | 'details' => ['nullable', 'string'], 26 | 'status' => ['required', 'in:active,disabled'], 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/admin-resources/components/shared/notification/notications-container.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 22 | 23 | 31 | -------------------------------------------------------------------------------- /app/Models/Invoice/Invoice.php: -------------------------------------------------------------------------------- 1 | hasMany(InvoiceItem::class); 19 | } 20 | 21 | public function payments() 22 | { 23 | return $this->hasMany(Payment::class); 24 | } 25 | 26 | public function party() 27 | { 28 | return $this->belongsTo(Party::class, 'party_id'); 29 | } 30 | 31 | public function warehouse() 32 | { 33 | return $this->belongsTo(Warehouse::class, 'warehouse_id'); 34 | } 35 | 36 | public function creator() 37 | { 38 | return $this->belongsTo(User::class, 'created_by'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*', 'sanctum/csrf-cookie'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name'); 17 | $table->string('user_name')->nullable(); 18 | $table->string('email')->unique(); 19 | $table->timestamp('email_verified_at')->nullable(); 20 | $table->string('password'); 21 | $table->rememberToken(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | */ 29 | public function down(): void 30 | { 31 | Schema::dropIfExists('users'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Product/UpdateProductCategoryRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 22 | 23 | return [ 24 | 'name' => ['required', 'string', Rule::unique('product_categories')->ignore($product_cat_id)], 25 | 'slug' => ['required', 'string', Rule::unique('product_categories')->ignore($product_cat_id)], 26 | ]; 27 | } 28 | 29 | protected function prepareForValidation(): void 30 | { 31 | $this->merge([ 32 | 'slug' => str()->slug($this->slug), 33 | ]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2023_07_23_134907_create_units_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name', 30)->unique(); 17 | $table->string('short_name', 10)->unique(); 18 | $table->unsignedBigInteger('base_unit_id')->nullable(); 19 | $table->string('operator', 15)->nullable(); // multiply or divide 20 | $table->unsignedDouble('operation_value')->nullable(); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('units'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/seeders/SuperAdminSeeder.php: -------------------------------------------------------------------------------- 1 | 'super admin', 17 | 'user_name' => 'superadmin', 18 | 'email' => 'superadmin@invextry.com', 19 | 'password' => Hash::make('**invextry**'), 20 | ]); 21 | 22 | // assing this super admin to super-admin role 23 | $super_admin_user->assignRole('super-admin'); 24 | 25 | // make super admin logged in 26 | Auth::attempt([ 27 | 'email' => 'superadmin@invextry.com', 28 | 'password' => '**invextry**', 29 | ], 100); 30 | } 31 | } 32 | 33 | // email: superadmin@invextry.com 34 | // password: **invextry** 35 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/sort-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | -------------------------------------------------------------------------------- /app/Http/Requests/Unit/UpdateUnitRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 'name' => ['required', 'max:30', Rule::unique('units')->ignore($unit_id)], 22 | 'short_name' => ['required', 'max:10', Rule::unique('units')->ignore($unit_id)], 23 | 'base_unit_id' => ['nullable', 'numeric', 'required_with_all:operator,operation_value'], 24 | 'operator' => ['nullable', Rule::in(['divide', 'multiply']), 'required_with:base_unit_id'], 25 | 'operation_value' => ['nullable', 'numeric', 'required_with:base_unit_id'], 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Providers/EventServiceProvider.php: -------------------------------------------------------------------------------- 1 | > 15 | */ 16 | protected $listen = [ 17 | Registered::class => [ 18 | SendEmailVerificationNotification::class, 19 | ], 20 | ]; 21 | 22 | /** 23 | * Register any events for your application. 24 | */ 25 | public function boot(): void 26 | { 27 | // 28 | } 29 | 30 | /** 31 | * Determine if events and listeners should be automatically discovered. 32 | */ 33 | public function shouldDiscoverEvents(): bool 34 | { 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Http/Resources/Party/CustomerDetailsRerource.php: -------------------------------------------------------------------------------- 1 | $this->id, 14 | 'name' => $this->name, 15 | 'status' => $this->status, 16 | 'phone' => $this->phone, 17 | 'email' => $this->email, 18 | 'address' => $this->address, 19 | 'billing_address' => $this->billing_address, 20 | 'shipping_address' => $this->shipping_address, 21 | 'tax_number' => $this->tax_number, 22 | 'country' => $this->country, 23 | 'city' => $this->city, 24 | 'postal_code' => $this->postal_code, 25 | 'sale_due' => $this->sale_due, 26 | 'sale_return_due' => $this->sale_return_due, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Resources/Party/SupplierDetailsRerource.php: -------------------------------------------------------------------------------- 1 | $this->id, 14 | 'status' => $this->status, 15 | 'name' => $this->name, 16 | 'phone' => $this->phone, 17 | 'email' => $this->email, 18 | 'address' => $this->address, 19 | 'billing_address' => $this->billing_address, 20 | 'shipping_address' => $this->shipping_address, 21 | 'tax_number' => $this->tax_number, 22 | 'country' => $this->country, 23 | 'city' => $this->city, 24 | 'postal_code' => $this->postal_code, 25 | 'purchase_due' => $this->purchase_due, 26 | 'purchase_return_due' => $this->purchase_return_due, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Resources/Invoice/SaleListResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'invoice_ref' => $this->invoice_ref, 16 | 'invoice_date' => $this->invoice_date, 17 | 'biller' => $this->creator->name, 18 | 'customer' => $this->party->name, 19 | 'warehouse' => $this->warehouse->name, 20 | 'paid_amount' => $this->paid_amount, 21 | 'due_amount' => $this->due_amount, 22 | 'returned_amount' => $this->returned_amount, 23 | 'total_amount' => $this->total_amount, 24 | 'shipping_cost' => $this->shipping_cost, 25 | 'invoice_status' => $this->invoice_status, 26 | 'payment_status' => $this->payment_status, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->morphs('tokenable'); 17 | $table->string('name'); 18 | $table->string('token', 64)->unique(); 19 | $table->text('abilities')->nullable(); 20 | $table->timestamp('last_used_at')->nullable(); 21 | $table->timestamp('expires_at')->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | */ 29 | public function down(): void 30 | { 31 | Schema::dropIfExists('personal_access_tokens'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /app/Http/Resources/Invoice/PurchaseListResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 15 | 'invoice_ref' => $this->invoice_ref, 16 | 'invoice_date' => $this->invoice_date, 17 | 'biller' => $this->creator->name, 18 | 'supplier' => $this->party->name, 19 | 'warehouse' => $this->warehouse->name, 20 | 'paid_amount' => $this->paid_amount, 21 | 'due_amount' => $this->due_amount, 22 | 'returned_amount' => $this->returned_amount, 23 | 'total_amount' => $this->total_amount, 24 | 'shipping_cost' => $this->shipping_cost, 25 | 'invoice_status' => $this->invoice_status, 26 | 'payment_status' => $this->payment_status, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/Payment/PaymentController.php: -------------------------------------------------------------------------------- 1 | paymentService = new PaymentService(); 18 | } 19 | 20 | public function store(CreatePaymentRequest $request) 21 | { 22 | try { 23 | 24 | $this->paymentService->createPayment($request->validated()); 25 | 26 | } catch (Exception $e) { 27 | 28 | return response()->json([ 29 | 'status' => 'error', 30 | 'message' => 'failed to create payment'.$e, 31 | ], 500); 32 | } 33 | 34 | return response()->json([ 35 | 'status' => 'success', 36 | 'message' => 'payment created succesfully', 37 | ], 201); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/beg-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/cart-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | 'scheme' => 'https', 22 | ], 23 | 24 | 'postmark' => [ 25 | 'token' => env('POSTMARK_TOKEN'), 26 | ], 27 | 28 | 'ses' => [ 29 | 'key' => env('AWS_ACCESS_KEY_ID'), 30 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 31 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 32 | ], 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class UserFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => fake()->name(), 22 | 'email' => fake()->unique()->safeEmail(), 23 | 'email_verified_at' => now(), 24 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 25 | 'remember_token' => Str::random(10), 26 | ]; 27 | } 28 | 29 | /** 30 | * Indicate that the model's email address should be unverified. 31 | */ 32 | public function unverified(): static 33 | { 34 | return $this->state(fn (array $attributes) => [ 35 | 'email_verified_at' => null, 36 | ]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2023_08_02_155740_create_product_stocks_table.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('product_id'); 17 | $table->unsignedBigInteger('warehouse_id'); 18 | $table->unsignedDouble('stock_quantity', 20, 4)->nullable(); 19 | 20 | $table->foreign('product_id')->references('id')->on('products') 21 | ->cascadeOnUpdate()->restrictOnDelete(); 22 | $table->foreign('warehouse_id')->references('id')->on('warehouses') 23 | ->cascadeOnUpdate()->restrictOnDelete(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | */ 30 | public function down(): void 31 | { 32 | Schema::dropIfExists('product_stocks'); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /resources/admin-resources/plugins/axios-settings.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { useNotificationStore } from "../components/shared/notification/notificationStore"; 3 | 4 | // Add a request interceptor 5 | // axios.interceptors.request.use( 6 | // function (config) 7 | // { 8 | 9 | // //console.log(config.headers); 10 | 11 | // if(config.method == "post"||config.method == "put"||config.method == "delete"){ 12 | // const notifcationStore = useNotificationStore() 13 | // notifcationStore.pushNotification({ 14 | // 'message':"Demo version doesn't allow to do this", 15 | // 'type' :'error', 16 | // 'time':3000 17 | // }) 18 | // throw new axios.Cancel('Operation canceled by the user.'); 19 | // } 20 | 21 | // return config; 22 | // }, 23 | // function (error) { 24 | // return Promise.reject(error); 25 | // } 26 | // ); 27 | 28 | // 29 | axios.defaults.headers.common = { 30 | "X-Requested-With": "XMLHttpRequest", 31 | "X-CSRF-TOKEN": document 32 | .querySelector('meta[name="csrf-token"]') 33 | .getAttribute("content"), 34 | }; 35 | -------------------------------------------------------------------------------- /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' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/view-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Payment/CreatePaymentRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 27 | 'account_id' => ['required'], 28 | 'payment_method' => ['required'], 29 | 'amount' => ['required', 'numeric'], 30 | 'date' => ['required', 'date'], 31 | 'note' => ['nullable'], 32 | ]; 33 | } 34 | 35 | public function messages() 36 | { 37 | return [ 38 | 'invoice_id.required' => 'The invoice field is required', 39 | 'account_id.required' => 'The account field is required', 40 | 'payment_method.required' => 'The payment method field is required', 41 | ]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /resources/admin-resources/components/shared/confirm-alert/confirmStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | 3 | export const useConfirmStore = defineStore("confirm", { 4 | state: () => ({ 5 | message: "Are you sure to do this action???", 6 | do_action: false, 7 | show_confirm_box: false, 8 | resolve: null, 9 | }), 10 | 11 | getters: { 12 | getActionState: (state) => state.do_action, 13 | }, 14 | 15 | actions: { 16 | async confirm_action() { 17 | this.do_action = true; 18 | this.hide_box(); 19 | }, 20 | 21 | async cancel_action() { 22 | this.do_action = false; 23 | this.hide_box(); 24 | }, 25 | 26 | hide_box() { 27 | this.resolve(); 28 | this.show_confirm_box = false; 29 | }, 30 | 31 | async show_box(data = {}) { 32 | this.message = data.message ? data.message : this.message; 33 | this.show_confirm_box = true; 34 | this.do_action = false; 35 | return new Promise((resolve, reject) => { 36 | this.resolve = resolve; 37 | }); 38 | }, 39 | }, 40 | }); 41 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | protected $fillable = [ 22 | 'name', 23 | 'user_name', 24 | 'email', 25 | 'password', 26 | ]; 27 | 28 | /** 29 | * The attributes that should be hidden for serialization. 30 | * 31 | * @var array 32 | */ 33 | protected $hidden = [ 34 | 'password', 35 | 'remember_token', 36 | ]; 37 | 38 | /** 39 | * The attributes that should be cast. 40 | * 41 | * @var array 42 | */ 43 | protected $casts = [ 44 | 'email_verified_at' => 'datetime', 45 | 'password' => 'hashed', 46 | ]; 47 | } 48 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/Unit 10 | 11 | 12 | ./tests/Feature 13 | 14 | 15 | 16 | 17 | ./app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /resources/admin-resources/components/shared/loader/Loader.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 58 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | by($request->user()?->id ?: $request->ip()); 29 | }); 30 | 31 | $this->routes(function () { 32 | Route::middleware('api') 33 | ->prefix('api') 34 | ->group(base_path('routes/api.php')); 35 | 36 | Route::middleware('web') 37 | ->group(base_path('routes/web.php')); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | LOG_DEPRECATIONS_CHANNEL=null 9 | LOG_LEVEL=debug 10 | 11 | DB_CONNECTION=mysql 12 | DB_HOST=127.0.0.1 13 | DB_PORT=3306 14 | DB_DATABASE=laravel 15 | DB_USERNAME=root 16 | DB_PASSWORD= 17 | 18 | BROADCAST_DRIVER=log 19 | CACHE_DRIVER=file 20 | FILESYSTEM_DISK=local 21 | QUEUE_CONNECTION=sync 22 | SESSION_DRIVER=file 23 | SESSION_LIFETIME=120 24 | 25 | MEMCACHED_HOST=127.0.0.1 26 | 27 | REDIS_HOST=127.0.0.1 28 | REDIS_PASSWORD=null 29 | REDIS_PORT=6379 30 | 31 | MAIL_MAILER=smtp 32 | MAIL_HOST=mailpit 33 | MAIL_PORT=1025 34 | MAIL_USERNAME=null 35 | MAIL_PASSWORD=null 36 | MAIL_ENCRYPTION=null 37 | MAIL_FROM_ADDRESS="hello@example.com" 38 | MAIL_FROM_NAME="${APP_NAME}" 39 | 40 | AWS_ACCESS_KEY_ID= 41 | AWS_SECRET_ACCESS_KEY= 42 | AWS_DEFAULT_REGION=us-east-1 43 | AWS_BUCKET= 44 | AWS_USE_PATH_STYLE_ENDPOINT=false 45 | 46 | PUSHER_APP_ID= 47 | PUSHER_APP_KEY= 48 | PUSHER_APP_SECRET= 49 | PUSHER_HOST= 50 | PUSHER_PORT=443 51 | PUSHER_SCHEME=https 52 | PUSHER_APP_CLUSTER=mt1 53 | 54 | VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 55 | VITE_PUSHER_HOST="${PUSHER_HOST}" 56 | VITE_PUSHER_PORT="${PUSHER_PORT}" 57 | VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" 58 | VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 59 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/twentyfour-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /app/Http/Requests/Party/CreateCustomerRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('parties')], 21 | 'phone' => ['required', 'string', Rule::unique('parties')], 22 | 'status' => ['required', 'in:active,disabled'], 23 | 24 | 'email' => ['nullable', 'string', Rule::unique('parties')], 25 | 'tax_number' => ['nullable', 'string', Rule::unique('parties')], 26 | 27 | 'company_name' => ['nullable', 'string'], 28 | 'country' => ['nullable', 'string'], 29 | 'city' => ['nullable', 'string'], 30 | 'postal_code' => ['nullable', 'string'], 31 | 'address' => ['nullable', 'string'], 32 | 'billing_address' => ['nullable', 'string'], 33 | 'shipping_address' => ['nullable', 'string'], 34 | 35 | 'sale_due' => ['nullable', 'numeric'], 36 | 'sale_return_due' => ['nullable', 'numeric'], 37 | 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/Dashboard/DashboardController.php: -------------------------------------------------------------------------------- 1 | reportService = $reportService; 15 | } 16 | 17 | public function getDashboardOverview() 18 | { 19 | $this->authorize('view_dashboard_overview'); 20 | 21 | return response()->json([ 22 | 'total_purchase_amount' => $this->reportService->getTotalPurchaseAmount(), 23 | 'total_purchase_due' => $this->reportService->getTotalPurchaseDueAmount(), 24 | 'total_sale_amount' => $this->reportService->getTotalSaleAmount(), 25 | 'total_sale_due' => $this->reportService->getTotalSaleDueAmount(), 26 | 27 | 'payment_send_current_week' => $this->reportService->getPaymentsSentCurrentWeek(), 28 | 'payment_received_current_week' => $this->reportService->getPaymentsReceivedCurrentWeek(), 29 | 30 | 'top_selling_products' => $this->reportService->getTopSellingProducts(), 31 | 32 | 'current_week_sales' => $this->reportService->getCurrentWeekSales(), 33 | 'current_week_purchases' => $this->reportService->getCurrentWeekPurchases(), 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Http/Requests/Party/CreateSupplierRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('parties')], 21 | 'phone' => ['required', 'string', Rule::unique('parties')], 22 | 'status' => ['required', 'in:active,disabled'], 23 | 24 | 'email' => ['nullable', 'string', Rule::unique('parties')], 25 | 'tax_number' => ['nullable', 'string', Rule::unique('parties')], 26 | 27 | 'company_name' => ['nullable', 'string'], 28 | 'country' => ['nullable', 'string'], 29 | 'city' => ['nullable', 'string'], 30 | 'postal_code' => ['nullable', 'string'], 31 | 'address' => ['nullable', 'string'], 32 | 'billing_address' => ['nullable', 'string'], 33 | 'shipping_address' => ['nullable', 'string'], 34 | 35 | 'purchase_due' => ['nullable', 'numeric'], 36 | 'purchase_return_due' => ['nullable', 'numeric'], 37 | 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Project License: 2 | =================== 3 | MIT License 4 | 5 | Copyright (c) 2023 Invextry: Inventory Management Solution 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | 26 | 27 | 28 | 29 | 30 | Admin Template: 31 | ==================== 32 | This project uses Voler Admin Template 33 | Link Of the Admin Template Repo: https://github.com/zuramai/voler 34 | License Link Of this Admin Template: https://github.com/zuramai/voler/blob/main/LICENSE -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/user-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Party/UpdateCustomerRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 22 | 'name' => ['required', 'string', Rule::unique('parties')->ignore($customer_id)], 23 | 'phone' => ['required', 'string', Rule::unique('parties')->ignore($customer_id)], 24 | 'status' => ['required', 'in:active,disabled'], 25 | 26 | 'email' => ['nullable', 'string', Rule::unique('parties')->ignore($customer_id)], 27 | 'tax_number' => ['nullable', 'string', Rule::unique('parties')->ignore($customer_id)], 28 | 29 | 'company_name' => ['nullable', 'string'], 30 | 'country' => ['nullable', 'string'], 31 | 'city' => ['nullable', 'string'], 32 | 'postal_code' => ['nullable', 'string'], 33 | 'address' => ['nullable', 'string'], 34 | 'billing_address' => ['nullable', 'string'], 35 | 'shipping_address' => ['nullable', 'string'], 36 | 37 | 'sale_due' => ['nullable', 'numeric'], 38 | 'sale_return_due' => ['nullable', 'numeric'], 39 | 40 | ]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Http/Requests/Party/UpdateSupplierRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 22 | 'name' => ['required', 'string', Rule::unique('parties')->ignore($supplier_id)], 23 | 'phone' => ['required', 'string', Rule::unique('parties')->ignore($supplier_id)], 24 | 'status' => ['required', 'in:active,disabled'], 25 | 26 | 'email' => ['nullable', 'string', Rule::unique('parties')->ignore($supplier_id)], 27 | 'tax_number' => ['nullable', 'string', Rule::unique('parties')->ignore($supplier_id)], 28 | 29 | 'company_name' => ['nullable', 'string'], 30 | 'country' => ['nullable', 'string'], 31 | 'city' => ['nullable', 'string'], 32 | 'postal_code' => ['nullable', 'string'], 33 | 'address' => ['nullable', 'string'], 34 | 'billing_address' => ['nullable', 'string'], 35 | 'shipping_address' => ['nullable', 'string'], 36 | 37 | 'purchase_due' => ['nullable', 'numeric'], 38 | 'purchase_return_due' => ['nullable', 'numeric'], 39 | 40 | ]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/coin-1-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/RegisterController.php: -------------------------------------------------------------------------------- 1 | validate([ 27 | 'name' => ['required', 'string', 'max:255'], 28 | 'user_name' => ['required', 'string', 'max:25'], 29 | 'email' => ['required', 'email', 'max:255', 'unique:users'], 30 | 'password' => ['required', Password::defaults()], 31 | ]); 32 | 33 | $user = User::create([ 34 | 'name' => $request->name, 35 | 'user_name' => $request->user_name, 36 | 'email' => $request->email, 37 | 'password' => Hash::make($request->password), 38 | ]); 39 | 40 | // assing created user to subscriber role 41 | $user->assignRole('subscriber'); 42 | 43 | if ($user) { 44 | //return redirect('/login'); 45 | return back()->with('registration-success', 'Account Created Successfully'); 46 | } else { 47 | return back(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/LoginController.php: -------------------------------------------------------------------------------- 1 | run(); 27 | 28 | $credentials = $request->validate([ 29 | 'email' => 'required|email', 30 | 'password' => 'required', 31 | ]); 32 | 33 | if (Auth::attempt($credentials, 100)) { 34 | $request->session()->regenerate(); 35 | if (User::find(Auth::id())->can('manage_dashboard')) { 36 | 37 | redirect()->route('admin'); 38 | } 39 | 40 | redirect()->route('home'); 41 | } 42 | 43 | return back()->with('login-error', 'Incorrect Credentials Provided')->onlyInput('email', 'password'); 44 | } 45 | 46 | public function logout(Request $request) 47 | { 48 | 49 | Auth::logout(); 50 | $request->session()->invalidate(); 51 | $request->session()->regenerateToken(); 52 | 53 | return redirect()->route('loginForm'); 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /database/seeders/AccountSeeder.php: -------------------------------------------------------------------------------- 1 | 1, 13 | 'name' => 'General Account', 14 | 'bank_name' => 'HSBC Bank', 15 | 'branch_name' => 'Dhaka Branch', 16 | 'account_number' => '984932489384298', 17 | 'balance' => 0, 18 | 'status' => 'active', 19 | 'details' => 'This Account is used for all general transaction of inventory', 20 | ], 21 | [ 22 | 'id' => 2, 23 | 'name' => 'Income Expense Handler Account', 24 | 'bank_name' => 'Asian Bank', 25 | 'branch_name' => 'Chittagong Branch', 26 | 'account_number' => '36493200334294', 27 | 'balance' => 0, 28 | 'status' => 'active', 29 | 'details' => 'This Account is used for all general transaction of inventory', 30 | ], 31 | [ 32 | 'id' => 3, 33 | 'name' => "Local Supplier's Paying Account", 34 | 'bank_name' => 'Jamuna Bank', 35 | 'branch_name' => 'Sylet Branch', 36 | 'account_number' => '33458220330244', 37 | 'balance' => 0, 38 | 'status' => 'disabled', 39 | 'details' => '', 40 | ], 41 | ]; 42 | 43 | public function run(): void 44 | { 45 | foreach ($this->accounts as $account) { 46 | Account::create($account); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Services/StockService.php: -------------------------------------------------------------------------------- 1 | where(['product_id' => $product_id, 'warehouse_id' => $warehouse_id])->count() > 0) { 17 | DB::table('product_stocks')->where(['product_id' => $product_id, 'warehouse_id' => $warehouse_id])->increment('stock_quantity', $product_quantity); 18 | DB::table('products')->where('id', $product_id)->increment('stock_quantity', $product_quantity); 19 | } else { 20 | DB::table('product_stocks')->insert(['product_id' => $product_id, 'warehouse_id' => $warehouse_id, 'stock_quantity' => $product_quantity]); 21 | DB::table('products')->where('id', $product_id)->increment('stock_quantity', $product_quantity); 22 | } 23 | } 24 | 25 | public function removeStock($warehouse_id, $product_id, $product_quantity) 26 | { 27 | if (DB::table('product_stocks')->where(['product_id' => $product_id, 'warehouse_id' => $warehouse_id])->sum('stock_quantity') > 0) { 28 | DB::table('product_stocks')->where(['product_id' => $product_id, 'warehouse_id' => $warehouse_id])->decrement('stock_quantity', $product_quantity); 29 | DB::table('products')->where('id', $product_id)->decrement('stock_quantity', $product_quantity); 30 | } else { 31 | new Error('Insufficient Stock Qunatity'); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/dashboard-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/globe-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | -------------------------------------------------------------------------------- /app/Http/Resources/Product/ProductListResource.php: -------------------------------------------------------------------------------- 1 | getMedia('gallery')) { 16 | foreach ($this->getMedia('gallery') as $m) { 17 | $gallery[] = [ 18 | 'id' => $m->id, 19 | 'url' => $m->getUrl(), 20 | ]; 21 | } 22 | } 23 | 24 | return [ 25 | 26 | 'id' => $this->id, 27 | // 'code' => $this->code, 28 | 'name' => $this->name, 29 | // 'slug' => $this->slug, 30 | // 'product_type' => $this->product_type, 31 | // 'barcode_symbology' => $this->barcode_symbology, 32 | 'stock_quantity' => $this->stock_quantity, 33 | // 'stock_alert_quantity' => $this->stock_alert_quantity, 34 | 'purchase_price' => $this->purchase_price, 35 | 'sale_price' => $this->sale_price, 36 | // 'parent_id' => $this->parent_id, 37 | 'brand' => $this->brand->name, 38 | 'category' => $this->category->name, 39 | 'unit' => $this->unit->short_name, 40 | // 'purchase_unit' => $this->purchase_unit, 41 | // 'sale_unit' => $this->sale_unit, 42 | // 'tax' => $this->tax, 43 | // 'tax_type' => $this->tax_type, 44 | // 'description' => $this->description, 45 | 46 | 'gallery' => $gallery, 47 | ]; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/setting-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /database/seeders/UnitSeeder.php: -------------------------------------------------------------------------------- 1 | 1, 'name' => 'Kilogram', 'short_name' => 'kg', 'base_unit_id' => null, 'operator' => null, 'operation_value' => null], 12 | ['id' => 2, 'name' => 'Grams', 'short_name' => 'g', 'base_unit_id' => 1, 'operator' => 'divide', 'operation_value' => 1000], 13 | ['id' => 3, 'name' => 'Meter', 'short_name' => 'm', 'base_unit_id' => null, 'operator' => null, 'operation_value' => null], 14 | ['id' => 4, 'name' => 'Centimeter', 'short_name' => 'cm', 'base_unit_id' => 3, 'operator' => 'divide', 'operation_value' => 100], 15 | ['id' => 5, 'name' => 'Liter', 'short_name' => 'l', 'base_unit_id' => null, 'operator' => null, 'operation_value' => null], 16 | ['id' => 6, 'name' => 'Mili Liter', 'short_name' => 'ml', 'base_unit_id' => 5, 'operator' => 'divide', 'operation_value' => 1000], 17 | ['id' => 7, 'name' => 'Piece', 'short_name' => 'pc', 'base_unit_id' => null, 'operator' => null, 'operation_value' => null], 18 | ['id' => 8, 'name' => 'Box', 'short_name' => 'box', 'base_unit_id' => null, 'operator' => null, 'operation_value' => null], 19 | ]; 20 | 21 | public function run(): void 22 | { 23 | foreach ($this->units as $unit) { 24 | Unit::create([ 25 | 'name' => $unit['name'], 26 | 'short_name' => $unit['short_name'], 27 | 'base_unit_id' => $unit['base_unit_id'], 28 | 'operator' => $unit['operator'], 29 | 'operation_value' => $unit['operation_value'], 30 | ]); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 65536, 48 | 'threads' => 1, 49 | 'time' => 4, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /database/migrations/2023_08_05_181011_create_invoice_items_table.php: -------------------------------------------------------------------------------- 1 | id(); 17 | $table->unsignedBigInteger('invoice_id'); 18 | $table->unsignedBigInteger('product_id'); 19 | 20 | $table->unsignedDouble('unit_price', 20, 4); 21 | $table->unsignedDouble('product_quantity', 20, 4); 22 | $table->unsignedBigInteger('unit_id')->nullable(); 23 | $table->unsignedBigInteger('tax_rate')->nullable(); 24 | $table->string('tax_type', 20); 25 | $table->string('discount_type')->nullable(); // flat/percentage 26 | $table->unsignedDouble('discount', 20, 4)->nullable(); 27 | //$table->unsignedDouble('item_total', 20, 4)->nullable(); 28 | 29 | $table->timestamps(); 30 | 31 | $table->foreign('invoice_id')->references('id')->on('invoices') 32 | ->cascadeOnUpdate()->restrictOnDelete(); 33 | $table->foreign('product_id')->references('id')->on('products') 34 | ->cascadeOnUpdate()->restrictOnDelete(); 35 | $table->foreign('unit_id')->references('id')->on('units') 36 | ->cascadeOnUpdate()->restrictOnDelete(); 37 | }); 38 | } 39 | 40 | /** 41 | * Reverse the migrations. 42 | */ 43 | public function down(): void 44 | { 45 | Schema::dropIfExists('invoice_items'); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/Invoice/SaleInvoiceController.php: -------------------------------------------------------------------------------- 1 | saleService = $saleService; 21 | } 22 | 23 | public function store(CreateSaleRequest $request) 24 | { 25 | try { 26 | DB::beginTransaction(); 27 | $this->saleService->create($request->input()); 28 | DB::commit(); 29 | 30 | } catch (Exception $e) { 31 | 32 | DB::rollback(); 33 | 34 | return response()->json([ 35 | 'status' => 'error', 36 | 'message' => $e, 37 | ], 500); 38 | } 39 | 40 | } 41 | 42 | public function index(Request $request) 43 | { 44 | $this->authorize('view_sale'); 45 | 46 | $page = $request->query('page'); 47 | $per_page = $request->query('per_page') && $request->query('per_page') < 100 ? $request->query('per_page') : 10; 48 | $search = $request->query('search'); 49 | 50 | $sales = Invoice::whereType('sale'); 51 | 52 | $sales->when($search, function ($query, $search) { 53 | $query->where('invoice_ref', 'LIKE', '%'.$search.'%'); 54 | }); 55 | 56 | $sales = $sales->latest()->paginate($per_page); 57 | 58 | return SaleListResource::collection($sales); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /resources/admin-resources/views/Admin.vue: -------------------------------------------------------------------------------- 1 | 27 | 53 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /database/migrations/2023_08_05_183542_create_payments_table.php: -------------------------------------------------------------------------------- 1 | id(); 17 | $table->unsignedBigInteger('party_id'); 18 | $table->unsignedBigInteger('account_id')->nullable(); 19 | $table->unsignedBigInteger('invoice_id')->nullable(); 20 | $table->string('invoice_type', 50)->nullable(); // sales/purchase/sales_return/purchase_return 21 | //$table->unsignedBigInteger('payment_method_id'); 22 | $table->string('payment_method', 50); 23 | $table->unsignedDouble('amount', 20, 4); 24 | $table->date('date'); 25 | $table->text('note')->nullable(); 26 | $table->timestamps(); 27 | 28 | $table->foreign('party_id')->references('id')->on('parties') 29 | ->cascadeOnUpdate()->restrictOnDelete(); 30 | $table->foreign('account_id')->references('id')->on('accounts') 31 | ->cascadeOnUpdate()->restrictOnDelete(); 32 | $table->foreign('invoice_id')->references('id')->on('invoices') 33 | ->cascadeOnUpdate()->restrictOnDelete(); 34 | // $table->foreign('payment_method_id')->references('id')->on('payment_methods') 35 | // ->cascadeOnUpdate()->restrictOnDelete(); 36 | }); 37 | } 38 | 39 | /** 40 | * Reverse the migrations. 41 | */ 42 | public function down(): void 43 | { 44 | Schema::dropIfExists('payments'); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /resources/admin-resources/components/shared/confirm-alert/confirm-box.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 30 | 31 | 61 | -------------------------------------------------------------------------------- /app/Models/Product/Product.php: -------------------------------------------------------------------------------- 1 | 'single', // variable/digital/single 37 | 'barcode_symbology' => 'CODE128', // CODE128,CODE39,EAN8,EAN13,UPC 38 | 'tax_type' => 'exclusive', 39 | 'stock_quantity' => 0, 40 | ]; 41 | 42 | public function category() 43 | { 44 | return $this->belongsTo(ProductCategory::class); 45 | } 46 | 47 | public function brand() 48 | { 49 | return $this->belongsTo(Brand::class, 'brand_id'); 50 | } 51 | 52 | public function unit() 53 | { 54 | return $this->belongsTo(Unit::class, 'unit_id'); 55 | } 56 | 57 | public function purchase_unit() 58 | { 59 | return $this->belongsTo(Unit::class, 'purchase_unit_id'); 60 | } 61 | 62 | public function sale_unit() 63 | { 64 | return $this->belongsTo(Unit::class, 'sale_unit_id'); 65 | } 66 | 67 | public function tax() 68 | { 69 | return $this->belongsTo(\App\Models\Setting\Tax::class, 'tax_id'); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = $kernel->handle( 52 | $request = Request::capture() 53 | )->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /database/migrations/2020_10_12_000000_add_variants_to_media.php: -------------------------------------------------------------------------------- 1 | string('variant_name', 255) 21 | ->after('size') 22 | ->nullable(); 23 | $table->integer('original_media_id') 24 | ->unsigned() 25 | ->after('variant_name') 26 | ->nullable(); 27 | 28 | $table->foreign('original_media_id', 'original_media_id') 29 | ->references('id')->on('media') 30 | ->nullOnDelete(); 31 | } 32 | ); 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::table( 43 | 'media', 44 | function (Blueprint $table) { 45 | if (DB::getDriverName() !== 'sqlite') { 46 | $table->dropForeign('original_media_id'); 47 | } 48 | $table->dropColumn('original_media_id'); 49 | } 50 | ); 51 | Schema::table( 52 | 'media', 53 | function (Blueprint $table) { 54 | $table->dropColumn('variant_name'); 55 | } 56 | ); 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function getConnection() 63 | { 64 | return config('mediable.connection_name', parent::getConnection()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/Invoice/PurchaseInvoiceController.php: -------------------------------------------------------------------------------- 1 | purchaseService = $purchaseService; 21 | } 22 | 23 | public function store(CreatePurchaseRequest $request) 24 | { 25 | try { 26 | DB::beginTransaction(); 27 | $this->purchaseService->create($request->input()); 28 | DB::commit(); 29 | 30 | } catch (Exception $e) { 31 | 32 | DB::rollback(); 33 | 34 | return response()->json([ 35 | 'status' => 'error', 36 | 'message' => $e, 37 | ], 500); 38 | } 39 | 40 | } 41 | 42 | public function index(Request $request) 43 | { 44 | $this->authorize('view_purchase'); 45 | 46 | $page = $request->query('page'); 47 | $per_page = $request->query('per_page') && $request->query('per_page') < 100 ? $request->query('per_page') : 10; 48 | $search = $request->query('search'); 49 | 50 | $purchases = Invoice::where('type', 'purchase'); 51 | 52 | $purchases->when($search, function ($query, $search) { 53 | $query->where('invoice_ref', 'LIKE', '%'.$search.'%'); 54 | }); 55 | 56 | $purchases = $page ? $purchases->orderBy('id', 'desc')->paginate($per_page) 57 | : $purchases->orderBy('id', 'desc')->get(); 58 | 59 | return PurchaseListResource::collection($purchases); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/Http/Resources/Product/SingleProductResource.php: -------------------------------------------------------------------------------- 1 | getMedia('gallery')) { 16 | foreach ($this->getMedia('gallery') as $m) { 17 | $gallery[] = [ 18 | 'id' => $m->id, 19 | 'url' => $m->getUrl(), 20 | ]; 21 | } 22 | } 23 | 24 | return [ 25 | 26 | 'id' => $this->id, 27 | 'code' => $this->code, 28 | 'name' => $this->name, 29 | 'slug' => $this->slug, 30 | 'product_type' => $this->product_type, 31 | 'barcode_symbology' => $this->barcode_symbology, 32 | 'stock_alert_quantity' => $this->stock_alert_quantity, 33 | 'stock_quantity' => $this->stock_quantity, 34 | 'purchase_price' => $this->purchase_price, 35 | 'sale_price' => $this->sale_price, 36 | 'parent_id' => $this->parent_id, 37 | 'brand_id' => $this->brand_id, 38 | 'brand' => $this->brand, 39 | 'category_id' => $this->category_id, 40 | 'category' => $this->category, 41 | 'unit_id' => $this->unit_id, 42 | 'unit' => $this->unit, 43 | 'purchase_unit_id' => $this->purchase_unit_id, 44 | 'purchase_unit' => $this->purchase_unit, 45 | 'sale_unit_id' => $this->sale_unit_id, 46 | 'sale_unit' => $this->sale_unit, 47 | 'tax_id' => $this->tax_id, 48 | 'tax' => $this->tax, 49 | 'tax_type' => $this->tax_type, 50 | 'description' => $this->description, 51 | 52 | 'gallery' => $gallery, 53 | ]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /resources/admin-resources/components/shared/notification/notification.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 36 | 37 | 66 | -------------------------------------------------------------------------------- /database/migrations/2023_08_05_135214_create_parties_table.php: -------------------------------------------------------------------------------- 1 | id(); 17 | $table->unsignedBigInteger('user_id')->nullable(); 18 | 19 | $table->string('name'); 20 | $table->string('phone')->unique(); 21 | $table->string('email')->unique()->nullable(); 22 | 23 | $table->string('company_name')->nullable(); 24 | $table->string('tax_number')->unique()->nullable(); 25 | 26 | $table->string('country', 50)->nullable(); 27 | $table->string('city', 50)->nullable(); 28 | $table->string('postal_code', 50)->nullable(); 29 | $table->text('address')->nullable(); 30 | $table->text('billing_address')->nullable(); 31 | $table->text('shipping_address')->nullable(); 32 | 33 | $table->string('status', 20); 34 | $table->boolean('isCustomer')->nullable(); 35 | $table->boolean('isSupplier')->nullable(); 36 | 37 | $table->unsignedDouble('purchase_due', 20, 4)->nullable(); 38 | $table->unsignedDouble('purchase_return_due', 20, 4)->nullable(); 39 | $table->unsignedDouble('sale_due', 20, 4)->nullable(); 40 | $table->unsignedDouble('sale_return_due', 20, 4)->nullable(); 41 | 42 | $table->timestamps(); 43 | 44 | $table->foreign('user_id')->references('id')->on('users')->cascadeOnUpdate()->restrictOnDelete(); 45 | }); 46 | } 47 | 48 | /** 49 | * Reverse the migrations. 50 | */ 51 | public function down(): void 52 | { 53 | Schema::dropIfExists('parties'); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /database/seeders/BrandSeeder.php: -------------------------------------------------------------------------------- 1 | 1, 'name' => 'walton', 'slug' => 'walton', 'logo' => 1], 12 | ['id' => 2, 'name' => 'bata', 'slug' => 'bata', 'logo' => 2], 13 | ['id' => 3, 'name' => 'pran', 'slug' => 'pran', 'logo' => 3], 14 | ['id' => 4, 'name' => 'regal', 'slug' => 'regal', 'logo' => 4], 15 | ['id' => 5, 'name' => 'arong', 'slug' => 'arong', 'logo' => 5], 16 | ['id' => 6, 'name' => 'philip', 'slug' => 'philip', 'logo' => 6], 17 | ['id' => 7, 'name' => 'mi', 'slug' => 'mi', 'logo' => 7], 18 | ['id' => 8, 'name' => 'panda', 'slug' => 'panda', 'logo' => 8], 19 | ['id' => 9, 'name' => 'samsung', 'slug' => 'samsung', 'logo' => 9], 20 | ['id' => 10, 'name' => 'vision', 'slug' => 'vision', 'logo' => 10], 21 | ['id' => 11, 'name' => 'hp', 'slug' => 'hp', 'logo' => 11], 22 | ['id' => 12, 'name' => 'fresh', 'slug' => 'fresh', 'logo' => 12], 23 | ['id' => 13, 'name' => 'nido', 'slug' => 'nido', 'logo' => 13], 24 | ['id' => 14, 'name' => 'pepsodent', 'slug' => 'pepsodent', 'logo' => 14], 25 | ['id' => 15, 'name' => 'rfl', 'slug' => 'rfl', 'logo' => 15], 26 | ['id' => 16, 'name' => 'dell', 'slug' => 'dell', 'logo' => 16], 27 | ['id' => 17, 'name' => 'asus', 'slug' => 'asus', 'logo' => 17], 28 | ['id' => 18, 'name' => 'dano', 'slug' => 'dano', 'logo' => 18], 29 | ['id' => 19, 'name' => 'casio', 'slug' => 'casio', 'logo' => 19], 30 | ['id' => 20, 'name' => 'yamah', 'slug' => 'yamah', 'logo' => 20], 31 | ]; 32 | 33 | public function run(): void 34 | { 35 | foreach ($this->brands as $brand) { 36 | Brand::create([ 37 | 'name' => $brand['name'], 38 | 'slug' => $brand['slug'], 39 | ])->attachMedia($brand['logo'], 'logo'); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Http/Requests/Product/CreateProductRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::unique('products')], 22 | 'name' => ['required', 'string', Rule::unique('products')], 23 | 'slug' => ['required', 'string', Rule::unique('products')], 24 | 25 | 'product_type' => ['required', 'string', Rule::in(['single', 'variable', 'digital'])], 26 | 'barcode_symbology' => ['required', 'string', Rule::in(['CODE128', 'CODE39', 'EAN8', 'EAN13', 'UPC'])], 27 | 28 | 'stock_alert_quantity' => ['nullable', 'numeric'], 29 | 'purchase_price' => ['required', 'numeric'], 30 | 'sale_price' => ['required', 'numeric'], 31 | 32 | 'parent_id' => ['nullable', 'numeric'], 33 | 34 | 'brand_id' => ['nullable', 'numeric'], 35 | 36 | 'category_id' => ['required', 'numeric'], 37 | 38 | 'unit_id' => ['required', 'numeric'], 39 | // 'purchase_unit_id' => ['required', 'numeric'], 40 | // 'sale_unit_id' => ['required', 'numeric'], 41 | 42 | 'tax_id' => ['nullable', 'numeric'], 43 | 'tax_type' => ['required', 'string', Rule::in(['inclusive', 'exclusive'])], 44 | 45 | 'description' => ['nullable', 'string'], 46 | 47 | ]; 48 | } 49 | 50 | protected function prepareForValidation(): void 51 | { 52 | $this->merge([ 53 | 'slug' => str()->slug($this->slug), 54 | // temporary configuration till our system is just for single type product 55 | 'product_type' => 'single', 56 | 'parent_id' => null, 57 | ]); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /resources/admin-resources/assets/icons/hand-love-svg-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /app/Http/Requests/Product/UpdateProductRequest.php: -------------------------------------------------------------------------------- 1 | route('id'); 19 | 20 | return [ 21 | 22 | 'code' => ['required', 'string', Rule::unique('products')->ignore($product_id)], 23 | 'name' => ['required', 'string', Rule::unique('products')->ignore($product_id)], 24 | 'slug' => ['required', 'string', Rule::unique('products')->ignore($product_id)], 25 | 26 | 'barcode_symbology' => ['required', 'string', Rule::in(['CODE128', 'CODE39', 'EAN8', 'EAN13', 'UPC'])], 27 | 28 | 'stock_alert_quantity' => ['nullable', 'numeric'], 29 | 'purchase_price' => ['required', 'numeric'], 30 | 'sale_price' => ['required', 'numeric'], 31 | 32 | 'brand_id' => ['nullable', 'numeric'], 33 | 34 | 'category_id' => ['required', 'numeric'], 35 | 36 | 'unit_id' => ['required', 'numeric'], 37 | // 'purchase_unit_id' => ['required', 'numeric'], 38 | // 'sale_unit_id' => ['required', 'numeric'], 39 | 40 | 'tax_id' => ['nullable', 'numeric'], 41 | 'tax_type' => ['required', 'string', Rule::in(['inclusive', 'exclusive'])], 42 | 43 | 'description' => ['nullable', 'string'], 44 | 45 | ]; 46 | } 47 | 48 | protected function prepareForValidation(): void 49 | { 50 | // remove product_type and parent_id so that user can not update product type and 51 | // parent of a product variation. This will help to preserve consistancy of records 52 | $this->offsetUnset('product_type'); 53 | $this->offsetUnset('parent_id'); 54 | 55 | $this->merge([ 56 | 'slug' => str()->slug($this->slug), 57 | ]); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/Upload/UploadController.php: -------------------------------------------------------------------------------- 1 | authorize('upload_file'); 16 | try { 17 | $files = $request->file('files'); 18 | $uploadedFiles = []; 19 | 20 | foreach ($files as $file) { 21 | $uploaded_media = MediaUploader::fromSource($file) 22 | ->setAllowedMimeTypes(['image/webp', 'image/png', 'image/jpg', 'image/jpeg']) 23 | ->setAllowedExtensions(['jpg', 'jpeg', 'png', 'webp']) 24 | ->toDestination('uploads', date('Y-m-d')) 25 | ->upload(); 26 | 27 | $uploadedFiles[] = [ 28 | 'id' => $uploaded_media->id, 29 | 'url' => $uploaded_media->getUrl(), 30 | ]; 31 | } 32 | } catch (Exception $e) { 33 | return response()->json([ 34 | 'status' => 'failed', 35 | 'message' => 'media upload failed'.$e->getMessage(), 36 | ], 500); 37 | } 38 | 39 | return response()->json([ 40 | 'status' => 'success', 41 | 'message' => 'media uploaded successfully', 42 | 'files' => $uploadedFiles, 43 | ], 200); 44 | } 45 | 46 | public function delete($id) 47 | { 48 | $this->authorize('delete_file'); 49 | try { 50 | $id = explode(',', $id); 51 | media::destroy($id); 52 | } catch (Exception $e) { 53 | return response()->json([ 54 | 'status' => 'failed', 55 | 'message' => 'failed to delete media', 56 | 57 | ], 500); 58 | } 59 | 60 | return response()->json([ 61 | 'status' => 'success', 62 | 'message' => 'media deleted successfully', 63 | ], 200); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /database/seeders/ProductCategorySeeder.php: -------------------------------------------------------------------------------- 1 | 1, 'name' => 'beg', 'slug' => 'beg', 'category_img' => 21], 12 | ['id' => 2, 'name' => 'camera', 'slug' => 'camera', 'category_img' => 22], 13 | ['id' => 3, 'name' => 'chocolate', 'slug' => 'chocolate', 'category_img' => 23], 14 | ['id' => 4, 'name' => 'drinks', 'slug' => 'drinks', 'category_img' => 24], 15 | ['id' => 5, 'name' => 'fruits', 'slug' => 'fruits', 'category_img' => 25], 16 | ['id' => 6, 'name' => 'furniture', 'slug' => 'furniture', 'category_img' => 26], 17 | ['id' => 7, 'name' => 'glass', 'slug' => 'glass', 'category_img' => 27], 18 | ['id' => 8, 'name' => 'headphone', 'slug' => 'headphone', 'category_img' => 28], 19 | ['id' => 9, 'name' => 'laptop', 'slug' => 'laptop', 'category_img' => 29], 20 | ['id' => 10, 'name' => 'milk powder', 'slug' => 'milk-powder', 'category_img' => 30], 21 | ['id' => 11, 'name' => 'oil', 'slug' => 'oil', 'category_img' => 31], 22 | ['id' => 12, 'name' => 'shoe', 'slug' => 'shoe', 'category_img' => 32], 23 | ['id' => 13, 'name' => 'smart phone', 'slug' => 'smart-phone', 'category_img' => 33], 24 | ['id' => 14, 'name' => 't shirt', 'slug' => 't-shirt', 'category_img' => 34], 25 | ['id' => 15, 'name' => 'tablet', 'slug' => 'tablet', 'category_img' => 35], 26 | ['id' => 16, 'name' => 'toy', 'slug' => 'toy', 'category_img' => 36], 27 | ['id' => 17, 'name' => 'tv', 'slug' => 'tv', 'category_img' => 37], 28 | ['id' => 18, 'name' => 'watch', 'slug' => 'watch', 'category_img' => 38], 29 | 30 | ]; 31 | 32 | public function run(): void 33 | { 34 | foreach ($this->product_cats as $product_cat) { 35 | ProductCategory::create([ 36 | 'name' => $product_cat['name'], 37 | 'slug' => $product_cat['slug'], 38 | ])->attachMedia($product_cat['category_img'], 'thumbnail'); 39 | } 40 | } 41 | } 42 | --------------------------------------------------------------------------------