Compare commits

...

245 Commits

Author SHA1 Message Date
4e9cecbb74 Merge branch 'Feature/Excel/instiutition-contract' 2025-12-29 17:21:58 +03:30
adf297455f feat: enhance Excel export for institution contracts by removing row number and adding dynamic physical contract status 2025-12-29 17:20:07 +03:30
1d656a590f Merge remote-tracking branch 'origin/master' 2025-12-29 16:26:08 +03:30
SamSys
a33d7c019c launchsettnig 2025-12-29 15:08:53 +03:30
SamSys
d62b5ca155 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-29 14:37:47 +03:30
SamSys
18a4334d8a change WarningMessage on InsuranceList Edit 2025-12-29 14:36:03 +03:30
84416fe1f5 feat: add validation for in-person contract approval and suppress documentation warnings 2025-12-29 13:29:32 +03:30
Mahan Chamani
bd1c1fa814 Refactor deployment script to use env variables
Updated deployment configuration to use environment variables for server host and credentials.
2025-12-29 12:22:10 +03:30
Mahan Chamani
8496b52013 Change deployment target from master to Main
Updated deployment configuration with new server details.
2025-12-29 11:17:59 +03:30
Mahan Chamani
5c1547dced Update dotnet-developPublish.yml 2025-12-29 09:51:06 +03:30
Mahan Chamani
c09321d89d Update dotnet-developPublish.yml 2025-12-29 09:50:40 +03:30
219e64c0f7 add menu 2025-12-29 09:35:33 +03:30
b42217ed94 Merge branch 'Feature/Excel/instiutiton-contract' 2025-12-28 19:31:14 +03:30
8b6786c09a add route for excel download 2025-12-28 19:20:25 +03:30
45c5d20323 add excel download 2025-12-28 19:17:50 +03:30
ad6f872145 fix: update contract and insurance list links to use dynamic domain 2025-12-28 18:31:13 +03:30
d22805892a Merge branch 'Feature/Insurance/client-api'
# Conflicts:
#	CompanyManagment.EFCore/Repository/InsuranceListRepository.cs
2025-12-28 18:25:14 +03:30
4da496cab8 Merge branch 'Feature/contracts/api' 2025-12-28 13:08:56 +03:30
aa0eae6c83 feat: implement Excel export for institution contracts with categorized tabs 2025-12-28 13:01:40 +03:30
SamSys
4b40580658 Merge branch 'master' into Feature/ClientLeavePageApi 2025-12-27 19:16:39 +03:30
SamSys
8bc9e044ae Warning Mesage For EmployeeShare bug Fixed 2025-12-27 18:24:50 +03:30
SamSys
cddaf2f709 changes 2025-12-27 16:58:36 +03:30
SamSys
337cd40a4e LeaveDuration daily and hourly on create modal completed 2025-12-27 16:51:08 +03:30
SamSys
a98300cacd GetHourlyLeaveDuration 2025-12-27 15:49:39 +03:30
SamSys
daded35ab1 Merge branch 'master' into Feature/ClientLeavePageApi 2025-12-27 14:06:29 +03:30
SamSys
ba778bb519 LeaveListPrint 2025-12-27 14:06:10 +03:30
SamSys
27e8d302d9 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-27 12:06:35 +03:30
SamSys
54c67fe8f7 add ListPrint 2025-12-27 12:06:02 +03:30
92e1d6de5c Merge branch 'Feature/institution-contract/refactor-list' 2025-12-27 10:26:35 +03:30
c488f61a09 refactor: enhance error logging and add installment amount to institution contract view model 2025-12-27 10:26:12 +03:30
SamSys
dc703fad3c Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-25 17:56:45 +03:30
54e5904951 add from form to verify gateway 2025-12-25 17:16:07 +03:30
SamSys
a638913172 create levave api and get rotating shift api 2025-12-25 16:16:50 +03:30
a986212834 add from form to verify gateway 2025-12-25 15:11:27 +03:30
649242fc76 refactor: optimize institution contract list retrieval and improve workshop group loading 2025-12-25 14:33:00 +03:30
SamSys
d254da1393 bacgrountTask InstitutionContract some changes 2025-12-25 12:32:10 +03:30
ad4b0be033 fix: improve error handling and streamline activation process in ActiveAll method 2025-12-25 11:28:29 +03:30
733f39db9f feat: add total amount and one month payment without discount to institution contract 2025-12-24 22:22:49 +03:30
94237434c5 fix: safely deactivate previous institution contract if it exists 2025-12-24 19:30:58 +03:30
2da8bc8a20 Merge remote-tracking branch 'origin/master' 2025-12-24 18:55:19 +03:30
8b217f6cd0 remove maximum length validation for project name in CreateProjectCommandValidator 2025-12-24 18:28:02 +03:30
SamSys
74bd802a3d sms settings frontEnd bug fixed 2025-12-24 18:24:37 +03:30
b58481a36f add employee client api 2025-12-24 18:07:43 +03:30
SamSys
3fd17299f9 fix 2025-12-24 17:20:26 +03:30
SamSys
fc315cc908 change backgrooundTask 2025-12-24 17:18:21 +03:30
SamSys
abe07e1c4b Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-24 16:58:47 +03:30
SamSys
6046f55ece backgroundTask change 2025-12-24 16:58:35 +03:30
d80a36ec35 add: create EmployeeController to manage employee selection for workshops 2025-12-24 16:31:32 +03:30
SamSys
7b648b135e add new logs 2025-12-24 16:22:51 +03:30
SamSys
5998bd212f Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-24 15:56:17 +03:30
SamSys
d77bffabdd add SeriLog on Backgroundtask InstitutionContract 2025-12-24 15:56:00 +03:30
4f0e5a34a4 add: implement reactivation logic for institution contracts and retrieve previous contracts 2025-12-24 15:40:06 +03:30
5faa2062b9 add: implement reactivation logic for contracting parties and associated employers after extension 2025-12-24 13:54:51 +03:30
SamSys
69476f3f2d add multiple get list for leaveController 2025-12-24 12:53:06 +03:30
SamSys
4bc65e500d Merge branch 'Feature/ClientLeavePageApi' of https://github.com/samsyntax24/OriginalGozareshgir into Feature/ClientLeavePageApi 2025-12-24 11:53:15 +03:30
07587d162f add: implement PrintAllAsync and PrintOneAsync methods for leave printing functionality 2025-12-24 11:17:53 +03:30
30b4f52896 add: refactor RollCall application to support asynchronous operations and enhance transaction handling 2025-12-23 20:16:33 +03:30
134466547e add: enhance InstitutionContractRepository to include employer workshops and left work details 2025-12-23 18:54:10 +03:30
a191968c15 add: include Installments in InstitutionContractRepository query 2025-12-23 18:16:50 +03:30
SamSys
59bbb7aae6 ini leave groupList 2025-12-23 18:15:48 +03:30
d740c36dc6 add: update ProjectBoardDetailResponse to use TotalTimeMinute and SpentTimeMinute 2025-12-23 17:33:09 +03:30
SamSys
89de3162de GetLewvList Api 2025-12-23 17:03:54 +03:30
SamSys
132c8ac5a4 init 2025-12-23 15:10:17 +03:30
SamSys
f00fde4084 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-23 13:47:25 +03:30
SamSys
e8b3700cdf GetList PlanPercentage CountAsync 2025-12-23 13:46:59 +03:30
0ca35e3295 Merge remote-tracking branch 'origin/master' 2025-12-23 11:51:47 +03:30
1a91743916 add: update CalculateDiscount method to include contractStart parameter 2025-12-23 10:50:11 +03:30
SamSys
dd68473150 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-23 04:18:08 +03:30
SamSys
72e3859d2c next ui upload from wbe completed 2025-12-23 04:17:52 +03:30
46d193b45e Merge branch 'Feature/program-manager/test-upload' 2025-12-22 19:51:49 +03:30
1bfe41418b add: enhance ProjectBoardDetailResponse to include RemainingTime and user time details 2025-12-22 19:51:21 +03:30
6a446d5972 add: implement AutoStopOverTimeTaskSections command and related functionality 2025-12-22 19:13:34 +03:30
Mahan Chamani
acec101c4c Update deployment password in workflow file 2025-12-22 18:24:02 +03:30
SamSys
7d92321d1c Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-22 17:46:31 +03:30
SamSys
19f78a230c change 2025-12-22 17:46:02 +03:30
0e91e6f287 Merge remote-tracking branch 'origin/master' 2025-12-22 17:44:20 +03:30
9df56ee19b Merge branch 'Feature/institution-contract/verify-mannually' 2025-12-22 17:44:04 +03:30
8750604d96 feat: add financial transaction handling during institution contract verification 2025-12-22 17:43:32 +03:30
f27ce460fd feat: integrate RollCallService repository into InstitutionContractApplication and WorkshopApplication 2025-12-22 17:33:37 +03:30
SamSys
934019c6c6 InsuranceNotCreated tab backend changed 2025-12-22 16:34:42 +03:30
SamSys
82bf10c2d5 ServiceAmount GetList 2025-12-22 14:21:01 +03:30
SamSys
19a72ac78d load data and create service percentage 2025-12-22 12:35:51 +03:30
SamSys
9cb42b7cef background job changed 2025-12-22 11:16:50 +03:30
8e5d4c312e fix: correct spelling of 'Month' and enhance insurance client list retrieval with additional properties 2025-12-21 11:03:23 +03:30
12fab5a9a5 add {id:guid} convention for controllers 2025-12-20 20:57:34 +03:30
20dd8f64f4 add: include OneMonthWithoutTax and OneMonthTax properties in InstitutionContractPrintViewModel 2025-12-20 20:28:08 +03:30
b827493306 refactor: remove unused discount-related classes from IInstitutionContractApplicationpnpm 2025-12-20 20:12:31 +03:30
04c65eae93 Merge branch 'Feature/institution-contract/print'
# Conflicts:
#	CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs
2025-12-20 20:10:30 +03:30
b4526a4338 Merge branch 'Feature/institution-contract/verify-mannually' 2025-12-20 20:09:13 +03:30
2d879ce80a fix: update workshop identification logic in InstitutionContractApplication 2025-12-20 20:06:28 +03:30
56e79d2099 fix: correct ContractAmountWithTax calculation for old contracts 2025-12-20 19:38:32 +03:30
93891f3837 add one month more details for InstitutionContract.cs print 2025-12-20 19:18:27 +03:30
SamSys
5bdfbc572b add next deploy and contractingParty add to workshop on AndroidApk page 2025-12-20 18:42:53 +03:30
4385a65cbc feat: add manual verification endpoint for institution contracts 2025-12-20 18:27:59 +03:30
722f8dae7c feat: implement manual verification for institution contracts and add signing type handling 2025-12-20 18:27:17 +03:30
SamSys
07113353c4 add uploadFrontEnd btn to AndroidApk page 2025-12-20 16:01:07 +03:30
4b39994de6 feat: add API endpoint for printing multiple contracts 2025-12-20 15:50:34 +03:30
0dd2dc7c43 add workshopCode on client contract print 2025-12-20 15:21:34 +03:30
8c6336b9bd fix: correct IsOldContract logic to properly identify old contracts 2025-12-20 14:35:02 +03:30
20c00893b6 feat: add API endpoint for printing contract details and enhance contract print logic 2025-12-20 14:23:23 +03:30
20e3d454cf feat: add ContractAmountWithTax calculation and update related references 2025-12-20 13:35:52 +03:30
b0d174a575 feat: implement contract printing methods and view models 2025-12-20 13:04:30 +03:30
2bf31db6b2 fix: enhance parameter binding logic for route parameters 2025-12-20 12:05:34 +03:30
7a4a6de84f feat: add OneMonthPrice to institution contract details 2025-12-20 10:56:36 +03:30
293ea0f6f4 feat: enhance insurance client print model with additional properties and update related logic 2025-12-20 10:13:13 +03:30
3ce4cf3966 add insurance print api for client 2025-12-18 13:34:31 +03:30
4f16d7680c feat: add insurance client list retrieval with pagination and filtering 2025-12-18 10:59:06 +03:30
SamSys
7a10d5ce59 changes 2025-12-18 10:40:11 +03:30
SamSys
3d88feeee7 Clent Add Employee Change to authorizedCanceled 2025-12-17 19:13:47 +03:30
SamSys
f408624463 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-17 13:25:38 +03:30
SamSys
8296292e49 checkout week finder switch fixed bug 2025-12-17 13:25:24 +03:30
be8deef167 fix: update license context setting for Excel packages 2025-12-17 11:33:40 +03:30
84fb29c8c8 feat: enhance project creation validation and add operation result filter 2025-12-16 20:18:54 +03:30
0969e8a5fd Merge remote-tracking branch 'origin/master' 2025-12-16 19:14:28 +03:30
92e2282381 refactor: change GetAllCodes to return a dictionary for improved structure 2025-12-16 19:13:30 +03:30
SamSys
3b71b7d707 add pmPermission to claim 2025-12-16 18:24:18 +03:30
6123a53f01 fix: update permission check for project board visibility 2025-12-16 17:15:22 +03:30
ec74db17eb Merge branch 'master' into Feature/program-manager/set-permission-board 2025-12-16 17:10:41 +03:30
dc118cf18b Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-16 17:09:54 +03:30
a11e54c333 Add project board detail endpoint & validation improvements
- Added GET /board/{id:guid} endpoint to ProjectController for detailed project board info.
- Enforced max length of 15 characters for project names in CreateProjectCommandValidator.
- Improved SetTimeProjectCommandHandler: skip zero/negative initial times, removed duplicate error message, and cleaned up formatting.
- Enhanced RollCallApplication to use employee-specific workshop shift settings when available.
2025-12-16 17:09:28 +03:30
SamSys
2383e7a54f Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-16 17:03:02 +03:30
SamSys
2ef1ea3d1a add new permission for workshop 2025-12-16 17:02:40 +03:30
SamSys
ebdc9b1e55 ProgramManager PermissionCodes set 2025-12-16 16:26:15 +03:30
9e5a494881 feat: enhance project board query with skill and user details 2025-12-16 14:18:00 +03:30
2972807c9f feat: add permission handling methods and project board detail query 2025-12-16 12:56:49 +03:30
f7351454f3 feat: implement method to update face embedding names for employees with changed names 2025-12-16 11:05:22 +03:30
b64d0e5ffd feat: add method to update employee full name in FaceEmbeddingService and integrate with RollCallEmployeeApplication 2025-12-16 10:39:51 +03:30
35b7a3a3dd remove documentation file generation from project settings 2025-12-16 09:32:42 +03:30
fe93ef60c9 Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-15 21:14:06 +03:30
ef865d9c68 Add Skill navigation to Phase/ProjectSection, refactor logic
- Add Skill navigation properties to PhaseSection and ProjectSection, with EF Core mappings and migration for foreign keys and indexes.
- Refactor SetSkillFlags in GetProjectsListQueryHandler for clarity and efficiency; use eager loading for Skill.
- Add HasRemainingTime() to TaskSection and enforce time check in ChangeStatusSectionCommandHandler.
- Optimize EmployeeDocumentsRepository queries; add EmployeeId to WorkshopWithEmployeeDocumentsViewModel.
- Improve CustomExceptionHandler to handle FluentValidation exceptions and return proper status codes.
- Add FluentValidation package reference and perform minor code cleanups.
2025-12-15 20:56:32 +03:30
SamSys
61e35100f9 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-15 18:49:35 +03:30
SamSys
01d33ff340 add InstitutionContract Confirm Reminder Sms completed 2025-12-15 18:49:13 +03:30
cd64e1d24d Merge remote-tracking branch 'origin/master' 2025-12-15 14:06:18 +03:30
d9da2e97ab feat: add method to retrieve task sections assigned to a user and enhance permission code structure 2025-12-15 14:06:07 +03:30
SamSys
1c1c8816a5 pm GetHolidaysInDates completed - remove OldholidayItems 2025-12-15 14:01:42 +03:30
a1e85261a6 Merge remote-tracking branch 'origin/master' 2025-12-15 13:49:53 +03:30
000af89fd7 feat: add permission checking and task assignment handling in ProjectBoardHub 2025-12-15 13:49:41 +03:30
SamSys
a4f3feba1c update account edit method 2025-12-15 13:26:09 +03:30
SamSys
a3d286c040 remove PmDbContext and depndencies 2025-12-15 13:05:05 +03:30
SamSys
902ef34757 Remove Pm Old Context 2025-12-15 12:42:19 +03:30
SamSys
e67aca37f9 Insurance HasCheckout change 2025-12-15 12:15:00 +03:30
2a31b27f9b feat: simplify StartWork and StopWork methods by removing userId parameter 2025-12-15 10:43:17 +03:30
e05eb1236b Merge branch 'refs/heads/Feature/program-manager/signalR-notification'
# Conflicts:
#	ServiceHost/Program.cs
2025-12-15 10:41:31 +03:30
a7d3b1e96f feat: update SignalR group handling for project status notifications 2025-12-15 10:14:32 +03:30
73bef104fb feat: implement custom parameter binding convention for ASP.NET Core 2025-12-15 09:45:39 +03:30
SamSys
b31559a29a add institutionContractConfirmTab SmsSettigs 2025-12-14 18:59:22 +03:30
SamSys
e62270a9b7 update sms settings js 2025-12-14 18:14:18 +03:30
SamSys
998759e2dc change smsSettings 2025-12-14 17:58:27 +03:30
SamSys
49d401856f change GetAverageWeeklyDuration method 2025-12-14 17:46:19 +03:30
SamSys
2faf6c1400 Get Average Weekly Duration query Handler 2025-12-14 16:27:36 +03:30
SamSys
a01a927f6f chnage pm shift duration method on domain 2025-12-14 15:11:39 +03:30
bca1e66f0f feat: update ProjectBoardHub endpoint to include API prefix 2025-12-14 14:21:45 +03:30
SamSys
097d5a6e86 sepration report js 2025-12-14 14:03:39 +03:30
83a7bbf5f3 feat: register SignalR notification publisher for board updates 2025-12-14 13:50:24 +03:30
SamSys
24501df615 sepration js and css for workshop and account 2025-12-14 12:50:19 +03:30
da46d45601 feat: implement SignalR notifications for project status changes 2025-12-14 12:13:23 +03:30
14fda440c1 Merge branch 'Feature/program-manager/move' 2025-12-14 11:19:31 +03:30
85ce92af2c feat: add permission attribute to program manager menu items 2025-12-14 09:41:16 +03:30
SamSys
5777a869cf migration changes 2025-12-13 22:42:08 +03:30
ed6301831c add program-manager in menu 2025-12-13 20:38:47 +03:30
2d0eb52211 merge from programManager Move 2025-12-13 20:24:20 +03:30
05d8b738cc Merge branch 'Feature/notification/create-api' 2025-12-13 20:18:29 +03:30
SamSys
5936f02421 Merge branch 'Feature/program-manager/move' of https://github.com/samsyntax24/OriginalGozareshgir into Feature/program-manager/move 2025-12-13 20:05:03 +03:30
SamSys
57116b14cc Update pmUser and create completed 2025-12-13 20:04:57 +03:30
a1e52ca48a feat: add ProgramManagerDbServer configuration and simplify OperationResult usage in GetSingleUserQueryHandler 2025-12-13 19:25:18 +03:30
f75d267ef5 Merge remote-tracking branch 'origin/Feature/program-manager/move' into Feature/program-manager/move 2025-12-13 18:56:04 +03:30
5be44432b1 feat: add user ID to GetSingleUserResponse and update PmUserQueryService for ID retrieval 2025-12-13 18:55:50 +03:30
SamSys
c0d2cae82e Merge branch 'Feature/program-manager/move' of https://github.com/samsyntax24/OriginalGozareshgir into Feature/program-manager/move 2025-12-13 18:51:14 +03:30
SamSys
955a6a3d21 edit pmRole completed 2025-12-13 18:51:08 +03:30
a52e313984 feat: register PmUserQueryService in Dependency Injection for user queries 2025-12-13 18:50:39 +03:30
58816ca383 feat: implement PmUserQueryService and integrate into AccountApplication for user ID retrieval 2025-12-13 18:38:08 +03:30
370feca81e Refactor bug report pages to use string identifiers and improve styling 2025-12-13 18:26:01 +03:30
SamSys
a4bf6c952d Merge branch 'Feature/program-manager/move' of https://github.com/samsyntax24/OriginalGozareshgir into Feature/program-manager/move 2025-12-13 18:25:26 +03:30
SamSys
c9d582877b create PmRole Completed 2025-12-13 18:25:19 +03:30
339cea998a Merge branch 'Feature/roll-call/camera-bug-report'
# Conflicts:
#	PersonalContractingParty.Config/PersonalBootstrapper.cs
2025-12-13 17:30:31 +03:30
32065aec33 refactor: remove unused authentication methods and clean up AuthHelper 2025-12-13 16:45:17 +03:30
f2293934d4 feat: restructure ProgramManager area and integrate Shared.Contracts 2025-12-13 16:41:27 +03:30
b12b3b9eb8 Revert "refactor: restructure controllers and update user references for ProgramManager"
This reverts commit c059066b13.
2025-12-13 15:49:57 +03:30
91259046f6 Revert "feat: introduce Shared.Contracts for account management and refactor related services"
This reverts commit 9469a5f76e.
2025-12-13 15:49:31 +03:30
c9882f0b59 update to 10 2025-12-13 14:54:45 +03:30
SamSys
e89aae1cc9 change accountTable 2025-12-13 14:11:41 +03:30
9469a5f76e feat: introduce Shared.Contracts for account management and refactor related services 2025-12-13 13:48:05 +03:30
c059066b13 refactor: restructure controllers and update user references for ProgramManager 2025-12-13 12:17:29 +03:30
ba0669bc55 Merge branch 'refs/heads/master' into Feature/program-manager/move 2025-12-13 11:36:44 +03:30
b3f42af77c Refactor bug report system to use Guid for identifiers instead of long 2025-12-13 11:19:17 +03:30
f42db3d21c fix: change token expiration time to local time in JWT settings 2025-12-13 10:28:19 +03:30
eb49bf771d changes mongo camera report 2025-12-12 19:42:08 +03:30
f829b8ddd1 Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-08 16:36:42 +03:30
5e6033db95 change ssologin url 2025-12-08 16:36:35 +03:30
27e8a26ed8 Add new domain models and interfaces for project management features 2025-12-08 14:47:03 +03:30
SamSys
0a2815946c change leavComput for staticWorkshop set 2025-12-08 14:37:04 +03:30
SamSys
7776dedd2a update SmsSettings js 2025-12-08 13:29:09 +03:30
SamSys
5da523e9a8 spreating js and css on SmsSettings 2025-12-08 13:24:18 +03:30
b7a7fb01d7 Merge remote-tracking branch 'origin/master' 2025-12-08 13:04:30 +03:30
8d49220532 Implement SSO token generation for Program Manager and update domain configuration 2025-12-08 13:04:19 +03:30
SamSys
def27929d9 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-07 19:54:23 +03:30
SamSys
ea6fcbc773 add new permissions 2025-12-07 19:53:41 +03:30
788d58b413 change Id to ENtityId in getting institution by installment Id from FInancial invoice Item for Verify gateway payment controller 2025-12-07 19:39:01 +03:30
de8181770d Merge branch 'Feature/authorize/program-manager'
# Conflicts:
#	ServiceHost/appsettings.Development.json
#	ServiceHost/appsettings.json
2025-12-07 18:25:18 +03:30
3a32d1ca9d Merge branch 'master' into Feature/authorize/program-manager 2025-12-07 18:22:56 +03:30
951a194961 Add Program Manager menu item and update SSO login URL 2025-12-07 18:22:44 +03:30
ea896c4c11 Add migration for camera bug report system with related logs and screenshots 2025-12-07 17:56:56 +03:30
167b2bce09 Implement camera bug report system with CRUD operations and logging 2025-12-07 17:54:55 +03:30
SamSys
32a05398de add ProgramManager ConnectionString on AppSettings 2025-12-07 16:41:47 +03:30
SamSys
57853e2d1f Merge branch 'master' into ProgramManagerUserAccount 2025-12-07 15:33:46 +03:30
SamSys
acd96bcdc7 Add ProgramManager Context 2025-12-07 15:21:53 +03:30
3c0ec01f77 Fix date comparison logic in roll call validation 2025-12-06 18:57:52 +03:30
517f2d06ca Add CountController to manage task, ticket, and workflow counts 2025-12-06 17:44:00 +03:30
SamSys
fb97d3453d Merge branch 'master' into ProgramManagerUserAccount 2025-12-06 17:06:58 +03:30
SamSys
2320185ade Change 2025-12-06 16:58:34 +03:30
SamSys
80fdd1fece add programManager Domains and context 2025-12-06 16:58:14 +03:30
343f830d0d Fix calculation of discounted payment amount in institution contract repository 2025-12-06 16:46:02 +03:30
323a46a623 Add Program Manager menu item and implement JWT token generation for SSO login 2025-12-06 16:24:11 +03:30
87ff7976fb Add menu item for bank account information
Added a new menu item with `permission="307"` to `_Menu.cshtml`
for accessing the `account-number-database` page. The link
is dynamically constructed using `AppSetting.Value.Domain`
and styled with `class="clik10"` and inline styles. Included
an SVG icon and the text "اطلاعات بانکی طرف حساب"
("Bank account information of the counterparty"). Maintained
the hierarchical structure of the menu.
2025-12-06 10:41:03 +03:30
a533850f24 Enhance contract removal logic and handle financial statement updates 2025-12-04 10:36:59 +03:30
b5c1a4c29d Refactor legal party handling logic
Replaced `realPersonalContractingParty` with `legalPersonalContractingParty` to ensure correct variable usage in legal party operations. Updated the authentication logic to handle both authenticated and unauthenticated states, introducing a new `else` block for `LegalAuthentication`. Adjusted method calls (`UnAuthenticateLegalEdit` and `EditLegalPartyFromInstitution`) to use the updated variable and ensure consistent updates to legal party details.
2025-12-03 20:21:08 +03:30
28607dec66 Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-03 12:10:52 +03:30
4a041ca8e2 add condition for null rollcall employee in IfEmloyeeHasNewLeftWorkDateAddEndDateToRollCallStatus 2025-12-03 12:10:48 +03:30
SamSys
de0de6fde8 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-02 15:01:41 +03:30
SamSys
70447a74ef change lunchSettings 2025-12-02 15:01:25 +03:30
90aa6058f0 Handle "*" in NationalCode assignment gracefully
Updated the `NationalCode` assignment in the `CreateInstitutionContractLegalPartyRequest` object to replace `"*"` with an empty string (`string.Empty`). This ensures compliance with business rules where `"*"` is not considered a valid value for `NationalCode`. Retains the original value otherwise.
2025-12-02 14:40:54 +03:30
3df296f205 Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-02 14:23:39 +03:30
6a2e4405de add check for gender if is empty 2025-12-02 14:00:01 +03:30
88c10ac141 Add phone and ID number series fields to temporary client registration result 2025-12-02 13:44:25 +03:30
SamSys
8de3939675 change lunch setting adddress 2025-12-02 13:06:22 +03:30
e78c838cab Add method to edit legal party details from institution in contracting party 2025-12-02 13:00:34 +03:30
SamSys
5e4b8a3a80 change static file permiission 2025-12-02 11:51:13 +03:30
SamSys
a18984fec1 add account to static list 2025-12-02 11:37:29 +03:30
a178fcd202 Add logic to count absences on Fridays and Thursdays without leave 2025-12-01 19:37:17 +03:30
9e92d2215f Add institution contract workflow count functionality to admin workflow 2025-12-01 10:53:26 +03:30
c63eb23b22 Handle null API response in employee authorization checks 2025-12-01 10:07:09 +03:30
238926118f Handle additional status code 3 in UID service response for employee authorization checks 2025-11-30 11:09:25 +03:30
c874164ca2 Merge branch 'Feature/InstitutionContract/set-discount' 2025-11-29 20:08:00 +03:30
720e998a54 Return null if FirstName is missing in UID service response and improve null checks in GetPersonalInfo 2025-11-29 12:30:12 +03:30
626722e805 Handle null response from UID service in GetPersonalInfo and return appropriate failure message 2025-11-29 11:43:58 +03:30
SamSys
901a4ebd35 check httpContext for api to currentUrl 2025-11-27 13:46:42 +03:30
SamSys
16b04fc75c ProgrmmaagerUserAccount completed 2025-11-27 10:48:03 +03:30
SamSys
86ac300e00 edit role completed 2025-11-26 13:37:04 +03:30
SamSys
90a420c8c5 unitOfWork Added 2025-11-23 12:28:05 +03:30
SamSys
73563b0421 add create ProgramManagerAccount Api 2025-11-22 19:47:11 +03:30
0fbd5c9d3e Add print methods and ContractPrintViewModel class
Updated the `IContractApplication` interface:
- Added `PrintOneAsync(long id)` and `PrintAllAsync(List<long> ids)` methods.
- Corrected formatting of `DeleteAllContarcts(List<long> ids)`.
- Grouped changes under the `NewChangeByHeydari` region.

Introduced the `ContractPrintViewModel` class (currently empty).

Implemented `PrintOneAsync` and `PrintAllAsync` in `ContractApplication` with `NotImplementedException`.

These changes prepare the codebase for contract printing functionality.
2025-11-11 19:29:51 +03:30
8436f70aa0 Refactor and enhance contract handling logic
- Added `DailyWage`, `AvgWorkingHour`, and `FamilyAllowance` properties to `GetContractListForClientResponse`.
- Refactored `WorkingHoursWeekly` conversion logic by introducing a reusable `WeeklyHourConvertor` method in `ContractRepository`.
- Updated query result mapping to include new properties and utilize `WeeklyHourConvertor` for `AvgWorkingHour`.
- Improved code readability and maintainability by centralizing repetitive logic.
2025-11-11 19:26:45 +03:30
9cf8447a83 feat: add API for retrieving paginated contract list for client with filtering options 2025-11-03 17:49:51 +03:30
e124a4d5d9 feat: implement method to retrieve paginated contract list for client with filtering options 2025-11-03 17:43:50 +03:30
7b9e7881c6 feat: add commented-out method for retrieving contract list for client 2025-11-03 14:45:41 +03:30
557 changed files with 68003 additions and 6887 deletions

View File

@@ -5,8 +5,6 @@ on:
branches:
- Main
env:
DOTNET_ENVIRONMENT: Development
jobs:
build-and-deploy:
@@ -37,12 +35,11 @@ jobs:
& "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" `
-verb:sync `
-source:contentPath="$publishFolder" `
-dest:contentPath="dadmehrg",computerName="https://171.22.24.15:8172/msdeploy.axd?site=dadmehrg",userName="Administrator",password="R2rNpdnetP3j>q5b18",authType="Basic" `
-dest:contentPath="dadmehrg",computerName="https://$env:SERVER_HOST:8172/msdeploy.axd?site=gozareshgir",userName="$env:DEPLOY_USER",password="$env:DEPLOY_PASSWORD",authType="Basic" `
-allowUntrusted `
-enableRule:AppOffline
env:
SERVER_HOST: your-server-ip-or-domain
SERVER_HOST: 171.22.24.15
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PASSWORD: ${{ secrets.DEPLOY_PASSWORD }}

View File

@@ -1,21 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>_0_Framework</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IPE.SmsIR" Version="1.0.5" />
<PackageReference Include="EPPlus" Version="7.5.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.1.34" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.2" />
<PackageReference Include="FluentValidation" Version="12.1.1" />
<PackageReference Include="IPE.SmsIR" Version="1.2.7" />
<PackageReference Include="EPPlus" Version="8.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.3" />
<PackageReference Include="PersianTools.Core" Version="2.0.4" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.2.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.1" />
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.6.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.0.1" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />

View File

@@ -56,6 +56,11 @@ public class AuthHelper : IAuthHelper
return Tools.DeserializeFromBsonList<int>(permissions); //Mahan
}
public bool HasPermission(int permission)
{
return GetPermissions().Any(x => x == permission);
}
public long CurrentAccountId()
{
return IsAuthenticated()
@@ -198,7 +203,8 @@ public class AuthHelper : IAuthHelper
new("workshopList",workshopBson),
new("WorkshopSlug",slug),
new("WorkshopId", account.WorkshopId.ToString()),
new("WorkshopName",account.WorkshopName??"")
new("WorkshopName",account.WorkshopName??""),
new("pm.userId", account.PmUserId.ToString()),
};

View File

@@ -27,10 +27,12 @@ public class AuthViewModel
#endregion
public long SubAccountId { get; set; }
public long? PmUserId { get; set; }
public AuthViewModel(long id, long roleId, string fullname, string username, string mobile,string profilePhoto,
List<int> permissions, string roleName, string adminAreaPermission, string clientAriaPermission, int? positionValue, long subAccountId = 0)
List<int> permissions, string roleName, string adminAreaPermission, string clientAriaPermission, int? positionValue,
long subAccountId = 0,long? pmUserId = null)
{
Id = id;
RoleId = roleId;
@@ -44,6 +46,7 @@ public class AuthViewModel
ClientAriaPermission = clientAriaPermission;
PositionValue = positionValue;
SubAccountId = subAccountId;
PmUserId = pmUserId;
}
public AuthViewModel()

View File

@@ -33,4 +33,9 @@ public enum TypeOfSmsSetting
/// </summary>
LegalAction,
/// <summary>
/// پیامک تایید قراداد
/// </summary>
InstitutionContractConfirm,
}

View File

@@ -11,6 +11,7 @@ public interface IFaceEmbeddingService
Task<OperationResult> RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding, float confidence, Dictionary<string, object> metadata = null);
Task<OperationResult> DeleteEmbeddingAsync(long employeeId, long workshopId);
Task<OperationResult<FaceEmbeddingResponse>> GetEmbeddingAsync(long employeeId, long workshopId);
Task<OperationResult> UpdateEmbeddingFullNameAsync(long employeeId, long workshopId, string newFullName);
}
public class FaceEmbeddingResponse

View File

@@ -12,6 +12,7 @@ public interface IAuthHelper
string CurrentAccountRole();
AuthViewModel CurrentAccountInfo();
List<int> GetPermissions();
bool HasPermission(int permission);
long CurrentAccountId();
string CurrentAccountMobile();

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _0_Framework.Application;
public static class SecretKeys
{
public static string ProgramManagerInternalApi => "JOb09$Ic3NJd0siLCJtYWMiOiI2%dmODJmNDV";
}

View File

@@ -27,7 +27,7 @@ public interface ISmsService
Task<double> GetCreditAmount();
public Task<bool> SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId);
public Task<bool> SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms = null);
public Task<bool> SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName,
long contractingPartyId, long institutionContractId);

View File

@@ -32,11 +32,22 @@ public static class StaticWorkshopAccounts
/// 392 - عمار حسن دوست
/// 20 - سمیرا الهی نیا
/// </summary>
public static List<long> StaticAccountIds = [2, 3, 380, 381, 392, 20];
public static List<long> StaticAccountIds = [2, 3, 380, 381, 392, 20, 476];
/// <summary>
/// این تاریخ در جدول اکانت لفت ورک به این معنیست
/// که کاربر همچنان به کارگاه دسترسی دارد
/// </summary>
public static DateTime ContinuesWorkingDate = new DateTime(2150, 1, 1);
/// <summary>
/// لیستی آی دی نقش هایی که مسئول بیمه کارگاه هستند
/// 7 : بیمه ارشد
/// 8 : بیمه ساده
/// </summary>
public static List<long> InsuranceAccountsRoleIds = [7, 8];
}

View File

@@ -17,7 +17,7 @@ public class ExcelGenerator
{
public ExcelGenerator()
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
}
public static byte[] GenerateExcel<T>(List<T> obj, string date = "") where T : class
{

View File

@@ -1,7 +1,10 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentValidation;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -21,12 +24,24 @@ public class CustomExceptionHandler : IExceptionHandler
public async ValueTask<bool> TryHandleAsync(HttpContext context, Exception exception, CancellationToken cancellationToken)
{
_logger.LogError(
"Error Message: {exceptionMessage}, Time of occurrence {time}",
exception.Message, DateTime.UtcNow);
_logger.LogError(exception,
"Error Message: {exceptionMessage}, Type: {exceptionType}, Time: {time}, Path: {path}, TraceId: {traceId}",
exception.Message,
exception.GetType().FullName,
DateTime.UtcNow,
context.Request.Path,
context.TraceIdentifier);
(string Detail, string Title, int StatusCode, Dictionary<string, object>? Extra) details = exception switch
{
ValidationException validationException =>
(
validationException.Errors.FirstOrDefault()?.ErrorMessage ?? "One or more validation errors occurred.",
"Validation Error",
context.Response.StatusCode = StatusCodes.Status400BadRequest,
null
),
InternalServerException =>
(
exception.Message,
@@ -34,6 +49,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status500InternalServerError,
null
),
BadRequestException bre =>
(
exception.Message,
@@ -41,6 +57,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status400BadRequest,
bre.Extra
),
NotFoundException =>
(
exception.Message,
@@ -48,6 +65,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status404NotFound,
null
),
UnAuthorizeException =>
(
exception.Message,
@@ -55,6 +73,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status401Unauthorized,
null
),
_ =>
(
exception.Message,
@@ -73,8 +92,6 @@ public class CustomExceptionHandler : IExceptionHandler
Extensions = details.Extra ?? new Dictionary<string, object>()
};
problemDetails.Extensions.Add("traceId", context.TraceIdentifier);
await context.Response.WriteAsJsonAsync(problemDetails, cancellationToken: cancellationToken);

View File

@@ -18,329 +18,387 @@ namespace _0_Framework.Infrastructure;
/// </summary>
public class FaceEmbeddingService : IFaceEmbeddingService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<FaceEmbeddingService> _logger;
private readonly IFaceEmbeddingNotificationService _notificationService;
private readonly string _apiBaseUrl;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<FaceEmbeddingService> _logger;
private readonly IFaceEmbeddingNotificationService _notificationService;
private readonly string _apiBaseUrl;
public FaceEmbeddingService(IHttpClientFactory httpClientFactory, ILogger<FaceEmbeddingService> logger,
IFaceEmbeddingNotificationService notificationService = null)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
_notificationService = notificationService;
_apiBaseUrl = "http://localhost:8000";
}
public FaceEmbeddingService(IHttpClientFactory httpClientFactory, ILogger<FaceEmbeddingService> logger,
IFaceEmbeddingNotificationService notificationService = null)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
_notificationService = notificationService;
_apiBaseUrl = "http://localhost:8000";
}
public async Task<OperationResult> GenerateEmbeddingsAsync(long employeeId, long workshopId,
string employeeFullName, string picture1Path, string picture2Path)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
public async Task<OperationResult> GenerateEmbeddingsAsync(long employeeId, long workshopId,
string employeeFullName, string picture1Path, string picture2Path)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
using var content = new MultipartFormDataContent();
using var content = new MultipartFormDataContent();
// Add form fields
content.Add(new StringContent(employeeId.ToString()), "employee_id");
content.Add(new StringContent(workshopId.ToString()), "workshop_id");
content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name");
// Add form fields
content.Add(new StringContent(employeeId.ToString()), "employee_id");
content.Add(new StringContent(workshopId.ToString()), "workshop_id");
content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name");
// Add picture files
if (File.Exists(picture1Path))
{
var picture1Bytes = await File.ReadAllBytesAsync(picture1Path);
var picture1Content = new ByteArrayContent(picture1Bytes);
picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture1Content, "picture1", "1.jpg");
}
else
{
_logger.LogWarning("Picture1 not found at path: {Path}", picture1Path);
return new OperationResult { IsSuccedded = false, Message = "تصویر اول یافت نشد" };
}
// Add picture files
if (File.Exists(picture1Path))
{
var picture1Bytes = await File.ReadAllBytesAsync(picture1Path);
var picture1Content = new ByteArrayContent(picture1Bytes);
picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture1Content, "picture1", "1.jpg");
}
else
{
_logger.LogWarning("Picture1 not found at path: {Path}", picture1Path);
return new OperationResult { IsSuccedded = false, Message = "تصویر اول یافت نشد" };
}
if (File.Exists(picture2Path))
{
var picture2Bytes = await File.ReadAllBytesAsync(picture2Path);
var picture2Content = new ByteArrayContent(picture2Bytes);
picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture2Content, "picture2", "2.jpg");
}
else
{
_logger.LogWarning("Picture2 not found at path: {Path}", picture2Path);
return new OperationResult { IsSuccedded = false, Message = "تصویر دوم یافت نشد" };
}
if (File.Exists(picture2Path))
{
var picture2Bytes = await File.ReadAllBytesAsync(picture2Path);
var picture2Content = new ByteArrayContent(picture2Bytes);
picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture2Content, "picture2", "2.jpg");
}
else
{
_logger.LogWarning("Picture2 not found at path: {Path}", picture2Path);
return new OperationResult { IsSuccedded = false, Message = "تصویر دوم یافت نشد" };
}
// Send request to Python API
var response = await httpClient.PostAsync("embeddings", content);
// Send request to Python API
var response = await httpClient.PostAsync("embeddings", content);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
_logger.LogInformation("Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}",
employeeId, workshopId);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
_logger.LogInformation(
"Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}",
employeeId, workshopId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName);
}
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName);
}
return new OperationResult
{
IsSuccedded = true,
Message = "Embedding با موفقیت ایجاد شد"
};
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to generate embeddings. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult
{
IsSuccedded = true,
Message = "Embedding با موفقیت ایجاد شد"
};
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to generate embeddings. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در تولید Embedding: {response.StatusCode}"
};
}
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "HTTP error while calling embeddings API for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در ارتباط با سرور Embedding"
};
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while calling embeddings API for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطای غیرمنتظره در تولید Embedding"
};
}
}
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در تولید Embedding: {response.StatusCode}"
};
}
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "HTTP error while calling embeddings API for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در ارتباط با سرور Embedding"
};
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while calling embeddings API for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطای غیرمنتظره در تولید Embedding"
};
}
}
public async Task<OperationResult> GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId,
string employeeFullName, Stream picture1Stream, Stream picture2Stream)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
public async Task<OperationResult> GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId,
string employeeFullName, Stream picture1Stream, Stream picture2Stream)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
using var content = new MultipartFormDataContent();
using var content = new MultipartFormDataContent();
// Add form fields
content.Add(new StringContent(employeeId.ToString()), "employee_id");
content.Add(new StringContent(workshopId.ToString()), "workshop_id");
content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name");
// Add form fields
content.Add(new StringContent(employeeId.ToString()), "employee_id");
content.Add(new StringContent(workshopId.ToString()), "workshop_id");
content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name");
// Add picture streams
var picture1Content = new StreamContent(picture1Stream);
picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture1Content, "picture1", "1.jpg");
// Add picture streams
var picture1Content = new StreamContent(picture1Stream);
picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture1Content, "picture1", "1.jpg");
var picture2Content = new StreamContent(picture2Stream);
picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture2Content, "picture2", "2.jpg");
var picture2Content = new StreamContent(picture2Stream);
picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
content.Add(picture2Content, "picture2", "2.jpg");
// Send request to Python API
var response = await httpClient.PostAsync("embeddings", content);
// Send request to Python API
var response = await httpClient.PostAsync("embeddings", content);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}", employeeId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName);
}
return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to generate embeddings from streams. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}",
employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در تولید Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در تولید Embedding"
};
}
}
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName);
}
public async Task<OperationResult> RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding,
float confidence, Dictionary<string, object> metadata = null)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to generate embeddings from streams. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
var requestBody = new
{
employeeId,
workshopId,
embedding,
confidence,
metadata = metadata ?? new Dictionary<string, object>()
};
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در تولید Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}",
employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در تولید Embedding"
};
}
}
var response = await httpClient.PostAsJsonAsync("embeddings/refine", requestBody);
public async Task<OperationResult> RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding,
float confidence, Dictionary<string, object> metadata = null)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embedding refined successfully for Employee {EmployeeId}", employeeId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId);
}
return new OperationResult { IsSuccedded = true, Message = "Embedding بهبود یافت" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
var requestBody = new
{
employeeId,
workshopId,
embedding,
confidence,
metadata = metadata ?? new Dictionary<string, object>()
};
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در بهبود Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while refining embedding for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در بهبود Embedding"
};
}
}
var response = await httpClient.PostAsJsonAsync("embeddings/refine", requestBody);
public async Task<OperationResult> DeleteEmbeddingAsync(long employeeId, long workshopId)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embedding refined successfully for Employee {EmployeeId}", employeeId);
var response = await httpClient.DeleteAsync($"embeddings/{workshopId}/{employeeId}");
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId);
}
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embedding deleted successfully for Employee {EmployeeId}", employeeId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingDeletedAsync(workshopId, employeeId);
}
return new OperationResult { IsSuccedded = true, Message = "Embedding حذف شد" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to delete embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult { IsSuccedded = true, Message = "Embedding بهبود یافت" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در حذف Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while deleting embedding for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در حذف Embedding"
};
}
}
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در بهبود Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while refining embedding for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در بهبود Embedding"
};
}
}
public async Task<OperationResult<FaceEmbeddingResponse>> GetEmbeddingAsync(long employeeId, long workshopId)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
public async Task<OperationResult> DeleteEmbeddingAsync(long employeeId, long workshopId)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
var response = await httpClient.GetAsync($"embeddings/{workshopId}/{employeeId}");
var response = await httpClient.DeleteAsync($"embeddings/{workshopId}/{employeeId}");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var embeddingData = JsonSerializer.Deserialize<FaceEmbeddingResponse>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embedding deleted successfully for Employee {EmployeeId}", employeeId);
_logger.LogInformation("Embedding retrieved successfully for Employee {EmployeeId}", employeeId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
await _notificationService.NotifyEmbeddingDeletedAsync(workshopId, employeeId);
}
return new OperationResult<FaceEmbeddingResponse>
{
IsSuccedded = true,
Message = "Embedding دریافت شد",
Data = embeddingData
};
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to get embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult<FaceEmbeddingResponse>
{
IsSuccedded = false,
Message = $"خطا در دریافت Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while getting embedding for Employee {EmployeeId}", employeeId);
return new OperationResult<FaceEmbeddingResponse>
{
IsSuccedded = false,
Message = "خطا در دریافت Embedding"
};
}
}
}
return new OperationResult { IsSuccedded = true, Message = "Embedding حذف شد" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to delete embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در حذف Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while deleting embedding for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در حذف Embedding"
};
}
}
public async Task<OperationResult<FaceEmbeddingResponse>> GetEmbeddingAsync(long employeeId, long workshopId)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
var response = await httpClient.GetAsync($"embeddings/{workshopId}/{employeeId}");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var embeddingData = JsonSerializer.Deserialize<FaceEmbeddingResponse>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
_logger.LogInformation("Embedding retrieved successfully for Employee {EmployeeId}", employeeId);
return new OperationResult<FaceEmbeddingResponse>
{
IsSuccedded = true,
Message = "Embedding دریافت شد",
Data = embeddingData
};
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to get embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult<FaceEmbeddingResponse>
{
IsSuccedded = false,
Message = $"خطا در دریافت Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while getting embedding for Employee {EmployeeId}", employeeId);
return new OperationResult<FaceEmbeddingResponse>
{
IsSuccedded = false,
Message = "خطا در دریافت Embedding"
};
}
}
public async Task<OperationResult> UpdateEmbeddingFullNameAsync(long employeeId, long workshopId,
string newFullName)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
var requestBody = new
{
employee_id = employeeId,
workshop_id = workshopId,
employee_full_name = newFullName
};
var response = await httpClient.PutAsJsonAsync("embeddings/update-name", requestBody);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Employee Name Changed For {EmployeeId} In workshop ={WorkshopId}", employeeId,
workshopId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
//await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId);
}
return new OperationResult { IsSuccedded = true, Message = "عملیات با موفقیت انجام شد" };
}
else
{
var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}",
response.StatusCode, errorContent);
return new OperationResult
{
IsSuccedded = false,
Message = $"خطا در بهبود Embedding: {response.StatusCode}"
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while Changing EmployeeFullName for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در بهبود Embedding"
};
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using AccountManagement.Application.Contracts.Role;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace AccountManagement.Application.Contracts.Account;
@@ -35,4 +36,20 @@ public class CreateAccount
public string Email { get; set; }
public string VerifyCode { get; set; }
public string IsActiveString { get; set; }
/// <summary>
/// آیا کاربر در پروگرام منیجر فعالیت مبکند؟
/// </summary>
public bool IsProgramManagerUser { get; set; }
/// <summary>
/// لیست نقش های پروگرام منیجر
/// </summary>
public List<long> UserRoles { get; set; }
/// <summary>
/// لیست نقشهای موجود در پروگرام منیجر
/// </summary>
public SelectList RoleList { get; set; }
}

View File

@@ -3,4 +3,5 @@
public class EditAccount : CreateAccount
{
public long Id { get; set; }
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AccountManagement.Application.Contracts.Account;
namespace AccountManagement.Application.Contracts.Account;
public class EditClientAccount : RegisterAccount
{

View File

@@ -2,15 +2,21 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Shared.Contracts.PmUser.Queries;
namespace AccountManagement.Application.Contracts.Account;
public interface IAccountApplication
{
AccountViewModel GetAccountBy(long id);
OperationResult Create(CreateAccount command);
/// <summary>
/// ایجاد کاربر گزارشگیر و پروگرام منیجر
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
Task<OperationResult> Create(CreateAccount command);
OperationResult RegisterClient(RegisterAccount command);
OperationResult Edit(EditAccount command);
Task<OperationResult> Edit(EditAccount command);
OperationResult EditClient(EditClientAccount command);
OperationResult ChangePassword(ChangePassword command);
OperationResult Login(Login command);
@@ -67,6 +73,9 @@ public interface IAccountApplication
List<AccountViewModel> GetAdminAccountsNew();
void CameraLogin(CameraLoginRequest request);
Task<GetPmUserDto> GetPmUserAsync(long accountId);
}
public class CameraLoginRequest

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _0_Framework.Application;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
namespace AccountManagement.Application.Contracts.Account;

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AccountManagement.Application.Contracts.Account;
namespace AccountManagement.Application.Contracts.Account;
public class WorkshopSelectList
{

View File

@@ -1,15 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\0_Framework\0_Framework.csproj" />
<ProjectReference Include="..\Shared.Contracts\Shared.Contracts.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,11 @@
namespace AccountManagement.Application.Contracts.ProgramManagerApiResult;
public record ApiResponse
{
public bool isSuccess { get; set; }
public string errorMessage { get; set; }
public ErrorType ErrorType { get; set; }
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace AccountManagement.Application.Contracts.ProgramManagerApiResult;
public record CreateProgramManagerRole
{
/// <summary>
/// نام نقش
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// کدهای دسترسی
/// </summary>
public List<int> Permissions { get; set; }
/// <summary>
/// آی دی اکانت گزارشگیر
/// </summary>
public long? GozareshgirRoleId { get; set; }
};

View File

@@ -0,0 +1,7 @@
using System.Collections.Generic;
namespace AccountManagement.Application.Contracts.ProgramManagerApiResult;
public record CreateProgramManagerUser(string FullName, string UserName, string Password, string Mobile, string Email, long? AccountId, List<long> Roles);
public record EditUserCommand(string FullName, string UserName, string Mobile, long AccountId, List<long> Roles, bool IsActive);

View File

@@ -0,0 +1,11 @@
namespace AccountManagement.Application.Contracts.ProgramManagerApiResult;
public enum ErrorType
{
None,
BadRequest,
NotFound,
Unauthorized,
Validation,
InternalServerError
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace AccountManagement.Application.Contracts.ProgramManagerApiResult;
public class RoleResponse
{
public bool isSuccess { get; set; }
public RolesData data { get; set; }
}
public class RolesData
{
public List<RoleList> role { get; set; }
}
public class RoleList
{
public int id { get; set; }
public string roleName { get; set; }
public int gozareshgirRoleId { get; set; }
public List<int> permissions { get; set; }
}

View File

@@ -0,0 +1,55 @@
using System.Collections.Generic;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace AccountManagement.Application.Contracts.ProgramManagerApiResult;
public record SingleUserResponseResult
{
public bool isSuccess { get; set; }
public SingleUserData Data { get; set; }
};
public record SingleUserData
{
public long id { get; set; }
/// <summary>
/// نام و نام خانوادگی
/// </summary>
public string fullName { get; set; }
/// <summary>
/// نام کاربری
/// </summary>
public string userName { get; set; }
/// <summary>
/// مسیر عکس پروفایل
/// </summary>
public string profilePhotoPath { get; set; }
/// <summary>
/// شماره موبایل
/// </summary>
public string mobile { get; set; }
/// <summary>
/// فعال/غیر فعال بودن یوزر
/// </summary>
public bool isActive { get; set; }
/// <summary>
/// گذرواژه
/// </summary>
public string password { get; set; }
/// <summary>
/// ای دی اکانت کاربر در گزارشگیر
/// </summary>
public long? accountId { get; set; }
public List<long> Roles { get; set; }
}

View File

@@ -9,6 +9,10 @@ namespace AccountManagement.Application.Contracts.Role
[Required(ErrorMessage = ValidationMessages.IsRequired)]
public string Name { get; set; }
public List<int> Permissions { get; set; }
/// <summary>
/// لیست پرمیشن های پروگرام منیجر
/// </summary>
public List<int> PmPermissions { get; set; }
}
}

View File

@@ -1,13 +1,26 @@
using _0_Framework.Application;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
using System.Threading.Tasks;
using Shared.Contracts.PmRole.Queries;
namespace AccountManagement.Application.Contracts.Role
{
public interface IRoleApplication
{
OperationResult Create(CreateRole command);
OperationResult Edit(EditRole command);
Task<OperationResult> Create(CreateRole command);
Task<OperationResult> Edit(EditRole command);
List<RoleViewModel> List();
EditRole GetDetails(long id);
#region ProgramManager
Task<SelectList> GetPmRoleList(long? gozareshgirRoleId);
Task<List<GetPmRolesDto>> GetPmRoleListToEdit(long? gozareshgirRoleId);
#endregion
}
}

View File

@@ -1,29 +1,26 @@
using System;
using System.Collections;
using _0_Framework.Application;
using _0_Framework.Application;
using _0_Framework.Application.Sms;
using _0_Framework.Exceptions;
using AccountManagement.Application.Contracts.Account;
using AccountManagement.Domain.AccountAgg;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using _0_Framework.Application.Sms;
using AccountManagement.Domain.AccountLeftWorkAgg;
using AccountManagement.Domain.CameraAccountAgg;
using AccountManagement.Domain.RoleAgg;
using CompanyManagment.App.Contracts.Workshop;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using Company.Domain.WorkshopAgg;
using System.Security.Claims;
using _0_Framework.Exceptions;
using AccountManagement.Domain.PositionAgg;
using AccountManagement.Domain.RoleAgg;
using AccountManagement.Domain.SubAccountAgg;
using AccountManagement.Domain.SubAccountPermissionSubtitle1Agg;
using AccountManagement.Domain.SubAccountRoleAgg;
using Company.Domain._common;
using Company.Domain.WorkshopAgg;
using Company.Domain.WorkshopSubAccountAgg;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Shared.Contracts.PmUser.Commands;
using Shared.Contracts.PmUser.Queries;
//using AccountManagement.Domain.RoleAgg;
@@ -39,15 +36,19 @@ public class AccountApplication : IAccountApplication
private readonly ISmsService _smsService;
private readonly ICameraAccountRepository _cameraAccountRepository;
private readonly IPositionRepository _positionRepository;
private readonly IAccountLeftworkRepository _accountLeftworkRepository;
private readonly IAccountLeftworkRepository _accountLeftworkRepository;
private readonly IWorkshopRepository _workshopRepository;
private readonly ISubAccountRepository _subAccountRepository;
private readonly ISubAccountRoleRepository _subAccountRoleRepository;
private readonly IWorkshopSubAccountRepository _workshopSubAccountRepository;
private readonly ISubAccountPermissionSubtitle1Repository _accountPermissionSubtitle1Repository;
public AccountApplication(IAccountRepository accountRepository, IPasswordHasher passwordHasher,
IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository)
private readonly IUnitOfWork _unitOfWork;
private readonly IPmUserQueryService _pmUserQueryService;
private readonly IPmUserCommandService _pmUserCommandService;
public AccountApplication(IAccountRepository accountRepository, IPasswordHasher passwordHasher,
IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserQueryService pmUserQueryService, IPmUserCommandService pmUserCommandService)
{
_authHelper = authHelper;
_roleRepository = roleRepository;
@@ -60,10 +61,14 @@ public class AccountApplication : IAccountApplication
_subAccountRoleRepository = subAccountRoleRepository;
_workshopSubAccountRepository = workshopSubAccountRepository;
_accountPermissionSubtitle1Repository = accountPermissionSubtitle1Repository;
_unitOfWork = unitOfWork;
_pmUserQueryService = pmUserQueryService;
_pmUserCommandService = pmUserCommandService;
_fileUploader = fileUploader;
_passwordHasher = passwordHasher;
_accountRepository = accountRepository;
}
public OperationResult EditClient(EditClientAccount command)
@@ -92,7 +97,7 @@ public class AccountApplication : IAccountApplication
var path = $"profilePhotos";
var picturePath = _fileUploader.Upload(command.ProfilePhoto, path);
editAccount.EditClient(command.Fullname,command.Username,command.Mobile,picturePath,command.Email,command.NationalCode);
editAccount.EditClient(command.Fullname, command.Username, command.Mobile, picturePath, command.Email, command.NationalCode);
_accountRepository.SaveChanges();
return opreation.Succcedded();
}
@@ -123,7 +128,7 @@ public class AccountApplication : IAccountApplication
};
}
public OperationResult Create(CreateAccount command)
public async Task<OperationResult> Create(CreateAccount command)
{
var operation = new OperationResult();
@@ -133,15 +138,59 @@ public class AccountApplication : IAccountApplication
var password = _passwordHasher.Hash(command.Password);
var roleName = _roleRepository.GetDetails(command.RoleId);
var path = $"profilePhotos";
var picturePath = "";
if (_fileUploader != null)
{
var picturePath = _fileUploader.Upload(command.ProfilePhoto, path);
var account = new Account(command.Fullname, command.Username, password, command.Mobile, command.RoleId,
picturePath, roleName.Name,"true","false");
_accountRepository.Create(account);
picturePath = _fileUploader.Upload(command.ProfilePhoto, path);
}
var account = new Account(command.Fullname, command.Username, password, command.Mobile, command.RoleId,
picturePath, roleName.Name, "true", "false");
_unitOfWork.BeginAccountContext();
_accountRepository.Create(account);
_accountRepository.SaveChanges();
if (command.IsProgramManagerUser)
{
if (command.UserRoles == null)
return operation.Failed("حداقل یک نقش برای کاربر مدیریت پروژه لازم است");
var pmUserRoles = command.UserRoles.Where(x => x > 0).ToList();
var createPm = await _pmUserCommandService.Create(new CreatePmUserDto(command.Fullname, command.Username, account.Password, command.Mobile,
null, account.id, pmUserRoles));
if (!createPm.isSuccess)
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر");
}
//var url = "api/user/create";
//var key = SecretKeys.ProgramManagerInternalApi;
//var response = InternalApiCaller.PostAsync<CreateProgramManagerUser, ApiResponse>(
// url,
// key,
// parameters
//);
//if (!response.Success)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Error);
//}
//if (!response.Result.isSuccess)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Result.errorMessage);
//}
}
_accountRepository.SaveChanges();
_unitOfWork.CommitAccountContext();
return operation.Succcedded();
}
@@ -155,8 +204,8 @@ public class AccountApplication : IAccountApplication
return opreation.Failed("پر کردن تمامی فیلدها الزامی است");
if (_accountRepository.Exists(x => x.Username == command.Username))
return opreation.Failed("نام کاربری تکراری است");
if (_accountRepository.Exists(x => x.Mobile == command.Mobile && x.IsActiveString =="true"))
if (_accountRepository.Exists(x => x.Mobile == command.Mobile && x.IsActiveString == "true"))
return opreation.Failed("مقادیر وارد شده تکراری است");
//var nationalCodeValidation = command.NationalCode.NationalCodeValid();
@@ -173,14 +222,14 @@ public class AccountApplication : IAccountApplication
// break;
//}
var password = _passwordHasher.Hash(command.Password);
var register =new Account(command.Fullname,command.Username, password, command.Mobile, command.NationalCode);
var register = new Account(command.Fullname, command.Username, password, command.Mobile, command.NationalCode);
_accountRepository.Create(register);
_accountRepository.SaveChanges();
return opreation.Succcedded(register.id,message: "ثبت نام شما با موفقیت انجام شد");
return opreation.Succcedded(register.id, message: "ثبت نام شما با موفقیت انجام شد");
}
public OperationResult Edit(EditAccount command)
public async Task<OperationResult> Edit(EditAccount command)
{
var operation = new OperationResult();
var account = _accountRepository.Get(command.Id);
@@ -194,8 +243,129 @@ public class AccountApplication : IAccountApplication
var roleName = _roleRepository.GetDetails(command.RoleId);
var path = $"profilePhotos";
var picturePath = _fileUploader.Upload(command.ProfilePhoto, path);
_unitOfWork.BeginAccountContext();
account.Edit(command.Fullname, command.Username, command.Mobile, command.RoleId, picturePath, roleName.Name);
_accountRepository.SaveChanges();
var key = SecretKeys.ProgramManagerInternalApi;
//var apiResult = InternalApiCaller.GetAsync<SingleUserResponseResult>(
// $"api/user/{account.id}",
// key
//);
var userResult =await _pmUserQueryService.GetPmUserDataByAccountId(account.id);
if (command.UserRoles == null)
return operation.Failed("حداقل یک نقش برای کاربر مدیریت پروژه لازم است");
var pmUserRoles = command.UserRoles.Where(x => x > 0).ToList();
//اگر کاربر در پروگرام منیجر قبلا ایجاد شده
if (userResult.Id >0)
{
if (!command.UserRoles.Any())
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("حداقل یک نقش باید انتخاب شود");
}
var editPm =await _pmUserCommandService.Edit(new EditPmUserDto(command.Fullname, command.Username, command.Mobile, account.id, pmUserRoles,
command.IsProgramManagerUser));
if (!editPm.isSuccess)
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر");
}
//var parameters = new EditUserCommand(
// command.Fullname,
// command.Username,
// command.Mobile,
// account.id,
// command.UserRoles,
// command.IsProgramManagerUser
//);
//var url = "api/user/edit";
//var response = InternalApiCaller.PostAsync<EditUserCommand, ApiResponse>(
// url,
// key,
// parameters
//);
//if (!response.Success)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Error);
//}
//if (!response.Result.isSuccess)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Error);
//}
}
else //اگر کاربر قبلا ایجاد نشده
{
//اگر تیک فعالیت در پروگرام منیجر روشن بود
if (command.IsProgramManagerUser)
{
if (!command.UserRoles.Any())
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("حداقل یک نقش باید انتخاب شود");
}
var createPm = await _pmUserCommandService.Create(new CreatePmUserDto(command.Fullname, command.Username, account.Password, command.Mobile,
null, account.id, pmUserRoles));
if (!createPm.isSuccess)
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر");
}
//var parameters = new CreateProgramManagerUser(
// command.Fullname,
// command.Username,
// account.Password,
// command.Mobile,
// command.Email,
// account.id,
// command.UserRoles
//);
//var url = "api/user/Create";
//var response = InternalApiCaller.PostAsync<CreateProgramManagerUser, ApiResponse>(
// url,
// key,
// parameters
//);
//if (!response.Success)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Error);
//}
//if (!response.Result.isSuccess)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Error);
//}
}
}
_unitOfWork.CommitAccountContext();
return operation.Succcedded();
}
@@ -210,18 +380,18 @@ public class AccountApplication : IAccountApplication
long idAutoriz = 0;
var operation = new OperationResult();
if (string.IsNullOrWhiteSpace(command.Password))
return operation.Failed(ApplicationMessages.EmptyPassword);
return operation.Failed(ApplicationMessages.EmptyPassword);
if (string.IsNullOrWhiteSpace(command.Username))
return operation.Failed(ApplicationMessages.EmptyUsername);
return operation.Failed(ApplicationMessages.EmptyUsername);
var account = _accountRepository.GetBy(command.Username);
var account = _accountRepository.GetBy(command.Username);
var cameraAccount = _cameraAccountRepository.GetBy(command.Username);
SubAccount subAccount = _subAccountRepository.GetBy(command.Username);
if (account == null && cameraAccount == null && subAccount == null)
return operation.Failed(ApplicationMessages.WrongUserPass);
SubAccount subAccount = _subAccountRepository.GetBy(command.Username);
if (account == null && cameraAccount == null && subAccount == null)
return operation.Failed(ApplicationMessages.WrongUserPass);
if (account != null)
if (account != null)
{
(bool Verified, bool NeedUpgrade) result = _passwordHasher.Check(account.Password, command.Password);
if (!result.Verified)
@@ -230,6 +400,23 @@ public class AccountApplication : IAccountApplication
.Permissions
.Select(x => x.Code)
.ToList();
//PmPermission
var PmUserData = _pmUserQueryService.GetPmUserDataByAccountId(account.id).GetAwaiter().GetResult();
if (PmUserData.AccountId > 0 && PmUserData.IsActive)
{
var pmUserPermissions =
PmUserData.RoleListDto != null
? PmUserData.RoleListDto
.SelectMany(x => x.Permissions)
.Where(p => p != 99)
.Distinct()
.ToList()
: new List<int>();
permissions.AddRange(pmUserPermissions);
}
int? positionValue;
if (account.PositionId != null)
{
@@ -239,14 +426,17 @@ public class AccountApplication : IAccountApplication
{
positionValue = null;
}
var pmUserId = PmUserData.AccountId > 0 ? PmUserData.AccountId : null;
var authViewModel = new AuthViewModel(account.id, account.RoleId, account.Fullname
, account.Username, account.Mobile, account.ProfilePhoto, permissions, account.RoleName, account.AdminAreaPermission, account.ClientAriaPermission, positionValue);
, account.Username, account.Mobile, account.ProfilePhoto,
permissions, account.RoleName, account.AdminAreaPermission,
account.ClientAriaPermission, positionValue,0,pmUserId);
if (account.ClientAriaPermission == "true" && account.AdminAreaPermission == "false" &&
account.IsActiveString == "true")
{
var clientPermissions = _accountPermissionSubtitle1Repository.GetAllPermissionCodes();
authViewModel.Permissions = clientPermissions;
var clientPermissions = _accountPermissionSubtitle1Repository.GetAllPermissionCodes();
authViewModel.Permissions = clientPermissions;
var workshopList = _workshopRepository.GetWorkshopsByClientAccountId(account.id).Select(x => new WorkshopClaim
{
PersonnelCount = x.PersonnelCount,
@@ -255,14 +445,14 @@ public class AccountApplication : IAccountApplication
Slug = _passwordHasher.SlugHasher(x.Id)
}).OrderByDescending(x => x.PersonnelCount).ToList();
authViewModel.WorkshopList = workshopList;
if (workshopList.Any())
{
var workshop = workshopList.First();
authViewModel.WorkshopName = workshop.Name;
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.Id);
if (workshopList.Any())
{
var workshop = workshopList.First();
authViewModel.WorkshopName = workshop.Name;
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.Id);
authViewModel.WorkshopId = workshop.Id;
}
}
}
_authHelper.Signin(authViewModel);
@@ -281,7 +471,7 @@ public class AccountApplication : IAccountApplication
var mobile = string.IsNullOrWhiteSpace(cameraAccount.Mobile) ? " " : cameraAccount.Mobile;
var authViewModel = new CameraAuthViewModel(cameraAccount.id, cameraAccount.WorkshopId,
cameraAccount.Username, mobile, cameraAccount.WorkshopName, cameraAccount.AccountId,cameraAccount.IsActiveSting);
cameraAccount.Username, mobile, cameraAccount.WorkshopName, cameraAccount.AccountId, cameraAccount.IsActiveSting);
if (cameraAccount.IsActiveSting == "true")
{
_authHelper.CameraSignIn(authViewModel);
@@ -291,41 +481,41 @@ public class AccountApplication : IAccountApplication
{
idAutoriz = 0;
}
}
if (subAccount != null)
{
(bool Verified, bool NeedUpgrade) result = _passwordHasher.Check(subAccount.Password, command.Password);
if (!result.Verified)
return operation.Failed(ApplicationMessages.WrongUserPass);
var role = _subAccountRoleRepository.Get(subAccount.SubAccountRoleId);
if (subAccount != null)
{
(bool Verified, bool NeedUpgrade) result = _passwordHasher.Check(subAccount.Password, command.Password);
if (!result.Verified)
return operation.Failed(ApplicationMessages.WrongUserPass);
var role = _subAccountRoleRepository.Get(subAccount.SubAccountRoleId);
var permissions = role.RolePermissions.Select(x => x.PermissionCode).ToList();
var authViewModel = new AuthViewModel(subAccount.AccountId, subAccount.SubAccountRoleId, subAccount.FullName
, subAccount.Username, subAccount.PhoneNumber, "", permissions, role.Title, "false",
"true", 0, subAccount.id);
var workshopList = _workshopSubAccountRepository.GetWorkshopsBySubAccountId(subAccount.id);
authViewModel.WorkshopList = workshopList.Select(x => new WorkshopClaim()
{
Slug = _passwordHasher.SlugHasher(x.WorkshopId),
Name = x.WorkshopName,
PersonnelCount = x.PersonnelCount,
Id = x.WorkshopId
}).ToList();
var permissions = role.RolePermissions.Select(x => x.PermissionCode).ToList();
var authViewModel = new AuthViewModel(subAccount.AccountId, subAccount.SubAccountRoleId, subAccount.FullName
, subAccount.Username, subAccount.PhoneNumber, "", permissions, role.Title, "false",
"true", 0, subAccount.id);
var workshopList = _workshopSubAccountRepository.GetWorkshopsBySubAccountId(subAccount.id);
authViewModel.WorkshopList = workshopList.Select(x => new WorkshopClaim()
{
Slug = _passwordHasher.SlugHasher(x.WorkshopId),
Name = x.WorkshopName,
PersonnelCount = x.PersonnelCount,
Id = x.WorkshopId
}).ToList();
if (workshopList.Any())
{
var workshop = workshopList.First();
authViewModel.WorkshopName = workshop.WorkshopName;
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.WorkshopId);
if (workshopList.Any())
{
var workshop = workshopList.First();
authViewModel.WorkshopName = workshop.WorkshopName;
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.WorkshopId);
authViewModel.WorkshopId = workshop.WorkshopId;
}
_authHelper.Signin(authViewModel);
idAutoriz = 2;
}
}
_authHelper.Signin(authViewModel);
idAutoriz = 2;
}
return operation.Succcedded(idAutoriz);
return operation.Succcedded(idAutoriz);
}
public OperationResult LoginWithMobile(long id)
{
@@ -356,24 +546,24 @@ public class AccountApplication : IAccountApplication
if (account.ClientAriaPermission == "true" && account.AdminAreaPermission == "false" &&
account.IsActiveString == "true")
{
var clientPermissions = _accountPermissionSubtitle1Repository.GetAllPermissionCodes();
authViewModel.Permissions = clientPermissions;
var workshopList = _workshopRepository.GetWorkshopsByClientAccountId(account.id).Select(x => new WorkshopClaim
{
PersonnelCount = x.PersonnelCount,
Id = x.Id,
Name = x.WorkshopFullName,
Slug = _passwordHasher.SlugHasher(x.Id)
}).OrderByDescending(x => x.PersonnelCount).ToList();
authViewModel.WorkshopList = workshopList;
if (workshopList.Any())
{
var workshop = workshopList.First();
authViewModel.WorkshopName = workshop.Name;
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.Id);
var clientPermissions = _accountPermissionSubtitle1Repository.GetAllPermissionCodes();
authViewModel.Permissions = clientPermissions;
var workshopList = _workshopRepository.GetWorkshopsByClientAccountId(account.id).Select(x => new WorkshopClaim
{
PersonnelCount = x.PersonnelCount,
Id = x.Id,
Name = x.WorkshopFullName,
Slug = _passwordHasher.SlugHasher(x.Id)
}).OrderByDescending(x => x.PersonnelCount).ToList();
authViewModel.WorkshopList = workshopList;
if (workshopList.Any())
{
var workshop = workshopList.First();
authViewModel.WorkshopName = workshop.Name;
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.Id);
authViewModel.WorkshopId = workshop.Id;
}
}
}
}
_authHelper.Signin(authViewModel);
long idAutoriz = 0;
@@ -429,7 +619,7 @@ public class AccountApplication : IAccountApplication
return _accountRepository.GetByUserNameAndId(id, username);
}
public async Task <OperationResult> SetVerifyCode(string phone, long id)
public async Task<OperationResult> SetVerifyCode(string phone, long id)
{
var operation = new OperationResult();
var account = _accountRepository.Get(id);
@@ -443,11 +633,11 @@ public class AccountApplication : IAccountApplication
_smsService.LoginSend(phone, r);
//TimeSpan delay = TimeSpan.FromSeconds(30);
await _accountRepository.RemoveCode(id);
return operation.Succcedded();
}
@@ -498,67 +688,67 @@ public class AccountApplication : IAccountApplication
.Select(x => x.Code)
.ToList();
_authHelper.SignOut();
var authViewModel = new AuthViewModel(account.id, account.RoleId, account.Fullname
, account.Username, account.Mobile, account.ProfilePhoto, permissions, account.RoleName, "false", "true",null);
var workshopList = _workshopRepository.GetWorkshopsByClientAccountId(account.id).Select(x => new WorkshopClaim
{
PersonnelCount = x.PersonnelCount,
Id = x.Id,
Name = x.WorkshopFullName,
Slug = _passwordHasher.SlugHasher(x.Id)
}).OrderByDescending(x => x.PersonnelCount).ToList();
, account.Username, account.Mobile, account.ProfilePhoto, permissions, account.RoleName, "false", "true", null);
var workshopList = _workshopRepository.GetWorkshopsByClientAccountId(account.id).Select(x => new WorkshopClaim
{
PersonnelCount = x.PersonnelCount,
Id = x.Id,
Name = x.WorkshopFullName,
Slug = _passwordHasher.SlugHasher(x.Id)
}).OrderByDescending(x => x.PersonnelCount).ToList();
authViewModel.WorkshopList = workshopList;
authViewModel.WorkshopList = workshopList;
var clientPermissions = _accountPermissionSubtitle1Repository.GetAllPermissionCodes();
var clientPermissions = _accountPermissionSubtitle1Repository.GetAllPermissionCodes();
authViewModel.Permissions = clientPermissions;
if (authViewModel.WorkshopList.Any())
{
var workshop = authViewModel.WorkshopList.First();
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.Id);
authViewModel.WorkshopName = workshop.Name;
if (authViewModel.WorkshopList.Any())
{
var workshop = authViewModel.WorkshopList.First();
authViewModel.WorkshopSlug = _passwordHasher.SlugHasher(workshop.Id);
authViewModel.WorkshopName = workshop.Name;
authViewModel.WorkshopId = workshop.Id;
}
_authHelper.Signin(authViewModel);
}
_authHelper.Signin(authViewModel);
return operation.Succcedded(2);
}
public OperationResult DirectCameraLogin(long cameraAccountId)
{
var prAcc = _authHelper.CurrentAccountInfo();
var operation = new OperationResult();
var cameraAccount = _cameraAccountRepository.GetById(cameraAccountId);
if (cameraAccount == null)
return operation.Failed("این اکانت وجود ندارد");
var prAcc = _authHelper.CurrentAccountInfo();
var operation = new OperationResult();
var cameraAccount = _cameraAccountRepository.GetById(cameraAccountId);
if (cameraAccount == null)
return operation.Failed("این اکانت وجود ندارد");
_authHelper.SignOut();
_authHelper.SignOut();
var mobile = string.IsNullOrWhiteSpace(cameraAccount.Mobile) ? " " : cameraAccount.Mobile;
var authViewModel = new CameraAuthViewModel(cameraAccount.id, cameraAccount.WorkshopId,
cameraAccount.Username, mobile, cameraAccount.WorkshopName, cameraAccount.AccountId, cameraAccount.IsActiveSting);
if (cameraAccount.IsActiveSting == "true")
{
_authHelper.CameraSignIn(authViewModel);
}
else
{
return operation.Failed("این اکانت غیر فعال شده است");
}
return operation.Succcedded(2);
var mobile = string.IsNullOrWhiteSpace(cameraAccount.Mobile) ? " " : cameraAccount.Mobile;
var authViewModel = new CameraAuthViewModel(cameraAccount.id, cameraAccount.WorkshopId,
cameraAccount.Username, mobile, cameraAccount.WorkshopName, cameraAccount.AccountId, cameraAccount.IsActiveSting);
if (cameraAccount.IsActiveSting == "true")
{
_authHelper.CameraSignIn(authViewModel);
}
else
{
return operation.Failed("این اکانت غیر فعال شده است");
}
return operation.Succcedded(2);
}
public AccountLeftWorkViewModel WorkshopList(long accountId)
{
string fullname = this._accountRepository.GetById(accountId).Fullname;
List<WorkshopAccountlistViewModel> source =_accountLeftworkRepository.WorkshopList(accountId);
List<WorkshopAccountlistViewModel> source = _accountLeftworkRepository.WorkshopList(accountId);
List<long> userWorkshopIds = source.Select(x => x.WorkshopId).ToList();
List<WorkshopSelectList> allWorkshops = this._accountLeftworkRepository.GetAllWorkshops();
List<AccountViewModel> accountSelectList = this._accountRepository.GetAdminAccountSelectList();
@@ -641,65 +831,65 @@ public class AccountApplication : IAccountApplication
#region Pooya
public OperationResult IsPhoneNumberAndPasswordValid(long accountId, string phoneNumber, string password, string rePassword)
{
OperationResult op = new();
OperationResult op = new();
var entity = _accountRepository.Get(accountId);
var entity = _accountRepository.Get(accountId);
if (entity == null)
return op.Failed(ApplicationMessages.RecordNotFound);
if (entity == null)
return op.Failed(ApplicationMessages.RecordNotFound);
if (!string.IsNullOrWhiteSpace(rePassword) || !string.IsNullOrWhiteSpace(password))
{
if (rePassword != password)
return op.Failed("تکرار رمز عبور با رمز عبور مطابقت ندارد");
if (!string.IsNullOrWhiteSpace(rePassword) || !string.IsNullOrWhiteSpace(password))
{
if (rePassword != password)
return op.Failed("تکرار رمز عبور با رمز عبور مطابقت ندارد");
if (password.Length < 8)
return op.Failed("رمز عبور نمی تواند کمتر از 8 کاراکتر باشد");
}
if (password.Length < 8)
return op.Failed("رمز عبور نمی تواند کمتر از 8 کاراکتر باشد");
}
if ((string.IsNullOrWhiteSpace(phoneNumber) || entity.Mobile == phoneNumber) && string.IsNullOrWhiteSpace(rePassword))
return op.Failed("چیزی برای تغییر وجود ندارد");
if ((string.IsNullOrWhiteSpace(phoneNumber) || entity.Mobile == phoneNumber) && string.IsNullOrWhiteSpace(rePassword))
return op.Failed("چیزی برای تغییر وجود ندارد");
if (!string.IsNullOrWhiteSpace(phoneNumber) && entity.Mobile != phoneNumber)
{
phoneNumber = phoneNumber.Trim();
if (phoneNumber.Length != 11)
return op.Failed("شماره تلفن همراه به درستی وارد نشده است");
if (_accountRepository.Exists(x => x.Mobile == phoneNumber && x.id != accountId) ||
_subAccountRepository.Exists(x => x.PhoneNumber == phoneNumber) ||
_cameraAccountRepository.Exists(x => x.Mobile == phoneNumber))
return op.Failed("قبلا یک حساب با این شماره ثبت شده است");
}
if (!string.IsNullOrWhiteSpace(phoneNumber) && entity.Mobile != phoneNumber)
{
phoneNumber = phoneNumber.Trim();
if (phoneNumber.Length != 11)
return op.Failed("شماره تلفن همراه به درستی وارد نشده است");
if (_accountRepository.Exists(x => x.Mobile == phoneNumber && x.id != accountId) ||
_subAccountRepository.Exists(x => x.PhoneNumber == phoneNumber) ||
_cameraAccountRepository.Exists(x => x.Mobile == phoneNumber))
return op.Failed("قبلا یک حساب با این شماره ثبت شده است");
}
return op.Succcedded();
}
return op.Succcedded();
}
public OperationResult ChangePasswordAndPhoneNumber(AccountChangePasswordAndPhoneNumber command)
{
OperationResult op = new();
command.PhoneNumber = command.PhoneNumber.Trim();
var entity = _accountRepository.Get(command.AccountId);
if (entity == null)
return op.Failed(ApplicationMessages.RecordNotFound);
var validationResult = IsPhoneNumberAndPasswordValid(command.AccountId, command.PhoneNumber, command.Password, command.RePassword);
if (validationResult.IsSuccedded == false)
return validationResult;
OperationResult op = new();
command.PhoneNumber = command.PhoneNumber.Trim();
var entity = _accountRepository.Get(command.AccountId);
if (entity == null)
return op.Failed(ApplicationMessages.RecordNotFound);
var validationResult = IsPhoneNumberAndPasswordValid(command.AccountId, command.PhoneNumber, command.Password, command.RePassword);
if (validationResult.IsSuccedded == false)
return validationResult;
if (!string.IsNullOrWhiteSpace(command.RePassword))
{
if (!string.IsNullOrWhiteSpace(command.RePassword))
{
entity.ChangePassword(_passwordHasher.Hash(command.Password));
}
entity.ChangePassword(_passwordHasher.Hash(command.Password));
}
if (!string.IsNullOrWhiteSpace(command.PhoneNumber))
{
entity.Edit(entity.Fullname, entity.Username, command.PhoneNumber, entity.RoleId, entity.ProfilePhoto, entity.RoleName);
}
_accountRepository.SaveChanges();
return op.Succcedded();
}
if (!string.IsNullOrWhiteSpace(command.PhoneNumber))
{
entity.Edit(entity.Fullname, entity.Username, command.PhoneNumber, entity.RoleId, entity.ProfilePhoto, entity.RoleName);
}
_accountRepository.SaveChanges();
return op.Succcedded();
}
//public UserClaimsResponseDTO GetClaimsForSignIn(Login command)
//{
// var operation = new OperationResult();
@@ -815,12 +1005,12 @@ public class AccountApplication : IAccountApplication
}
(bool Verified, bool NeedUpgrade) result = _passwordHasher.Check(cameraAccount.Password, request.Password);
if (!result.Verified)
throw new BadRequestException(ApplicationMessages.WrongUserPass);
var mobile = string.IsNullOrWhiteSpace(cameraAccount.Mobile) ? " " : cameraAccount.Mobile;
var authViewModel = new CameraAuthViewModel(cameraAccount.id, cameraAccount.WorkshopId,
cameraAccount.Username, mobile, cameraAccount.WorkshopName, cameraAccount.AccountId,
cameraAccount.IsActiveSting);
@@ -829,4 +1019,9 @@ public class AccountApplication : IAccountApplication
_authHelper.CameraSignIn(authViewModel);
}
public async Task<GetPmUserDto> GetPmUserAsync(long accountId)
{
return await _pmUserQueryService.GetPmUserDataByAccountId(accountId);
}
}

View File

@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AccountManagement.Application.Contracts\AccountManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\AccountManagement.Domain\AccountManagement.Domain.csproj" />
<ProjectReference Include="..\Company.Domain\Company.Domain.csproj" />
<ProjectReference Include="..\Shared.Contracts\Shared.Contracts.csproj" />
</ItemGroup>

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _0_Framework.Application;
using AccountManagement.Application.Contracts.Account;
using AccountManagement.Application.Contracts.CameraAccount;

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using _0_Framework.Application;

View File

@@ -2,6 +2,14 @@
using AccountManagement.Application.Contracts.Role;
using AccountManagement.Domain.RoleAgg;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Company.Domain._common;
using Microsoft.AspNetCore.Mvc.Rendering;
using Shared.Contracts.PmRole.Commands;
using GetPmRolesDto = Shared.Contracts.PmRole.Queries.GetPmRolesDto;
using Role = AccountManagement.Domain.RoleAgg.Role;
using Shared.Contracts.PmRole.Queries;
namespace AccountManagement.Application;
@@ -9,32 +17,82 @@ public class RoleApplication : IRoleApplication
{
private readonly IRoleRepository _roleRepository;
public RoleApplication(IRoleRepository roleRepository)
private readonly IPmRoleQueryService _pmRoleQueryService;
private readonly IPmRoleCommandService _pmRoleCommandService;
private readonly IUnitOfWork _unitOfWork;
public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService)
{
_roleRepository = roleRepository;
_unitOfWork = unitOfWork;
_pmRoleQueryService = pmRoleQueryService;
_pmRoleCommandService = pmRoleCommandService;
}
public OperationResult Create(CreateRole command)
public async Task<OperationResult> Create(CreateRole command)
{
var operation = new OperationResult();
if (_roleRepository.Exists(x => x.Name == command.Name))
return operation.Failed(ApplicationMessages.DuplicatedRecord);
var permissions = new List<Permission>();
foreach (var code in command.Permissions)
{
if (code > 0)
{
permissions.Add(new Permission(code));
}
}
//command.Permissions.ForEach(code => permissions.Add(new Permission(code)));
var permissions = command.Permissions.Where(x => x > 0).Select(x => new Permission(x)).ToList();
var role = new Role(command.Name, permissions);
_unitOfWork.BeginAccountContext();
_roleRepository.Create(role);
_roleRepository.SaveChanges();
var pmPermissions = command.PmPermissions.Where(x => x > 0).ToList();
if (pmPermissions.Any())
{
var pmRole = new CreatePmRoleDto{ RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id};
var res =await _pmRoleCommandService.Create(pmRole);
if (!res.Item1)
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر");
}
//var parameters = new CreateProgramManagerRole
//{
// RoleName = command.Name,
// Permissions = pmPermissions,
// GozareshgirRoleId = role.id
//};
//var url = "api/role";
//var key = SecretKeys.ProgramManagerInternalApi;
//var response = InternalApiCaller.PostAsync<CreateProgramManagerRole, ApiResponse>(
// url,
// key,
// parameters
//);
//if (!response.Success)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed("ارتباط با اپلیکیش پروگرام منیجر برقرار نشد");
//}
//if (!response.Result.isSuccess)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Result.errorMessage);
//}
}
//command.Permissions.ForEach(code => permissions.Add(new Permission(code)));
_unitOfWork.CommitAccountContext();
return operation.Succcedded();
}
public OperationResult Edit(EditRole command)
public async Task<OperationResult> Edit(EditRole command)
{
var operation = new OperationResult();
var role = _roleRepository.Get(command.Id);
@@ -47,17 +105,134 @@ public class RoleApplication : IRoleApplication
//var permissions = new List<Permission>();
//command.Permissions.ForEach(code => permissions.Add(new Permission(code)));
var permissions = new List<Permission>();
foreach (var code in command.Permissions)
{
if (code > 0)
{
permissions.Add(new Permission(code));
}
}
var permissions = command.Permissions.Where(x => x > 0).Select(x => new Permission(x)).ToList();
_unitOfWork.BeginAccountContext();
role.Edit(command.Name, permissions);
_roleRepository.SaveChanges();
var key = SecretKeys.ProgramManagerInternalApi;
var pmPermissions = command.PmPermissions.Where(x => x > 0).ToList();
//یافتن نقش در پروگرام منیجر
//var apiResult = InternalApiCaller.GetAsync<RoleResponse>(
// "api/role",
// key,
// new Dictionary<string, object>
// {
// { "RoleName", "" },
// { "GozareshgirRoleId", command.Id}
// }
//);
var pmRoleListResult = await _pmRoleQueryService.GetPmRoleList(command.Id);
var pmRoleResult = pmRoleListResult.FirstOrDefault();
//اگر این نقش در پروگرام منیجر وجود داشت ویرایش کن
if (pmRoleResult != null)
{
var edit = new CreatePmRoleDto { RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id };
var res = await _pmRoleCommandService.Edit(edit);
if (!res.Item1)
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر");
}
//var parameters = new CreateProgramManagerRole
//{
// RoleName = command.Name,
// Permissions = pmPermissions,
// GozareshgirRoleId = role.id
//};
//var url = "api/role/edit";
//var response = InternalApiCaller.PostAsync<CreateProgramManagerRole, ApiResponse>(
// url,
// key,
// parameters
//);
//if (!response.Success)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed("ارتباط با اپلیکیش پروگرام منیجر برقرار نشد");
//}
//if (!response.Result.isSuccess)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Result.errorMessage);
//}
}
else //اگر نقش در پروگرام منیجر وجود نداشت
{
//اگر تیک پرمیشن های پروگرام منیجر زده شده
//این نقش را سمت پروگرام منیجر بساز
if (pmPermissions.Any())
{
var pmRole = new CreatePmRoleDto { RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id };
var res = await _pmRoleCommandService.Create(pmRole);
if (!res.Item1)
{
_unitOfWork.RollbackAccountContext();
return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر");
}
//try
//{
// var pmPermissionsData = pmPermissions.Where(x => x > 0).Select(x => new PmPermission(x)).ToList();
// var pmRole = new PmRole(command.Name, command.Id, pmPermissionsData);
// await _pmRoleRepository.CreateAsync(pmRole);
// await _pmRoleRepository.SaveChangesAsync();
//}
//catch (System.Exception)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر");
//}
//var parameters = new CreateProgramManagerRole
//{
// RoleName = command.Name,
// Permissions = pmPermissions,
// GozareshgirRoleId = role.id
//};
//var url = "api/role";
//var response = InternalApiCaller.PostAsync<CreateProgramManagerRole, ApiResponse>(
// url,
// key,
// parameters
//);
//if (!response.Success)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed("ارتباط با اپلیکیش پروگرام منیجر برقرار نشد");
//}
//if (!response.Result.isSuccess)
//{
// _unitOfWork.RollbackAccountContext();
// return operation.Failed(response.Result.errorMessage);
//}
}
}
_unitOfWork.CommitAccountContext();
return operation.Succcedded();
}
@@ -70,4 +245,23 @@ public class RoleApplication : IRoleApplication
{
return _roleRepository.List();
}
public async Task<SelectList> GetPmRoleList(long? gozareshgirRoleId)
{
var rolse = await _pmRoleQueryService.GetPmRoleList(gozareshgirRoleId);
return new SelectList(rolse, "Id", "RoleName");
}
public async Task<List<GetPmRolesDto>> GetPmRoleListToEdit(long? gozareshgirRoleId)
{
return await _pmRoleQueryService.GetPmRoleList(gozareshgirRoleId);
}
}

View File

@@ -5,14 +5,11 @@ using AccountManagement.Domain.AccountAgg;
using AccountManagement.Domain.CameraAccountAgg;
using AccountManagement.Domain.SubAccountAgg;
using AccountManagement.Domain.SubAccountRoleAgg;
using Company.Domain.WorkshopAccountAgg;
using Company.Domain.WorkshopSubAccountAgg;
using CompanyManagment.App.Contracts.Workshop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace AccountManagement.Application

View File

@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using _0_Framework.Application;
using AccountManagement.Application.Contracts.TaskSubject;
using AccountManagement.Domain.TaskSubjectAgg;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace AccountManagement.Application;

View File

@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -1,9 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\0_Framework\0_Framework.csproj" />
<ProjectReference Include="..\AccountManagement.Application.Contracts\AccountManagement.Application.Contracts.csproj" />

View File

@@ -0,0 +1,155 @@
using Newtonsoft.Json;
using System.Net.Http;
using System.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
namespace AccountManagement.Domain.InternalApiCaller;
public class ApiResult<T>
{
public bool Success { get; set; }
public T Result { get; set; }
public string Error { get; set; }
}
public static class InternalApiCaller
{
private static string _baseUrl = "";
public static void SetBaseUrl(string baseUrl)
{
_baseUrl = baseUrl.TrimEnd('/'); // حذف / اضافی
}
/// <summary>
///api post متد
/// </summary>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TResponse"></typeparam>
/// <param name="url"></param>
/// <param name="internalKey"></param>
/// <param name="body"></param>
/// <returns></returns>
public static ApiResult<TResponse> PostAsync<TRequest, TResponse>(
string url,
string internalKey,
TRequest body
)
{
try
{
var client = new HttpClient();
// ساخت URL نهایی
var finalUrl = $"{_baseUrl}/{url.TrimStart('/')}";
var request = new HttpRequestMessage(HttpMethod.Post, finalUrl);
request.Headers.Add("X-INTERNAL-KEY", internalKey);
var json = JsonConvert.SerializeObject(body);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
var response = client.SendAsync(request).GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
return new ApiResult<TResponse>
{
Success = false,
Error = $"HTTP Error: {response.StatusCode}"
};
}
var text = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var deserialized = JsonConvert.DeserializeObject<TResponse>(text);
return new ApiResult<TResponse>
{
Success = true,
Result = deserialized
};
}
catch (Exception ex)
{
return new ApiResult<TResponse>
{
Success = false,
Error = ex.Message
};
}
}
/// <summary>
/// Api Get متد
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="url"></param>
/// <param name="internalKey"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public static ApiResult<TResponse> GetAsync<TResponse>(
string url,
string internalKey,
Dictionary<string, object> parameters = null
)
{
try
{
if (parameters != null && parameters.Any())
{
var query = string.Join("&",
parameters
.Where(p => p.Value != null)
.Select(p => $"{p.Key}={p.Value}")
);
url += url.Contains("?") ? "&" + query : "?" + query;
}
// ساخت URL نهایی
var finalUrl = $"{_baseUrl}/{url.TrimStart('/')}";
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, finalUrl);
request.Headers.Add("X-INTERNAL-KEY", internalKey);
var response = client.SendAsync(request).GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
return new ApiResult<TResponse>
{
Success = false,
Error = $"HTTP Error: {response.StatusCode}"
};
}
var text = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var deserialized = JsonConvert.DeserializeObject<TResponse>(text);
return new ApiResult<TResponse>
{
Success = true,
Result = deserialized
};
}
catch (Exception ex)
{
return new ApiResult<TResponse>
{
Success = false,
Error = ex.Message
};
}
}
}

View File

@@ -1,4 +1,4 @@
using AccountManagement.Domain.AccountAgg;
using AccountManagement.Domain.AccountAgg;
using AccountMangement.Infrastructure.EFCore.Mappings;
using Microsoft.EntityFrameworkCore;
using System;
@@ -26,7 +26,6 @@ using AccountManagement.Domain.SubAccountPermissionSubtitle2Agg;
using AccountManagement.Domain.SubAccountPermissionSubtitle3Agg;
using AccountManagement.Domain.SubAccountPermissionSubtitle4Agg;
using AccountManagement.Domain.SubAccountRoleAgg;
using AccountMangement.Infrastructure.EFCore.Seed;
using AccountManagement.Domain.TaskScheduleAgg;
namespace AccountMangement.Infrastructure.EFCore
@@ -60,9 +59,10 @@ namespace AccountMangement.Infrastructure.EFCore
public DbSet<TaskSchedule> TaskSchedules { get; set; }
#endregion
#region Pooya
public DbSet<SubAccount> SubAccounts { get; set; }
public DbSet<SubAccountRole> SubAccountRoles { get; set; }

View File

@@ -1,13 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
<PackageReference Include="Azure.Identity" Version="1.17.1" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@@ -18,4 +20,12 @@
<ProjectReference Include="..\Company.Domain\Company.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Mappings\BugReportMapping.cs" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,31 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AccountMangement.Infrastructure.EFCore.Migrations
{
/// <inheritdoc />
public partial class addprogrammangerbooinaccount : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsProgramManagerUser",
table: "Accounts",
type: "bit",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsProgramManagerUser",
table: "Accounts");
}
}
}

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AccountMangement.Infrastructure.EFCore.Migrations
{
/// <inheritdoc />
public partial class romoveIsProgramManagerUserFromAccount : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsProgramManagerUser",
table: "Accounts");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsProgramManagerUser",
table: "Accounts",
type: "bit",
nullable: false,
defaultValue: false);
}
}
}

View File

@@ -17,7 +17,7 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("ProductVersion", "10.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@@ -377,6 +377,87 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations
b.ToTable("Medias", (string)null);
});
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<long?>("GozareshgirRoleId")
.HasColumnType("bigint");
b.Property<string>("RoleName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.HasKey("id");
b.ToTable("PmRoles", null, t =>
{
t.ExcludeFromMigrations();
});
});
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<long?>("AccountId")
.HasColumnType("bigint");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("nvarchar(150)");
b.Property<string>("FullName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Mobile")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("ProfilePhotoPath")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("VerifyCode")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.HasKey("id");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b =>
{
b.Property<long>("id")
@@ -1001,6 +1082,71 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations
b.Navigation("Media");
});
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b =>
{
b.OwnsMany("AccountManagement.Domain.PmDomains.PmPermissionAgg.PmPermission", "PmPermission", b1 =>
{
b1.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
b1.Property<int>("Code")
.HasColumnType("int");
b1.Property<long>("Roleid")
.HasColumnType("bigint");
b1.HasKey("Id");
b1.HasIndex("Roleid");
b1.ToTable("PmRolePermissions", null, t =>
{
t.ExcludeFromMigrations();
});
b1.WithOwner("Role")
.HasForeignKey("Roleid");
b1.Navigation("Role");
});
b.Navigation("PmPermission");
});
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b =>
{
b.OwnsMany("AccountManagement.Domain.PmDomains.PmRoleUserAgg.PmRoleUser", "RoleUser", b1 =>
{
b1.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
b1.Property<long>("RoleId")
.HasColumnType("bigint");
b1.Property<long>("Userid")
.HasColumnType("bigint");
b1.HasKey("Id");
b1.HasIndex("Userid");
b1.ToTable("RoleUsers", (string)null);
b1.WithOwner("User")
.HasForeignKey("Userid");
b1.Navigation("User");
});
b.Navigation("RoleUser");
});
modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b =>
{
b.OwnsMany("AccountManagement.Domain.RoleAgg.Permission", "Permissions", b1 =>

175
BUG_REPORT_SYSTEM.md Normal file
View File

@@ -0,0 +1,175 @@
# سیستم گزارش خرابی (Bug Report System)
## نمای کلی
این سیستم برای جمع‌آوری، ذخیره و مدیریت گزارش‌های خرابی از تطبیق موبایلی طراحی شده است.
## ساختار فایل‌ها
### Domain Layer
- `AccountManagement.Domain/BugReportAgg/`
- `BugReport.cs` - موجودیت اصلی
- `BugReportLog.cs` - لاگ‌های گزارش
- `BugReportScreenshot.cs` - تصاویر ضمیمه شده
### Application Contracts
- `AccountManagement.Application.Contracts/BugReport/`
- `IBugReportApplication.cs` - اینترفیس سرویس
- `CreateBugReportCommand.cs` - درخواست ایجاد
- `EditBugReportCommand.cs` - درخواست ویرایش
- `BugReportViewModel.cs` - نمایش لیست
- `BugReportDetailViewModel.cs` - نمایش جزئیات
- `IBugReportRepository.cs` - اینترفیس Repository
### Application Service
- `AccountManagement.Application/BugReportApplication.cs` - پیاده‌سازی سرویس
### Infrastructure
- `AccountMangement.Infrastructure.EFCore/`
- `Mappings/BugReportMapping.cs`
- `Mappings/BugReportLogMapping.cs`
- `Mappings/BugReportScreenshotMapping.cs`
- `Repository/BugReportRepository.cs`
### API Controller
- `ServiceHost/Controllers/BugReportController.cs`
### Admin Pages
- `ServiceHost/Areas/AdminNew/Pages/BugReport/`
- `BugReportPageModel.cs` - base model
- `Index.cshtml.cs / Index.cshtml` - لیست گزارش‌ها
- `Details.cshtml.cs / Details.cshtml` - جزئیات کامل
- `Edit.cshtml.cs / Edit.cshtml` - ویرایش وضعیت/اولویت
- `Delete.cshtml.cs / Delete.cshtml` - حذف
## روش استفاده
### 1. ثبت گزارش از موبایل
```csharp
POST /api/bugreport/submit
{
"title": "برنامه هنگام ورود خراب می‌شود",
"description": "هنگام وارد کردن نام کاربری، برنامه کرش می‌کند",
"userEmail": "user@example.com",
"deviceModel": "Samsung Galaxy S21",
"osVersion": "Android 12",
"platform": "Android",
"manufacturer": "Samsung",
"deviceId": "device-unique-id",
"screenResolution": "1440x3200",
"memoryInMB": 8000,
"storageInMB": 256000,
"batteryLevel": 75,
"isCharging": false,
"networkType": "4G",
"appVersion": "1.0.0",
"buildNumber": "100",
"packageName": "com.example.app",
"installTime": "2024-01-01T10:00:00Z",
"lastUpdateTime": "2024-12-01T14:30:00Z",
"flavor": "production",
"type": 1, // Crash = 1
"priority": 2, // High = 2
"stackTrace": "...",
"logs": ["log1", "log2"],
"screenshots": ["base64-encoded-image-1"]
}
```
### 2. دسترسی به Admin Panel
```
https://yourdomain.com/AdminNew/BugReport
```
**صفحات موجود:**
- **Index** - لیست تمام گزارش‌ها با فیلترها
- **Details** - نمایش جزئیات کامل شامل:
- معلومات کاربر و گزارش
- معلومات دستگاه
- معلومات برنامه
- لاگ‌ها
- تصاویر
- Stack Trace
- **Edit** - تغییر وضعیت و اولویت
- **Delete** - حذف گزارش
### 3. درخواست‌های API
#### دریافت لیست
```
GET /api/bugreport/list?type=1&priority=2&status=1&searchTerm=crash&pageNumber=1&pageSize=10
```
#### دریافت جزئیات
```
GET /api/bugreport/{id}
```
#### ویرایش
```
PUT /api/bugreport/{id}
{
"id": 1,
"priority": 2,
"status": 3
}
```
#### حذف
```
DELETE /api/bugreport/{id}
```
## انواع (Enums)
### BugReportType
- `1` - Crash (کرش)
- `2` - UI (مشکل رابط)
- `3` - Performance (عملکرد)
- `4` - Feature (فیچر)
- `5` - Network (شبکه)
- `6` - Camera (دوربین)
- `7` - FaceRecognition (تشخیص چهره)
- `8` - Database (دیتابیس)
- `9` - Login (ورود)
- `10` - Other (سایر)
### BugPriority
- `1` - Critical (بحرانی)
- `2` - High (بالا)
- `3` - Medium (متوسط)
- `4` - Low (پایین)
### BugReportStatus
- `1` - Open (باز)
- `2` - InProgress (در حال بررسی)
- `3` - Fixed (رفع شده)
- `4` - Closed (بسته شده)
- `5` - Reopened (مجدداً باز)
## Migration
برای اعمال تغییرات دیتابیس:
```powershell
Add-Migration AddBugReportTables
Update-Database
```
## نکات مهم
1. **تصاویر**: تصاویر به صورت Base64 encoded ذخیره می‌شوند
2. **لاگ‌ها**: تمام لاگ‌ها به صورت جدا ذخیره می‌شوند
3. **وضعیت پیش‌فرض**: وقتی گزارش ثبت می‌شود، وضعیت آن "Open" است
4. **تاریخ**: تاریخ ایجاد و بروزرسانی خودکار ثبت می‌شود
## Security
- API endpoints از `authentication` محافظت می‌شوند
- Admin pages تنها برای کاربرانی با دسترسی AdminArea قابل دسترس هستند
- حذف و ویرایش نیاز به تأیید دارد

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<AssemblyName>BackgroundInstitutionContract.Task</AssemblyName>
@@ -12,8 +12,14 @@
<ProjectReference Include="..\..\0_Framework\0_Framework.csproj" />
<ProjectReference Include="..\..\AccountManagement.Configuration\AccountManagement.Configuration.csproj" />
<ProjectReference Include="..\..\PersonalContractingParty.Config\PersonalContractingParty.Config.csproj" />
<ProjectReference Include="..\..\ProgramManager\src\Infrastructure\GozareshgirProgramManager.Infrastructure\GozareshgirProgramManager.Infrastructure.csproj" />
<ProjectReference Include="..\..\Query.Bootstrapper\Query.Bootstrapper.csproj" />
<ProjectReference Include="..\..\WorkFlow\Infrastructure\WorkFlow.Infrastructure.Config\WorkFlow.Infrastructure.Config.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,6 @@
using _0_Framework.Application;
using _0_Framework.Application.Sms;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.InstitutionContractAgg;
using Hangfire;
@@ -13,18 +14,22 @@ public class JobSchedulerRegistrator
private readonly IInstitutionContractRepository _institutionContractRepository;
private static DateTime? _lastRunCreateTransaction;
private static DateTime? _lastRunSendMonthlySms;
private readonly ISmsService _smsService;
private readonly ILogger<JobSchedulerRegistrator> _logger;
public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository)
public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository, ISmsService smsService, ILogger<JobSchedulerRegistrator> logger)
{
_smsReminder = smsReminder;
_backgroundJobClient = backgroundJobClient;
_institutionContractRepository = institutionContractRepository;
_smsService = smsService;
_logger = logger;
}
public void Register()
{
_logger.LogInformation("hangfire Started");
RecurringJob.AddOrUpdate(
"InstitutionContract.CreateFinancialTransaction",
() => CreateFinancialTransaction(),
@@ -47,6 +52,11 @@ public class JobSchedulerRegistrator
() => SendBlockSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
RecurringJob.AddOrUpdate(
"InstitutionContract.SendInstitutionContractConfirmSms",
() => SendInstitutionContractConfirmSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
}
@@ -60,7 +70,7 @@ public class JobSchedulerRegistrator
var now =DateTime.Now;
var endOfMonth = now.ToFarsi().FindeEndOfMonth();
var endOfMonthGr = endOfMonth.ToGeorgianDateTime();
_logger.LogInformation("CreateFinancialTransaction job run");
if (now.Date == endOfMonthGr.Date && now.Hour >= 2 && now.Hour < 4 &&
now.Date != _lastRunCreateTransaction?.Date)
{
@@ -86,8 +96,8 @@ public class JobSchedulerRegistrator
}
catch (Exception e)
{
//_smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
await _smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
}
}
@@ -105,7 +115,7 @@ public class JobSchedulerRegistrator
var now = DateTime.Now;
var endOfMonth = now.ToFarsi().FindeEndOfMonth();
var endOfMonthGr = endOfMonth.ToGeorgianDateTime();
_logger.LogInformation("SendFirstDayOfMonthSms job run");
if (now.Date == endOfMonthGr.Date && now.Hour >= 10 && now.Hour < 11 &&
now.Date != _lastRunSendMonthlySms?.Date)
{
@@ -133,6 +143,7 @@ public class JobSchedulerRegistrator
[DisableConcurrentExecution(timeoutInSeconds: 1200)]
public async System.Threading.Tasks.Task SendReminderSms()
{
_logger.LogInformation("SendReminderSms job run");
await _institutionContractRepository.SendReminderSmsForBackgroundTask();
}
@@ -143,7 +154,20 @@ public class JobSchedulerRegistrator
[DisableConcurrentExecution(timeoutInSeconds: 100)]
public async System.Threading.Tasks.Task SendBlockSms()
{
_logger.LogInformation("SendBlockSms job run");
await _institutionContractRepository.SendBlockSmsForBackgroundTask();
}
/// <summary>
/// ارسال پیامک یادآور تایید قراداد مالی
/// </summary>
/// <returns></returns>
[DisableConcurrentExecution(timeoutInSeconds: 100)]
public async System.Threading.Tasks.Task SendInstitutionContractConfirmSms()
{
_logger.LogInformation("SendInstitutionContractConfirmSms job run");
await _institutionContractRepository.SendInstitutionContractConfirmSmsTask();
}
}

View File

@@ -0,0 +1,10 @@
using GozareshgirProgramManager.Application.Interfaces;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
public class NullBoardNotificationPublisher:IBoardNotificationPublisher
{
public Task SendProjectStatusChanged(long userId, TaskSectionStatus oldStatus, TaskSectionStatus newStatus, Guid sectionId)
{
throw new NotImplementedException();
}
}

View File

@@ -7,13 +7,47 @@ using BackgroundInstitutionContract.Task;
using BackgroundInstitutionContract.Task.Jobs;
using CompanyManagment.App.Contracts.Hubs;
using CompanyManagment.EFCore.Services;
using GozareshgirProgramManager.Application._Bootstrapper;
using GozareshgirProgramManager.Application.Interfaces;
using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser;
using GozareshgirProgramManager.Infrastructure;
using GozareshgirProgramManager.Infrastructure.Persistence.Seed;
using Hangfire;
using Microsoft.AspNetCore.Identity;
using MongoDB.Driver;
using PersonalContractingParty.Config;
using Query.Bootstrapper;
using Serilog;
using Serilog.Events;
using Shared.Contracts.PmUser.Queries;
using WorkFlow.Infrastructure.Config;
var logDirectory = @"C:\Logs\Hangfire\BackgroundInstitutionContract\";
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
Log.Logger = new LoggerConfiguration()
//NO EF Core log
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
//NO DbCommand log
.MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning)
//NO Microsoft Public log
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
//.MinimumLevel.Information()
.WriteTo.File(
path: Path.Combine(logDirectory, "institution-contract-log-.txt"),
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30,
shared: true,
outputTemplate:
"{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
).CreateLogger();
var builder = WebApplication.CreateBuilder(args);
var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireDb");
builder.Services.AddHangfire(x => x.UseSqlServerStorage(hangfireConnectionString));
@@ -26,7 +60,7 @@ builder.Services.AddTransient<ISmsService, SmsService>();
builder.Services.AddTransient<IUidService, UidService>();
builder.Services.AddTransient<IFileUploader, FileUploader>();
builder.Services.Configure<AppSettingConfiguration>(builder.Configuration);
builder.Services.AddScoped<IBoardNotificationPublisher, NullBoardNotificationPublisher>();
#region MongoDb
var mongoConnectionSection = builder.Configuration.GetSection("MongoDb");
@@ -38,17 +72,28 @@ builder.Services.AddSingleton<IMongoDatabase>(mongoDatabase);
#endregion
builder.Services.AddProgramManagerApplication();
builder.Services.AddProgramManagerInfrastructure(builder.Configuration);
PersonalBootstrapper.Configure(builder.Services, connectionString);
TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb);
AccountManagementBootstrapper.Configure(builder.Services, connectionString);
WorkFlowBootstrapper.Configure(builder.Services, connectionString);
QueryBootstrapper.Configure(builder.Services);
JobsBootstrapper.Configure(builder.Services);
builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor();
builder.Services.AddSignalR();
builder.Host.UseSerilog();
Log.Information("SERILOG STARTED SUCCESSFULLY");
var app = builder.Build();
app.MapHub<SendSmsHub>("/sendSmsHub");
app.MapHangfireDashboard();

View File

@@ -25,8 +25,8 @@
//mahan Docker
//"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;",
//"HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;",
"HangfireDb": "Data Source=185.208.175.186;Initial Catalog=hangfire_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;"
"HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;",
//"HangfireDb": "Data Source=185.208.175.186;Initial Catalog=hangfire_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;"
},
"GoogleRecaptchaV3": {

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

314
CHANGELOG.md Normal file
View File

@@ -0,0 +1,314 @@
# خلاصه تغییرات سیستم گزارش خرابی
## 📝 فایل‌های اضافه شده (23 فایل)
### 1⃣ Domain Layer (3 فایل)
```
✓ AccountManagement.Domain/BugReportAgg/
├── BugReport.cs
├── BugReportLog.cs
└── BugReportScreenshot.cs
```
### 2⃣ Application Contracts (6 فایل)
```
✓ AccountManagement.Application.Contracts/BugReport/
├── IBugReportRepository.cs
├── IBugReportApplication.cs
├── CreateBugReportCommand.cs
├── EditBugReportCommand.cs
├── BugReportViewModel.cs
└── BugReportDetailViewModel.cs
```
### 3⃣ Application Service (1 فایل)
```
✓ AccountManagement.Application/
└── BugReportApplication.cs
```
### 4⃣ Infrastructure EFCore (4 فایل)
```
✓ AccountMangement.Infrastructure.EFCore/
├── Mappings/
│ ├── BugReportMapping.cs
│ ├── BugReportLogMapping.cs
│ └── BugReportScreenshotMapping.cs
└── Repository/
└── BugReportRepository.cs
```
### 5⃣ API Controller (1 فایل)
```
✓ ServiceHost/Controllers/
└── BugReportController.cs
```
### 6⃣ Admin Pages (8 فایل)
```
✓ ServiceHost/Areas/AdminNew/Pages/BugReport/
├── BugReportPageModel.cs
├── Index.cshtml.cs
├── Index.cshtml
├── Details.cshtml.cs
├── Details.cshtml
├── Edit.cshtml.cs
├── Edit.cshtml
├── Delete.cshtml.cs
└── Delete.cshtml
```
### 7⃣ Documentation (2 فایل)
```
✓ BUG_REPORT_SYSTEM.md
✓ FLUTTER_BUG_REPORT_EXAMPLE.dart
```
---
## ✏️ فایل‌های اصلاح شده (2 فایل)
### 1. AccountManagement.Configuration/AccountManagementBootstrapper.cs
**تغییر:** اضافه کردن using برای BugReport
```csharp
using AccountManagement.Application.Contracts.BugReport;
```
**تغییر:** رجیستریشن سرویس‌ها
```csharp
services.AddTransient<IBugReportApplication, BugReportApplication>();
services.AddTransient<IBugReportRepository, BugReportRepository>();
```
### 2. AccountMangement.Infrastructure.EFCore/AccountContext.cs
**تغییر:** اضافه کردن using
```csharp
using AccountManagement.Domain.BugReportAgg;
```
**تغییر:** اضافه کردن DbSets
```csharp
#region BugReport
public DbSet<BugReport> BugReports { get; set; }
public DbSet<BugReportLog> BugReportLogs { get; set; }
public DbSet<BugReportScreenshot> BugReportScreenshots { get; set; }
#endregion
```
---
## 🔧 موارد مورد نیاز قبل از استفاده
### 1. Database Migration
```powershell
# در Package Manager Console
cd AccountMangement.Infrastructure.EFCore
Add-Migration AddBugReportSystem
Update-Database
```
### 2. الگوی Enum برای Flutter
```dart
enum BugReportType {
crash, // 1
ui, // 2
performance, // 3
feature, // 4
network, // 5
camera, // 6
faceRecognition, // 7
database, // 8
login, // 9
other, // 10
}
enum BugPriority {
critical, // 1
high, // 2
medium, // 3
low, // 4
}
```
---
## 🚀 نقاط ورود
### API Endpoints
```
POST /api/bugreport/submit - ثبت گزارش جدید
GET /api/bugreport/list - دریافت لیست
GET /api/bugreport/{id} - دریافت جزئیات
PUT /api/bugreport/{id} - ویرایش وضعیت/اولویت
DELETE /api/bugreport/{id} - حذف گزارش
```
### Admin Pages
```
/AdminNew/BugReport - لیست گزارش‌ها
/AdminNew/BugReport/Details/{id} - جزئیات کامل
/AdminNew/BugReport/Edit/{id} - ویرایش
/AdminNew/BugReport/Delete/{id} - حذف
```
---
## 📊 Database Schema
### BugReports جدول
```sql
- id (bigint, PK)
- Title (nvarchar(200))
- Description (ntext)
- UserEmail (nvarchar(150))
- AccountId (bigint, nullable)
- DeviceModel (nvarchar(100))
- OsVersion (nvarchar(50))
- Platform (nvarchar(50))
- Manufacturer (nvarchar(100))
- DeviceId (nvarchar(200))
- ScreenResolution (nvarchar(50))
- MemoryInMB (int)
- StorageInMB (int)
- BatteryLevel (int)
- IsCharging (bit)
- NetworkType (nvarchar(50))
- AppVersion (nvarchar(50))
- BuildNumber (nvarchar(50))
- PackageName (nvarchar(150))
- InstallTime (datetime2)
- LastUpdateTime (datetime2)
- Flavor (nvarchar(50))
- Type (int)
- Priority (int)
- Status (int)
- StackTrace (ntext, nullable)
- CreationDate (datetime2)
- UpdateDate (datetime2, nullable)
```
### BugReportLogs جدول
```sql
- id (bigint, PK)
- BugReportId (bigint, FK)
- Message (ntext)
- Timestamp (datetime2)
```
### BugReportScreenshots جدول
```sql
- id (bigint, PK)
- BugReportId (bigint, FK)
- Base64Data (ntext)
- FileName (nvarchar(255))
- UploadDate (datetime2)
```
---
## ✨ مثال درخواست API
```json
POST /api/bugreport/submit
Content-Type: application/json
{
"title": "برنامه هنگام ورود خراب می‌شود",
"description": "هنگام فشار دادن دکمه ورود، برنامه کرش می‌کند",
"userEmail": "user@example.com",
"accountId": 123,
"deviceModel": "Samsung Galaxy S21",
"osVersion": "Android 12",
"platform": "Android",
"manufacturer": "Samsung",
"deviceId": "device-12345",
"screenResolution": "1440x3200",
"memoryInMB": 8000,
"storageInMB": 256000,
"batteryLevel": 75,
"isCharging": false,
"networkType": "4G",
"appVersion": "1.0.0",
"buildNumber": "100",
"packageName": "com.example.app",
"installTime": "2024-01-01T10:00:00Z",
"lastUpdateTime": "2024-12-07T14:30:00Z",
"flavor": "production",
"type": 1,
"priority": 2,
"stackTrace": "...",
"logs": ["log line 1", "log line 2"],
"screenshots": ["base64-string"]
}
```
---
## 🔐 Security Features
- ✅ Authorization برای Admin Pages (AdminAreaPermission required)
- ✅ API Authentication
- ✅ XSS Protection (Html.Raw محدود)
- ✅ CSRF Protection (ASP.NET Core default)
- ✅ Input Validation
- ✅ Safe Delete with Confirmation
---
## 📚 Documentation Files
1. **BUG_REPORT_SYSTEM.md** - راهنمای کامل سیستم
2. **FLUTTER_BUG_REPORT_EXAMPLE.dart** - مثال پیاده‌سازی Flutter
3. **CHANGELOG.md** (این فایل) - خلاصه تغییرات
---
## ✅ Checklist پیاده‌سازی
- [x] Domain Models
- [x] Database Mappings
- [x] Repository Pattern
- [x] Application Services
- [x] API Endpoints
- [x] Admin UI Pages
- [x] Dependency Injection
- [x] Error Handling
- [x] Documentation
- [x] Flutter Example
- [ ] Database Migration (باید دستی اجرا شود)
- [ ] Testing
---
## 🎯 مراحل بعدی
1. **اجرای Migration:**
```powershell
Add-Migration AddBugReportSystem
Update-Database
```
2. **تست API:**
- استفاده از Postman/Thunder Client
- تست تمام endpoints
3. **تست Admin Panel:**
- دسترسی به /AdminNew/BugReport
- تست فیلترها و جستجو
- تست ویرایش و حذف
4. **Integration Flutter:**
- کپی کردن `FLUTTER_BUG_REPORT_EXAMPLE.dart`
- سازگار کردن با پروژه Flutter
- تست ثبت گزارش‌ها
---
## 📞 پشتیبانی
برای هر سوال یا مشکل:
1. بررسی کنید `BUG_REPORT_SYSTEM.md`
2. بررسی کنید logs و error messages
3. مطمئن شوید Migration اجرا شده است

View File

@@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using _0_Framework.Domain;
using MongoDB.Bson.Serialization.Attributes;
namespace Company.Domain.CameraBugReportAgg;
/// <summary>
/// مدل دامنه برای گزارش خرابی دوربین
/// </summary>
public class CameraBugReport
{
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public Guid Id { get; set; }
public CameraBugReport()
{
Id = Guid.NewGuid();
CreationDate = DateTime.Now;
Status = CameraBugReportStatus.Open;
Screenshots = new List<CameraBugReportScreenshot>();
Logs = new List<CameraBugReportLog>();
}
public CameraBugReport(
string title,
string description,
string userEmail,
string deviceModel,
string osVersion,
string manufacturer,
string buildNumber,
string appVersion,
string screenResolution,
bool isCharging,
int batteryLevel,
int storageInMB,
int memoryInMB,
string networkType,
string platform,
string deviceId,
string packageName,
DateTime installTime,
DateTime lastUpdateTime,
string flavor,
CameraBugReportType type,
CameraBugPriority priority,
long? accountId = null,
string stackTrace = null) : this()
{
Priority = priority;
Type = type;
Flavor = flavor;
LastUpdateTime = lastUpdateTime;
InstallTime = installTime;
PackageName = packageName;
BuildNumber = buildNumber;
AppVersion = appVersion;
NetworkType = networkType;
IsCharging = isCharging;
BatteryLevel = batteryLevel;
StorageInMB = storageInMB;
MemoryInMB = memoryInMB;
ScreenResolution = screenResolution;
DeviceId = deviceId;
Manufacturer = manufacturer;
Platform = platform;
OsVersion = osVersion;
DeviceModel = deviceModel;
AccountId = accountId;
UserEmail = userEmail;
Description = description;
Title = title;
StackTrace = stackTrace;
}
[BsonElement("screenshots")]
public List<CameraBugReportScreenshot> Screenshots { get; private set; }
[BsonElement("logs")]
public List<CameraBugReportLog> Logs { get; private set; }
[BsonElement("updateDate")]
public DateTime? UpdateDate { get; private set; }
[BsonElement("creationDate")]
public DateTime CreationDate { get; private set; }
[BsonElement("stackTrace")]
public string StackTrace { get; private set; }
[BsonElement("status")]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public CameraBugReportStatus Status { get; private set; }
[BsonElement("priority")]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public CameraBugPriority Priority { get; private set; }
[BsonElement("type")]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public CameraBugReportType Type { get; private set; }
[BsonElement("flavor")]
public string Flavor { get; private set; }
[BsonElement("lastUpdateTime")]
public DateTime LastUpdateTime { get; private set; }
[BsonElement("installTime")]
public DateTime InstallTime { get; private set; }
[BsonElement("packageName")]
public string PackageName { get; private set; }
[BsonElement("buildNumber")]
public string BuildNumber { get; private set; }
[BsonElement("appVersion")]
public string AppVersion { get; private set; }
[BsonElement("networkType")]
public string NetworkType { get; private set; }
[BsonElement("isCharging")]
public bool IsCharging { get; private set; }
[BsonElement("batteryLevel")]
public int BatteryLevel { get; private set; }
[BsonElement("storageInMB")]
public int StorageInMB { get; private set; }
[BsonElement("memoryInMB")]
public int MemoryInMB { get; private set; }
[BsonElement("screenResolution")]
public string ScreenResolution { get; private set; }
[BsonElement("deviceId")]
public string DeviceId { get; private set; }
[BsonElement("manufacturer")]
public string Manufacturer { get; private set; }
[BsonElement("platform")]
public string Platform { get; private set; }
[BsonElement("osVersion")]
public string OsVersion { get; private set; }
[BsonElement("deviceModel")]
public string DeviceModel { get; private set; }
[BsonElement("accountId")]
public long? AccountId { get; private set; }
[BsonElement("userEmail")]
public string UserEmail { get; private set; }
[BsonElement("description")]
public string Description { get; private set; }
[BsonElement("title")]
public string Title { get; private set; }
public void ChangeStatus(CameraBugReportStatus newStatus)
{
UpdateDate = DateTime.Now;
Status = newStatus;
}
public void ChangePriority(CameraBugPriority newPriority)
{
Priority = newPriority;
UpdateDate = DateTime.Now;
}
public void AddScreenshot(string base64Data, string fileName)
{
Screenshots.Add(new CameraBugReportScreenshot
{ Base64Data = base64Data, FileName = fileName, UploadDate = DateTime.Now });
}
public void AddLog(string logMessage)
{
Logs.Add(new CameraBugReportLog { Message = logMessage, Timestamp = DateTime.Now });
}
}

View File

@@ -0,0 +1,20 @@
using System;
using _0_Framework.Domain;
using MongoDB.Bson.Serialization.Attributes;
namespace Company.Domain.CameraBugReportAgg
{
/// <summary>
/// لاگ‌های گزارش خرابی دوربین
/// </summary>
public class CameraBugReportLog : EntityBase
{
// FK و navigation property حذف شد برای MongoDB
[BsonElement("message")]
public string Message { get; set; }
[BsonElement("timestamp")]
public DateTime Timestamp { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using System;
using _0_Framework.Domain;
using MongoDB.Bson.Serialization.Attributes;
namespace Company.Domain.CameraBugReportAgg
{
/// <summary>
/// عکس‌های ضمیمه شده به گزارش خرابی دوربین (Base64 encoded)
/// </summary>
public class CameraBugReportScreenshot : EntityBase
{
// FK و navigation property حذف شد برای MongoDB
[BsonElement("base64Data")]
public string Base64Data { get; set; }
[BsonElement("fileName")]
public string FileName { get; set; }
[BsonElement("uploadDate")]
public DateTime UploadDate { get; set; }
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using _0_Framework.InfraStructure;
namespace Company.Domain.CameraBugReportAgg;
/// <summary>
/// رابط انبار گزارش خرابی دوربین برای MongoDB
/// </summary>
public interface ICameraBugReportRepository
{
// Async methods for MongoDB operations
Task CreateAsync(CameraBugReport bugReport);
Task UpdateAsync(CameraBugReport bugReport);
Task<CameraBugReport> GetByIdAsync(Guid id);
Task<List<CameraBugReport>> GetAllAsync();
Task<List<CameraBugReport>> GetAllAsync(int skip, int take);
Task DeleteAsync(Guid id);
Task<bool> IsExistAsync(Guid id);
Task<List<CameraBugReport>> FilterAsync(
CameraBugReportType? type = null,
CameraBugPriority? priority = null,
CameraBugReportStatus? status = null,
string searchTerm = null,
int skip = 0,
int take = 10);
Task<int> CountAsync(
CameraBugReportType? type = null,
CameraBugPriority? priority = null,
CameraBugReportStatus? status = null,
string searchTerm = null);
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -16,10 +16,15 @@
<ItemGroup>
<Folder Include="CheckoutAgg\ValueObjects\" />
<Folder Include="_common\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Bson" Version="3.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
<PackageReference Include="MongoDB.Bson" Version="3.5.2" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
</ItemGroup>
</Project>

View File

@@ -290,4 +290,13 @@ public class PersonalContractingParty : EntityBase
this.Gender = gender;
this.IsAuthenticated = true;
}
public void EditLegalPartyFromInstitution(string legalPosition, string companyName,
string registerId,string nationalId)
{
LegalPosition = legalPosition;
LName = companyName;
RegisterId = registerId;
NationalId = nationalId;
}
}

View File

@@ -48,6 +48,10 @@ public interface IContractRepository : IRepository<long, Contract>
bool Remove(long id);
List<ContractViweModel> SearchForClient(ContractSearchModel searchModel);
Task<PagedResult<GetContractListForClientResponse>> GetContractListForClient(GetContractListForClientRequest searchModel);
Task<List<ContractPrintViewModel>> PrintAllAsync(List<long> ids);
#endregion
#region NewChangeByHeydari
@@ -63,4 +67,8 @@ public interface IContractRepository : IRepository<long, Contract>
ContractViweModel GetByWorkshopIdEmployeeIdInDates(long workshopId, long employeeId, DateTime startOfMonth, DateTime endOfMonth);
List<ContractViweModel> GetByWorkshopIdInDates(long workshopId, DateTime contractStart, DateTime contractEnd);
#endregion
}
}

View File

@@ -76,6 +76,7 @@ public interface IEmployeeRepository : IRepository<long, Employee>
#region Api
Task<List<EmployeeSelectListViewModel>> GetSelectList(string searchText,long id);
Task<List<GetEmployeeListViewModel>> GetList(GetEmployeeListSearchModel searchModel);
Task<List<GetClientEmployeeListViewModel>> GetClientEmployeeList(GetClientEmployeeListSearchModel searchModel, long workshopId);
#endregion

View File

@@ -37,7 +37,7 @@ namespace Company.Domain.EmployeeDocumentsAgg
{
WorkshopId = workshopId;
EmployeeId = employeeId;
Gender = gender;
Gender = gender??string.Empty;
}
private EmployeeDocuments()

View File

@@ -56,7 +56,7 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
void UpdateStatusIfNeeded(long institutionContractId);
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
Task<InstitutionContract> GetByPublicIdAsync(Guid id);
InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request);
InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request,string contractStart = null);
InstitutionContractDiscountResponse ResetDiscountCreate(InstitutionContractResetDiscountForCreateRequest request);
@@ -140,6 +140,11 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
/// <returns></returns>
Task SendReminderSmsToContractingParties(List<SmsListData> smsListData, string typeOfSms, string sendMessStart, string sendMessEnd);
/// <summary>
/// ارسال پیامک یادآور تایید قراداد مالی
/// </summary>
/// <returns></returns>
Task SendInstitutionContractConfirmSmsTask();
#endregion
#region CreateMontlyTransaction
@@ -154,4 +159,5 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
#endregion
Task<long> GetIdByInstallmentId(long installmentId);
Task<InstitutionContract> GetPreviousContract(long currentInstitutionContractId);
}

View File

@@ -98,6 +98,11 @@ public class InstitutionContract : EntityBase
// مبلغ قرارداد
public double ContractAmount { get; private set; }
public double ContractAmountWithTax => !IsOldContract ? ContractAmount + ContractAmountTax
: ContractAmount;
public double ContractAmountTax => ContractAmount*0.10;
//خسارت روزانه
public double DailyCompenseation { get; private set; }
@@ -159,6 +164,10 @@ public class InstitutionContract : EntityBase
public List<InstitutionContractAmendment> Amendments { get; private set; }
public InstitutionContractSigningType? SigningType { get; private set; }
public bool IsOldContract => LawId== 0;
public InstitutionContract()
{
ContactInfoList = [];
@@ -262,6 +271,10 @@ public class InstitutionContract : EntityBase
{
WorkshopGroup = null;
}
public void SetSigningType(InstitutionContractSigningType signingType)
{
SigningType = signingType;
}
}
public class InstitutionContractAmendment : EntityBase

View File

@@ -10,13 +10,15 @@ public class InstitutionContractWorkshopCurrent:InstitutionContractWorkshopBase
public InstitutionContractWorkshopCurrent(string workshopName, bool hasRollCallPlan,
bool hasRollCallPlanInPerson, bool hasCustomizeCheckoutPlan, bool hasContractPlan,
bool hasContractPlanInPerson, bool hasInsurancePlan, bool hasInsurancePlanInPerson,
int personnelCount, double price,long institutionContractWorkshopGroupId,InstitutionContractWorkshopGroup workshopGroup,long workshopId) : base(workshopName, hasRollCallPlan,
int personnelCount, double price,long institutionContractWorkshopGroupId,
InstitutionContractWorkshopGroup workshopGroup,long workshopId,long initialWorkshopId) : base(workshopName, hasRollCallPlan,
hasRollCallPlanInPerson, hasCustomizeCheckoutPlan, hasContractPlan,
hasContractPlanInPerson, hasInsurancePlan, hasInsurancePlanInPerson, personnelCount, price)
{
InstitutionContractWorkshopGroupId = institutionContractWorkshopGroupId;
WorkshopGroup = workshopGroup;
WorkshopId = workshopId;
InitialWorkshopId = initialWorkshopId;
}
public long InstitutionContractWorkshopGroupId { get; private set; }
public InstitutionContractWorkshopGroup WorkshopGroup { get; private set; }

View File

@@ -23,6 +23,8 @@ public class InstitutionContractWorkshopGroup : EntityBase
!InitialWorkshops.Cast<InstitutionContractWorkshopBase>()
.SequenceEqual(CurrentWorkshops.Cast<InstitutionContractWorkshopBase>());
public bool IsInPersonContract => InitialWorkshops.Any(x => x.Services.ContractInPerson);
public InstitutionContractWorkshopGroup(long institutionContractId,
List<InstitutionContractWorkshopInitial> initialDetails)
{
@@ -37,4 +39,10 @@ public class InstitutionContractWorkshopGroup : EntityBase
CurrentWorkshops = updatedDetails.ToList();
LastModifiedDate = DateTime.Now;
}
public void AddCurrentWorkshop(InstitutionContractWorkshopCurrent currentWorkshop)
{
CurrentWorkshops.Add(currentWorkshop);
LastModifiedDate = DateTime.Now;
}
}

View File

@@ -31,7 +31,7 @@ public class InstitutionContractWorkshopInitial:InstitutionContractWorkshopBase
WorkshopCreated = true;
WorkshopCurrent = new InstitutionContractWorkshopCurrent(WorkshopName,Services.RollCall,Services.RollCallInPerson,
Services.CustomizeCheckout,Services.Contract,Services.ContractInPerson,Services.Insurance,
Services.InsuranceInPerson,PersonnelCount,Price,InstitutionContractWorkshopGroupId,WorkshopGroup,workshopId);
Services.InsuranceInPerson,PersonnelCount,Price,InstitutionContractWorkshopGroupId,WorkshopGroup,workshopId,id);
WorkshopCurrent.SetEmployers(Employers.Select(x=>x.EmployerId).ToList());
}

View File

@@ -1,7 +1,9 @@
using _0_Framework.Domain;
using _0_Framework.Application;
using _0_Framework.Domain;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Company.Domain.InstitutionPlanAgg;
@@ -26,4 +28,18 @@ public interface IPlanPercentageRepository : IRepository<long, PlanPercentage>
/// <param name="command"></param>
/// <returns></returns>
InstitutionPlanViewModel GetInstitutionPlanForWorkshop(WorkshopTempViewModel command);
/// <summary>
/// دریافت دیتای مودال ایجاد
/// </summary>
/// <returns></returns>
Task<CreateServiceAmountDto> GetCreateModalData();
/// <summary>
/// دریافت لیست مبالغ سرویس ها
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
Task<PagedResult<InstitutionPlanListDto>> GetList(
InstitutionPlanSearchModel searchModel);
}

View File

@@ -73,10 +73,12 @@ public interface IInsuranceListRepository:IRepository<long, InsuranceList>
Task<InsuranceListConfirmOperation> GetInsuranceOperationDetails(long id);
Task<InsuranceListTabsCountViewModel> GetTabCounts(InsuranceListSearchModel searchModel);
Task<PagedResult<InsuranceClientListViewModel>> GetInsuranceClientList(InsuranceClientSearchModel searchModel);
#endregion
Task<List<InsuranceListViewModel>> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel);
Task<InsuranceClientPrintViewModel> ClientPrintOne(long id);
}

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using _0_Framework.Application;
using _0_Framework.Application;
using _0_Framework.Domain;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.Leave;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Company.Domain.LeaveAgg;
@@ -10,7 +12,7 @@ public interface ILeaveRepository : IRepository<long, Leave>
{
EditLeave GetDetails(long id);
List<LeaveViewModel> search(LeaveSearchModel searchModel);
OperationResult RemoveLeave(long id);
Task<OperationResult> RemoveLeave(long id);
#region Pooya
List<LeaveViewModel> GetByWorkshopIdEmployeeIdInDates(long workshopId, long employeeId, DateTime start, DateTime end);
@@ -27,6 +29,8 @@ public interface ILeaveRepository : IRepository<long, Leave>
List<LeaveMainViewModel> searchClient(LeaveSearchModel searchModel);
LeavePrintViewModel PrintOne(long id);
List<LeavePrintViewModel> PrintAll(List<long> id);
Task<List<LeavePrintResponseViewModel>> PrintAllAsync(List<long> ids, long workshopId);
#region Vafa
@@ -34,4 +38,27 @@ public interface ILeaveRepository : IRepository<long, Leave>
#endregion
bool CheckIfValidToEdit(long id);
/// <summary>
/// دریافت لیست مرخصی ها در کلاینت
/// Api
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
Task<PagedResult<leaveListDto>> GetList(
LeaveListSearchModel searchModel);
/// <summary>
/// دریافت لیست گروه بندی شده
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
Task<List<GroupLeaveListDto>> GetGroupList(LeaveListSearchModel searchModel);
/// <summary>
/// پرینت لیستی
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
Task<LeaveListPrintDto> ListPrint(List<long> ids);
}

View File

@@ -316,7 +316,10 @@ public class Workshop : EntityBase
IsStaticCheckout = isStaticCheckout;
}
public void AddContractingPartyId(long contractingPartyId)
{
ContractingPartyId = contractingPartyId;
}
public void Active(string archiveCode)
{
this.IsActive = true;

View File

@@ -0,0 +1,8 @@
namespace Company.Domain._common;
public interface IUnitOfWork
{
void BeginAccountContext();
void CommitAccountContext();
void RollbackAccountContext();
}

View File

@@ -26,7 +26,7 @@ public class CustomizeWorkshopGroupSettingExcelGenerator
{
public static byte[] Generate(List<CustomizeWorkshopGroupExcelViewModel> groups)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("GroupsAndEmployees");

View File

@@ -24,7 +24,7 @@ public class CaseManagementExcelGenerator
};
public static byte[] GenerateCheckoutTempExcelInfo(List<FileExcelViewModel> data)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
CreateSheet(data, package,"همه");
CreateSheet(data.Where(x=>x.Status ==2).ToList(), package,"فعال");

View File

@@ -46,7 +46,7 @@ public class CustomizeCheckoutExcelGenerator
};
public static byte[] GenerateCheckoutTempExcelInfo(List<CustomizeCheckoutTempExcelViewModel> data, List<string> selectedParameters)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");

View File

@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EPPlus" Version="7.5.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
<PackageReference Include="Azure.Identity" Version="1.17.1" />
<PackageReference Include="EPPlus" Version="8.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AccountMangement.Infrastructure.EFCore\AccountMangement.Infrastructure.EFCore.csproj" />

View File

@@ -7,7 +7,7 @@ public class EmployeeBankInfoExcelGenerator
{
public static byte[] Generate(List<EmployeeBankInfoExcelViewModel> list)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("EmployeeBankInfo");
@@ -166,7 +166,7 @@ public class EmployeeBankInfoExcelGenerator
public static byte[] Generate2(List<EmployeeBankInfoExcelViewModel> list)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
foreach (var employee in list)
{
@@ -220,4 +220,4 @@ public class EmployeeBankInfoExcelGenerator
cell.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
cell.Style.Fill.PatternType = ExcelFillStyle.Solid;
}
}
}

View File

@@ -8,86 +8,129 @@ using System.Text.RegularExpressions;
namespace CompanyManagement.Infrastructure.Excel.InstitutionContract;
// Enum برای تعریف ستون‌های موجود
public enum ExcelColumnType
{
RowNumber, // ردیف
PhysicalContract, // قرارداد فیزیکی
ContractNo, // شماره قرارداد
Representative, // معرف
ContractingPartyName, // طرف حساب
ArchiveCode, // شماره کارفرما
EmployerName, // کارفرما
WorkshopName, // کارگاه‌ها (چندخطی)
WorkshopCount, // تعداد کارگاه
EmployeeCount, // مجموع پرسنل
ContractStartDate, // شروع قرارداد
ContractEndDate, // پایان قرارداد
InstallmentAmount, // مبلغ قسط
ContractAmount, // مبلغ قرارداد
FinancialStatus // وضعیت مالی
}
// کلاس کانفیگ برای تنظیم ستون‌های نمایشی
public class ExcelColumnConfig
{
public List<ExcelColumnType> VisibleColumns { get; set; }
public ExcelColumnConfig()
{
// فعلاً تمام ستون‌ها فعال هستند
VisibleColumns = new List<ExcelColumnType>
{
ExcelColumnType.PhysicalContract,
ExcelColumnType.ContractNo,
ExcelColumnType.Representative,
ExcelColumnType.ContractingPartyName,
ExcelColumnType.ArchiveCode,
ExcelColumnType.EmployerName,
ExcelColumnType.WorkshopName,
ExcelColumnType.WorkshopCount,
ExcelColumnType.EmployeeCount,
ExcelColumnType.ContractStartDate,
ExcelColumnType.ContractEndDate,
ExcelColumnType.InstallmentAmount,
ExcelColumnType.ContractAmount,
ExcelColumnType.FinancialStatus
};
}
}
public class InstitutionContractExcelGenerator
{
private static ExcelColumnConfig _columnConfig = new ExcelColumnConfig();
public static byte[] GenerateExcel(List<InstitutionContractViewModel> institutionContractViewModels)
public static byte[] GenerateExcel(List<InstitutionContractExcelViewModel> contractViewModels)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var allWorksheet = package.Workbook.Worksheets.Add("همه");
var blueWorksheet = package.Workbook.Worksheets.Add("آبی");
blueWorksheet.TabColor = Color.LightBlue;
var grayWorksheet = package.Workbook.Worksheets.Add("خاکستری");
grayWorksheet.TabColor = Color.LightGray;
var redWorksheet = package.Workbook.Worksheets.Add("قرمز");
redWorksheet.TabColor = Color.LightCoral;
var purpleWorksheet = package.Workbook.Worksheets.Add("بنفش");
purpleWorksheet.TabColor = Color.MediumPurple;
var blackWorksheet = package.Workbook.Worksheets.Add("مشکی");
blackWorksheet.TabColor = Color.DimGray;
var yellowWorksheet = package.Workbook.Worksheets.Add("زرد");
yellowWorksheet.TabColor = Color.Yellow;
var whiteWorksheet = package.Workbook.Worksheets.Add("سفید");
whiteWorksheet.TabColor = Color.White;
CreateExcelSheet(institutionContractViewModels, allWorksheet);
var blueContracts = institutionContractViewModels.Where(x=>x.ExpireColor == "blue").ToList();
CreateExcelSheet(blueContracts, blueWorksheet);
institutionContractViewModels = institutionContractViewModels.Except(blueContracts).ToList();
var grayContracts = institutionContractViewModels.Where(x => x.IsContractingPartyBlock == "true").ToList();
CreateExcelSheet(grayContracts, grayWorksheet);
institutionContractViewModels = institutionContractViewModels.Except(grayContracts).ToList();
var redContracts = institutionContractViewModels.Where(x=>x.ExpireColor == "red").ToList();
CreateExcelSheet(redContracts, redWorksheet);
institutionContractViewModels = institutionContractViewModels.Except(redContracts).ToList();
var purpleContracts = institutionContractViewModels.Where(x=>x.ExpireColor == "purple").ToList();
CreateExcelSheet(purpleContracts, purpleWorksheet);
institutionContractViewModels = institutionContractViewModels.Except(purpleContracts).ToList();
var blackContracts = institutionContractViewModels.Where(x=>x.ExpireColor == "black").ToList();
CreateExcelSheet(blackContracts, blackWorksheet);
institutionContractViewModels = institutionContractViewModels.Except(blackContracts).ToList();
var yellowContracts = institutionContractViewModels
.Where(x => string.IsNullOrWhiteSpace(x.ExpireColor) && x.WorkshopCount == "0").ToList();
CreateExcelSheet(yellowContracts, yellowWorksheet);
institutionContractViewModels = institutionContractViewModels.Except(yellowContracts).ToList();
var otherContracts = institutionContractViewModels;
CreateExcelSheet(otherContracts, whiteWorksheet);
// ایجاد شیت برای هر تب با داده‌های مربوطه
foreach (var viewModel in contractViewModels)
{
var worksheet = CreateWorksheet(package, viewModel.Tab);
CreateExcelSheet(viewModel.GetInstitutionContractListItemsViewModels ?? new List<GetInstitutionContractListItemsViewModel>(), worksheet);
}
return package.GetAsByteArray();
}
private static void CreateExcelSheet(List<InstitutionContractViewModel> institutionContractViewModels, ExcelWorksheet worksheet)
/// <summary>
/// ایجاد شیت بر اساس نوع تب
/// </summary>
private static ExcelWorksheet CreateWorksheet(ExcelPackage package, InstitutionContractListStatus? status)
{
// Headers
worksheet.Cells[1, 1].Value = "شماره قرارداد";
worksheet.Cells[1, 2].Value = "طرف حساب";
worksheet.Cells[1, 3].Value = "شماره کارفرما";
worksheet.Cells[1, 4].Value = "کارفرما ها";
worksheet.Cells[1, 5].Value = "کارگاه ها";
worksheet.Cells[1, 6].Value = "مجبوع پرسنل";
worksheet.Cells[1, 7].Value = "شروع قرارداد";
worksheet.Cells[1, 8].Value = "پایان قرارداد";
worksheet.Cells[1, 9].Value = "مبلغ قرارداد (بدون کارگاه)";
worksheet.Cells[1, 10].Value = "مبلغ قرارداد";
worksheet.Cells[1, 11].Value = "وضعیت مالی";
return status switch
{
InstitutionContractListStatus.DeactiveWithDebt =>
CreateColoredWorksheet(package, "غیرفعال دارای بدهی", Color.LightBlue),
InstitutionContractListStatus.Deactive =>
CreateColoredWorksheet(package, "غیرفعال", Color.LightGray),
InstitutionContractListStatus.PendingForRenewal =>
CreateColoredWorksheet(package, "در انتظار تمدید", Color.LightCoral),
InstitutionContractListStatus.Free =>
CreateColoredWorksheet(package, "بنفش", Color.MediumPurple),
InstitutionContractListStatus.Block =>
CreateColoredWorksheet(package, "بلاک", Color.DimGray),
InstitutionContractListStatus.WithoutWorkshop =>
CreateColoredWorksheet(package, "بدون کارگاه", Color.Yellow),
InstitutionContractListStatus.Active =>
CreateColoredWorksheet(package, "فعال", Color.White),
InstitutionContractListStatus.PendingForVerify =>
CreateColoredWorksheet(package, "در انتظار تایید", Color.OrangeRed),
null => CreateColoredWorksheet(package, "کل قرارداد ها", Color.White),
_ => throw new ArgumentOutOfRangeException(nameof(status), status, null)
};
}
using (var range = worksheet.Cells[1, 1, 1, 11])
/// <summary>
/// ایجاد شیت با رنگ تب
/// </summary>
private static ExcelWorksheet CreateColoredWorksheet(ExcelPackage package, string sheetName, Color tabColor)
{
var worksheet = package.Workbook.Worksheets.Add(sheetName);
worksheet.TabColor = tabColor;
return worksheet;
}
private static void CreateExcelSheet(List<GetInstitutionContractListItemsViewModel> contractItems, ExcelWorksheet worksheet)
{
// دریافت نقشه ستون‌های مرئی
var visibleColumnIndices = GetVisibleColumnIndices();
int columnCount = visibleColumnIndices.Count;
// تنظیم Headers
SetupHeaders(worksheet, visibleColumnIndices, columnCount);
using (var range = worksheet.Cells[1, 1, 1, columnCount])
{
range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
range.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
@@ -110,30 +153,35 @@ public class InstitutionContractExcelGenerator
int row = 2;
for (int i = 0; i < institutionContractViewModels.Count; i++)
for (int i = 0; i < contractItems.Count; i++)
{
var contract = institutionContractViewModels[i];
var employers = contract.EmployerViewModels?.ToList() ?? new();
var workshops = contract.WorkshopViewModels?.ToList() ?? new();
var contract = contractItems[i];
var employers = contract.EmployerNames?.ToList() ?? new();
var workshops = contract.WorkshopNames?.ToList() ?? new();
int maxRows = Math.Max(employers.Count, workshops.Count);
maxRows = Math.Max(1, maxRows);
int maxRows = 1; // هر قرارداد فقط یک ردیف؛ نیازی به مرج عمودی نیست
int startRow = row;
int endRow = row + maxRows - 1;
// 🎨 دریافت رنگ پس‌زمینه از مقدار رنگ موجود در داده
string colorName = contract.ExpireColor.ToLower();
var fillColor = GetColorByName(colorName, contract.WorkshopCount, contract.IsContractingPartyBlock);
// 🎨 دریافت رنگ پس‌زمینه بر اساس وضعیت قرارداد
var fillColor = GetColorByStatus(contract.ListStatus, contract.WorkshopsCount);
for (int j = 0; j < maxRows; j++)
{
int currentRow = row + j;
worksheet.Cells[currentRow, 4].Value = j < employers.Count ? employers[j].FullName : null;
worksheet.Cells[currentRow, 5].Value = j < workshops.Count ? workshops[j].WorkshopFullName : null;
// پر کردن ستون‌های employer و workshop
var employerColIndex = GetColumnIndexForType(ExcelColumnType.EmployerName, visibleColumnIndices);
var workshopColIndex = GetColumnIndexForType(ExcelColumnType.WorkshopName, visibleColumnIndices);
for (int col = 1; col <= 11; col++)
if (employerColIndex > 0)
worksheet.Cells[currentRow, employerColIndex].Value = j < employers.Count ? employers[j] : null;
if (workshopColIndex > 0)
worksheet.Cells[currentRow, workshopColIndex].Value = j < workshops.Count ? workshops[j] : null;
for (int col = 1; col <= columnCount; col++)
{
var cell = worksheet.Cells[currentRow, col];
@@ -154,109 +202,235 @@ public class InstitutionContractExcelGenerator
}
// 🧱 مرج و مقداردهی ستون‌های اصلی
worksheet.Cells[startRow, 1, endRow, 1].Merge = true;
worksheet.Cells[startRow, 1].Value = contract.ContractNo;
worksheet.Cells[startRow, 2, endRow, 2].Merge = true;
worksheet.Cells[startRow, 2].Value = contract.ContractingPartyName;
worksheet.Cells[startRow, 3, endRow, 3].Merge = true;
worksheet.Cells[startRow, 3].Value = contract.ArchiveCode;
worksheet.Cells[startRow, 6, endRow, 6].Merge = true;
worksheet.Cells[startRow, 6].Value = contract.EmployeeCount;
worksheet.Cells[startRow, 7, endRow, 7].Merge = true;
worksheet.Cells[startRow, 7].Value = contract.ContractStartFa;
worksheet.Cells[startRow, 8, endRow, 8].Merge = true;
worksheet.Cells[startRow, 8].Value = contract.ContractEndFa;
worksheet.Cells[startRow, 9, endRow, 9].Merge = true;
var contractWithoutWorkshopAmountCell = worksheet.Cells[startRow, 9];
contractWithoutWorkshopAmountCell.Value = contract.WorkshopCount == "0" ? MoneyToDouble(contract.ContractAmount) : "";
contractWithoutWorkshopAmountCell.Style.Numberformat.Format = "#,##0";
worksheet.Cells[startRow, 10, endRow, 10].Merge = true;
var contractAmountCell = worksheet.Cells[startRow, 10];
contractAmountCell.Value = contract.WorkshopCount != "0" ? MoneyToDouble(contract.ContractAmount) : "";
contractAmountCell.Style.Numberformat.Format = "#,##0";
worksheet.Cells[startRow, 11, endRow, 11].Merge = true;
var balance = MoneyToDouble(contract.BalanceStr);
var balanceCell = worksheet.Cells[startRow, 11];
balanceCell.Value = balance;
balanceCell.Style.Numberformat.Format = "#,##0";
if (balance > 0)
balanceCell.Style.Font.Color.SetColor(Color.Red);
else if (balance < 0)
balanceCell.Style.Font.Color.SetColor(Color.Green);
FillColumnData(worksheet, contract, startRow, endRow, visibleColumnIndices);
// 📦 بوردر ضخیم خارجی برای هر سطر
var boldRange = worksheet.Cells[startRow, 1, endRow, 11];
var boldRange = worksheet.Cells[startRow, 1, endRow, columnCount];
boldRange.Style.Border.BorderAround(ExcelBorderStyle.Medium);
row += maxRows;
}
SetupPrintSettings(worksheet, visibleColumnIndices, columnCount);
}
/// <summary>
/// دریافت فهرست ستون‌های مرئی بر اساس کانفیگ
/// </summary>
private static List<ExcelColumnType> GetVisibleColumnIndices()
{
return _columnConfig.VisibleColumns;
}
/// <summary>
/// دریافت شماره ستون برای یک نوع ستون خاص
/// </summary>
private static int GetColumnIndexForType(ExcelColumnType columnType, List<ExcelColumnType> visibleColumns)
{
var index = visibleColumns.IndexOf(columnType);
return index >= 0 ? index + 1 : 0; // 1-based indexing
}
/// <summary>
/// دریافت متن header برای یک نوع ستون
/// </summary>
private static string GetColumnHeader(ExcelColumnType columnType)
{
return columnType switch
{
ExcelColumnType.RowNumber => "ردیف",
ExcelColumnType.PhysicalContract => "قرارداد فیزیکی",
ExcelColumnType.ContractNo => "شماره قرارداد",
ExcelColumnType.Representative => "معرف",
ExcelColumnType.ContractingPartyName => "طرف حساب",
ExcelColumnType.ArchiveCode => "شماره کارفرما",
ExcelColumnType.EmployerName => "کارفرما",
ExcelColumnType.WorkshopName => "کارگاه‌ها",
ExcelColumnType.WorkshopCount => "تعداد کارگاه",
ExcelColumnType.EmployeeCount => "مجموع پرسنل",
ExcelColumnType.ContractStartDate => "شروع قرارداد",
ExcelColumnType.ContractEndDate => "پایان قرارداد",
ExcelColumnType.InstallmentAmount => "مبلغ قسط",
ExcelColumnType.ContractAmount => "مبلغ قرارداد",
ExcelColumnType.FinancialStatus => "وضعیت مالی",
_ => ""
};
}
/// <summary>
/// تنظیم Headerهای ستون‌ها
/// </summary>
private static void SetupHeaders(ExcelWorksheet worksheet, List<ExcelColumnType> visibleColumns, int columnCount)
{
for (int i = 0; i < visibleColumns.Count; i++)
{
worksheet.Cells[1, i + 1].Value = GetColumnHeader(visibleColumns[i]);
}
}
/// <summary>
/// پر کردن داده‌های ستون‌ها برای یک قرارداد
/// </summary>
private static void FillColumnData(ExcelWorksheet worksheet, GetInstitutionContractListItemsViewModel contract, int startRow, int endRow, List<ExcelColumnType> visibleColumns)
{
for (int i = 0; i < visibleColumns.Count; i++)
{
int columnIndex = i + 1; // 1-based indexing
var columnType = visibleColumns[i];
// Merge cells for non-repeating columns
worksheet.Cells[startRow, columnIndex, endRow, columnIndex].Merge = true;
var cell = worksheet.Cells[startRow, columnIndex];
switch (columnType)
{
case ExcelColumnType.PhysicalContract:
var physicalText = contract.IsOldContract
? (contract.HasSigniture ? "موجود" : "ناموجود")
: (contract.IsInPersonContract ? "الکترونیکی حضوری" : "الکترونیکی غیر حضوری");
cell.Value = physicalText;
cell.Style.Font.Bold = true;
cell.Style.Font.Color.SetColor(physicalText switch
{
"موجود" => Color.Green,
"ناموجود" => Color.Red,
"الکترونیکی حضوری" => Color.Purple,
_ => Color.Blue
});
break;
case ExcelColumnType.ContractNo:
cell.Value = contract.ContractNo;
break;
case ExcelColumnType.Representative:
cell.Value = contract.RepresentativeName;
break;
case ExcelColumnType.ContractingPartyName:
cell.Value = contract.ContractingPartyName;
break;
case ExcelColumnType.ArchiveCode:
cell.Value = contract.ArchiveNo;
break;
case ExcelColumnType.EmployerName:
// این ستون چندخطی است و داخل loop پر می‌شود
break;
case ExcelColumnType.WorkshopName:
// این ستون چندخطی است و داخل loop پر می‌شود
break;
case ExcelColumnType.WorkshopCount:
cell.Value = contract.WorkshopsCount;
break;
case ExcelColumnType.EmployeeCount:
cell.Value = contract.EmployeesCount;
break;
case ExcelColumnType.ContractStartDate:
cell.Value = contract.ContractStartFa;
break;
case ExcelColumnType.ContractEndDate:
cell.Value = contract.ContractEndFa;
break;
case ExcelColumnType.InstallmentAmount:
cell.Value = contract.InstallmentAmount;
cell.Style.Numberformat.Format = "#,##0";
break;
case ExcelColumnType.ContractAmount:
cell.Value = contract.ContractAmount;
cell.Style.Numberformat.Format = "#,##0";
break;
case ExcelColumnType.FinancialStatus:
cell.Value = contract.Balance;
cell.Style.Numberformat.Format = "#,##0";
if (contract.Balance > 0)
cell.Style.Font.Color.SetColor(Color.Red);
else if (contract.Balance < 0)
cell.Style.Font.Color.SetColor(Color.Green);
break;
}
}
}
/// <summary>
/// تنظیم تنظیمات چاپ و عرض ستون‌ها
/// </summary>
private static void SetupPrintSettings(ExcelWorksheet worksheet, List<ExcelColumnType> visibleColumns, int columnCount)
{
worksheet.PrinterSettings.PaperSize = ePaperSize.A4;
worksheet.PrinterSettings.Orientation = eOrientation.Landscape;
worksheet.PrinterSettings.FitToPage = true;
worksheet.PrinterSettings.FitToWidth = 1;
worksheet.PrinterSettings.FitToHeight = 0;
worksheet.PrinterSettings.Scale = 85;
int contractNoCol = 1;
int contractingPartyNameCol = 2;
int archiveNoCol = 3;
int employersCol = 4;
int workshopsCol = 5;
int employeeCountCol = 6;
int startContractCol = 7;
int endContractCol = 8;
int contractWithoutWorkshopAmountCol = 9;
int contractAmountCol = 10;
int balanceCol = 11;
worksheet.Columns[contractNoCol].Width = 17;
worksheet.Columns[contractingPartyNameCol].Width = 40;
worksheet.Columns[archiveNoCol].Width = 10;
worksheet.Columns[employersCol].Width = 40;
worksheet.Columns[workshopsCol].Width = 45;
worksheet.Columns[employeeCountCol].Width = 12;
worksheet.Columns[startContractCol].Width = 12;
worksheet.Columns[endContractCol].Width = 12;
worksheet.Columns[contractWithoutWorkshopAmountCol].Width = 18;
worksheet.Columns[contractAmountCol].Width = 12;
worksheet.Columns[balanceCol].Width = 12;
// تنظیم عرض ستون‌ها بر اساس نوع ستون
for (int i = 0; i < visibleColumns.Count; i++)
{
int columnIndex = i + 1;
worksheet.Columns[columnIndex].Width = GetColumnWidth(visibleColumns[i]);
}
worksheet.View.RightToLeft = true; // فارسی
//worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
}
/// <summary>
/// دریافت عرض ستون پیش‌فرض برای هر نوع ستون
/// </summary>
private static double GetColumnWidth(ExcelColumnType columnType)
{
return columnType switch
{
ExcelColumnType.RowNumber => 8,
ExcelColumnType.PhysicalContract => 15,
ExcelColumnType.ContractNo => 17,
ExcelColumnType.Representative => 15,
ExcelColumnType.ContractingPartyName => 40,
ExcelColumnType.ArchiveCode => 10,
ExcelColumnType.EmployerName => 40,
ExcelColumnType.WorkshopName => 45,
ExcelColumnType.WorkshopCount => 12,
ExcelColumnType.EmployeeCount => 12,
ExcelColumnType.ContractStartDate => 12,
ExcelColumnType.ContractEndDate => 12,
ExcelColumnType.InstallmentAmount => 15,
ExcelColumnType.ContractAmount => 15,
ExcelColumnType.FinancialStatus => 12,
_ => 12
};
}
private static double MoneyToDouble(string value)
{
Console.WriteLine(value);
if (string.IsNullOrEmpty(value))
return 0;
var min = value.Length > 1 ? value.Substring(0, 2) : "";
var test = min == "\u200e\u2212" ? value.MoneyToDouble() * -1 : value.MoneyToDouble();
Console.WriteLine(test);
return test;
}
private static Color GetColorByName(string name, string workshopCount, string IsContractingPartyBlock)
/// <summary>
/// دریافت رنگ بر اساس وضعیت قرارداد
/// </summary>
private static Color GetColorByStatus(InstitutionContractListStatus status, int workshopsCount)
{
return name switch
return status switch
{
"blue" => Color.LightBlue,
_ when IsContractingPartyBlock == "true" => Color.LightGray,
"red" => Color.LightCoral,
"purple" => Color.MediumPurple,
"black" => Color.DimGray,
var n when string.IsNullOrWhiteSpace(n) && workshopCount == "0" => Color.Yellow,
InstitutionContractListStatus.DeactiveWithDebt => Color.LightBlue,
InstitutionContractListStatus.Deactive => Color.LightGray,
InstitutionContractListStatus.PendingForRenewal => Color.LightCoral,
InstitutionContractListStatus.Free => Color.MediumPurple,
InstitutionContractListStatus.Block => Color.DimGray,
InstitutionContractListStatus.WithoutWorkshop => Color.Yellow,
InstitutionContractListStatus.Active => Color.White,
_ => Color.White
};
}
}
}
public class InstitutionContractExcelViewModel
{
public InstitutionContractListStatus? Tab { get; set; }
public List<GetInstitutionContractListItemsViewModel> GetInstitutionContractListItemsViewModels { get; set; }
}

View File

@@ -8,7 +8,7 @@ public class RollCallExcelGenerator : ExcelGenerator
{
public static byte[] CaseHistoryExcelForEmployee(CaseHistoryRollCallExcelForEmployeeViewModel data)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new OfficeOpenXml.ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
var rollCalls = data.RollCalls;
@@ -181,7 +181,7 @@ public class RollCallExcelGenerator : ExcelGenerator
public static byte[] CaseHistoryExcelForOneDay(CaseHistoryRollCallForOneDayViewModel data)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new OfficeOpenXml.ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
var rollCalls = data.RollCalls;

View File

@@ -43,7 +43,7 @@ public class SalaryAidImportExcel
ValidData = []
};
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
if (file == null || file.Length == 0)
{

View File

@@ -9,7 +9,7 @@ public class WorkshopRollCallExcelExporter
{
public static byte[] Export(List<WorkshopRollCallExcelViewModel> workshops)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using (var package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("Workshops");

View File

@@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Company.Domain.CameraBugReportAgg;
using MongoDB.Bson;
using MongoDB.Driver;
namespace CompanyManagement.Infrastructure.Mongo.CameraBugReportRepo;
/// <summary>
/// پیاده‌سازی انبار گزارش خرابی دوربین برای MongoDB
/// </summary>
public class CameraBugReportRepository : ICameraBugReportRepository
{
private readonly IMongoCollection<CameraBugReport> _cameraBugReports;
public CameraBugReportRepository(IMongoDatabase database)
{
_cameraBugReports = database.GetCollection<CameraBugReport>("CameraBugReports");
}
public async Task CreateAsync(CameraBugReport bugReport)
{
await _cameraBugReports.InsertOneAsync(bugReport);
}
public async Task UpdateAsync(CameraBugReport bugReport)
{
await _cameraBugReports.ReplaceOneAsync(
x => x.Id == bugReport.Id,
bugReport);
}
public async Task<CameraBugReport> GetByIdAsync(Guid id)
{
return await _cameraBugReports
.Find(x => x.Id == id)
.FirstOrDefaultAsync();
}
public async Task<List<CameraBugReport>> GetAllAsync()
{
return await _cameraBugReports
.Find(_ => true)
.ToListAsync();
}
public async Task<List<CameraBugReport>> GetAllAsync(int skip, int take)
{
return await _cameraBugReports
.Find(_ => true)
.Skip(skip)
.Limit(take)
.SortByDescending(x => x.CreationDate)
.ToListAsync();
}
public async Task DeleteAsync(Guid id)
{
await _cameraBugReports.DeleteOneAsync(x => x.Id == id);
}
public async Task<bool> IsExistAsync(Guid id)
{
var result = await _cameraBugReports
.Find(x => x.Id == id)
.FirstOrDefaultAsync();
return result != null;
}
public async Task<List<CameraBugReport>> FilterAsync(
CameraBugReportType? type = null,
CameraBugPriority? priority = null,
CameraBugReportStatus? status = null,
string searchTerm = null,
int skip = 0,
int take = 10)
{
var filterDefinition = BuildFilterDefinition(type, priority, status, searchTerm);
return await _cameraBugReports
.Find(filterDefinition)
.Skip(skip)
.Limit(take)
.SortByDescending(x => x.CreationDate)
.ToListAsync();
}
public async Task<int> CountAsync(
CameraBugReportType? type = null,
CameraBugPriority? priority = null,
CameraBugReportStatus? status = null,
string searchTerm = null)
{
var filterDefinition = BuildFilterDefinition(type, priority, status, searchTerm);
var count = await _cameraBugReports.CountDocumentsAsync(filterDefinition);
return (int)count;
}
private FilterDefinition<CameraBugReport> BuildFilterDefinition(
CameraBugReportType? type = null,
CameraBugPriority? priority = null,
CameraBugReportStatus? status = null,
string searchTerm = null)
{
var filters = new List<FilterDefinition<CameraBugReport>>();
if (type.HasValue)
filters.Add(Builders<CameraBugReport>.Filter.Eq(x => x.Type, type.Value));
if (priority.HasValue)
filters.Add(Builders<CameraBugReport>.Filter.Eq(x => x.Priority, priority.Value));
if (status.HasValue)
filters.Add(Builders<CameraBugReport>.Filter.Eq(x => x.Status, status.Value));
if (!string.IsNullOrEmpty(searchTerm))
{
var searchFilter = Builders<CameraBugReport>.Filter.Or(
Builders<CameraBugReport>.Filter.Regex(x => x.Title, new BsonRegularExpression(searchTerm, "i")),
Builders<CameraBugReport>.Filter.Regex(x => x.Description, new BsonRegularExpression(searchTerm, "i")),
Builders<CameraBugReport>.Filter.Regex(x => x.UserEmail, new BsonRegularExpression(searchTerm, "i"))
);
filters.Add(searchFilter);
}
if (filters.Count == 0)
return Builders<CameraBugReport>.Filter.Empty;
return Builders<CameraBugReport>.Filter.And(filters);
}
// Sync methods from IRepository interface (not used in MongoDB flow but required for interface implementation)
public CameraBugReport Get(long id)
{
throw new NotImplementedException("استفاده از GetByIdAsync برای MongoDB");
}
public List<CameraBugReport> Get()
{
throw new NotImplementedException("استفاده از GetAllAsync برای MongoDB");
}
public void Create(CameraBugReport entity)
{
throw new NotImplementedException("استفاده از CreateAsync برای MongoDB");
}
public bool ExistsIgnoreQueryFilter(System.Linq.Expressions.Expression<Func<CameraBugReport, bool>> expression)
{
throw new NotImplementedException("استفاده از IsExistAsync برای MongoDB");
}
public bool Exists(System.Linq.Expressions.Expression<Func<CameraBugReport, bool>> expression)
{
throw new NotImplementedException("استفاده از FilterAsync برای MongoDB");
}
public void SaveChanges()
{
throw new NotImplementedException("MongoDB نیازی به SaveChanges ندارد");
}
public async Task SaveChangesAsync()
{
// MongoDB خودکار ذخیره می‌کند، بنابراین این متد خالی است
await Task.CompletedTask;
}
public Task<Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction> BeginTransactionAsync()
{
throw new NotImplementedException("MongoDB اعاملات را بصورت متفاوت مدیریت می‌کند");
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
@@ -11,7 +11,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="MongoDB.Driver" Version="3.5.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class CameraBugReportDetailViewModel
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string UserEmail { get; set; }
public long? AccountId { get; set; }
public string DeviceModel { get; set; }
public string OsVersion { get; set; }
public string Platform { get; set; }
public string Manufacturer { get; set; }
public string DeviceId { get; set; }
public string ScreenResolution { get; set; }
public int MemoryInMB { get; set; }
public int StorageInMB { get; set; }
public int BatteryLevel { get; set; }
public bool IsCharging { get; set; }
public string NetworkType { get; set; }
public string AppVersion { get; set; }
public string BuildNumber { get; set; }
public string PackageName { get; set; }
public DateTime InstallTime { get; set; }
public DateTime LastUpdateTime { get; set; }
public string Flavor { get; set; }
public CameraBugReportType Type { get; set; }
public CameraBugPriority Priority { get; set; }
public CameraBugReportStatus Status { get; set; }
public string StackTrace { get; set; }
public DateTime CreationDate { get; set; }
public DateTime? UpdateDate { get; set; }
public List<string> Logs { get; set; }
public List<CameraBugReportScreenshotViewModel> Screenshots { get; set; }
}
public class CameraBugReportScreenshotViewModel
{
public string FileName { get; set; }
public DateTime UploadDate { get; set; }
public string Base64Data { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using System;
namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class CameraBugReportViewModel
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string UserEmail { get; set; }
public long? AccountId { get; set; }
public string DeviceModel { get; set; }
public string AppVersion { get; set; }
public CameraBugReportType Type { get; set; }
public CameraBugPriority Priority { get; set; }
public CameraBugReportStatus Status { get; set; }
public DateTime CreationDate { get; set; }
public DateTime? UpdateDate { get; set; }
public int LogsCount { get; set; }
public int ScreenshotsCount { get; set; }
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class CreateCameraBugReportCommand
{
public string Title { get; set; }
public string Description { get; set; }
public string UserEmail { get; set; }
public long? AccountId { get; set; }
public string DeviceModel { get; set; }
public string OsVersion { get; set; }
public string Platform { get; set; }
public string Manufacturer { get; set; }
public string DeviceId { get; set; }
public string ScreenResolution { get; set; }
public int MemoryInMB { get; set; }
public int StorageInMB { get; set; }
public int BatteryLevel { get; set; }
public bool IsCharging { get; set; }
public string NetworkType { get; set; }
public string AppVersion { get; set; }
public string BuildNumber { get; set; }
public string PackageName { get; set; }
public DateTime InstallTime { get; set; }
public DateTime LastUpdateTime { get; set; }
public string Flavor { get; set; }
public CameraBugReportType Type { get; set; }
public CameraBugPriority Priority { get; set; }
public string StackTrace { get; set; }
public List<string> Logs { get; set; }
public List<string> Screenshots { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class EditCameraBugReportCommand
{
public Guid Id { get; set; }
public CameraBugPriority Priority { get; set; }
public CameraBugReportStatus Status { get; set; }
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using _0_Framework.Application;
namespace CompanyManagment.App.Contracts.CameraBugReport
{
public interface ICameraBugReportApplication
{
Task<OperationResult> CreateAsync(CreateCameraBugReportCommand command);
Task<OperationResult> EditAsync(EditCameraBugReportCommand command);
Task<OperationResult> DeleteAsync(Guid id);
Task<List<CameraBugReportViewModel>> GetAllAsync(CameraBugReportSearchModel searchModel);
Task<CameraBugReportDetailViewModel> GetDetailsAsync(Guid id);
Task<bool> IsExistAsync(Guid id);
// Keep sync methods for backward compatibility but they delegate to async
OperationResult Create(CreateCameraBugReportCommand command);
OperationResult Edit(EditCameraBugReportCommand command);
OperationResult Delete(Guid id);
List<CameraBugReportViewModel> GetAll(CameraBugReportSearchModel searchModel);
CameraBugReportDetailViewModel GetDetails(Guid id);
bool IsExist(Guid id);
}
public class CameraBugReportSearchModel
{
public CameraBugReportType? Type { get; set; }
public CameraBugPriority? Priority { get; set; }
public CameraBugReportStatus? Status { get; set; }
public string SearchTerm { get; set; }
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
}
/// </summary>
/// وضعیت گزارش خرابی دوربین
/// <summary>
public enum CameraBugReportStatus
{
Reopened = 5, // مجدداً باز شده
Closed = 4, // بسته شده
Fixed = 3, // رفع شده
InProgress = 2, // در حال بررسی
Open = 1, // باز
}
/// </summary>
/// اولویت گزارش خرابی دوربین
/// <summary>
public enum CameraBugPriority
{
Low = 4, // پایین
Medium = 3, // متوسط
High = 2, // بالا
Critical = 1, // بحرانی
}
/// </summary>
/// انواع گزارش خرابی دوربین
/// <summary>
public enum CameraBugReportType
{
Other = 8, // سایر
CrashOnCapture = 7, // کرش هنگام عکس‌برداری
LightingIssue = 6, // مشکل روشنایی
FocusIssue = 5, // مشکل فوکوس
PerformanceIssue = 4, // مشکل عملکردی
FaceRecognitionFailed = 3, // شناسایی چهره ناموفق
BlurryImage = 2, // تصویر مبهم
CameraNotWorking = 1, // دوربین کار نمی‌کند
}

View File

@@ -1,12 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
<PackageReference Include="PersianTools.Core" Version="2.0.4" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,12 @@
namespace CompanyManagment.App.Contracts.Contract;
public enum ContractListOrderType
{
ByContractCreationDate,
BySignedContract,
ByUnSignedContract,
ByPersonnelCode,
ByPersonnelCodeDescending,
ByContractStartDate,
ByContractStartDateDescending
}

View File

@@ -0,0 +1,13 @@
using _0_Framework.Application;
namespace CompanyManagment.App.Contracts.Contract;
public class GetContractListForClientRequest: PaginationRequest
{
public int Year { get; set; }
public int Month { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public long EmployeeId { get; set; }
public ContractListOrderType? OrderType { get; set; }
}

View File

@@ -0,0 +1,15 @@
namespace CompanyManagment.App.Contracts.Contract;
public class GetContractListForClientResponse
{
public long Id { get; set; }
public string PersonnelCode { get; set; }
public string ContractNo { get; set; }
public string EmployeeFullName { get; set; }
public string ContractStart { get; set; }
public string ContractEnd { get; set; }
public bool IsSigned { get; set; }
public string DailyWage { get; set; }
public string AvgWorkingHour { get; set; }
public string FamilyAllowance { get; set; }
}

View File

@@ -3,6 +3,8 @@ using System.Collections.Generic;
using _0_Framework.Application;
using CompanyManagment.App.Contracts.Workshop;
using System.Threading.Tasks;
using _0_Framework.Application.Enums;
namespace CompanyManagment.App.Contracts.Contract;
public interface IContractApplication
@@ -45,16 +47,101 @@ public interface IContractApplication
#region Client
OperationResult Remove(long id);
[Obsolete("این متد منسوخ شده است. لطفاً از متد GetContractListForClient استفاده کنید.")]
List<ContractViweModel> SearchForClient(ContractSearchModel searchModel);
#endregion
/// <summary>
/// لیست قراردادها برای کلاینت
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
Task<PagedResult<GetContractListForClientResponse>>
GetContractListForClient(GetContractListForClientRequest searchModel);
Task<ContractPrintViewModel> PrintOneAsync(long id);
Task<List<ContractPrintViewModel>> PrintAllAsync(List<long> ids);
#region NewChangeByHeydari
#endregion
OperationResult DeleteAllContarcts(List<long> ids);
#region NewChangeByHeydari
OperationResult DeleteAllContarcts(List<long> ids);
OperationResult DeleteContarcts(long id);
List<long> CheckHasCheckout(List<long> ids);
List<long> CheckHasSignature(List<long> ids);
List<ContractViweModel> SearchForMainContract(ContractSearchModel searchModel);
#endregion
}
public class ContractPrintViewModel
{
public string ContractNo { get; set; }
public ContractPrintEmployerViewModel Employer { get; set; }
public ContractPrintEmployeeViewModel Employee { get; set; }
public ContractPrintTypeOfContractViewModel TypeOfContract { get; set; }
public ContractPrintFeesViewModel Fees { get; set; }
public string ConditionAndDetials { get; set; }
}
public class ContractPrintFeesViewModel
{
public string DailyWage { get; set; }
public string FamilyAllowance { get; set; }
public string ConsumableItems { get; set; }
public string HousingAllowance { get; set; }
}
public class ContractPrintTypeOfContractViewModel
{
public string ContractType { get; set; }
public string JobName { get; set; }
public string SetContractDate { get; set; }
public string ContarctStart { get; set; }
public string ContractEnd { get; set; }
public string WorkingHoursWeekly { get; set; }
public List<string> WorkshopAddress { get; set; }
}
public class ContractPrintEmployeeViewModel
{
public string FullName { get; set; }
public string NationalCode { get; set; }
public string IdNumber { get; set; }
public string DateOfBirth { get; set; }
public string FatherName { get; set; }
public string LevelOfEducation { get; set; }
public string Address { get; set; }
}
public class ContractPrintEmployerViewModel
{
public LegalType LegalType { get; set; }
public ContractPrintRealEmployerViewModel RealEmployer { get; set; }
public ContractPrintLegalEmployerViewModel LegalEmployer { get; set; }
public string WorkshopName { get; set; }
public string Address { get; set; }
public string WorkshopCode { get; set; }
}
public class ContractPrintLegalEmployerViewModel
{
public string CompanyName { get; set; }
public string NationalId { get; set; }
public string RegisterId { get; set; }
}
public class ContractPrintRealEmployerViewModel
{
public string FullName { get; set; }
public string NationalCode { get; set; }
public string IdNumber { get; set; }
}

View File

@@ -60,7 +60,7 @@ public interface IEmployeeApplication
/// <returns></returns>
Task<OperationResult<EmployeeByNationalCodeInWorkshopViewModel>>
ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode,
string birthDate, long workshopId);
string birthDate,bool authorizedCanceled, long workshopId);
/// <summary>
/// پرسنل هایی که در کارگاهی از سمت ادمین شروع به کار کرده اند
@@ -94,7 +94,42 @@ public interface IEmployeeApplication
/// </summary>
/// <returns></returns>
Task<List<GetEmployeeListViewModel>> GetList(GetEmployeeListSearchModel searchModel);
/// <summary>
/// لیست کل پرسنل کلاینت
/// </summary>
/// <param name="searchModel"></param>
/// <param name="workshopId"></param>
/// <returns></returns>
Task<List<GetClientEmployeeListViewModel>> GetClientEmployeeList(GetClientEmployeeListSearchModel searchModel, long workshopId);
#endregion
}
public class GetClientEmployeeListSearchModel
{
}
public class GetClientEmployeeListViewModel
{
public string FullName { get; set; }
public long EmployeeId { get; set; }
public long WorkshopId { get; set; }
public long PersonnelCode { get; set; }
public string MaritalStatus { get; set; }
public string NationalCode { get; set; }
public string IdNumber { get; set; }
public string DateOfBirthFa { get; set; }
public string FatherName { get; set; }
public int ChildrenCount { get; set; }
public string LastStartInsuranceWork { get; set; }
public string LastLeftInsuranceWork { get; set; }
public string LastStartContractWork { get; set; }
public string LastLeftContractWork { get; set; }
public bool HasContractLeftWork { get; set; }
public bool HasInsuranceLeftWork { get; set; }
public bool LeftWorkCompletely { get; set; }
public bool PendingStartWork { get; set; }
public bool PendingLeftWork { get; set; }
}

View File

@@ -13,5 +13,6 @@ namespace CompanyManagment.App.Contracts.EmployeeDocuments
public string EmployerName { get; set; }
public List<EmployeeDocumentItemViewModel> SubmittedItems { get; set; }
public int EmployeesWithoutDocumentCount { get; set; }
public long EmployeeId { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
namespace CompanyManagment.App.Contracts.InstitutionContract;
public enum InstitutionContractSigningType
{
/// <summary>
/// قدیمی
/// </summary>
Legacy = 0,
/// <summary>
/// الکترونیکی با کد یکبار مصرف
/// </summary>
OtpBased = 1,
/// <summary>
/// به صورت فیزیکی
/// </summary>
Physical = 2
}

View File

@@ -91,6 +91,11 @@ public class GetInstitutionContractListItemsViewModel
public bool IsInPersonContract { get; set; }
public bool IsOldContract { get; set; }
/// <summary>
/// مبلغ قسط
/// </summary>
public double InstallmentAmount { get; set; }
}
public class InstitutionContractListWorkshop

View File

@@ -7,7 +7,6 @@ using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.Application.Sms;
using CompanyManagment.App.Contracts.Checkout;
using CompanyManagment.App.Contracts.Law;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using CompanyManagment.App.Contracts.Workshop;
using CompanyManagment.App.Contracts.WorkshopPlan;
@@ -260,154 +259,13 @@ public interface IInstitutionContractApplication
/// <returns></returns>
Task<InstitutionContractPrintViewModel> PrintOneAsync(long id);
Task<OperationResult> SetPendingWorkflow(long entityId);
Task<OperationResult> SetPendingWorkflow(long entityId,InstitutionContractSigningType signingType);
Task<long> GetIdByInstallmentId(long installmentId);
}
public class InstitutionContractDiscountResponse
{
public InstitutionContractDiscountOneTimeViewModel OneTime { get; set; }
public InstitutionContractDiscountMonthlyViewModel Monthly { get; set; }
}
public class InstitutionContractDiscountMonthlyViewModel:InstitutionContractDiscountOneTimeViewModel
{
public List<MonthlyInstallment> Installments { get; set; }
}
public class InstitutionContractDiscountOneTimeViewModel
{
/// <summary>
/// مجموع مبالغ
/// تایید قرارداد مالی به صورت دستی
/// </summary>
public string TotalAmount { get; set; }
/// <summary>
/// ارزش افزوده
/// </summary>
public string Tax { get; set; }
/// <summary>
/// مبلغ قابل پرداخت
/// </summary>
public string PaymentAmount { get; set; }
public string DiscountedAmount { get; set; }
public int DiscountPercetage { get; set; }
/// <param name="institutionContractId"></param>
/// <returns></returns>
Task<OperationResult> VerifyInstitutionContractManually(long institutionContractId);
public string Obligation { get; set; }
public string OneMonthAmount { get; set; }
}
public class InstitutionContractResetDiscountForCreateRequest
{
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
public InstitutionContractDuration Duration { get; set; }
public double OneMonthAmount { get; set; }
}
public class InstitutionContractSetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractResetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractSetDiscountRequest
{
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public InstitutionContractDuration Duration { get; set; }
public double OneMonthAmount { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractPrintViewModel
{
public InstitutionContratVerificationParty FirstParty { get; set; }
public InstitutionContratVerificationParty SecondParty { get; set; }
public string ContractNo { get; set; }
public string CreationDate { get; set; }
public string ContractStart { get; set; }
public string ContractEnd { get; set; }
public List<GetInstitutionVerificationDetailsWorkshopsViewModel> Workshops { get; set; }
public string TotalPrice { get; set; }
public string TaxPrice { get; set; }
public string PaymentPrice { get; set; }
public string VerifyCode { get; set; }
public string VerifyDate { get; set; }
public string VerifyTime { get; set; }
public string VerifierFullName { get; set; }
public string VerifierPhoneNumber { get; set; }
public LawViewModel LawViewModel { get; set; }
public string Obligation { get; set; }
}
public class InsertAmendmentTempWorkshopResponse
{
public Guid WorkshopTempId { get; set; }
public string Amount { get; set; }
}
public class InstitutionContractAmendmentWorkshopsResponse
{
/// <summary>
///
/// </summary>
public List<InstitutionContractAmendmentTempWorkshopViewModel> Workshops { get; set; }
public Guid TempId { get; set; }
}
public class InstitutionContractSelectListViewModel : SelectListViewModel;
public class InstitutionContractExtensionInquiryResponse
{
public long Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string DateOfBirthFa { get; set; }
public string FatherName { get; set; }
public string IdNumberSerial { get; set; }
public string IdNumber { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string City { get; set; }
public string State { get; set; }
public long RepresentativeId { get; set; }
public string NationalCode { get; set; }
}
public class InstitutionContractExtensionPaymentMonthly:InstitutionContractExtensionPaymentOneTime
{
public List<MonthlyInstallment> Installments { get; set; }
}
public class InstitutionContractExtensionPaymentOneTime
{
/// <summary>
/// مجموع مبالغ
/// </summary>
public string TotalAmount { get; set; }
/// <summary>
/// ارزش افزوده
/// </summary>
public string Tax { get; set; }
/// <summary>
/// مبلغ قابل پرداخت
/// </summary>
public string PaymentAmount { get; set; }
}

View File

@@ -0,0 +1,9 @@
using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InsertAmendmentTempWorkshopResponse
{
public Guid WorkshopTempId { get; set; }
public string Amount { get; set; }
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractAmendmentWorkshopsResponse
{
/// <summary>
///
/// </summary>
public List<InstitutionContractAmendmentTempWorkshopViewModel> Workshops { get; set; }
public Guid TempId { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More