{"id":15039314,"url":"https://github.com/rsemihkoca/expensemanagementapp","last_synced_at":"2025-09-11T05:13:31.267Z","repository":{"id":219076838,"uuid":"730184819","full_name":"rsemihkoca/ExpenseManagementApp","owner":"rsemihkoca","description":"Expense management system written in C# and .Net 8 SDK","archived":false,"fork":false,"pushed_at":"2024-03-02T08:34:51.000Z","size":1533,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-13T15:17:02.382Z","etag":null,"topics":["akbank-bootcamp","csharp","docker","dot-net","hangfire"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rsemihkoca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-12-11T11:37:47.000Z","updated_at":"2024-04-17T12:36:40.000Z","dependencies_parsed_at":"2024-01-25T11:16:49.690Z","dependency_job_id":"13851a45-c2ef-4066-a19e-c4a06f9511be","html_url":"https://github.com/rsemihkoca/ExpenseManagementApp","commit_stats":null,"previous_names":["rsemihkoca/akbankfinalcase","rsemihkoca/expensemanagementapp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rsemihkoca/ExpenseManagementApp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsemihkoca%2FExpenseManagementApp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsemihkoca%2FExpenseManagementApp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsemihkoca%2FExpenseManagementApp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsemihkoca%2FExpenseManagementApp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rsemihkoca","download_url":"https://codeload.github.com/rsemihkoca/ExpenseManagementApp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsemihkoca%2FExpenseManagementApp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274580278,"owners_count":25311127,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["akbank-bootcamp","csharp","docker","dot-net","hangfire"],"created_at":"2024-09-24T20:42:24.478Z","updated_at":"2025-09-11T05:13:31.203Z","avatar_url":"https://github.com/rsemihkoca.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n---\n\n# Expense Application - [Loom Demo](https://www.loom.com/share/a5ce7a3dd11f4793b86aecbbb9b8f918)\n\n## Prerequisites\n\n- [.NET SDK 8](https://dotnet.microsoft.com/download) installed on your machine.\n- Docker/Docker Compose installed on your machine.\n- Git installed on your machine.\n\n## Clone the Repository\n\n```bash\ngit clone https://github.com/yourusername/ExpenseApplication.git\ncd ExpenseApplication\n```\n\n\n## Docker Configuration\n\n\n### 1. Restart Docker Containers\n\nExecute the following command to bring down existing Docker containers, volumes, and remove orphaned containers, then bring the Docker environment back up:\n\n```bash\ndocker-compose down -v --remove-orphans \u0026\u0026 docker-compose up\n```\n\n### 2. Apply Migrations\n\nRun the following commands to apply Entity Framework migrations and update the database:\n\n```bash\ncd ExpenseApplication\ndotnet ef migrations add InitialCreate --project Infrastructure --startup-project Api\ndotnet ef database update --project Infrastructure --startup-project Api\n```\nIf you already have migrations, you can run the following command to drop the database and re-create it:\n\n```bash\ncd ExpenseApplication\ndotnet ef database update --project Infrastructure --startup-project Api\n```\n\nThe application will be accessible at `http://localhost:5245` by default.\n\n## Entity Relationship Diagram (ERD)\n\n![erd.png](.github%2Fassets%2Ferd.png)\n\nCreatedBy: Admin UserId \\\nStatus: Only admin can approve or reject expense requests.\\\nDescription: User add description for expense request.\\\nPaymentDescription: Admin add description for expense request. Or error code from background job.\n\n---\n\n\n\n## Expense\n\n\n### Create Expense\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nCreate an expense record. Authorized users: \u003cb\u003e[Admin, Personnel]\u003c/b\u003e\n\n### Get All Expenses\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nRetrieve expense records. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n### Update Expense\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePUT    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/{expenseRequestId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nUpdate an expense record by expense request ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\\\nUpdating expense as approved do not fire background job. Only approve endpoint fires background job.\nThis endpoint can be used if expens is paid manually.\n\n### Delete Expense\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eDELETE    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/{expenseRequestId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nDelete an expense record by expense request ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n\n### Get Expense by ID\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/{expenseRequestId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nRetrieve an expense record by expense request ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n\n### Approve Expense\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePATCH    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/Approve/{expenseRequestId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nApprove an expense record by expense request ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e. \\\nAdmin users approve expense records by giving expense request id.\nChecks if already approved and completed or paymentstatus is in progress. If not, updates expense record and fires background job.\n\n### Reject Expense\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePATCH    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/Reject/{expenseRequestId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nReject an expense record by expense request ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e. \\\nReject endpoint do not fire background job. Updates expense record immediately. And relevant fields are updated. Payment description, status, last updated date...\n\n### Get Expenses by User\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Expense/ByUser\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description: \nRetrieve expense records for the authenticated user. Authorized users: \u003cb\u003e[Admin, Personnel]\u003c/b\u003e.\\\nAdmin users can give null user id to retrieve all expenses.\nPersonnel can only retrieve their own expenses.\nPersonnel can filter expenses by status and date range. Also Admin can filter expenses.\nThis api is queryable.\n\n---\n\n### ExpenseCategory\n\n#### Create Expense Category\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/ExpenseCategory\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nCreate a new expense category. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n#### Get All Expense Categories\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/ExpenseCategory\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nRetrieve all expense categories. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n#### Update Expense Category\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePUT    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/ExpenseCategory/{expenseCategoryId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nUpdate an expense category by expense category ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n#### Delete Expense Category\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eDELETE    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/ExpenseCategory/{expenseCategoryId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nDelete an expense category by expense category ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\nCategory can not be deleted if category has pending expenses.\n\n#### Get All Expense Categories\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/ExpenseCategory/GetAllExpenseCategory\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nRetrieve all expense categories. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e\n\n---\n\n### PaymentSimulator\n\n#### Process Payment\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/PaymentSimulator/ProcessPayment\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nSimulate the process of making a payment. Authorized users: \u003cb\u003e[Anonymous]\u003c/b\u003e. \\\nHangfire is used to simulate payment process. Hangfire is a background job library. It is used to simulate payment process.\n\n---\n\n### Report\n\n#### Approved Payment Frequency Report\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Report/ApprovedPaymentFrequencyReport\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nGenerate a report on the frequency of approved payments. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\\\nExample response:\n```json\n{\n  \"type\": \"monthly\",\n  \"startDate\": \"01/01/2024 00:00:00\",\n  \"endDate\": \"31/01/2024 23:59:59\",\n  \"approvedCount\": 16,\n  \"approvedSum\": 14400,\n  \"averageApprovedAmount\": 900\n}\n```\n\n#### Rejected Payment Frequency Report\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Report/RejectedPaymentFrequencyReport\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nGenerate a report on the frequency of rejected payments. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\\\nExample response:\n```json\n{\n  \"type\": \"weekly\",\n  \"startDate\": \"22/01/2024 00:00:00\",\n  \"endDate\": \"28/01/2024 23:59:59\",\n  \"rejectedCount\": 0,\n  \"rejectedSum\": 0,\n  \"averageRejectedAmount\": 0\n}\n```\n\n#### Personnel Expense Frequency Report\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Report/PersonnelExpenseFrequencyReport\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nGenerate a report on the frequency of personnel expenses. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\\\nExample response:\n```json\n{\n  \"type\": \"monthly\",\n  \"startDate\": \"01/01/2024 00:00:00\",\n  \"endDate\": \"31/01/2024 23:59:59\",\n  \"totalPendingCount\": 16,\n  \"totalPendingSum\": 6040,\n  \"averagePendingAmount\": 377.5,\n  \"personnelExpenseFrequencies\": [\n    {\n      \"userId\": 1,\n      \"fullName\": \"Admin 1\",\n      \"pendingCount\": 4,\n      \"pendingSum\": 1400,\n      \"averagePendingAmount\": 350\n    },\n    {\n      \"userId\": 2,\n      \"fullName\": \"Admin 2\"\n    }...\n```\n\n\n#### Personnel Summary Report\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Report/PersonnelSummaryReport\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nGenerate a summary report on personnel expenses. Authorized users: \u003cb\u003e[Admin, Personnel]\u003c/b\u003e.\\\nPersonnel can only retrieve their own expenses.\\\nAdmin can retrieve all expenses if userId is null.\\\nExample response:\n```json\n{\n  \"userId\": 3,\n  \"totalCount\": 10,\n  \"approvedCount\": 4,\n  \"rejectedCount\": 2,\n  \"pendingCount\": 4,\n  \"approvedPercentage\": \"40%\",\n  \"approvedSum\": 6500,\n  \"rejectedSum\": 6500,\n  \"pendingSum\": 6500,\n  \"expenses\": [\n    {\n      \"expenseRequestId\": 3,\n      \"userId\": 0,\n      \"categoryId\": 3,\n      \"expenseStatus\": \"Approved\",\n      \"paymentStatus\": \"Completed\",\n      \"paymentDescription\": \"Payment Not Made\",\n      \"amount\": 2500,\n      \"paymentMethod\": \"Cash\",\n      \"paymentLocation\": \"Office\",\n      \"documents\": \"PayrollDocs\",\n      \"description\": \"Personel maaşları ödendi.\",\n      \"creationDate\": \"09/01/2024 00:00:00\",\n      \"lastUpdateTime\": \"09/01/2024 00:00:00\"\n    }...\n    {\n```\n\n---\n\n### Token\n\n#### Generate Token\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/Token\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nGenerate a new authentication token. Authorized users: \u003cb\u003e[Anonymous]\u003c/b\u003e.\\\nJWT is used for authentication.\\\nRoles: Admin, Personnel\\\n\n---\n### User\n\n#### Create User\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePOST    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nCreate a new user. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\n\n#### Get All Users\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nRetrieve all user records. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\n\n#### Update User\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePUT    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User/{UserId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nUpdate a user by user ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\n\n#### Delete User\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eDELETE    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User/{UserId}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nDelete a user by user ID. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\\\nUser can not be deleted if user has pending expenses.\n\n#### Activate User\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePATCH    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User/ActivateUser\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nActivate a user account. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e. \\\nIf a user try to login with deactivated account, user will get error message.\nUsers are blocked if they have 3 failed login attempts. Only admin can activate user.\n\n#### Deactivate User\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003ePATCH    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User/DeactivateUser\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nDeactivate a user account. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e. \\\nIf a user try to login with deactivated account, user will get error message. \\\nBlocked users can not login. So they can not be created expenses.\n\n#### Get All Users\n\u003ctable\u003e\n\u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"200px\"\u003eMethod\u003c/th\u003e\n      \u003cth width=\"800px\"\u003ePath \u003c/th\u003e\n    \u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n  \u003ctr width=\"600px\"\u003e\n    \u003ctd align=\"center\"\u003eGET    \u003c/td\u003e\n    \u003ctd  align=\"center\"\u003e/api/User/GetAllUser\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n#### Description:\nRetrieve all user records. Authorized users: \u003cb\u003e[Admin]\u003c/b\u003e.\n\n---\n### Additional Information\n\n- Handlervalidator.cs and fluentvalidation is used for validation.\n- Entities have unique index fields so additional validations are added for those like CategoryName, UserName, Email.\n- Dependencies injected, code is decoupled. Avoid code duplication. Code can extended easily.\n- 2 Admin, 2 Personnel users are created in migration. 42 expenses are created.\n- Further Improvements: ApiResponse Class, I did not used apiresponse class so as to return appropriate status code and message. But it can be improved. Handling enums, ClassLevelCascadeMode etc.\n\n### Runtime Screenshots(Projenin Çalışma Örneği)\nGet token\n\n\n![img_1.png](.github%2Fassets%2Fimg_1.png)\n\nGet JWT Token and use it in Authorization header.\n\n![img_2.png](.github%2Fassets%2Fimg_2.png)\n\nAfter Authorization, you can use api endpoints. Here a test token you can also use it.\n```jwttoken\neyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjEiLCJFbWFpbCI6ImFkbWluMUBleGFtcGxlLmNvbSIsIlVzZXJuYW1lIjoiYWRtaW4xIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQWRtaW4iLCJleHAiOjE2NzA1ODkzNDg5LCJpc3MiOiJFeHBlbnNlQXBwbGljYXRpb24iLCJhdWQiOiJFeHBlbnNlQXBwbGljYXRpb24ifQ.iyL7pHsWY8q-O_gRqCIMctZtrSfK1rZ8vFYASk02utQ\n```\n\nExpenseRequestId 42 is pending. Admin can approve it.\n```json\n{\n  \"expenseRequestId\": 42,\n  \"userId\": 1,\n  \"categoryId\": 10,\n  \"expenseStatus\": \"Pending\",\n  \"paymentStatus\": \"Pending\",\n  \"paymentDescription\": \"Payment Not Made\",\n  \"amount\": 300,\n  \"paymentMethod\": \"Cash\",\n  \"paymentLocation\": \"Office\",\n  \"documents\": \"EducationReceipts\",\n  \"description\": \"Eğitim masrafları ödendi.\",\n  \"creationDate\": \"13/01/2024 00:00:00\",\n  \"lastUpdateTime\": \"06/01/2024 00:00:00\"\n}\n```\n\nApprove Expense\n\n![img_3.png](.github%2Fassets%2Fimg_3.png)\n\nPayment simulator sleeps 6 seconds. And probabilisticly approves(90%) or rejects(10%) expense.\\\n\n![img_4.png](.github%2Fassets%2Fimg_4.png)\n\nFurther information can be found in the [link](https://documenter.getpostman.com/view/23348379/2s9YymFQ2G).\nAlso in documentation folder there is a postman collection. You can import it to postman and test the api.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsemihkoca%2Fexpensemanagementapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frsemihkoca%2Fexpensemanagementapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsemihkoca%2Fexpensemanagementapp/lists"}