From c702b2baa2477ae0d00f175a2960e7bfad96320d Mon Sep 17 00:00:00 2001 From: Rosiel Victor Date: Sat, 5 Mar 2022 03:22:37 -0300 Subject: [PATCH 1/6] Added user creation --- .gitignore | 7 + README.md | 112 ++---- app/Controllers/CreateUsers.php | 32 ++ app/Controllers/Validation/CPF.php | 31 ++ app/Models/Users.php | 49 +++ composer.json | 22 ++ composer.lock | 563 +++++++++++++++++++++++++++++ config.php | 12 + index.php | 22 ++ 9 files changed, 762 insertions(+), 88 deletions(-) create mode 100644 .gitignore create mode 100644 app/Controllers/CreateUsers.php create mode 100644 app/Controllers/Validation/CPF.php create mode 100644 app/Models/Users.php create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config.php create mode 100644 index.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f80936404 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +### Composer template +composer.phar +/vendor/ + +### Dotenv +.env +.idea diff --git a/README.md b/README.md index c74ac566e..3620f43c6 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,24 @@ -# Back End Test Project - -You should see this challenge as an opportunity to create an application following modern development best practices (given the stack of your choice), but also feel free to use your own architecture preferences (coding standards, code organization, third-party libraries, etc). It’s perfectly fine to use vanilla code or any framework or libraries. - -## Scope - -In this challenge you should build an API for an application that stores and manages investments, it should have the following features: - -1. __Creation__ of an investment with an owner, a creation date and an amount. - 1. The creation date of an investment can be today or a date in the past. - 2. An investment should not be or become negative. -2. __View__ of an investment with its initial amount and expected balance. - 1. Expected balance should be the sum of the invested amount and the [gains][]. -3. __Withdrawal__ of a investment. - 1. The withdraw will always be the sum of the initial amount and its gains, - partial withdrawn is not supported. - 2. Withdrawals can happen in the past or today, but can't happen before the investment creation or the future. - 3. [Taxes][taxes] need to be applied to the withdrawals before showing the - final value. -4. __List__ of a person's investments - 1. This list should have pagination. - -__NOTE:__ the implementation of an interface will not be evaluated. - -### Gain Calculation - -The investment will pay 0.52% every month in the same day of the investment creation. - -Given that the gain is paid every month, it should be treated as [compound gain][], which means that every new period (month) the amount gained will become part of the investment balance for the next payment. - -### Taxation - -When money is withdrawn, tax is triggered. Taxes apply only to the profit/gain portion of the money withdrawn. For example, if the initial investment was 1000.00, the current balance is 1200.00, then the taxes will be applied to the 200.00. - -The tax percentage changes according to the age of the investment: -* If it is less than one year old, the percentage will be 22.5% (tax = 45.00). -* If it is between one and two years old, the percentage will be 18.5% (tax = 37.00). -* If older than two years, the percentage will be 15% (tax = 30.00). - -## Requirements -1. Create project using any technology of your preference. It’s perfectly OK to use vanilla code or any framework or libraries; -2. Although you can use as many dependencies as you want, you should manage them wisely; -3. It is not necessary to send the notification emails, however, the code required for that would be welcome; -4. The API must be documented in some way. - -## Deliverables -The project source code and dependencies should be made available in GitHub. Here are the steps you should follow: -1. Fork this repository to your GitHub account (create an account if you don't have one, you will need it working with us). -2. Create a "development" branch and commit the code to it. Do not push the code to the main branch. -3. Include a README file that describes: - - Special build instructions, if any - - List of third-party libraries used and short description of why/how they were used - - A link to the API documentation. -4. Once the work is complete, create a pull request from "development" into "main" and send us the link. -5. Avoid using huge commits hiding your progress. Feel free to work on a branch and use `git rebase` to adjust your commits before submitting the final version. - -## Coding Standards -When working on the project be as clean and consistent as possible. - -## Project Deadline -Ideally you'd finish the test project in 5 days. It shouldn't take you longer than a entire week. - -## Quality Assurance -Use the following checklist to ensure high quality of the project. - -### General -- First of all, the application should run without errors. -- Are all requirements set above met? -- Is coding style consistent? -- The API is well documented? -- The API has unit tests? - -## Submission -1. A link to the Github repository. -2. Briefly describe how you decided on the tools that you used. - -## Have Fun Coding 🤘 -- This challenge description is intentionally vague in some aspects, but if you need assistance feel free to ask for help. -- If any of the seems out of your current level, you may skip it, but remember to tell us about it in the pull request. - -## Credits - -This coding challenge was inspired on [kinvoapp/kinvo-back-end-test](https://github.com/kinvoapp/kinvo-back-end-test/blob/2f17d713de739e309d17a1a74a82c3fd0e66d128/README.md) - -[gains]: #gain-calculation -[taxes]: #taxation -[interest]: #interest-calculation -[compound gain]: https://www.investopedia.com/terms/g/gain.asp +# Invest API + +## Documentação + +### /createUser +Método resposável pela criação de um usuário no sistema + + +- Método: **POST** +- Parametros: + - name + - CPF + + **Resultado:** +```json +{ + "status": "ok", + "message": "User created successfully", + "credentials": { + "id": "1", + "token": "db953f68da472f7be995db04b4186dfg" + } +} +``` \ No newline at end of file diff --git a/app/Controllers/CreateUsers.php b/app/Controllers/CreateUsers.php new file mode 100644 index 000000000..ea06e188d --- /dev/null +++ b/app/Controllers/CreateUsers.php @@ -0,0 +1,32 @@ + false, + 'message' => 'All fields are required' + ]; + } + // CPF is invalid + if(!CPF::Verify($cpf)) { + return [ + 'status' => false, + 'message' => 'This CPF is invalid' + ]; + } + + // Create user in database + $cpf = preg_replace('/\D/','', $cpf); + return Users::Create($name, $cpf); + } +} \ No newline at end of file diff --git a/app/Controllers/Validation/CPF.php b/app/Controllers/Validation/CPF.php new file mode 100644 index 000000000..2b09cd62d --- /dev/null +++ b/app/Controllers/Validation/CPF.php @@ -0,0 +1,31 @@ + 1 ? 11 - $result : 0; + } +} \ No newline at end of file diff --git a/app/Models/Users.php b/app/Models/Users.php new file mode 100644 index 000000000..c5c1732a4 --- /dev/null +++ b/app/Models/Users.php @@ -0,0 +1,49 @@ +select('cpf ='. $cpf); + if($res->fetchObject(self::class)) { + return [ + 'status' => false, + 'message' => 'This user has already been created, use your ID and Token to use the API' + ]; + } + + $token = MD5($cpf); // For example Only + $id = $obUser->insert([ + 'name' => $name, + 'cpf' => $cpf, + 'token' => $token + ]); + + return [ + 'status' => 'ok', + 'message' => 'User created successfully', + 'credentials' => [ + 'id' => $id, + 'token' => $token + ] + ]; + } + + public static function isUser($id) + { + $obUser = new Database('users'); + + $res = $obUser->select('id ='. $id); + if($res->fetchObject(self::class)) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..7cac29048 --- /dev/null +++ b/composer.json @@ -0,0 +1,22 @@ +{ + "name": "misterioso013/invest-api", + "description": "API para uma aplicações que gerenciam investimentos", + "minimum-stability": "stable", + "license": "MIT", + "authors": [ + { + "name": "Rosiel Victor", + "email": "codepremium917@gmail.com" + } + ], + "require": { + "steampixel/simple-php-router": "^0.7.0", + "vlucas/phpdotenv": "^5.4", + "william-costa/database-manager": "^0.1.0" + }, + "autoload": { + "psr-4": { + "App\\": "app/" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 000000000..13202b501 --- /dev/null +++ b/composer.lock @@ -0,0 +1,563 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "3672b1b15dfbc48bff66a30b6204833f", + "packages": [ + { + "name": "graham-campbell/result-type", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "0690bde05318336c7221785f2a932467f98b64ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/0690bde05318336c7221785f2a932467f98b64ca", + "reference": "0690bde05318336c7221785f2a932467f98b64ca", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "phpoption/phpoption": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2021-11-21T21:41:47+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15", + "reference": "eab7a0df01fe2344d172bff4cd6dbd3f8b84ad15", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2021-12-04T23:24:31+00:00" + }, + { + "name": "steampixel/simple-php-router", + "version": "0.7.0", + "source": { + "type": "git", + "url": "https://github.com/steampixel/simplePHPRouter.git", + "reference": "91aec2d0bca3619c0552e2bfcebb8936e6f83bb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/steampixel/simplePHPRouter/zipball/91aec2d0bca3619c0552e2bfcebb8936e6f83bb9", + "reference": "91aec2d0bca3619c0552e2bfcebb8936e6f83bb9", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Steampixel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christoph Stitz", + "email": "info@steampixel.de", + "homepage": "https://steampixel.de/" + }, + { + "name": "Maximilian Götz", + "email": "contact@maxbits.net", + "homepage": "https://www.maxbits.net/" + } + ], + "description": "This is a simple and small PHP router that can handel the whole url routing for your project.", + "support": { + "issues": "https://github.com/steampixel/simplePHPRouter/issues", + "source": "https://github.com/steampixel/simplePHPRouter/tree/0.7.0" + }, + "time": "2021-03-22T08:11:59+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "30885182c981ab175d4d034db0f6f469898070ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-10-20T20:35:02+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-11-30T18:21:41+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-09-13T13:58:33+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.4.1", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "264dce589e7ce37a7ba99cb901eed8249fbec92f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/264dce589e7ce37a7ba99cb901eed8249fbec92f", + "reference": "264dce589e7ce37a7ba99cb901eed8249fbec92f", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "phpunit/phpunit": "^7.5.20 || ^8.5.21 || ^9.5.10" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.4.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2021-12-12T23:22:04+00:00" + }, + { + "name": "william-costa/database-manager", + "version": "v0.1.0", + "source": { + "type": "git", + "url": "https://github.com/william-costa/database-manager.git", + "reference": "ed871363f27251a882b9e5dc036dcac566b271c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/william-costa/database-manager/zipball/ed871363f27251a882b9e5dc036dcac566b271c4", + "reference": "ed871363f27251a882b9e5dc036dcac566b271c4", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "WilliamCosta\\DatabaseManager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-or-later" + ], + "authors": [ + { + "name": "William Costa", + "email": "canalwdev@gmail.com" + } + ], + "description": "A simple library for managing database connections, results pagination and building queries in PHP.", + "support": { + "issues": "https://github.com/william-costa/database-manager/issues", + "source": "https://github.com/william-costa/database-manager/tree/v0.1.0" + }, + "time": "2021-03-19T18:51:35+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.2.0" +} diff --git a/config.php b/config.php new file mode 100644 index 000000000..436200455 --- /dev/null +++ b/config.php @@ -0,0 +1,12 @@ +load(); + +Database::config($_ENV['DB_HOST'],$_ENV['DB_NAME'],$_ENV['DB_USER'],$_ENV['DB_PASS'],$_ENV['DB_PORT']); diff --git a/index.php b/index.php new file mode 100644 index 000000000..6427c87ec --- /dev/null +++ b/index.php @@ -0,0 +1,22 @@ +Create($_POST['name'], $_POST['cpf'])); +},'post'); + +Route::add('/investment/create', function () { + $createInvestment = new InvestController(); + $date = $_POST['date'] ?? date("Y-m-d H:i:s"); + echo json_encode($createInvestment->Create($_POST['user_id'], $_POST['value'], $date)); +},'post'); + +// Run the router +Route::run('/'); \ No newline at end of file From 56ee2c2baec88c54dfbde49545f171bb7d7e74b4 Mon Sep 17 00:00:00 2001 From: Rosiel Victor Date: Sat, 5 Mar 2022 03:23:15 -0300 Subject: [PATCH 2/6] Added investment creation --- app/Controllers/InvestController.php | 23 +++++++++++++++ app/Models/Investments.php | 43 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 app/Controllers/InvestController.php create mode 100644 app/Models/Investments.php diff --git a/app/Controllers/InvestController.php b/app/Controllers/InvestController.php new file mode 100644 index 000000000..f992a41fc --- /dev/null +++ b/app/Controllers/InvestController.php @@ -0,0 +1,23 @@ +id = $id; + $this->token = $token; + } + + public function Create(int $user_id, float $value, string $date): array + { + + return Investments::Create($value,$user_id, $date); + } +} \ No newline at end of file diff --git a/app/Models/Investments.php b/app/Models/Investments.php new file mode 100644 index 000000000..d5a50f1ae --- /dev/null +++ b/app/Models/Investments.php @@ -0,0 +1,43 @@ + false, + 'message' => 'User not registered' + ]; + } + + $obInvest = new Database('investments'); + + $id = $obInvest->insert([ + 'user_id' => $user_id, + 'value' => $value, + 'created_at' => $date + ]); + + return [ + 'status' => 'ok', + 'message' => 'Investment created successfully', + 'details' => [ + 'investment_id' => $id, + 'created_at' => $date + ] + ]; + } + + public function getInvestmentById(int $id) + { + $obinvestment = new Database('investments'); + $res = $obinvestment->select('id ='. $id); + return $res->fetchObject(self::class); + } +} \ No newline at end of file From 81db2b7bcfb46cfd3c69352d04bdc8b9f473f7aa Mon Sep 17 00:00:00 2001 From: Rosiel Victor Date: Tue, 8 Mar 2022 00:27:25 -0300 Subject: [PATCH 3/6] Investment view --- app/Controllers/InvestController.php | 55 +++++++++++++++++++++++++--- app/Models/Investments.php | 39 +++++++++++++++++++- app/Models/Users.php | 15 +++++++- composer.json | 3 +- composer.lock | 26 +++++++------ index.php | 10 ++++- 6 files changed, 126 insertions(+), 22 deletions(-) diff --git a/app/Controllers/InvestController.php b/app/Controllers/InvestController.php index f992a41fc..359821bca 100644 --- a/app/Controllers/InvestController.php +++ b/app/Controllers/InvestController.php @@ -3,21 +3,66 @@ namespace App\Controllers; use App\Models\Investments; +use App\Models\Users; class InvestController { - private int $id; - private string $token; + public int $id; + public string $token; - public function __constructor(int $id, string $token) + public function __construct(int $id, string $token) { $this->id = $id; $this->token = $token; } - public function Create(int $user_id, float $value, string $date): array + + public function Create($value, $date): array { + if(empty($this->id) or empty($value)) { + return [ + 'status' => false, + 'message' => 'User.id, user.token and value fields are required' + ]; + } + if(!is_numeric($value) or $value <= 0) { + return [ + 'status' => false, + 'message' => 'Your investment must be greater than 0' + ]; + } + if(!Users::validateToken($this->id, $this->token)){ + return [ + 'status' => false, + 'message' => 'Invalid user ID or token' + ]; + } + $dateVerify = strtotime($date); + if($dateVerify > strtotime(date('Y-m-d H:i:s'))) { + return [ + 'status' => false, + 'message' => 'The investment date is incorrect' + ]; + } + return Investments::Create($value,$this->id, $date); + } + + public function view($id): array + { + if(!Investments::isInvestment($id)){ + return [ + 'status' => false, + 'message' => 'Investment not found' + ]; + } + $getInvestment = Investments::getInvestmentById($id); + return [ + 'status' => 'ok', + 'initial_investment' => $getInvestment->value, + 'current_investment' => Investments::getInvestmentCurrent($id), + 'income' => Investments::getInvestmentCurrent($id, 'income') + + ]; - return Investments::Create($value,$user_id, $date); } } \ No newline at end of file diff --git a/app/Models/Investments.php b/app/Models/Investments.php index d5a50f1ae..f9483c1f4 100644 --- a/app/Models/Investments.php +++ b/app/Models/Investments.php @@ -34,10 +34,47 @@ public static function Create(string $value, int $user_id, string $date): array ]; } - public function getInvestmentById(int $id) + public static function isInvestment($id): bool + { + $obinvestments = new Database('investments'); + + $res = $obinvestments->select('id ='. $id); + if($res->fetchObject(self::class)) { + return true; + } + return false; + } + + public static function getInvestmentById(int $id) { $obinvestment = new Database('investments'); $res = $obinvestment->select('id ='. $id); return $res->fetchObject(self::class); } + + public static function getInvestmentCurrent(int $id, $type = null): string + { + $obinvestment = new Database('investments'); + $res = $obinvestment->select('id ='. $id); + $result = $res->fetchObject(self::class); + + $balance = $result->value; + + $dateinitial = strtotime($result->created_at); + + $difference = strtotime(date('Y-m-d')) - $dateinitial; + $days = floor($difference / (60 * 60 * 24)); + $calcule = floor($days/30); + $arg = 0; + + for( ; 0 < $calcule; $calcule--) { + $arg += 0.52/100 * $balance; + } + if($type == "income") { + + return number_format($arg,2); + } + + return number_format($arg + $balance, 2, '.',''); + } } \ No newline at end of file diff --git a/app/Models/Users.php b/app/Models/Users.php index c5c1732a4..c7f191f34 100644 --- a/app/Models/Users.php +++ b/app/Models/Users.php @@ -36,7 +36,7 @@ public static function Create(string $name, int $cpf): array ]; } - public static function isUser($id) + public static function isUser($id): bool { $obUser = new Database('users'); @@ -46,4 +46,17 @@ public static function isUser($id) } return false; } + + public static function validateToken($id, $token): bool + { + $obUser = new Database('users'); + + $res = $obUser->select('id ='. $id.' AND token= "'.$token.'"'); + if($res->fetchObject(self::class)) { + return true; + } + return false; + + } + } \ No newline at end of file diff --git a/composer.json b/composer.json index 7cac29048..90a21ecae 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "require": { "steampixel/simple-php-router": "^0.7.0", "vlucas/phpdotenv": "^5.4", - "william-costa/database-manager": "^0.1.0" + "william-costa/database-manager": "^0.1.0", + "ext-gmp": "*" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 13202b501..4c2b155ed 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3672b1b15dfbc48bff66a30b6204833f", + "content-hash": "625498499491990973a9a83e2cfbc15f", "packages": [ { "name": "graham-campbell/result-type", @@ -184,7 +184,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -246,7 +246,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" }, "funding": [ { @@ -266,7 +266,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -329,7 +329,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" }, "funding": [ { @@ -349,16 +349,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.24.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", "shasum": "" }, "require": { @@ -412,7 +412,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" }, "funding": [ { @@ -428,7 +428,7 @@ "type": "tidelift" } ], - "time": "2021-09-13T13:58:33+00:00" + "time": "2022-03-04T08:16:47+00:00" }, { "name": "vlucas/phpdotenv", @@ -557,7 +557,9 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "ext-gmp": "*" + }, "platform-dev": [], "plugin-api-version": "2.2.0" } diff --git a/index.php b/index.php index 6427c87ec..d3b1dd57b 100644 --- a/index.php +++ b/index.php @@ -13,9 +13,15 @@ },'post'); Route::add('/investment/create', function () { - $createInvestment = new InvestController(); + $createInvestment = new InvestController($_POST['user_id'], $_POST['token']); $date = $_POST['date'] ?? date("Y-m-d H:i:s"); - echo json_encode($createInvestment->Create($_POST['user_id'], $_POST['value'], $date)); + echo json_encode($createInvestment->Create($_POST['value'], $date)); +},'post'); + +Route::add('/investment/view', function () { + $createInvestment = new InvestController($_POST['user_id'], $_POST['token']); + + echo json_encode($createInvestment->view($_POST["id"])); },'post'); // Run the router From 045f8b2d21e2cf4d50e5bb10d6132cccee6b78be Mon Sep 17 00:00:00 2001 From: Rosiel Victor Date: Tue, 8 Mar 2022 01:44:36 -0300 Subject: [PATCH 4/6] added withdrawal --- app/Controllers/InvestController.php | 48 ++++++++++++++++++++++++++-- app/Models/Investments.php | 34 +++++++++++++++++++- index.php | 9 ++++++ 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/app/Controllers/InvestController.php b/app/Controllers/InvestController.php index 359821bca..988317d87 100644 --- a/app/Controllers/InvestController.php +++ b/app/Controllers/InvestController.php @@ -4,6 +4,7 @@ use App\Models\Investments; use App\Models\Users; +use DateTime; class InvestController { @@ -16,6 +17,11 @@ public function __construct(int $id, string $token) $this->token = $token; } + function validateDate($date, $format = 'Y-m-d H:i:s'): bool + { + $d = DateTime::createFromFormat($format, $date); + return $d && $d->format($format) == $date; + } public function Create($value, $date): array { @@ -38,7 +44,7 @@ public function Create($value, $date): array ]; } $dateVerify = strtotime($date); - if($dateVerify > strtotime(date('Y-m-d H:i:s'))) { + if($dateVerify > strtotime(date('Y-m-d H:i:s')) or !$this->validateDate($date)) { return [ 'status' => false, 'message' => 'The investment date is incorrect' @@ -49,7 +55,14 @@ public function Create($value, $date): array public function view($id): array { - if(!Investments::isInvestment($id)){ + if(!Users::validateToken($this->id, $this->token)){ + return [ + 'status' => false, + 'message' => 'Invalid user ID or token' + ]; + } + + if(!Investments::isInvestment($id) or !Investments::isOwner($id, $this->id)){ return [ 'status' => false, 'message' => 'Investment not found' @@ -58,11 +71,40 @@ public function view($id): array $getInvestment = Investments::getInvestmentById($id); return [ 'status' => 'ok', + 'id' => $id, 'initial_investment' => $getInvestment->value, 'current_investment' => Investments::getInvestmentCurrent($id), - 'income' => Investments::getInvestmentCurrent($id, 'income') + 'income' => Investments::getInvestmentCurrent($id, 'income'), + 'withdrawal' => Investments::getInvestmentCurrent($id, 'withdrawal') ]; } + + public function Withdrawal($id, $date): array + { + if(!Investments::isInvestment($id)){ + return [ + 'status' => false, + 'message' => 'Investment not found' + ]; + } + $dateVerify = strtotime($date); + + $getInvestment = Investments::getInvestmentById($id); + + if($dateVerify > strtotime(date('Y-m-d H:i:s')) or $dateVerify < strtotime($getInvestment->created_at) or !$this->validateDate($date)) { + return [ + 'status' => false, + 'message' => 'The withdrawal date is invalid' + ]; + } + return [ + 'status' => 'ok', + 'message' => 'Withdrawal successful', + 'initial_investment' => $getInvestment->value, + 'withdrawal' => Investments::getInvestmentCurrent($id, 'withdrawal') + + ]; + } } \ No newline at end of file diff --git a/app/Models/Investments.php b/app/Models/Investments.php index f9483c1f4..30a1305bc 100644 --- a/app/Models/Investments.php +++ b/app/Models/Investments.php @@ -45,6 +45,18 @@ public static function isInvestment($id): bool return false; } + + public static function isOwner($id, $user_id): bool + { + $obinvestments = new Database('investments'); + + $res = $obinvestments->select("id = '$id' AND user_id = '$user_id'"); + if($res->fetchObject(self::class)) { + return true; + } + return false; + } + public static function getInvestmentById(int $id) { $obinvestment = new Database('investments'); @@ -72,9 +84,29 @@ public static function getInvestmentCurrent(int $id, $type = null): string } if($type == "income") { - return number_format($arg,2); + return number_format($arg,2, '.',''); } + if($type == "withdrawal") { + $year = floor($days/30/12); + + self::withdrawal($id); + + if($year > 2){ + return number_format($arg + $balance - 15/100 * $arg, 2, '.',''); + }elseif($year >= 1) { + return number_format($arg + $balance - 18.5/100 * $arg, 2, '.',''); + }else{ + return number_format($arg + $balance - 22.5/100 * $arg, 2, '.',''); + } + + } return number_format($arg + $balance, 2, '.',''); } + + private static function withdrawal($id): bool + { + $obinvestment = new Database('investments'); + return $res = $obinvestment->delete('id ='. $id); + } } \ No newline at end of file diff --git a/index.php b/index.php index d3b1dd57b..532b67dc1 100644 --- a/index.php +++ b/index.php @@ -24,5 +24,14 @@ echo json_encode($createInvestment->view($_POST["id"])); },'post'); + +Route::add('/investment/withdrawal', function () { + $createInvestment = new InvestController($_POST['user_id'], $_POST['token']); + $date = $_POST['date'] ?? date("Y-m-d H:i:s"); + echo json_encode($createInvestment->Withdrawal($_POST["id"], $date)); +},'post'); + + + // Run the router Route::run('/'); \ No newline at end of file From 518a206e56cd2d53a16d7835ec3de16ef4e18284 Mon Sep 17 00:00:00 2001 From: Rosiel Victor Date: Tue, 8 Mar 2022 04:47:28 -0300 Subject: [PATCH 5/6] Project completion --- .env.example | 6 + .htaccess | 15 +++ Database.sql | 86 ++++++++++++++ README.md | 169 +++++++++++++++++++++++++-- app/Controllers/InvestController.php | 48 +++++++- app/Models/Investments.php | 10 +- index.php | 14 ++- 7 files changed, 332 insertions(+), 16 deletions(-) create mode 100644 .env.example create mode 100644 .htaccess create mode 100644 Database.sql diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..bcae5e531 --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +# Database MySQL +DB_HOST=localhost +DB_NAME=invest +DB_USER=root +DB_PASS=pass +DB_PORT=3306 \ No newline at end of file diff --git a/.htaccess b/.htaccess new file mode 100644 index 000000000..467df8e2c --- /dev/null +++ b/.htaccess @@ -0,0 +1,15 @@ +DirectoryIndex index.php + +# enable apache rewrite engine +RewriteEngine on + +# set your rewrite base +# Edit this in your init method too if you script lives in a subfolder +RewriteBase / + +# Deliver the folder or file directly if it exists on the server +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +# Push every request to index.php +RewriteRule ^(.*)$ index.php [QSA] \ No newline at end of file diff --git a/Database.sql b/Database.sql new file mode 100644 index 000000000..9e362453c --- /dev/null +++ b/Database.sql @@ -0,0 +1,86 @@ +-- phpMyAdmin SQL Dump +-- version 5.1.3-2.fc35.remi +-- https://www.phpmyadmin.net/ +-- +-- Host: localhost +-- Tempo de geração: 08-Mar-2022 às 05:49 +-- Versão do servidor: 8.0.28 +-- versão do PHP: 7.4.28 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Banco de dados: `invest` +-- + +-- -------------------------------------------------------- + +-- +-- Estrutura da tabela `investments` +-- + +CREATE TABLE `investments` ( + `id` int NOT NULL, + `user_id` int NOT NULL, + `value` decimal(15,2) NOT NULL DEFAULT '0.00', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +-- -------------------------------------------------------- + +-- +-- Estrutura da tabela `users` +-- + +CREATE TABLE `users` ( + `id` int NOT NULL, + `name` varchar(255) NOT NULL, + `cpf` varchar(11) NOT NULL, + `token` varchar(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +-- +-- Índices para tabelas despejadas +-- + +-- +-- Índices para tabela `investments` +-- +ALTER TABLE `investments` + ADD PRIMARY KEY (`id`); + +-- +-- Índices para tabela `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `cpf` (`cpf`); + +-- +-- AUTO_INCREMENT de tabelas despejadas +-- + +-- +-- AUTO_INCREMENT de tabela `investments` +-- +ALTER TABLE `investments` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=54; + +-- +-- AUTO_INCREMENT de tabela `users` +-- +ALTER TABLE `users` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/README.md b/README.md index 3620f43c6..1226be138 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,175 @@ # Invest API +### Requisitos: +* PHP 7.6+ +* Banco de dados MySQL 8+ +## Instalação +```shell +git clone https://github.com/misterioso013/backend-test.git -## Documentação +cd backend-test + +php -S localhost:8080 +``` +- Importe o arquivo `Database.sql` no seu banco de dados +- Agora é só renomear o arquivo `.env.example` para .`env` e alterar seus valores de acordo com o seu banco de dados MySQL. +## Documentação +- O único método aceito nas requisições é *POST* +- Exemplo de URL da API padrão: `localhost:8080/` +### Exemplo de uso: +```shell +curl -X POST http://localhost:8080/createUser -H "Content-Type: application/x-www-form-urlencoded" -d "name=Name+Aqui&cpf=12345678900" +``` ### /createUser Método resposável pela criação de um usuário no sistema +| Parâmetro| Tipo| Obrigatório | Descrição | +|----------|-----|----------|-----------------| +| name| string | Sim | Nome do cliente | +| cpf | number/string | Sim | CPF válido do cliente | -- Método: **POST** -- Parametros: - - name - - CPF - - **Resultado:** + #### Resultado: ```json { "status": "ok", "message": "User created successfully", "credentials": { "id": "1", - "token": "db953f68da472f7be995db04b4186dfg" + "token": "db953f68da472h7be995db04b4186dfg" + } +} +``` +#### Sobre os campos +| Campo | Descrição | +|---------------------|---------------------------------------------------------| +| credentials > id | Indetificador único do usuário | +| credentials > token | Chave de acesso para acessar os ivestimentos do usuário | + +### /investment/create +Método resposável pela criação do investimento + +| Parâmetro| Tipo | Obrigatório | Descrição | +|----------|-------|--|--------------------------------------------------------------------| +| user_id | integer | Sim | Identificador do usuário | +| token | string | Sim | Token para validar a autenticação do usuário | +| value | float | Sim | Valor do investimento. Exemplo, para `R$1.234,56` digite `1234.56` | +| date | timestamp | Opcional | Data da criação do investimento. exemplo: 2022-03-06 21:20:37 | + +#### Resultado: +```json +{ + "status":"ok", + "message":"Investment created successfully", + "details":{ + "investment_id":"1", + "created_at":"2022-03-07 21:21:37" } } -``` \ No newline at end of file +``` +#### Sobre os campos +| Campo | Descrição | +|-------------------------|-------------------------------------| +| details > investment_id | Indetificador único do investimento | +| details > created_at | Data da criação do investimento | + + +### /investment/view +Este método retornará detalhes sobre um investimento + +| Parâmetro| Tipo | Obrigatório | Descrição | +|----------|-------|--|--------------------------------------------------------------------| +| user_id | integer | Sim | Identificador do usuário | +| token | string | Sim | Token para validar a autenticação do usuário | +| id | integer | Sim | ID do investimento, que poderá ser recuperado através do método [listar](#/investment/list) | + +#### Resultado: + +```json +{ + "status":"ok", + "id":"54", + "initial_investment":"20000.00", + "current_investment":"21248.00", + "income":"1248.00", + "withdrawal":"21017.12" +} +``` +#### Sobre os campos + +| Campo | Descrição | +|--------------------|-----------------------------------------------------| +| id | Indetificador único do investimento | + | initial_investment | Valor inicial do investimento | +| current_investment | Valor atual do investimento com juros acrescentados | +| income | Valor da renda total gerada até o momento | +| withdrawal | Valor disponível para a retirada | + +### /investment/list +Este método retornará uma lista com todos os investimentos + +| Parâmetro| Tipo | Obrigatório | Descrição | +|----------|-------|--|--------------------------------------------------------------------| +| user_id | integer | Sim | Identificador do usuário | +| token | string | Sim | Token para validar a autenticação do usuário | +| page | integer | Opcional | Número da página que deseja acessar, são exibidos 5 resultados por página | + +#### Resultado: + +```json +{ + "status":"ok", + "pages":8, + "results":[ + { + "id":"54", + "initial_investment":"20000.00", + "current_investment":"21248.00", + "income":"1248.00", + "withdrawal":"21017.12" + }, + { + "id":"55", + "initial_investment":"100000.00", + "current_investment":"100000.00", + "income":"0.00", + "withdrawal":"100000.00" + } + ] +} +``` +#### Sobre os campos + +| Campo | Descrição | +|-------------------------------------|------------------------------------------------------| +| pages | Número de páginas disponíveis | +| result | Retonar um Array com os detalhes de cada investimeto | +| result > valor > initial_investment | Valor inicial do investimento | +| result > valor > current_investment | Valor atual do investimento com juros acrescentados | +| result > valor > income | Valor da renda total gerada até o momento | +| result > valor > withdrawal | Valor disponível para a retirada | + +### investment/withdrawal +Método resposável por fazer a retirada de um investimento + +| Parâmetro| Tipo | Obrigatório | Descrição | +|---------|-------|--|------------------------------------| +| user_id | integer | Sim | Identificador do usuário | +| token | string | Sim | Token para validar a autenticação do usuário | +| id | integer | Sim | ID do investimento que deseja retirar | +| date | timestamp | Opcional | Data da retirada do investimento. Exemplo: 2022-03-06 21:20:37 | + + +#### Resultado: +```json +{ + "status":"ok", + "message":"Withdrawal successful", + "initial_investment":"100000.00", + "withdrawal":"121216.00" +} +``` +#### Sobre os campos +| Campo | Descrição | +|--------------------|------------------------------------------------| +| initial_investment | Valor do investimento inical | +| withdrawal | Valor da retirada já com os impostos aplicados | \ No newline at end of file diff --git a/app/Controllers/InvestController.php b/app/Controllers/InvestController.php index 988317d87..e3b00199e 100644 --- a/app/Controllers/InvestController.php +++ b/app/Controllers/InvestController.php @@ -5,6 +5,8 @@ use App\Models\Investments; use App\Models\Users; use DateTime; +use WilliamCosta\DatabaseManager\Database; +use WilliamCosta\DatabaseManager\Pagination; class InvestController { @@ -99,12 +101,54 @@ public function Withdrawal($id, $date): array 'message' => 'The withdrawal date is invalid' ]; } + $withdrawal = Investments::getInvestmentCurrent($id, 'withdrawal'); + Investments::withdrawal($id); return [ 'status' => 'ok', 'message' => 'Withdrawal successful', 'initial_investment' => $getInvestment->value, - 'withdrawal' => Investments::getInvestmentCurrent($id, 'withdrawal') + 'withdrawal' => $withdrawal + ]; + } + + public function list($page = 1): array + { + if(!Users::validateToken($this->id, $this->token)){ + return [ + 'status' => false, + 'message' => 'Invalid user ID or token' + ]; + } + $qtd = Investments::getAllInvestmentsById($this->id); + + $itemsPerPage = 5; + + //PAGINATION + $obPagination = new Pagination($qtd,$page,$itemsPerPage); + + $obinvestment = new Database('investments'); + + $results= $obinvestment->select('user_id = '. $this->id,null,$obPagination->getLimit()); + //PAGES (array) + $pages = $obPagination->getPages(); + + $return = [ + 'status' => 'ok', + 'pages' => count($pages) ]; + + while ($result = $results->fetchObject()) { + + $return["results"][] = [ + 'id' => $result->id, + 'initial_investment' => $result->value, + 'current_investment' => Investments::getInvestmentCurrent($result->id), + 'income' => Investments::getInvestmentCurrent($result->id, 'income'), + 'withdrawal' => Investments::getInvestmentCurrent($result->id, 'withdrawal') + + ]; + } + return $return; } -} \ No newline at end of file +} diff --git a/app/Models/Investments.php b/app/Models/Investments.php index 30a1305bc..de614131a 100644 --- a/app/Models/Investments.php +++ b/app/Models/Investments.php @@ -64,6 +64,12 @@ public static function getInvestmentById(int $id) return $res->fetchObject(self::class); } + public static function getAllInvestmentsById(int $user_id) + { + $obinvestment = new Database('investments'); + return $obinvestment->select('user_id = '. $user_id,null,null,'COUNT(*) as total')->fetchObject()->total; + } + public static function getInvestmentCurrent(int $id, $type = null): string { $obinvestment = new Database('investments'); @@ -90,8 +96,6 @@ public static function getInvestmentCurrent(int $id, $type = null): string if($type == "withdrawal") { $year = floor($days/30/12); - self::withdrawal($id); - if($year > 2){ return number_format($arg + $balance - 15/100 * $arg, 2, '.',''); }elseif($year >= 1) { @@ -104,7 +108,7 @@ public static function getInvestmentCurrent(int $id, $type = null): string return number_format($arg + $balance, 2, '.',''); } - private static function withdrawal($id): bool + public static function withdrawal($id): bool { $obinvestment = new Database('investments'); return $res = $obinvestment->delete('id ='. $id); diff --git a/index.php b/index.php index 532b67dc1..83534291b 100644 --- a/index.php +++ b/index.php @@ -24,6 +24,12 @@ echo json_encode($createInvestment->view($_POST["id"])); },'post'); +Route::add('/investment/list', function () { + $createInvestment = new InvestController($_POST['user_id'], $_POST['token']); + + echo json_encode($createInvestment->list($_POST["page"]??1)); +},'post'); + Route::add('/investment/withdrawal', function () { $createInvestment = new InvestController($_POST['user_id'], $_POST['token']); @@ -31,7 +37,11 @@ echo json_encode($createInvestment->Withdrawal($_POST["id"], $date)); },'post'); - - +Route::add('/(.*)', function() { + echo json_encode([ + 'status' => false, + 'message' => 'unsupported method' + ]); +},'get'); // Run the router Route::run('/'); \ No newline at end of file From dbbfa0c1497e164749f37f8d52a5029186f3e532 Mon Sep 17 00:00:00 2001 From: Rosiel Victor Date: Tue, 8 Mar 2022 05:05:58 -0300 Subject: [PATCH 6/6] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1226be138..bd4ffe4d2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # Invest API +Dependências usadas: +- [PHP Dotenv](https://github.com/vlucas/phpdotenv) - Para ter a leitura do arquivo .env e aceitar variáveis de ambiente no projeto +- [ Simple Database Manager](https://github.com/william-costa/database-manager) - Uma pequena classe PHP para gerenciar bancos dados MySQL, que foi desenvolvido em live no YouTube. +- [Simple Route PHP](https://github.com/steampixel/simplePHPRouter) - Facilita a criação de rotas e os trabalhos com Request e Response das aplicações PHP ### Requisitos: -* PHP 7.6+ +* PHP 8+ +* [Composer 2.+](https://getcomposer.org/) * Banco de dados MySQL 8+ ## Instalação ```shell @@ -8,6 +13,8 @@ git clone https://github.com/misterioso013/backend-test.git cd backend-test +composer install + php -S localhost:8080 ``` - Importe o arquivo `Database.sql` no seu banco de dados