Compare commits
319 Commits
1.15.1
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
3d2d759d6b | |||
b73de03d27 | |||
a9e953812c | |||
4344265ed5 | |||
4fb94bdd6d | |||
e2582373ad | |||
309483ea08 | |||
b2bc200eb1 | |||
a0ab0deb2a | |||
1f9491ce73 | |||
1663f19b2a | |||
07277862cf | |||
f1016bd9cc | |||
c39f479b96 | |||
a4d1a2bf76 | |||
8bba04305f | |||
516d6fc136 | |||
2e096cb495 | |||
3505f915c5 | |||
254cd02649 | |||
97e37f34a1 | |||
ae6b66b270 | |||
7a1aecebd5 | |||
387ffc9ade | |||
d0c3537753 | |||
eb97bfbeeb | |||
7fee33999f | |||
99c0e92336 | |||
46494c033c | |||
85986ce13e | |||
bdeae5b38b | |||
edc7aedbe0 | |||
900e03791a | |||
2a977bbf47 | |||
d29df73d05 | |||
1150e1b047 | |||
cf7eeb5bde | |||
c2a367bd28 | |||
3c19e9d4cf | |||
e295e53f86 | |||
be02061b94 | |||
08dbe1e35b | |||
8e9dca56bc | |||
2e9fe29e99 | |||
b0a6f207cd | |||
a51a79a763 | |||
b2d1903009 | |||
53f99f620c | |||
312267567f | |||
34b2571a2e | |||
b79874d056 | |||
27e42fac56 | |||
4124d5eb38 | |||
bb8c6378bc | |||
c3109f1894 | |||
59b4b5ff39 | |||
2d7335ff85 | |||
2e49de8573 | |||
a4772e3c25 | |||
de9937606e | |||
1b749e9f1a | |||
f0b3748596 | |||
2ea42d10e6 | |||
55cf10d289 | |||
09ab52b971 | |||
c00aa6fa73 | |||
817c8d63e1 | |||
cce885d961 | |||
6d92c484cd | |||
f5be3b0f8e | |||
85afbbc01e | |||
e0c0c69d35 | |||
df82650931 | |||
3196006bad | |||
820755b9e0 | |||
1946c7aa88 | |||
7c35a2d427 | |||
c4ee706591 | |||
4ee5f349f0 | |||
21a1974ba1 | |||
969b4d22fc | |||
6169324ffd | |||
003cad1f58 | |||
c8df4b21a0 | |||
7f49fb2d0e | |||
1cb028c273 | |||
4ad6c10a64 | |||
899df95994 | |||
0fa7ffa34a | |||
c46a597828 | |||
764f1b20d9 | |||
01b4a681da | |||
16299d480e | |||
b0cb9f6fd0 | |||
5b133c951d | |||
e29a7ec0e2 | |||
e7213d8a70 | |||
4d7510ad3a | |||
d8ef918a67 | |||
cb49d0fbf7 | |||
70c835eb93 | |||
40b51f1a77 | |||
1bff76c637 | |||
24b6bcfa47 | |||
b22baefa5a | |||
a6e0f4e728 | |||
e366220e8b | |||
f71e304731 | |||
55f58bb689 | |||
03b752759f | |||
85c6ed8483 | |||
a081c6a371 | |||
6c3122a3d8 | |||
0c80b87606 | |||
b6da539fcd | |||
d4d99772b9 | |||
4f8be43527 | |||
eb2282efac | |||
85b5bf7b58 | |||
626a5ccb11 | |||
806ffb2754 | |||
5900c13e08 | |||
d399698eb1 | |||
457d329b0b | |||
45c428d30a | |||
7ddb72239e | |||
580820ef44 | |||
d037150eb3 | |||
35a102e4a9 | |||
f7c75df9be | |||
d0e18fe75a | |||
e30c08fd5b | |||
1058659174 | |||
b9ac588f87 | |||
40b4bb0a3e | |||
9bd9652b3d | |||
46c4fe9516 | |||
a71b5e6aba | |||
e0cbf1447f | |||
b69e54f1e9 | |||
ecb1c21179 | |||
acff19ad58 | |||
f79f796a14 | |||
a08a43e2bd | |||
8238e97a45 | |||
88202b57ee | |||
324fa39b56 | |||
233393e853 | |||
84afc3274a | |||
a5bfc4977d | |||
19205bbe8b | |||
f144e0b8ef | |||
8473d00148 | |||
c8391caf07 | |||
d19bb3a204 | |||
ed71e935fc | |||
5ba243a1ea | |||
88a30650a5 | |||
420b223ca4 | |||
7168d519d1 | |||
4a09463f0a | |||
0a52029840 | |||
6841b30a77 | |||
dbaff89b8d | |||
b7cd9ea75c | |||
b54f3b7ab4 | |||
83d7c38c38 | |||
644dbc8159 | |||
e566a5edf1 | |||
ef5c6b73af | |||
3d7b133005 | |||
37a18d3c6e | |||
d6290471ba | |||
c13b360ca5 | |||
e5cb0261ba | |||
6c91cb008c | |||
9561301500 | |||
349d67fa7b | |||
ce64664447 | |||
370b8cd40f | |||
efde919689 | |||
9a88b75654 | |||
0ceab03334 | |||
c8cec06d85 | |||
018cd7d245 | |||
471b5c08f6 | |||
b11a978962 | |||
95aba2b44b | |||
5d6d0e95ec | |||
f0f75ecaa8 | |||
975a71bdd6 | |||
f9e59835c1 | |||
6ea66f7379 | |||
fb768d1432 | |||
baa61155f7 | |||
c773fbc3a5 | |||
8c84ff7c52 | |||
85d4cc8220 | |||
70a2d502ef | |||
393c8ce0ce | |||
92bc4aec43 | |||
4c46681d39 | |||
a898549469 | |||
4e75faafb8 | |||
1718a1cf14 | |||
64757826da | |||
927776b9a7 | |||
4ea5ddf122 | |||
847a5550e8 | |||
ea38665dab | |||
440adc09f4 | |||
9fcb1a8a44 | |||
22808cf6c8 | |||
f978839ccc | |||
54af17d75a | |||
c7eef1a97c | |||
59741e4197 | |||
2518873e23 | |||
029ab6bc06 | |||
a583db4b65 | |||
9f8789f390 | |||
c0b27c2886 | |||
cdacb19c30 | |||
471a1249c0 | |||
53abf219a3 | |||
51c238734a | |||
efb0f52e8a | |||
39dc8ad39f | |||
db47d0e160 | |||
da13343b27 | |||
8100030870 | |||
5097db6f94 | |||
b729842a1c | |||
bc1d5ffc03 | |||
ae1f600147 | |||
edc3f9fd3c | |||
8dc922a8bb | |||
9461cdaf9d | |||
a923a21660 | |||
dcd60a5152 | |||
50882a4732 | |||
9cd59e8446 | |||
9905edc28c | |||
98479f39e6 | |||
bdfd3f42c4 | |||
ca022e0697 | |||
1719b6c417 | |||
bb0f9b56e6 | |||
107a3aa17f | |||
1c9be27e1f | |||
dc25d483fc | |||
33362a28d5 | |||
b476bd458e | |||
c152dd13f1 | |||
677cc55e04 | |||
b6146b7d14 | |||
dbc849d3f1 | |||
8d1098ec9e | |||
63923e8a9b | |||
7261f60e3b | |||
fef14b8be8 | |||
17e4cb4148 | |||
99211b7505 | |||
c4e81ffbed | |||
683b134053 | |||
2a5c86d961 | |||
ca28a67194 | |||
d904ce7100 | |||
daf30de835 | |||
7c9819efd1 | |||
42bea64ff5 | |||
537f167b9e | |||
0a630cf51a | |||
29e07e6cac | |||
0f21f8daf0 | |||
6289fad8ad | |||
705b245514 | |||
9e1a426240 | |||
c80a5b5232 | |||
eddd2534ea | |||
9dc1ae2d05 | |||
4b8cb9633e | |||
8016c4b4c8 | |||
3efadfa75f | |||
66bbace8be | |||
7ff638ed58 | |||
ddebf50e88 | |||
64144ea76f | |||
633df58964 | |||
f280f408ee | |||
d1715f4457 | |||
e80647ffd1 | |||
1a5f328a24 | |||
4872c6d1c8 | |||
a695b4563d | |||
b89993f89d | |||
8f69e6ec79 | |||
8984aeebb8 | |||
a0d750b1f5 | |||
75618de977 | |||
2e1358da83 | |||
8ecb1fe01a | |||
0ff8f8650b | |||
529a7fa385 | |||
6258fb2a33 | |||
0a2ede62b7 | |||
559e65f990 | |||
e71f7a6942 | |||
f12a2e37f3 | |||
c1614b1182 | |||
6b4bd4db35 | |||
163d7bcd6c | |||
d131d2499b | |||
4e03c2bf31 | |||
9e05410f28 | |||
9c88c23bb3 | |||
e4588771e8 | |||
507c42faea | |||
9302627c6f |
2
.cz.yaml
2
.cz.yaml
@ -17,5 +17,5 @@ commitizen:
|
||||
prerelease_offset: 1
|
||||
tag_format: $version
|
||||
update_changelog_on_bump: false
|
||||
version: 1.15.1
|
||||
version: 1.18.0
|
||||
version_scheme: semver
|
||||
|
56
.github/ISSUE_TEMPLATE/new_model.md
vendored
56
.github/ISSUE_TEMPLATE/new_model.md
vendored
@ -29,10 +29,16 @@ Describe in detail the following:
|
||||
|
||||
<!-- Don't remove tasks strike them out. use `~~` before and after the item. i.e. `- ~~[ ] Model Created~~` note: don't include the list dash-->
|
||||
|
||||
- [ ] 🆕 Model Created
|
||||
- [ ] 🆕 [Model Created](https://nofusscomputing.com/projects/centurion_erp/development/models/)
|
||||
|
||||
- [ ] 🛠️ Migrations added
|
||||
|
||||
- [ ] ♻️ Serializer Created
|
||||
|
||||
- [ ] 🔄 [ViewSet Created](https://nofusscomputing.com/projects/centurion_erp/development/views/)
|
||||
|
||||
- [ ] 🔗 URL Route Added
|
||||
|
||||
- [ ] 🏷️ Model tag added to `app/core/lib/slash_commands/linked_model.CommandLinkedModel.get_model()` function
|
||||
|
||||
- [ ] 📘 Tag updated in the [docs](https://nofusscomputing.com/projects/centurion_erp/user/core/markdown/#model-reference)
|
||||
@ -44,7 +50,13 @@ Describe in detail the following:
|
||||
> - Two words are not to contain a space char, `\s`. It is to be replaced with an underscore `_`
|
||||
> - As much as practical, keep the tag as close to the model name as possible
|
||||
|
||||
- [ ] 📝 New [History model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_history/) created
|
||||
- [ ] 📝 New [History model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_history/) created
|
||||
|
||||
- Sub-Models **_ONLY_**
|
||||
|
||||
- [ ] Model class variable [`history_app_label`](https://nofusscomputing.com/projects/centurion_erp/development/models/#history) set to correct application label
|
||||
|
||||
- [ ] Model class variable [`history_model_name`](https://nofusscomputing.com/projects/centurion_erp/development/models/#history) set to correct model label
|
||||
|
||||
- [ ] 📓 New [Notes model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_notes/) created
|
||||
- [ ] 🆕 Model Created
|
||||
@ -66,16 +78,18 @@ Describe in detail the following:
|
||||
|
||||
### 🧪 Tests
|
||||
|
||||
- [ ] Unit Test Model
|
||||
- [ ] Unit Test Tenancy Object
|
||||
- [ ] Unit Test Serializer
|
||||
- [ ] Unit Test ViewSet
|
||||
- [ ] Function Test ViewSet
|
||||
- [ ] Function Test API Metadata
|
||||
- [ ] Function Test API Permissions
|
||||
- [ ] Function Test API Render (fields)
|
||||
- [ ] Function Test History Entries
|
||||
- [ ] Function Test History API Render (fields)
|
||||
- Unit Tests
|
||||
- [ ] API Render (fields)
|
||||
- [ ] [Model](https://nofusscomputing.com/projects/centurion_erp/development/models/#tests)
|
||||
- [ ] ViewSet
|
||||
- Function Test
|
||||
- [ ] History API Render (fields)
|
||||
- [ ] History Entries
|
||||
- [ ] API Metadata
|
||||
- [ ] API Permissions
|
||||
- [ ] Model
|
||||
- [ ] Serializer
|
||||
- [ ] ViewSet
|
||||
|
||||
|
||||
## ✅ Requirements
|
||||
@ -84,6 +98,24 @@ A Requirement is a must have. In addition will also be tested.
|
||||
|
||||
- [ ] Must have a [model_tag](https://nofusscomputing.com/projects/centurion_erp/user/core/markdown/#model-reference)
|
||||
|
||||
<!--
|
||||
|
||||
When detailing requirements the following must be taken into account:
|
||||
|
||||
- what the user should be able to do
|
||||
|
||||
- what the user should not be able to do
|
||||
|
||||
- what should occur when a user performs an action
|
||||
|
||||
-->
|
||||
|
||||
- Functional Requirements
|
||||
|
||||
|
||||
- Non-Functional Requirements
|
||||
|
||||
|
||||
---
|
||||
|
||||
<!-- Add additional requirement here and as a check box list -->
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,9 +1,10 @@
|
||||
venv/**
|
||||
*/static/**
|
||||
__pycache__
|
||||
**.sqlite3
|
||||
**.sqlite*
|
||||
**.sqlite
|
||||
**.coverage
|
||||
.coverage*
|
||||
artifacts/
|
||||
**.tmp.*
|
||||
volumes/
|
||||
@ -15,4 +16,8 @@ node_modules/
|
||||
package-lock.json
|
||||
package.json
|
||||
**.junit.xml
|
||||
**.JUnit.xml
|
||||
feature_flags.json
|
||||
coverage_*.json
|
||||
*-coverage.xml
|
||||
log/
|
||||
|
35
.vscode/launch.json
vendored
35
.vscode/launch.json
vendored
@ -4,7 +4,6 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "Centurion",
|
||||
"type": "debugpy",
|
||||
@ -18,7 +17,6 @@
|
||||
"program": "${workspaceFolder}/app/manage.py"
|
||||
},
|
||||
{
|
||||
|
||||
"name": "Debug: Gunicorn",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
@ -32,7 +30,6 @@
|
||||
"--bind",
|
||||
"0.0.0.0:8002",
|
||||
"app.wsgi:application",
|
||||
|
||||
],
|
||||
"django": true,
|
||||
"autoStartBrowser": false,
|
||||
@ -53,7 +50,6 @@
|
||||
"autoStartBrowser": false,
|
||||
"program": "${workspaceFolder}/app/manage.py"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "Migrate",
|
||||
"type": "debugpy",
|
||||
@ -64,7 +60,6 @@
|
||||
"django": true,
|
||||
"autoStartBrowser": false,
|
||||
"program": "${workspaceFolder}/app/manage.py"
|
||||
|
||||
},
|
||||
{
|
||||
"name": "Debug: Celery",
|
||||
@ -82,6 +77,34 @@
|
||||
"debug-itsm@%h"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/app"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debug pytest (collect)",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"module": "pytest",
|
||||
"args": [
|
||||
"--override-ini", "addopts=",
|
||||
"--collect-only",
|
||||
"app",
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": "Python Debugger: Local Attach",
|
||||
"type": "debugpy",
|
||||
"request": "attach",
|
||||
"connect": {
|
||||
"host": "localhost",
|
||||
"port": 5678
|
||||
},
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceFolder}",
|
||||
"remoteRoot": "."
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
@ -5,19 +5,23 @@
|
||||
"!python"
|
||||
],
|
||||
"python.testing.pytestArgs": [
|
||||
// "-v",
|
||||
// "--cov",
|
||||
// "--cov-report xml",
|
||||
"-s",
|
||||
"--override-ini", "addopts=",
|
||||
"app",
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"testing.coverageToolbarEnabled": true,
|
||||
"cSpell.words": [
|
||||
"ITSM"
|
||||
],
|
||||
"cSpell.language": "en-AU",
|
||||
"jest.enable": false,
|
||||
"pylint.enabled": true,
|
||||
"testing.showCoverageInExplorer": true,
|
||||
"testing.coverageToolbarEnabled": true,
|
||||
"testing.coverageBarThresholds": {
|
||||
"red": 0,
|
||||
"yellow": 60,
|
||||
"green": 90
|
||||
},
|
||||
"telemetry.feedback.enabled": false,
|
||||
}
|
302
CHANGELOG.md
302
CHANGELOG.md
@ -1,3 +1,305 @@
|
||||
## 1.18.0 (2025-07-03)
|
||||
|
||||
### feat
|
||||
|
||||
- **python**: upgrade django 5.1.9 -> 5.1.10
|
||||
|
||||
### Fixes
|
||||
|
||||
- **itim**: Correct config that is in the incorrect format
|
||||
|
||||
## 1.17.1 (2025-06-02)
|
||||
|
||||
### Fixes
|
||||
|
||||
- **base**: Add python metrics to prometheus exporter
|
||||
|
||||
## 1.17.0 (2025-05-16)
|
||||
|
||||
### feat
|
||||
|
||||
- **access**: model access.Company feature flag `2025-00008`
|
||||
- **access**: URL route for model access.Company
|
||||
- **access**: Migration for model access.Company
|
||||
- **access**: Serializer for model access.Company
|
||||
- **access**: New model access.Company
|
||||
- **access**: Organization -> Tenant Permission Migration
|
||||
- **docker**: Serve a robots.txt file for NO indexing
|
||||
- **access**: Organization -> Tenant Permission Migration
|
||||
- **base**: Add var `AUTH_USER_MODEL` to settings
|
||||
- **core**: Add Action comments on ticket change
|
||||
- **core**: Remove add, change and delete permissions for model TicketCommentAction from permission selector
|
||||
- **core**: Serializer for model TicketCommentAction
|
||||
- **core**: Migrations for model TicketCommentAction
|
||||
- **core**: New model TicketCommentAction
|
||||
- **core**: Setup serializer to meet requirements
|
||||
- **core**: Setup model to meet requirements
|
||||
- **api**: Add exception logging to ViewSetCommon
|
||||
- **python**: Upgrade DRF Spectacular 0.27.2 -> 0.28.0
|
||||
- **python**: Upgrade DRF 3.15.2 -> 3.16.0
|
||||
- **core**: When processing slash command duration, cater for new ticket models
|
||||
- **api**: Add Logging function to Common ViewSet
|
||||
- **access**: Add Logging function to Tenancy model
|
||||
- **base**: Enable user to customize log file location
|
||||
- **core**: Do validate the comment_type field for TicketCommentBase
|
||||
- **itam**: Add Feature Flag `2025-00007` ITAMAssetBase
|
||||
- **itam**: Add endpoint for ITAMAssetBase
|
||||
- Model tag migration for Asset and IT Asset
|
||||
- **itam**: Model tag for ITAsset
|
||||
- **accounting**: Model tag for Asset
|
||||
- **accounting**: Add app label to kb articles for notes
|
||||
- **accounting**: Migrations for notes model for AssetBase
|
||||
- **accounting**: Migrations for history model for AssetBase
|
||||
- **accounting**: Notes Viewset for AssetBase
|
||||
- **accounting**: Notes Serializer for AssetBase
|
||||
- **accounting**: Notes model for AssetBase
|
||||
- **accounting**: History model for AssetBase
|
||||
- **itam**: Serializer for ITAssetBase
|
||||
- **itam**: Migrations for ITAssetBase
|
||||
- **itam**: Add Model ITAssetBase
|
||||
- **accounting**: Viewset for Assets
|
||||
- **accounting**: Serializer for model AssetBase
|
||||
- **accounting**: Migrations for model AssetBase
|
||||
- **accounting**: Add Model AssetBase
|
||||
|
||||
### Fixes
|
||||
|
||||
- **api**: Dont try to access attribute if not exist in common viewset
|
||||
- **api**: Dont try to access attribute if not exist in common viewset
|
||||
- **api**: Correct ViewSet Sub-Model lookup
|
||||
- **core**: Only take action on ticket comment if view exists
|
||||
- **api**: Ensure multi-nested searching for sub-models works
|
||||
- **core**: ensure slash command is called on ticket description
|
||||
- **core**: Spent slash command is valid for time spent
|
||||
- **core**: Correct logic for TicketCommentSolution
|
||||
- **core**: Correct logic for TicketCommentBase
|
||||
- **accounting**: Ensure correct sub-model check is conducted within model type
|
||||
- **itam**: ensure RO field asset_type is set
|
||||
- **itim**: Ensure that itam base model is always imported
|
||||
|
||||
### Refactoring
|
||||
|
||||
- **human_resources**: Update Functional ViewSet to use PyTest for Employee Model
|
||||
- **Access**: Update Functional ViewSet to use PyTest for Person Model
|
||||
- **Access**: Update Functional ViewSet to use PyTest for Entity Model
|
||||
- **Access**: Update Functional ViewSet to use PyTest for Contact Model
|
||||
- **Access**: Update Functional Permission to use PyTest for Person Model
|
||||
- **Access**: Update Functional Permission to use PyTest for Entity Model
|
||||
- **Access**: Update Functional Permission to use PyTest for Contact Model
|
||||
- **Access**: Update Functional Serializer to use PyTest for Contact Model
|
||||
- **Access**: Update Functional Serializer to use PyTest for Entity Model
|
||||
- **Access**: Update Functional Serializer to use PyTest for Person Model
|
||||
- **human_resources**: Update Functional Serializer to use PyTest for Employee Model
|
||||
- **human_resources**: Update Functional Permissions to use PyTest for Employee Model
|
||||
- **human_resources**: Update Functional Metadata to use PyTest for Employee Model
|
||||
- **access**: Update Functional Metadata to use PyTest for Person Model
|
||||
- **access**: Update Functional Metadata to use PyTest for Entity Model
|
||||
- **access**: Update Functional Metadata to use PyTest for Contact Model
|
||||
- **access**: Update Model Entity to use PyTest for Model Test Suite
|
||||
- **access**: Update Model Contact to use PyTest for Model Test Suite
|
||||
- **access**: Update Model Person to use PyTest for Model Test Suite
|
||||
- **human_resources**: Update Model Employee to use PyTest for Model Test Suite
|
||||
- **human_resources**: Update Model Employee to use PyTest API Fields Render
|
||||
- **access**: Update Model Person to use PyTest API Fields Render
|
||||
- **access**: Update Model Contact to use PyTest API Fields Render
|
||||
- **access**: Update Model Entity to use PyTest API Fields Render
|
||||
- **access**: Rename model Organization -> Tenant
|
||||
- **settings**: Update all references to `User` to use `get_user_model()`
|
||||
- **project_management**: Update all references to `User` to use `get_user_model()`
|
||||
- **itam**: Update all references to `User` to use `get_user_model()`
|
||||
- **devops**: Update all references to `User` to use `get_user_model()`
|
||||
- **core**: Update all references to `User` to use `get_user_model()`
|
||||
- **config_management**: Update all references to `User` to use `get_user_model()`
|
||||
- **assistance**: Update all references to `User` to use `get_user_model()`
|
||||
- **app**: Update all references to `User` to use `get_user_model()`
|
||||
- **api**: Update all references to `User` to use `get_user_model()`
|
||||
- **accounting**: Update all references to `User` to use `get_user_model()`
|
||||
- **access**: Update all references to `User` to use `get_user_model()`
|
||||
- **access**: when fetching parent object, use the parent_model get function
|
||||
- **api**: Limit url pk regex to ensure the value is a number
|
||||
|
||||
### Tests
|
||||
|
||||
- **access**: Functional ViewSet Test Suite Company model
|
||||
- **access**: Functional Serializer Test Suite Company model
|
||||
- **access**: Functional Permissions Test Suite Company model
|
||||
- **access**: Functional MetaData Test Suite Company model
|
||||
- **access**: ViewSet Test Suite Company model
|
||||
- **access**: API field render Test Suite Company model
|
||||
- **access**: Model Test Suite Company model
|
||||
- **core**: Unit viewset Test Cases for TicketCommentAction model
|
||||
- **core**: Unit model Test Cases for TicketCommentAction model
|
||||
- **core**: Unit API Render Test Cases for TicketCommentAction model
|
||||
- **core**: Interim Functional model Test Case TicketCommentAction
|
||||
- **core**: Ensure that a ticket milestone comes from the same assigned project
|
||||
- **core**: SKIP Tests TicketBase Description Slash command Checks
|
||||
- **core**: TicketBase Description Slash command Checks
|
||||
- **core**: TicketBase Remaining Serializer Chacks
|
||||
- **core**: Partial functional Model Test Suite covering some slash commande for TicketCommentSolution
|
||||
- **core**: ensure ticket is un-solved for ticketcomment unit api render fields check
|
||||
- **core**: ensure slash command is called on ticket comment
|
||||
- **core**: Unit ViewSet Test Suite for TicketCommentSolution
|
||||
- **core**: Unit ViewSet Test Suite for TicketCommentBase
|
||||
- **core**: Skip Related slash command checks until migrating tickets to new model
|
||||
- **core**: Add ability to unit api field rendering test case for second api request if required
|
||||
- **core**: Partial Functional Model test cases (Slash Commands) for TicketCommentBase
|
||||
- **core**: Functional Model test cases (Slash Commands) for TicketBaseModel
|
||||
- **core**: Partial Slash Command re-write
|
||||
- **core**: correct field so its valid for unit TicketCommentBase model
|
||||
- **core**: Unit API Fields Render for TicketCommentSolution model
|
||||
- **core**: Unit API Fields Render for TicketCommentBase model
|
||||
- **core**: Unit Model assert save and call are called for TicketBase
|
||||
- **core**: Unit Model Checks for TicketCommentSolution
|
||||
- **core**: Unit Model Checks for TicketCommentBase
|
||||
- **itam**: test meta attribute itam_sub_model_type for ITAMBaseModel
|
||||
- **itam**: Dont use constants where variables should be used
|
||||
- **itam**: Remaining Unit Model test cases for AssetBase
|
||||
- **accounting**: Remaining Unit Model test cases for AssetBase
|
||||
- **itam**: Functional ViewSet Test Cases for ITAMAssetBase
|
||||
- **itam**: Functional Serializer Test Cases for ITAMAssetBase
|
||||
- **itam**: Functional Permissions Test Cases for ITAMAssetBase
|
||||
- **itam**: Functional Metadata Test Cases for ITAMAssetBase
|
||||
- **itam**: Functional History Test Cases for ITAMAssetBase
|
||||
- **accounting**: Functional ViewSet Test Cases for AssetBase
|
||||
- **accounting**: Functional Serializer Test Cases for AssetBase
|
||||
- **accounting**: Functional Permissions Test Cases for AssetBase
|
||||
- **accounting**: Functional Metadata Test Cases for AssetBase
|
||||
- **accounting**: History Test Cases for AssetBase
|
||||
- add missing merge of add_data for api permissions tests
|
||||
- remove ticket only vars from api permissions tests
|
||||
- **api**: dont use constants for variable data
|
||||
- correct viewset tests
|
||||
- **itam**: Unit Viewset checks for AssetBase Model
|
||||
- **core**: Add missing fields is_global checks for ticket base
|
||||
- **api**: Add submodel url resolution for metadata
|
||||
- **itam**: Unit API Fields checks for ITAM AssetBase Model
|
||||
- **accounting**: Unit API Fields checks for AssetBase Model
|
||||
- Support variables that were defined as properties.
|
||||
- **api**: Ensure that model notes is added to model create for api field tests
|
||||
- **accounting**: Unit Viewset checks for AssetBase Model
|
||||
- **itam**: Unit Model checks for ITAMAssetBase Model
|
||||
- **base**: update Model base test suite for model_notes field
|
||||
- **accounting**: Unit Model checks for AssetBase Model
|
||||
|
||||
## 1.16.0 (2025-05-04)
|
||||
|
||||
### feat
|
||||
|
||||
- **core**: Add ViewSet for Ticket Comments
|
||||
- **project_management**: Depreciate Project Task Ticket Endpoint
|
||||
- **itim**: Depreciate Problem Ticket Endpoint
|
||||
- **itim**: Depreciate Incident Ticket Endpoint
|
||||
- **itim**: Depreciate Change Ticket Endpoint
|
||||
- **assistance**: Depreciate Ticket Comment
|
||||
- **assistance**: Depreciate Request Ticket Endpoint
|
||||
- **core**: Add routes for Ticket Comments
|
||||
- **core**: update ticket serializer to use new comment base url
|
||||
- **core**: Add permissions `import`, `purge` and `triage` to model TicketCommentSolution
|
||||
- **core**: Add permissions `import`, `purge` and `triage` to model TicketCommentBase
|
||||
- **core**: Filter ticket_comment_model routes to those defined in `Meta.sub_model_type`
|
||||
- **core**: Filter ticket_model routes to those defined in `Meta.sub_model_type`
|
||||
- **access**: Filter entity_model routes to thos defined in `Meta.sub_model_type`
|
||||
- **core**: Serializer for TicketCommentBase
|
||||
- **core**: Serializer for TicketCommentSolution
|
||||
- **core**: Ticket Comment Get URL functions
|
||||
- **core**: Ticket Comment Validation for comment_type
|
||||
- **core**: Update choices fields for TicketCommentBase model
|
||||
- **core**: init for model TicketCommentSolution
|
||||
- **core**: Migrations for choice fields for TicketBase model
|
||||
- **core**: Migrations for model TicketCommentSolution
|
||||
- **core**: Update choice fields for TicketBase model
|
||||
- **core**: New model TicketCommentSolution
|
||||
- **api**: when fetching related_object, default to base_model for SubModelViewSet
|
||||
- Add field `Meta.sub_model_type` to sub-models
|
||||
- **core**: New interim model TicketCommentSolution
|
||||
- **core**: add ticket routes
|
||||
- **itim**: serializer for SLMTicketBase
|
||||
- **itim**: Serializer for RequestTicket
|
||||
- **itim**: migrations for RequestTicket
|
||||
- **itim**: New Model RequestTicket
|
||||
- **itim**: migration for SLMTicketBase
|
||||
- **itim**: New Model SLMTicketBase
|
||||
- **core**: migrations for TicketCommentBase
|
||||
- **core**: New Model TicketCommentBase
|
||||
- **core**: viewset for TicketBase
|
||||
- **core**: serializer for TicketBase
|
||||
- **core**: migrations for TicketBase
|
||||
- **core**: New Model TicketBase
|
||||
- **project_management**: add estimation field to project api fields
|
||||
- **human_resources**: nav menu entries for Employee
|
||||
- **human_resources**: Serializer for Employee
|
||||
- **human_resources**: Migration for Employee
|
||||
- **human_resources**: New model Employee
|
||||
- **devops**: add missing api index menu entry for devops
|
||||
- **access**: add missing nav menu entries for entities
|
||||
- **human_resources**: add module to perms selector
|
||||
|
||||
### Fixes
|
||||
|
||||
- **test**: correct typo in attribute parameterized_
|
||||
- **core**: Ticktet comment can have empty body
|
||||
- **core**: If model does not save history, dont attempt to cache before
|
||||
- **itam**: provide return_url as part of software version meta
|
||||
- **itim**: correct ticket_slm serializer
|
||||
- **itim**: correct ticket_request serializer
|
||||
- **api**: SubModelViewSet.related_objects must be the same class as the base model
|
||||
- **access**: Ensure related model is a sub-model
|
||||
- **human_resources**: Correct history link generation and add docs
|
||||
- **human_resources**: Correct history link generation
|
||||
- **access**: add missing attribute to Tenancy object
|
||||
|
||||
### Refactoring
|
||||
|
||||
- **test**: rewrite model unit tests to use PyTest
|
||||
- **test**: Update test parameterization
|
||||
- **api**: SubModelViewSet must inherit from ModelViewSet as it's an extension
|
||||
- **core**: rename ticket model filename in preparation for base ticket model
|
||||
- **access**: migrate sub-model viewset logic to common
|
||||
- **project_management**: add duration field to project api fields
|
||||
- **human_resources**: Move employee details to its own section
|
||||
|
||||
### Tests
|
||||
|
||||
- **core**: Serializer Validation for ticket status change for TicketBase model
|
||||
- **core**: Prevent Closing / Solving of TicketBase Model if not ready
|
||||
- **itim**: Incomplete Model Unit Tests for RequestTicket
|
||||
- **itim**: Incomplete Model Unit Tests for SLMTicketBase
|
||||
- **core**: Incomplete Model Unit Tests for TicketBase
|
||||
- **itim**: RequestTicket Updated, yet incomplete Test Suite for Serializer
|
||||
- **itim**: SLMTicketBase Updated, yet incomplete Test Suite for Serializer
|
||||
- **core**: TicketBase Updated, yet incomplete Test Suite for Serializer
|
||||
- Correct Test Suite for Serializer for models TicketBase, TicketRequest and TicketSLM
|
||||
- **itim**: RequestTicket Initial Test Suite for Serializer
|
||||
- **itim**: SLMTicket Initial Test Suite for Serializer
|
||||
- **core**: TicketBase Initial Test Suite for Serializer
|
||||
- **core**: SLMTicket Test Suite for ViewSet
|
||||
- **core**: SLMTicket Test Suite for Metadata
|
||||
- **core**: Request Test Suite for ViewSet
|
||||
- **core**: Request Test Suite for Metadata
|
||||
- **core**: TicketBase Test Suite for ViewSet
|
||||
- **core**: TicketBase Test Suite for Metadata
|
||||
- **api**: update test cases for SubModelViewSet Base Test Class
|
||||
- **itim**: RequestTicket ViewSet Test Suite
|
||||
- **core**: TicketBase ViewSet Test Suite
|
||||
- **api**: Incomplete SubModelViewSet Test Cases
|
||||
- **api**: SubModelViewSet Test Suite Setup
|
||||
- correct tests from Meta.sub_model_type changes
|
||||
- correct serializer imports from recent file renames
|
||||
- Fixture for creating model with random data
|
||||
- **itim**: API Field checks for TicketSLMBase
|
||||
- **itim**: API Field checks for TicketRequest
|
||||
- **core**: API fields Tests for TicketBase
|
||||
- **core**: API fields Unit Test Suite
|
||||
- **core**: Correct model notes test suite
|
||||
- **core**: API Permission Test Cases for ticket_base model
|
||||
- **api**: add API Permission Test Cases
|
||||
- **access**: Correct history link test cases
|
||||
- **project_management**: Add test cases for api field render for model fields `estimation_project` and `duration_project`
|
||||
- **human_resources**: History Serializer and ViewSet Functional test suites for employee
|
||||
- **human_resources**: APIv2, History, Model and ViewSet Unit test suites for employee
|
||||
- Migrate models to use refactored model tests
|
||||
- Consolidate All model tests to remove duplicates and to simplify
|
||||
|
||||
## 1.15.1 (2025-04-10)
|
||||
|
||||
### Fixes
|
||||
|
@ -1,3 +1,49 @@
|
||||
## Version 1.17.0
|
||||
|
||||
- Added setting for log files.
|
||||
|
||||
Enables user to specify a default path for centurion's logging. Add the following to your settings file `/etc/itsm/settings.py`
|
||||
|
||||
``` py
|
||||
LOG_FILES = {
|
||||
"centurion": "/var/log/centurion.log", # Normal Centurion Operations
|
||||
"weblog": "/var/log/weblog.log", # All web requests made to Centurion
|
||||
"rest_api": "/var/log/rest_api.log", # Rest API
|
||||
"catch_all":"/var/log/catch-all.log" # A catch all log. Note: does not log anything that has already been logged.
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
With this new setting, the previous setting `LOGGING` will no longer function.
|
||||
|
||||
- Renamed `Organization` model to `Tenant` so as to reflect what is actually is.
|
||||
|
||||
- `robots.txt` file now being served from the API container at path `/robots.txt` with `User-agent: *` and `Disallow: /`
|
||||
|
||||
|
||||
## Version 1.16.0
|
||||
|
||||
- Employees model added behind feature flag `2025-00002` and will remain behind this flag until production ready.
|
||||
|
||||
- Ticket and Ticket Comment added behind feature flag `2025-00006` and will remain behind this flag until production ready.
|
||||
|
||||
- In preparation of the [Ticket and Ticket Comment model re-write](https://github.com/nofusscomputing/centurion_erp/issues/564)
|
||||
|
||||
- Depreciated Change Ticket
|
||||
|
||||
- Depreciated Ticket Comment Endpoint
|
||||
|
||||
- Depreciated Request Ticket
|
||||
|
||||
- Depreciated Incident Ticket
|
||||
|
||||
- Depreciated Problem Ticket
|
||||
|
||||
- Depreciated Project Task Ticket
|
||||
|
||||
These endpoints still work and will remain so until the new Ticket and Ticket Comment Models are production ready.
|
||||
|
||||
|
||||
## Version 1.15.0
|
||||
|
||||
- Entities model added behind feature flag `2025-00002` and will remain behind this flag until production ready.
|
||||
|
@ -1,17 +0,0 @@
|
||||
[run]
|
||||
source = .
|
||||
omit =
|
||||
*migrations/*
|
||||
*tests/*/*
|
||||
|
||||
[report]
|
||||
omit =
|
||||
*/tests/*/*
|
||||
*/migrations/*
|
||||
*apps.py
|
||||
*manage.py
|
||||
*__init__.py
|
||||
*asgi*
|
||||
*wsgi*
|
||||
*admin.py
|
||||
*urls.py
|
@ -1,12 +1,15 @@
|
||||
import django
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
admin.site.unregister(Group)
|
||||
|
||||
class TeamInline(admin.TabularInline):
|
||||
|
@ -3,7 +3,7 @@ from django.db.models import Q
|
||||
|
||||
from app import settings
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
|
||||
|
@ -9,11 +9,13 @@ def permission_queryset():
|
||||
|
||||
apps = [
|
||||
'access',
|
||||
'accounting',
|
||||
'assistance',
|
||||
'config_management',
|
||||
'core',
|
||||
'devops',
|
||||
'django_celery_results',
|
||||
'human_resources',
|
||||
'itam',
|
||||
'itim',
|
||||
'project_management',
|
||||
@ -35,14 +37,17 @@ def permission_queryset():
|
||||
'add_history',
|
||||
'add_organization',
|
||||
'add_taskresult',
|
||||
'add_ticketcommentaction',
|
||||
'change_checkin',
|
||||
'change_history',
|
||||
'change_organization',
|
||||
'change_taskresult',
|
||||
'change_ticketcommentaction',
|
||||
'delete_checkin',
|
||||
'delete_history',
|
||||
'delete_organization',
|
||||
'delete_taskresult',
|
||||
'delete_ticketcommentaction',
|
||||
'view_checkin',
|
||||
'view_history',
|
||||
]
|
||||
|
@ -1,18 +1,22 @@
|
||||
import django
|
||||
|
||||
from django.contrib.auth.middleware import (
|
||||
AuthenticationMiddleware,
|
||||
SimpleLazyObject,
|
||||
partial,
|
||||
)
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.contrib.auth.models import Group
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
|
||||
|
||||
from settings.models.app_settings import AppSettings
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
class RequestTenancy(MiddlewareMixin):
|
||||
"""Access Middleware
|
||||
|
25
app/access/migrations/0007_rename_organization_tenant.py
Normal file
25
app/access/migrations/0007_rename_organization_tenant.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.1.9 on 2025-05-14 11:06
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0005_entity_person_entityhistory_entitynotes_role_and_more'),
|
||||
('assistance', '0005_knowledgebasecategoryhistory_knowledgebasehistory'),
|
||||
('config_management', '0007_configgroupshistory_configgrouphostshistory_and_more'),
|
||||
('core', '0022_ticketcommentbase_ticketbase_ticketcommentsolution_and_more'),
|
||||
('devops', '0011_alter_gitgroup_unique_together_and_more'),
|
||||
('itam', '0010_alter_software_organization'),
|
||||
('itim', '0009_slmticket_requestticket'),
|
||||
('project_management', '0005_projecthistory_projectmilestonehistory_and_more'),
|
||||
('settings', '0011_appsettingshistory_externallinkhistory'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name = 'Organization',
|
||||
new_name = 'Tenant'
|
||||
),
|
||||
]
|
@ -0,0 +1,47 @@
|
||||
# Generated by Django 5.1.9 on 2025-05-14 13:48
|
||||
|
||||
import access.models.team
|
||||
import access.models.tenancy
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0007_rename_organization_tenant'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='tenant',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Tenant', 'verbose_name_plural': 'Tenants'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='entity',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Tenancy this belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='+', to='access.tenant', validators=[access.models.tenancy.TenancyObject.validatate_organization_exists], verbose_name='Tenant'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Tenancy this belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='+', to='access.tenant', validators=[access.models.tenancy.TenancyObject.validatate_organization_exists], verbose_name='Tenant'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Tenant this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.tenant', validators=[access.models.team.Team.validatate_organization_exists], verbose_name='Tenant'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tenant',
|
||||
name='manager',
|
||||
field=models.ForeignKey(help_text='Manager for this Tenancy', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Manager'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tenant',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Name of this Tenancy', max_length=50, unique=True, verbose_name='Name'),
|
||||
),
|
||||
]
|
@ -0,0 +1,135 @@
|
||||
|
||||
from django.contrib.auth.models import ContentType, Permission
|
||||
from django.db import migrations
|
||||
|
||||
from access.models.team import Team
|
||||
|
||||
ContentType.DoesNotExist
|
||||
|
||||
def add_tenancy_permissions(apps, schema_editor):
|
||||
|
||||
print('')
|
||||
print(f"Begin permission migration for rename of Organization to Tenant.")
|
||||
|
||||
try:
|
||||
|
||||
add_permission = Permission.objects.get(
|
||||
codename = 'add_tenant',
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = 'access',
|
||||
model = 'tenant',
|
||||
)
|
||||
)
|
||||
|
||||
change_permission = Permission.objects.get(
|
||||
codename = 'change_tenant',
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = 'access',
|
||||
model = 'tenant',
|
||||
)
|
||||
)
|
||||
|
||||
delete_permission = Permission.objects.get(
|
||||
codename = 'delete_tenant',
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = 'access',
|
||||
model = 'tenant',
|
||||
)
|
||||
)
|
||||
|
||||
view_permission = Permission.objects.get(
|
||||
codename = 'view_tenant',
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = 'access',
|
||||
model = 'tenant',
|
||||
)
|
||||
)
|
||||
|
||||
print(f' Searching for Teams.')
|
||||
|
||||
teams = Team.objects.select_related('group_ptr__permissions')
|
||||
|
||||
print(f'Found {str(len(teams))} Teams.')
|
||||
|
||||
for team in teams:
|
||||
|
||||
print(f' Processing Team {str(team.team_name)}.')
|
||||
|
||||
permissions = team.group_ptr.permissions.all()
|
||||
|
||||
print(f' Searching for Organization Permissions.')
|
||||
print(f' Found {str(len(permissions))} Permissions.')
|
||||
|
||||
for permission in permissions:
|
||||
|
||||
if '_organization' not in permission.codename:
|
||||
|
||||
continue
|
||||
|
||||
action = str(permission.codename).split('_')[0]
|
||||
|
||||
print(f' Found Organization Permission {str(action)}')
|
||||
|
||||
if action == 'add':
|
||||
|
||||
team.group_ptr.permissions.add( add_permission )
|
||||
|
||||
print(f' Add Tenant Permission {str(action)}')
|
||||
|
||||
team.group_ptr.permissions.remove( permission )
|
||||
|
||||
print(f' Remove Organization Permission {str(action)}')
|
||||
|
||||
elif action == 'change':
|
||||
|
||||
team.group_ptr.permissions.add( change_permission )
|
||||
|
||||
print(f' Add Tenant Permission {str(action)}')
|
||||
|
||||
team.group_ptr.permissions.remove( permission )
|
||||
|
||||
print(f' Remove Organization Permission {str(action)}')
|
||||
|
||||
elif action == 'delete':
|
||||
|
||||
team.group_ptr.permissions.add( delete_permission )
|
||||
|
||||
print(f' Add Tenant Permission {str(action)}')
|
||||
|
||||
team.group_ptr.permissions.remove( permission )
|
||||
|
||||
print(f' Remove Organization Permission {str(action)}')
|
||||
|
||||
elif action == 'view':
|
||||
|
||||
team.group_ptr.permissions.add( view_permission )
|
||||
|
||||
print(f' Add Tenant Permission {str(action)}')
|
||||
|
||||
team.group_ptr.permissions.remove( permission )
|
||||
|
||||
print(f' Remove Organization Permission {str(action)}')
|
||||
|
||||
|
||||
print(f' Completed Team {str(team.team_name)}.')
|
||||
|
||||
except ContentType.DoesNotExist:
|
||||
# DB is new so no content types. no migration to be done.
|
||||
pass
|
||||
|
||||
print(' Permission Migration Actions Complete.')
|
||||
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0008_alter_tenant_options_alter_entity_organization_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_tenancy_permissions),
|
||||
]
|
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
# Generated by Django 5.1.9 on 2025-05-16 09:58
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0009_migrate_organization_permission_tenant'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Company',
|
||||
fields=[
|
||||
('entity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='access.entity')),
|
||||
('name', models.CharField(help_text='The name of this entity', max_length=80, verbose_name='Name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Company',
|
||||
'verbose_name_plural': 'Companies',
|
||||
'ordering': ['name'],
|
||||
'sub_model_type': 'company',
|
||||
},
|
||||
bases=('access.entity',),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='entity',
|
||||
name='entity_type',
|
||||
field=models.CharField(help_text='Type this entity is', max_length=30, verbose_name='Entity Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='person',
|
||||
name='dob',
|
||||
field=models.DateField(blank=True, help_text='The Persons Date of Birth (DOB)', null=True, verbose_name='DOB'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='person',
|
||||
name='m_name',
|
||||
field=models.CharField(blank=True, help_text='The persons middle name(s)', max_length=100, null=True, verbose_name='Middle Name(s)'),
|
||||
),
|
||||
]
|
@ -4,7 +4,7 @@ from django.contrib.auth.models import Group
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
|
||||
|
||||
@ -260,7 +260,7 @@ class OrganizationMixin():
|
||||
self.permission_required = permissions_required
|
||||
|
||||
organization_manager_models = [
|
||||
'access.organization',
|
||||
'access.tenant',
|
||||
'access.team',
|
||||
'access.teamusers',
|
||||
]
|
||||
@ -326,7 +326,7 @@ class OrganizationMixin():
|
||||
|
||||
if required_permission.replace(
|
||||
'view_', ''
|
||||
) == 'access.organization' and len(self.kwargs) == 0:
|
||||
) == 'access.tenant' and len(self.kwargs) == 0:
|
||||
|
||||
return True
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
from django.contrib.auth.models import User, Group
|
||||
import django
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db import models
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class OrganizationMixin:
|
||||
@ -89,7 +93,7 @@ class OrganizationMixin:
|
||||
|
||||
self._obj_organization = obj.organization
|
||||
|
||||
elif str(self.model._meta.verbose_name).lower() == 'organization':
|
||||
elif str(self.model._meta.verbose_name).lower() == 'tenant':
|
||||
|
||||
self._obj_organization = obj
|
||||
|
||||
@ -130,7 +134,7 @@ class OrganizationMixin:
|
||||
parent_model (Model): with PK from kwargs['pk']
|
||||
"""
|
||||
|
||||
return self.parent_model.objects.get(pk=self.kwargs[self.parent_model_pk_kwarg])
|
||||
return self.get_parent_model().objects.get(pk=self.kwargs[self.parent_model_pk_kwarg])
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.permissions import DjangoObjectPermissions
|
||||
|
||||
from access.models.tenancy import Organization, TenancyObject
|
||||
from access.models.tenancy import Tenant, TenancyObject
|
||||
|
||||
from core import exceptions as centurion_exceptions
|
||||
|
||||
@ -14,10 +14,10 @@ from core import exceptions as centurion_exceptions
|
||||
class OrganizationPermissionMixin(
|
||||
DjangoObjectPermissions,
|
||||
):
|
||||
"""Organization Permission Mixin
|
||||
"""Tenant Permission Mixin
|
||||
|
||||
This class is to be used as the permission class for API `Views`/`ViewSets`.
|
||||
In combination with the `OrganizationPermissionsMixin`, permission checking
|
||||
In combination with the `TenantPermissionsMixin`, permission checking
|
||||
will be done to ensure the user has the correct permissions to perform the
|
||||
CRUD operation.
|
||||
|
||||
@ -166,7 +166,7 @@ class OrganizationPermissionMixin(
|
||||
raise centurion_exceptions.PermissionDenied()
|
||||
|
||||
|
||||
obj_organization: Organization = view.get_obj_organization(
|
||||
obj_organization: Tenant = view.get_obj_organization(
|
||||
request = request
|
||||
)
|
||||
|
||||
|
@ -1,2 +1,4 @@
|
||||
from . import contact
|
||||
from . import company_base
|
||||
from . import person
|
||||
from . import role
|
||||
|
102
app/access/models/company_base.py
Normal file
102
app/access/models/company_base.py
Normal file
@ -0,0 +1,102 @@
|
||||
from django.db import models
|
||||
|
||||
from access.models.entity import Entity
|
||||
|
||||
|
||||
|
||||
class Company(
|
||||
Entity
|
||||
):
|
||||
# This model is intended to be called `Organization`, however at the time of
|
||||
# creation this was not possible as Tenant (ne Organization) still has
|
||||
# references in code to `organization` witch clashes with the intended name of
|
||||
# this model.
|
||||
|
||||
|
||||
class Meta:
|
||||
|
||||
ordering = [
|
||||
'name',
|
||||
]
|
||||
|
||||
sub_model_type = 'company'
|
||||
|
||||
verbose_name = 'Company'
|
||||
|
||||
verbose_name_plural = 'Companies'
|
||||
|
||||
|
||||
name = models.CharField(
|
||||
blank = False,
|
||||
help_text = 'The name of this entity',
|
||||
max_length = 80,
|
||||
unique = False,
|
||||
verbose_name = 'Name'
|
||||
)
|
||||
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
||||
return self.name
|
||||
|
||||
|
||||
documentation = ''
|
||||
|
||||
history_model_name = 'company'
|
||||
|
||||
page_layout: dict = [
|
||||
{
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "double",
|
||||
"left": [
|
||||
'organization',
|
||||
'name',
|
||||
],
|
||||
"right": [
|
||||
'model_notes',
|
||||
'created',
|
||||
'modified',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Knowledge Base",
|
||||
"slug": "kb_articles",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "table",
|
||||
"field": "knowledge_base",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Tickets",
|
||||
"slug": "tickets",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "table",
|
||||
"field": "tickets",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Notes",
|
||||
"slug": "notes",
|
||||
"sections": []
|
||||
},
|
||||
]
|
||||
|
||||
table_fields: list = [
|
||||
'name',
|
||||
'organization',
|
||||
'created',
|
||||
]
|
||||
|
||||
|
||||
def clean(self):
|
||||
|
||||
super().clean()
|
@ -15,6 +15,8 @@ class Contact(
|
||||
'email',
|
||||
]
|
||||
|
||||
sub_model_type = 'contact'
|
||||
|
||||
verbose_name = 'Contact'
|
||||
|
||||
verbose_name_plural = 'Contacts'
|
||||
@ -42,6 +44,8 @@ class Contact(
|
||||
|
||||
documentation = ''
|
||||
|
||||
history_model_name = 'contact'
|
||||
|
||||
page_layout: list = [
|
||||
{
|
||||
"name": "Details",
|
||||
|
@ -22,6 +22,8 @@ class Entity(
|
||||
'organization',
|
||||
]
|
||||
|
||||
sub_model_type = 'entity'
|
||||
|
||||
verbose_name = 'Entity'
|
||||
|
||||
verbose_name_plural = 'Entities'
|
||||
@ -35,9 +37,9 @@ class Entity(
|
||||
verbose_name = 'ID'
|
||||
)
|
||||
|
||||
|
||||
entity_type = models.CharField(
|
||||
blank = False,
|
||||
default = Meta.verbose_name.lower(),
|
||||
help_text = 'Type this entity is',
|
||||
max_length = 30,
|
||||
unique = False,
|
||||
@ -93,6 +95,10 @@ class Entity(
|
||||
|
||||
for related_object in getattr(meta, 'related_objects', []):
|
||||
|
||||
if not issubclass(related_object.related_model, Entity):
|
||||
|
||||
continue
|
||||
|
||||
if getattr(self, related_object.name, None):
|
||||
|
||||
if(
|
||||
@ -125,15 +131,17 @@ class Entity(
|
||||
|
||||
if related_model_name == '':
|
||||
|
||||
return None
|
||||
related_model = None
|
||||
|
||||
elif related_model is None:
|
||||
|
||||
return self
|
||||
related_model = self
|
||||
|
||||
elif related_model.get_related_field_name() != '':
|
||||
elif hasattr(related_model, 'get_related_field_name'):
|
||||
|
||||
related_model = related_model.get_related_model()
|
||||
if related_model.get_related_field_name() != '':
|
||||
|
||||
related_model = related_model.get_related_model()
|
||||
|
||||
|
||||
return related_model
|
||||
|
@ -1,155 +1 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.fields import (
|
||||
AutoCreatedField,
|
||||
AutoLastModifiedField,
|
||||
AutoSlugField
|
||||
)
|
||||
|
||||
from core.mixin.history_save import SaveHistory
|
||||
|
||||
|
||||
|
||||
class Organization(SaveHistory):
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Organization"
|
||||
verbose_name_plural = "Organizations"
|
||||
ordering = ['name']
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
if self.slug == '_':
|
||||
self.slug = self.name.lower().replace(' ', '_')
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
id = models.AutoField(
|
||||
blank=False,
|
||||
help_text = 'ID of this item',
|
||||
primary_key=True,
|
||||
unique=True,
|
||||
verbose_name = 'ID'
|
||||
)
|
||||
|
||||
name = models.CharField(
|
||||
blank = False,
|
||||
help_text = 'Name of this Organization',
|
||||
max_length = 50,
|
||||
unique = True,
|
||||
verbose_name = 'Name'
|
||||
)
|
||||
|
||||
manager = models.ForeignKey(
|
||||
User,
|
||||
blank = False,
|
||||
help_text = 'Manager for this organization',
|
||||
null = True,
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name = 'Manager'
|
||||
)
|
||||
|
||||
model_notes = models.TextField(
|
||||
blank = True,
|
||||
default = None,
|
||||
help_text = 'Tid bits of information',
|
||||
null= True,
|
||||
verbose_name = 'Notes',
|
||||
)
|
||||
|
||||
slug = AutoSlugField()
|
||||
|
||||
created = AutoCreatedField()
|
||||
|
||||
modified = AutoLastModifiedField()
|
||||
|
||||
|
||||
def get_organization(self):
|
||||
return self
|
||||
|
||||
def __int__(self):
|
||||
|
||||
return self.id
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
table_fields: list = [
|
||||
'nbsp',
|
||||
'name',
|
||||
'created',
|
||||
'modified',
|
||||
'nbsp'
|
||||
]
|
||||
|
||||
page_layout: list = [
|
||||
{
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "double",
|
||||
"left": [
|
||||
'name',
|
||||
'manager',
|
||||
'created',
|
||||
'modified',
|
||||
],
|
||||
"right": [
|
||||
'model_notes',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Teams",
|
||||
"slug": "teams",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "table",
|
||||
"field": "teams"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Knowledge Base",
|
||||
"slug": "kb_articles",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "table",
|
||||
"field": "knowledge_base",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Notes",
|
||||
"slug": "notes",
|
||||
"sections": []
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def get_url( self, request = None ) -> str:
|
||||
|
||||
if request:
|
||||
|
||||
return reverse("v2:_api_v2_organization-detail", request=request, kwargs={'pk': self.id})
|
||||
|
||||
return reverse("v2:_api_v2_organization-detail", kwargs={'pk': self.id})
|
||||
|
||||
|
||||
def save_history(self, before: dict, after: dict) -> bool:
|
||||
|
||||
from access.models.organization_history import OrganizationHistory
|
||||
|
||||
history = super().save_history(
|
||||
before = before,
|
||||
after = after,
|
||||
history_model = OrganizationHistory
|
||||
)
|
||||
|
||||
|
||||
return history
|
||||
from .tenant import Tenant as Organization
|
||||
|
@ -2,7 +2,7 @@ from django.db import models
|
||||
|
||||
from core.models.model_history import ModelHistory
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ class OrganizationHistory(
|
||||
|
||||
|
||||
model = models.ForeignKey(
|
||||
Organization,
|
||||
Tenant,
|
||||
blank = False,
|
||||
help_text = 'Model this note belongs to',
|
||||
null = False,
|
||||
@ -46,8 +46,8 @@ class OrganizationHistory(
|
||||
|
||||
model = None
|
||||
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
model = OrganizationBaseSerializer(self.model, context = serializer_context)
|
||||
model = TenantBaseSerializer(self.model, context = serializer_context)
|
||||
|
||||
return model
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django.db import models
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
|
||||
from core.models.model_notes import ModelNotes
|
||||
|
||||
@ -23,7 +23,7 @@ class OrganizationNotes(
|
||||
|
||||
|
||||
model = models.ForeignKey(
|
||||
Organization,
|
||||
Tenant,
|
||||
blank = False,
|
||||
help_text = 'Model this note belongs to',
|
||||
null = False,
|
||||
|
@ -20,6 +20,8 @@ class Person(
|
||||
'dob',
|
||||
]
|
||||
|
||||
sub_model_type = 'person'
|
||||
|
||||
verbose_name = 'Person'
|
||||
|
||||
verbose_name_plural = 'People'
|
||||
@ -34,7 +36,6 @@ class Person(
|
||||
|
||||
m_name = models.CharField(
|
||||
blank = True,
|
||||
default = None,
|
||||
help_text = 'The persons middle name(s)',
|
||||
max_length = 100,
|
||||
null = True,
|
||||
@ -52,7 +53,6 @@ class Person(
|
||||
|
||||
dob = models.DateField(
|
||||
blank = True,
|
||||
default = None,
|
||||
help_text = 'The Persons Date of Birth (DOB)',
|
||||
null = True,
|
||||
unique = False,
|
||||
@ -65,6 +65,8 @@ class Person(
|
||||
|
||||
documentation = ''
|
||||
|
||||
history_model_name = 'person'
|
||||
|
||||
page_layout: dict = []
|
||||
|
||||
table_fields: list = [
|
||||
|
@ -8,7 +8,7 @@ from access.fields import (
|
||||
AutoLastModifiedField
|
||||
)
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
from access.models.tenancy import TenancyObject
|
||||
|
||||
from core import exceptions as centurion_exceptions
|
||||
@ -27,7 +27,9 @@ class Team(Group, TenancyObject):
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
|
||||
self.name = self.organization.name.lower().replace(' ', '_') + '_' + self.team_name.lower().replace(' ', '_')
|
||||
if self.organization_id:
|
||||
|
||||
self.name = self.organization.name.lower().replace(' ', '_') + '_' + self.team_name.lower().replace(' ', '_')
|
||||
|
||||
super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
|
||||
|
||||
@ -53,13 +55,13 @@ class Team(Group, TenancyObject):
|
||||
)
|
||||
|
||||
organization = models.ForeignKey(
|
||||
Organization,
|
||||
Tenant,
|
||||
blank = False,
|
||||
help_text = 'Organization this belongs to',
|
||||
help_text = 'Tenant this belongs to',
|
||||
null = False,
|
||||
on_delete = models.CASCADE,
|
||||
validators = [validatate_organization_exists],
|
||||
verbose_name = 'Organization'
|
||||
verbose_name = 'Tenant'
|
||||
)
|
||||
|
||||
created = AutoCreatedField()
|
||||
|
@ -1,6 +1,8 @@
|
||||
import django
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
@ -9,12 +11,14 @@ from access.fields import (
|
||||
AutoLastModifiedField
|
||||
)
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
from access.models.team import Team
|
||||
|
||||
from core.lib.feature_not_used import FeatureNotUsed
|
||||
from core.mixin.history_save import SaveHistory
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class TeamUsers(SaveHistory):
|
||||
@ -95,7 +99,7 @@ class TeamUsers(SaveHistory):
|
||||
user.groups.remove(group)
|
||||
|
||||
|
||||
def get_organization(self) -> Organization:
|
||||
def get_organization(self) -> Tenant:
|
||||
return self.team.organization
|
||||
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
# from django.conf import settings
|
||||
import django
|
||||
import logging
|
||||
|
||||
from django.db import models
|
||||
# from django.contrib.auth.models import User, Group
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
# from .fields import *
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
|
||||
from core import exceptions as centurion_exceptions
|
||||
from core.middleware.get_request import get_request
|
||||
@ -137,14 +136,14 @@ class TenancyObject(SaveHistory):
|
||||
)
|
||||
|
||||
organization = models.ForeignKey(
|
||||
Organization,
|
||||
Tenant,
|
||||
blank = False,
|
||||
help_text = 'Organization this belongs to',
|
||||
help_text = 'Tenancy this belongs to',
|
||||
null = False,
|
||||
on_delete = models.CASCADE,
|
||||
related_name = '+',
|
||||
validators = [validatate_organization_exists],
|
||||
verbose_name = 'Organization'
|
||||
verbose_name = 'Tenant'
|
||||
)
|
||||
|
||||
is_global = models.BooleanField(
|
||||
@ -162,7 +161,7 @@ class TenancyObject(SaveHistory):
|
||||
verbose_name = 'Notes',
|
||||
)
|
||||
|
||||
def get_organization(self) -> Organization:
|
||||
def get_organization(self) -> Tenant:
|
||||
return self.organization
|
||||
|
||||
app_namespace: str = None
|
||||
@ -193,6 +192,18 @@ class TenancyObject(SaveHistory):
|
||||
only be used when there is model inheritence.
|
||||
"""
|
||||
|
||||
_log: logging.Logger = None
|
||||
|
||||
def get_log(self):
|
||||
|
||||
if self._log is None:
|
||||
|
||||
self._log = logging.getLogger('centurion.' + self._meta.app_label)
|
||||
|
||||
return self._log
|
||||
|
||||
page_layout: list = None
|
||||
|
||||
note_basename: str = None
|
||||
"""URL BaseName for the notes endpoint.
|
||||
|
||||
@ -280,7 +291,7 @@ class TenancyObject(SaveHistory):
|
||||
|
||||
raise centurion_exceptions.ValidationError(
|
||||
detail = {
|
||||
'organization': 'Organization is required'
|
||||
'organization': 'Tenant is required'
|
||||
},
|
||||
code = 'required'
|
||||
)
|
||||
|
161
app/access/models/tenant.py
Normal file
161
app/access/models/tenant.py
Normal file
@ -0,0 +1,161 @@
|
||||
import django
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.fields import (
|
||||
AutoCreatedField,
|
||||
AutoLastModifiedField,
|
||||
AutoSlugField
|
||||
)
|
||||
|
||||
from core.mixin.history_save import SaveHistory
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
class Tenant(SaveHistory):
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Tenant"
|
||||
verbose_name_plural = "Tenants"
|
||||
ordering = ['name']
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
if self.slug == '_':
|
||||
self.slug = self.name.lower().replace(' ', '_')
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
id = models.AutoField(
|
||||
blank=False,
|
||||
help_text = 'ID of this item',
|
||||
primary_key=True,
|
||||
unique=True,
|
||||
verbose_name = 'ID'
|
||||
)
|
||||
|
||||
name = models.CharField(
|
||||
blank = False,
|
||||
help_text = 'Name of this Tenancy',
|
||||
max_length = 50,
|
||||
unique = True,
|
||||
verbose_name = 'Name'
|
||||
)
|
||||
|
||||
manager = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
blank = False,
|
||||
help_text = 'Manager for this Tenancy',
|
||||
null = True,
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name = 'Manager'
|
||||
)
|
||||
|
||||
model_notes = models.TextField(
|
||||
blank = True,
|
||||
default = None,
|
||||
help_text = 'Tid bits of information',
|
||||
null= True,
|
||||
verbose_name = 'Notes',
|
||||
)
|
||||
|
||||
slug = AutoSlugField()
|
||||
|
||||
created = AutoCreatedField()
|
||||
|
||||
modified = AutoLastModifiedField()
|
||||
|
||||
|
||||
def get_organization(self):
|
||||
return self
|
||||
|
||||
def __int__(self):
|
||||
|
||||
return self.id
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
table_fields: list = [
|
||||
'nbsp',
|
||||
'name',
|
||||
'created',
|
||||
'modified',
|
||||
'nbsp'
|
||||
]
|
||||
|
||||
page_layout: list = [
|
||||
{
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "double",
|
||||
"left": [
|
||||
'name',
|
||||
'manager',
|
||||
'created',
|
||||
'modified',
|
||||
],
|
||||
"right": [
|
||||
'model_notes',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Teams",
|
||||
"slug": "teams",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "table",
|
||||
"field": "teams"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Knowledge Base",
|
||||
"slug": "kb_articles",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "table",
|
||||
"field": "knowledge_base",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Notes",
|
||||
"slug": "notes",
|
||||
"sections": []
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def get_url( self, request = None ) -> str:
|
||||
|
||||
if request:
|
||||
|
||||
return reverse("v2:_api_v2_organization-detail", request=request, kwargs={'pk': self.id})
|
||||
|
||||
return reverse("v2:_api_v2_organization-detail", kwargs={'pk': self.id})
|
||||
|
||||
|
||||
def save_history(self, before: dict, after: dict) -> bool:
|
||||
|
||||
from access.models.organization_history import OrganizationHistory
|
||||
|
||||
history = super().save_history(
|
||||
before = before,
|
||||
after = after,
|
||||
history_model = OrganizationHistory
|
||||
)
|
||||
|
||||
|
||||
return history
|
||||
|
||||
|
||||
|
||||
Organization = Tenant
|
@ -6,7 +6,7 @@ from access.models.entity import Entity
|
||||
|
||||
from api.serializers import common
|
||||
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
|
||||
|
||||
@ -87,4 +87,4 @@ class ModelSerializer(
|
||||
class ViewSerializer(ModelSerializer):
|
||||
"""Entity Base View Model"""
|
||||
|
||||
organization = OrganizationBaseSerializer(many=False, read_only=True)
|
||||
organization = TenantBaseSerializer(many=False, read_only=True)
|
||||
|
70
app/access/serializers/entity_company.py
Normal file
70
app/access/serializers/entity_company.py
Normal file
@ -0,0 +1,70 @@
|
||||
from drf_spectacular.utils import extend_schema_serializer
|
||||
|
||||
from access.models.company_base import Company
|
||||
|
||||
from access.serializers.entity import (
|
||||
BaseSerializer as BaseBaseSerializer,
|
||||
ModelSerializer as BaseModelSerializer,
|
||||
)
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
|
||||
|
||||
class BaseSerializer(
|
||||
BaseBaseSerializer,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@extend_schema_serializer(component_name = 'CompanyEntityModelSerializer')
|
||||
class ModelSerializer(
|
||||
BaseSerializer,
|
||||
BaseModelSerializer,
|
||||
):
|
||||
"""Company Model
|
||||
|
||||
This model inherits from the Entity base model.
|
||||
"""
|
||||
|
||||
|
||||
class Meta:
|
||||
|
||||
model = Company
|
||||
|
||||
fields = [
|
||||
'id',
|
||||
'entity_ptr_id',
|
||||
'organization',
|
||||
'entity_type',
|
||||
'display_name',
|
||||
'name',
|
||||
'model_notes',
|
||||
'is_global',
|
||||
'created',
|
||||
'modified',
|
||||
'_urls',
|
||||
]
|
||||
|
||||
read_only_fields = [
|
||||
'id',
|
||||
'display_name',
|
||||
'entity_type',
|
||||
'created',
|
||||
'modified',
|
||||
'_urls',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@extend_schema_serializer(component_name = 'CompanyEntityViewSerializer')
|
||||
class ViewSerializer(
|
||||
ModelSerializer,
|
||||
):
|
||||
"""Company View Model
|
||||
|
||||
This model inherits from the Entity base model.
|
||||
"""
|
||||
|
||||
organization = TenantBaseSerializer(many=False, read_only=True)
|
@ -2,11 +2,11 @@ from drf_spectacular.utils import extend_schema_serializer
|
||||
|
||||
from access.models.contact import Contact
|
||||
|
||||
from access.serializers.person import (
|
||||
from access.serializers.entity_person import (
|
||||
BaseSerializer as BaseBaseSerializer,
|
||||
ModelSerializer as BaseModelSerializer,
|
||||
)
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
|
||||
|
||||
@ -72,4 +72,4 @@ class ViewSerializer(
|
||||
This model inherits from the Person model.
|
||||
"""
|
||||
|
||||
organization = OrganizationBaseSerializer(many=False, read_only=True)
|
||||
organization = TenantBaseSerializer(many=False, read_only=True)
|
@ -6,7 +6,7 @@ from access.serializers.entity import (
|
||||
BaseSerializer as BaseBaseSerializer,
|
||||
ModelSerializer as BaseModelSerializer,
|
||||
)
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
|
||||
|
||||
@ -70,4 +70,4 @@ class ViewSerializer(
|
||||
This model inherits from the Entity base model.
|
||||
"""
|
||||
|
||||
organization = OrganizationBaseSerializer(many=False, read_only=True)
|
||||
organization = TenantBaseSerializer(many=False, read_only=True)
|
@ -2,15 +2,16 @@ from rest_framework.reverse import reverse
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
|
||||
from app.serializers.user import UserBaseSerializer
|
||||
|
||||
from core import fields as centurion_field
|
||||
|
||||
Organization = Tenant
|
||||
|
||||
|
||||
class OrganizationBaseSerializer(serializers.ModelSerializer):
|
||||
class TenantBaseSerializer(serializers.ModelSerializer):
|
||||
|
||||
display_name = serializers.SerializerMethodField('get_display_name')
|
||||
|
||||
@ -24,7 +25,7 @@ class OrganizationBaseSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
|
||||
model = Organization
|
||||
model = Tenant
|
||||
|
||||
fields = [
|
||||
'id',
|
||||
@ -42,8 +43,8 @@ class OrganizationBaseSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
|
||||
class OrganizationModelSerializer(
|
||||
OrganizationBaseSerializer
|
||||
class TenantModelSerializer(
|
||||
TenantBaseSerializer
|
||||
):
|
||||
|
||||
_urls = serializers.SerializerMethodField('get_url')
|
||||
@ -74,7 +75,7 @@ class OrganizationModelSerializer(
|
||||
|
||||
class Meta:
|
||||
|
||||
model = Organization
|
||||
model = Tenant
|
||||
|
||||
fields = '__all__'
|
||||
|
||||
@ -98,7 +99,7 @@ class OrganizationModelSerializer(
|
||||
]
|
||||
|
||||
|
||||
class OrganizationViewSerializer(OrganizationModelSerializer):
|
||||
class TenantViewSerializer(TenantModelSerializer):
|
||||
pass
|
||||
|
||||
manager = UserBaseSerializer(many=False, read_only = True)
|
||||
|
@ -5,7 +5,7 @@ from drf_spectacular.utils import extend_schema_serializer
|
||||
|
||||
from access.functions.permissions import permission_queryset
|
||||
from access.models.role import Role
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
from api.serializers import common
|
||||
|
||||
@ -109,6 +109,6 @@ class ModelSerializer(
|
||||
class ViewSerializer(ModelSerializer):
|
||||
"""Role Base View Model"""
|
||||
|
||||
organization = OrganizationBaseSerializer( many=False, read_only=True )
|
||||
organization = TenantBaseSerializer( many=False, read_only=True )
|
||||
|
||||
permissions = PermissionBaseSerializer( many=True, read_only=True )
|
||||
|
@ -7,7 +7,7 @@ from access.models.team import Team
|
||||
from api.serializers import common
|
||||
|
||||
from access.functions.permissions import permission_queryset
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
from access.serializers.organization import TenantBaseSerializer
|
||||
|
||||
from app.serializers.permission import Permission, PermissionBaseSerializer
|
||||
|
||||
@ -127,6 +127,6 @@ class TeamModelSerializer(
|
||||
|
||||
class TeamViewSerializer(TeamModelSerializer):
|
||||
|
||||
organization = OrganizationBaseSerializer(many=False, read_only=True)
|
||||
organization = TenantBaseSerializer(many=False, read_only=True)
|
||||
|
||||
permissions = PermissionBaseSerializer(many = True)
|
||||
|
@ -1,7 +1,3 @@
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
from access.models.tenancy import TenancyManager
|
||||
|
||||
|
||||
|
||||
@ -19,83 +15,18 @@ class TenancyObject:
|
||||
"""
|
||||
|
||||
|
||||
def test_history_save(self):
|
||||
"""Confirm the desired intent for saving model history."""
|
||||
# def test_history_save(self):
|
||||
# """Confirm the desired intent for saving model history."""
|
||||
|
||||
assert self.model.save_model_history == self.should_model_history_be_saved
|
||||
|
||||
|
||||
def test_has_attr_get_organization(self):
|
||||
""" TenancyObject attribute check
|
||||
|
||||
TenancyObject has function get_organization
|
||||
"""
|
||||
|
||||
assert hasattr(self.model, 'get_organization')
|
||||
|
||||
|
||||
def test_has_attr_is_global(self):
|
||||
""" TenancyObject attribute check
|
||||
|
||||
TenancyObject has field is_global
|
||||
"""
|
||||
|
||||
assert hasattr(self.model, 'is_global')
|
||||
# assert self.model.save_model_history == self.should_model_history_be_saved
|
||||
|
||||
|
||||
|
||||
def test_has_attr_model_notes(self):
|
||||
""" TenancyObject attribute check
|
||||
# @pytest.mark.skip(reason="to be written")
|
||||
# def test_edit_no_organization_fails(self):
|
||||
# """ Devices must be assigned an organization
|
||||
|
||||
TenancyObject has field model_notes
|
||||
"""
|
||||
# Must not be able to edit an item without an organization
|
||||
# """
|
||||
# pass
|
||||
|
||||
assert hasattr(self.model, 'model_notes')
|
||||
|
||||
|
||||
|
||||
def test_has_attr_organization(self):
|
||||
""" TenancyObject attribute check
|
||||
|
||||
TenancyObject has field organization
|
||||
"""
|
||||
|
||||
assert hasattr(self.model, 'organization')
|
||||
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="to be written")
|
||||
def test_create_no_organization_fails(self):
|
||||
""" Devices must be assigned an organization
|
||||
|
||||
Must not be able to create an item without an organization
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="to be written")
|
||||
def test_edit_no_organization_fails(self):
|
||||
""" Devices must be assigned an organization
|
||||
|
||||
Must not be able to edit an item without an organization
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def test_has_attr_organization(self):
|
||||
""" TenancyObject attribute check
|
||||
|
||||
TenancyObject has function objects
|
||||
"""
|
||||
|
||||
assert hasattr(self.model, 'objects')
|
||||
|
||||
|
||||
def test_attribute_is_type_objects(self):
|
||||
""" Attribute Check
|
||||
|
||||
attribute `objects` must be set to `access.models.TenancyManager()`
|
||||
"""
|
||||
|
||||
assert type(self.model.objects) is TenancyManager
|
||||
|
24
app/access/tests/functional/company/conftest.py
Normal file
24
app/access/tests/functional/company/conftest.py
Normal file
@ -0,0 +1,24 @@
|
||||
import pytest
|
||||
|
||||
from access.models.company_base import Company
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Company
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def create_serializer():
|
||||
|
||||
from access.serializers.entity_company import ModelSerializer
|
||||
|
||||
|
||||
yield ModelSerializer
|
@ -0,0 +1,72 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.company_base import Company
|
||||
from access.tests.functional.entity.test_functional_entity_metadata import (
|
||||
EntityMetadataInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CompanyMetadataTestCases(
|
||||
EntityMetadataInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'name': 'Ian1'
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'name': 'Ian2',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'name': 'Ian3',
|
||||
}
|
||||
|
||||
model = Company
|
||||
|
||||
|
||||
|
||||
|
||||
class CompanyMetadataInheritedCases(
|
||||
CompanyMetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
# self.url_kwargs = {
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# }
|
||||
|
||||
# self.url_view_kwargs = {
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# }
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class CompanyMetadataTest(
|
||||
CompanyMetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
pass
|
@ -0,0 +1,43 @@
|
||||
import pytest
|
||||
|
||||
from access.tests.functional.entity.test_functional_entity_permission import (
|
||||
EntityPermissionsAPIInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CompanyPermissionsAPITestCases(
|
||||
EntityPermissionsAPIInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'name': 'Ian1',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'name': 'Ian2',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'name': 'Ian3',
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CompanyPermissionsAPIInheritedCases(
|
||||
CompanyPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
|
||||
class CompanyPermissionsAPIPyTest(
|
||||
CompanyPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -0,0 +1,46 @@
|
||||
import pytest
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.tests.functional.entity.test_functional_entity_serializer import (
|
||||
MockView,
|
||||
EntitySerializerInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CompanySerializerTestCases(
|
||||
EntitySerializerInheritedCases
|
||||
):
|
||||
|
||||
|
||||
parameterized_test_data: dict = {
|
||||
"name": {
|
||||
'will_create': False,
|
||||
'exception_key': 'required'
|
||||
},
|
||||
}
|
||||
|
||||
valid_data: dict = {
|
||||
'name': 'Ian',
|
||||
}
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
|
||||
class CompanySerializerInheritedCases(
|
||||
CompanySerializerTestCases,
|
||||
):
|
||||
|
||||
parameterized_test_data: dict = None
|
||||
|
||||
valid_data: dict = None
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
|
||||
class CompanySerializerPyTest(
|
||||
CompanySerializerTestCases,
|
||||
):
|
||||
|
||||
parameterized_test_data: dict = None
|
@ -0,0 +1,58 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.company_base import Company
|
||||
from access.tests.functional.entity.test_functional_entity_viewset import (
|
||||
EntityViewSetInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ViewSetTestCases(
|
||||
EntityViewSetInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'name': 'Ian',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'name': 'Ian2',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'name': 'Ian3',
|
||||
}
|
||||
|
||||
model = Company
|
||||
|
||||
|
||||
|
||||
class CompanyViewSetInheritedCases(
|
||||
ViewSetTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class CompanyViewSetTest(
|
||||
ViewSetTestCases,
|
||||
TestCase,
|
||||
):
|
||||
pass
|
24
app/access/tests/functional/contact/conftest.py
Normal file
24
app/access/tests/functional/contact/conftest.py
Normal file
@ -0,0 +1,24 @@
|
||||
import pytest
|
||||
|
||||
from access.models.contact import Contact
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Contact
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def create_serializer():
|
||||
|
||||
from access.serializers.entity_contact import ModelSerializer
|
||||
|
||||
|
||||
yield ModelSerializer
|
@ -0,0 +1,65 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.contact import Contact
|
||||
|
||||
from access.tests.functional.person.test_functional_person_metadata import (
|
||||
PersonMetadataInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ContactMetadataTestCases(
|
||||
PersonMetadataInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'email': 'ipweird@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'email': 'ipstrange@unit.test',
|
||||
}
|
||||
|
||||
model = Contact
|
||||
|
||||
|
||||
|
||||
|
||||
class ContactMetadataInheritedCases(
|
||||
ContactMetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class ContactMetadataTest(
|
||||
ContactMetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
pass
|
@ -0,0 +1,70 @@
|
||||
import pytest
|
||||
|
||||
from access.tests.functional.person.test_functional_person_permission import (
|
||||
PersonPermissionsAPIInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ContactPermissionsAPITestCases(
|
||||
PersonPermissionsAPIInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'email': 'ipweird@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'email': 'ipstrange@unit.test',
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ContactPermissionsAPIInheritedCases(
|
||||
ContactPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
# url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
# @pytest.fixture(scope='class')
|
||||
# def inherited_var_setup(self, request):
|
||||
|
||||
# request.cls.url_kwargs.update({
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# })
|
||||
|
||||
# request.cls.url_view_kwargs.update({
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# })
|
||||
|
||||
|
||||
|
||||
# @pytest.fixture(scope='class', autouse = True)
|
||||
# def class_setup(self, request, django_db_blocker,
|
||||
# model,
|
||||
# var_setup,
|
||||
# prepare,
|
||||
# inherited_var_setup,
|
||||
# diff_org_model,
|
||||
# create_model,
|
||||
# ):
|
||||
|
||||
# pass
|
||||
|
||||
|
||||
class ContactPermissionsAPIPyTest(
|
||||
ContactPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -1,129 +1,46 @@
|
||||
import pytest
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.serializers.contact import (
|
||||
Contact,
|
||||
ModelSerializer
|
||||
)
|
||||
from access.tests.functional.person.test_functional_person_serializer import (
|
||||
MockView,
|
||||
PersonSerializerInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class SerializerTestCases(
|
||||
PersonSerializerInheritedCases,
|
||||
class ContactSerializerTestCases(
|
||||
PersonSerializerInheritedCases
|
||||
):
|
||||
|
||||
duplicate_f_name_l_name_dob = {
|
||||
'email': 'contactentityduplicateone@unit.test',
|
||||
|
||||
parameterized_test_data: dict = {
|
||||
"email": {
|
||||
'will_create': False,
|
||||
'exception_key': 'required'
|
||||
}
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item_duplicate_f_name_l_name_dob = {
|
||||
'email': 'contactentityduplicatetwo@unit.test',
|
||||
}
|
||||
|
||||
model = Contact
|
||||
"""Model to test"""
|
||||
|
||||
create_model_serializer = ModelSerializer
|
||||
"""Serializer to test"""
|
||||
|
||||
valid_data: dict = {
|
||||
'email': 'ipweird@unit.test',
|
||||
'email': 'contactentityduplicatetwo@unit.test',
|
||||
}
|
||||
|
||||
|
||||
|
||||
def test_serializer_validation_no_email_exception(self):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating with valid data and field email is missing
|
||||
a validation error occurs.
|
||||
"""
|
||||
|
||||
data = self.valid_data.copy()
|
||||
|
||||
del data['email']
|
||||
|
||||
with pytest.raises(ValidationError) as err:
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
serializer.is_valid(raise_exception = True)
|
||||
|
||||
assert err.value.get_codes()['email'][0] == 'required'
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
|
||||
class ContactSerializerInheritedCases(
|
||||
SerializerTestCases,
|
||||
ContactSerializerTestCases,
|
||||
):
|
||||
|
||||
create_model_serializer = None
|
||||
"""Serializer to test"""
|
||||
|
||||
duplicate_f_name_l_name_dob: dict = None
|
||||
""" Duplicate model serializer dict
|
||||
|
||||
used for testing for duplicate f_name, l_name and dob fields.
|
||||
"""
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
""" Model kwargs to create item"""
|
||||
|
||||
kwargs_create_item_duplicate_f_name_l_name_dob: dict = None
|
||||
"""model kwargs to create object
|
||||
|
||||
**None:** Ensure that the fields of sub-model to person do not match
|
||||
`self.duplicate_f_name_l_name_dob`. if they do the wrong exception will be thrown.
|
||||
|
||||
used for testing for duplicate f_name, l_name and dob fields.
|
||||
"""
|
||||
|
||||
model = None
|
||||
"""Model to test"""
|
||||
parameterized_test_data: dict = None
|
||||
|
||||
valid_data: dict = None
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test"""
|
||||
|
||||
self.duplicate_f_name_l_name_dob.update(
|
||||
super().duplicate_f_name_l_name_dob
|
||||
)
|
||||
|
||||
self.kwargs_create_item_duplicate_f_name_l_name_dob.update(
|
||||
super().kwargs_create_item_duplicate_f_name_l_name_dob
|
||||
)
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
|
||||
self.valid_data.update(
|
||||
super().valid_data
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class ContactSerializerTest(
|
||||
SerializerTestCases,
|
||||
TestCase,
|
||||
class ContactSerializerPyTest(
|
||||
ContactSerializerTestCases,
|
||||
):
|
||||
|
||||
pass
|
||||
parameterized_test_data: dict = None
|
||||
|
@ -2,91 +2,28 @@ from django.test import TestCase
|
||||
|
||||
from access.models.contact import Contact
|
||||
from access.tests.functional.person.test_functional_person_viewset import (
|
||||
PersonMetadataInheritedCases,
|
||||
PersonPermissionsAPIInheritedCases,
|
||||
PersonViewSetInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
|
||||
add_data = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org = {
|
||||
'email': 'ipstrange@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item = {
|
||||
'email': 'ipweird@unit.test',
|
||||
}
|
||||
|
||||
model = Contact
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
|
||||
|
||||
class PermissionsAPITestCases(
|
||||
ViewSetBase,
|
||||
PersonPermissionsAPIInheritedCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ContactPermissionsAPIInheritedCases(
|
||||
PermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.add_data.update(
|
||||
super().add_data
|
||||
)
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
|
||||
self.kwargs_create_item_diff_org.update(
|
||||
super().kwargs_create_item_diff_org
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class ContactPermissionsAPITest(
|
||||
PermissionsAPITestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ViewSetTestCases(
|
||||
ViewSetBase,
|
||||
PersonViewSetInheritedCases,
|
||||
):
|
||||
|
||||
pass
|
||||
add_data: dict = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'email': 'ipweird@unit.test',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'email': 'ipstrange@unit.test',
|
||||
}
|
||||
|
||||
model = Contact
|
||||
|
||||
|
||||
|
||||
@ -96,21 +33,19 @@ class ContactViewSetInheritedCases(
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org.update(
|
||||
super().kwargs_create_item_diff_org
|
||||
)
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
@ -120,50 +55,4 @@ class ContactViewSetTest(
|
||||
ViewSetTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class MetadataTestCases(
|
||||
ViewSetBase,
|
||||
PersonMetadataInheritedCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ContactMetadataInheritedCases(
|
||||
MetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
|
||||
self.kwargs_create_item_diff_org.update(
|
||||
super().kwargs_create_item_diff_org
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class ContactMetadataTest(
|
||||
MetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
|
||||
pass
|
||||
|
24
app/access/tests/functional/entity/conftest.py
Normal file
24
app/access/tests/functional/entity/conftest.py
Normal file
@ -0,0 +1,24 @@
|
||||
import pytest
|
||||
|
||||
from access.models.entity import Entity
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Entity
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def create_serializer():
|
||||
|
||||
from access.serializers.entity import ModelSerializer
|
||||
|
||||
|
||||
yield ModelSerializer
|
@ -0,0 +1,260 @@
|
||||
import django
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.entity import Entity
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from accounting.models.asset_base import AssetBase
|
||||
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class EntityMetadataTestCases(
|
||||
MetadataAttributesFunctional,
|
||||
):
|
||||
|
||||
add_data: dict = {}
|
||||
|
||||
app_namespace = 'v2'
|
||||
|
||||
base_model = Entity
|
||||
"""Base model for this sub model
|
||||
don't change or override this value
|
||||
"""
|
||||
|
||||
change_data = None
|
||||
|
||||
delete_data = {}
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
model = Entity
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
url_name = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a team
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
self.different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = organization,
|
||||
**self.kwargs_create_item
|
||||
)
|
||||
|
||||
self.other_org_item = self.model.objects.create(
|
||||
organization = self.different_organization,
|
||||
**self.kwargs_create_item_diff_org
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs.update({ 'pk': self.item.id })
|
||||
|
||||
if self.add_data is not None:
|
||||
|
||||
self.add_data.update({
|
||||
'organization': self.organization.id,
|
||||
})
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
|
||||
|
||||
add_permissions = Permission.objects.get(
|
||||
codename = 'add_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_team = Team.objects.create(
|
||||
team_name = 'add_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
add_team.permissions.set([add_permissions])
|
||||
|
||||
|
||||
|
||||
change_permissions = Permission.objects.get(
|
||||
codename = 'change_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
change_team = Team.objects.create(
|
||||
team_name = 'change_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
change_team.permissions.set([change_permissions])
|
||||
|
||||
|
||||
|
||||
delete_permissions = Permission.objects.get(
|
||||
codename = 'delete_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
delete_team = Team.objects.create(
|
||||
team_name = 'delete_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
delete_team.permissions.set([delete_permissions])
|
||||
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.add_user = User.objects.create_user(username="test_user_add", password="password")
|
||||
TeamUsers.objects.create(
|
||||
team = add_team,
|
||||
user = self.add_user
|
||||
)
|
||||
|
||||
self.change_user = User.objects.create_user(username="test_user_change", password="password")
|
||||
TeamUsers.objects.create(
|
||||
team = change_team,
|
||||
user = self.change_user
|
||||
)
|
||||
|
||||
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
|
||||
TeamUsers.objects.create(
|
||||
team = delete_team,
|
||||
user = self.delete_user
|
||||
)
|
||||
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = self.different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
add_permissions,
|
||||
change_permissions,
|
||||
delete_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
||||
|
||||
|
||||
def test_sanity_is_entity_sub_model(self):
|
||||
"""Sanity Test
|
||||
|
||||
This test ensures that the model being tested `self.model` is a
|
||||
sub-model of `self.base_model`.
|
||||
This test is required as the same viewset is used for all sub-models
|
||||
of `AssetBase`
|
||||
"""
|
||||
|
||||
assert issubclass(self.model, self.base_model)
|
||||
|
||||
|
||||
|
||||
class EntityMetadataInheritedCases(
|
||||
EntityMetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
self.url_kwargs = {
|
||||
'entity_model': self.model._meta.sub_model_type
|
||||
}
|
||||
|
||||
self.url_view_kwargs = {
|
||||
'entity_model': self.model._meta.sub_model_type
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class EntityMetadataTest(
|
||||
EntityMetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
|
||||
url_name = '_api_v2_entity'
|
@ -0,0 +1,89 @@
|
||||
import pytest
|
||||
|
||||
from api.tests.functional.test_functional_api_permissions import (
|
||||
APIPermissionsInheritedCases,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class EntityPermissionsAPITestCases(
|
||||
APIPermissionsInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {}
|
||||
|
||||
app_namespace = 'v2'
|
||||
|
||||
change_data = {}
|
||||
|
||||
delete_data = {}
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_name = '_api_v2_entity'
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
|
||||
|
||||
def test_returned_data_from_user_and_global_organizations_only(self):
|
||||
"""Check items returned
|
||||
|
||||
This test case is a over-ride of a test case with the same name.
|
||||
This model is not a tenancy model making this test not-applicable.
|
||||
|
||||
Items returned from the query Must be from the users organization and
|
||||
global ONLY!
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class EntityPermissionsAPIInheritedCases(
|
||||
EntityPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def inherited_var_setup(self, request):
|
||||
|
||||
request.cls.url_kwargs.update({
|
||||
'entity_model': self.model._meta.sub_model_type
|
||||
})
|
||||
|
||||
request.cls.url_view_kwargs.update({
|
||||
'entity_model': self.model._meta.sub_model_type
|
||||
})
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='class', autouse = True)
|
||||
def class_setup(self, request, django_db_blocker,
|
||||
model,
|
||||
var_setup,
|
||||
prepare,
|
||||
inherited_var_setup,
|
||||
diff_org_model,
|
||||
create_model,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class EntityPermissionsAPIPyTest(
|
||||
EntityPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -1,94 +1,171 @@
|
||||
import django
|
||||
import pytest
|
||||
|
||||
from django.test import TestCase
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.serializers.entity import (
|
||||
Entity,
|
||||
ModelSerializer
|
||||
)
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class SerializerTestCases:
|
||||
class MockView:
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
""" Model kwargs to create item"""
|
||||
_has_import: bool = False
|
||||
"""User Permission
|
||||
|
||||
model = Entity
|
||||
"""Model to test"""
|
||||
get_permission_required() sets this to `True` when user has import permission.
|
||||
"""
|
||||
|
||||
create_model_serializer = ModelSerializer
|
||||
"""Serializer to test"""
|
||||
_has_purge: bool = False
|
||||
"""User Permission
|
||||
|
||||
valid_data: dict = {}
|
||||
get_permission_required() sets this to `True` when user has purge permission.
|
||||
"""
|
||||
|
||||
_has_triage: bool = False
|
||||
"""User Permission
|
||||
|
||||
get_permission_required() sets this to `True` when user has triage permission.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class EntitySerializerTestCases:
|
||||
|
||||
|
||||
parameterized_test_data: dict = {
|
||||
"model_notes": {
|
||||
'will_create': True,
|
||||
}
|
||||
}
|
||||
|
||||
valid_data: dict = {
|
||||
'model_notes': 'model notes field'
|
||||
}
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test"""
|
||||
|
||||
self.organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.kwargs_create_item.update({
|
||||
'model_notes': 'model notes field'
|
||||
})
|
||||
@pytest.fixture( scope = 'class')
|
||||
def setup_data(self,
|
||||
request,
|
||||
model,
|
||||
django_db_blocker,
|
||||
organization_one,
|
||||
):
|
||||
|
||||
self.valid_data.update({
|
||||
'organization': self.organization.pk,
|
||||
'model_notes': 'model notes field'
|
||||
})
|
||||
with django_db_blocker.unblock():
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = self.organization,
|
||||
**self.kwargs_create_item,
|
||||
)
|
||||
request.cls.organization = organization_one
|
||||
|
||||
valid_data = {}
|
||||
|
||||
for base in reversed(request.cls.__mro__):
|
||||
|
||||
if hasattr(base, 'valid_data'):
|
||||
|
||||
if base.valid_data is None:
|
||||
|
||||
continue
|
||||
|
||||
valid_data.update(**base.valid_data)
|
||||
|
||||
|
||||
if len(valid_data) > 0:
|
||||
|
||||
request.cls.valid_data = valid_data
|
||||
|
||||
|
||||
if 'organization' not in request.cls.valid_data:
|
||||
|
||||
request.cls.valid_data.update({
|
||||
'organization': request.cls.organization.pk
|
||||
})
|
||||
|
||||
|
||||
request.cls.view_user = User.objects.create_user(username="cafs_test_user_view", password="password")
|
||||
|
||||
|
||||
yield
|
||||
|
||||
with django_db_blocker.unblock():
|
||||
|
||||
request.cls.view_user.delete()
|
||||
|
||||
del request.cls.valid_data
|
||||
|
||||
|
||||
|
||||
def test_serializer_valid_data(self):
|
||||
@pytest.fixture( scope = 'class', autouse = True)
|
||||
def class_setup(self,
|
||||
setup_data,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test_serializer_valid_data(self, create_serializer):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating an object with valid data, no validation
|
||||
error occurs.
|
||||
"""
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
view_set = MockView()
|
||||
|
||||
serializer = create_serializer(
|
||||
context = {
|
||||
'view': view_set,
|
||||
},
|
||||
data = self.valid_data
|
||||
)
|
||||
|
||||
assert serializer.is_valid(raise_exception = True)
|
||||
|
||||
|
||||
def test_serializer_validation_no_model_notes(self):
|
||||
|
||||
def test_serializer_valid_data_missing_field_is_valid(self, parameterized, param_key_test_data,
|
||||
create_serializer,
|
||||
param_value,
|
||||
param_will_create,
|
||||
):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that if creating and no model_notes is provided no validation
|
||||
error occurs
|
||||
Ensure that when creating an object with a user with import permission
|
||||
and with valid data, no validation error occurs.
|
||||
"""
|
||||
|
||||
data = self.valid_data.copy()
|
||||
|
||||
del data['model_notes']
|
||||
valid_data = self.valid_data.copy()
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
del valid_data[param_value]
|
||||
|
||||
view_set = MockView()
|
||||
|
||||
view_set._has_import = True
|
||||
|
||||
serializer = create_serializer(
|
||||
context = {
|
||||
'view': view_set,
|
||||
},
|
||||
data = valid_data
|
||||
)
|
||||
|
||||
assert serializer.is_valid(raise_exception = True)
|
||||
is_valid = serializer.is_valid(raise_exception = False)
|
||||
|
||||
assert (
|
||||
(
|
||||
not param_will_create
|
||||
and param_will_create == is_valid
|
||||
)
|
||||
or param_will_create == is_valid
|
||||
)
|
||||
|
||||
|
||||
|
||||
class EntitySerializerInheritedCases(
|
||||
SerializerTestCases,
|
||||
EntitySerializerTestCases,
|
||||
):
|
||||
|
||||
create_model_serializer = None
|
||||
"""Serializer to test"""
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
""" Model kwargs to create item"""
|
||||
parameterized_test_data: dict = None
|
||||
|
||||
model = None
|
||||
"""Model to test"""
|
||||
@ -97,10 +174,40 @@ class EntitySerializerInheritedCases(
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
def test_serializer_valid_data_missing_field_raises_exception(self, parameterized, param_key_test_data,
|
||||
create_serializer,
|
||||
param_value,
|
||||
param_exception_key,
|
||||
):
|
||||
"""Serializer Validation Check
|
||||
|
||||
class EntitySerializerTest(
|
||||
SerializerTestCases,
|
||||
TestCase,
|
||||
Ensure that when creating an object with a user with import permission
|
||||
and with valid data, no validation error occurs.
|
||||
"""
|
||||
|
||||
valid_data = self.valid_data.copy()
|
||||
|
||||
del valid_data[param_value]
|
||||
|
||||
view_set = MockView()
|
||||
|
||||
with pytest.raises(ValidationError) as err:
|
||||
|
||||
serializer = create_serializer(
|
||||
context = {
|
||||
'view': view_set,
|
||||
},
|
||||
data = valid_data
|
||||
)
|
||||
|
||||
is_valid = serializer.is_valid(raise_exception = True)
|
||||
|
||||
assert err.value.get_codes()[param_value][0] == param_exception_key
|
||||
|
||||
|
||||
|
||||
class EntitySerializerPyTest(
|
||||
EntitySerializerTestCases,
|
||||
):
|
||||
|
||||
pass
|
||||
parameterized_test_data: dict = None
|
||||
|
@ -1,37 +1,49 @@
|
||||
from django.contrib.auth.models import Permission, User
|
||||
import django
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.entity import Entity
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
|
||||
add_data: dict = None
|
||||
add_data: dict = {
|
||||
'model_notes': 'added model note'
|
||||
}
|
||||
|
||||
app_namespace = 'v2'
|
||||
|
||||
base_model = Entity
|
||||
"""Base model for this sub model
|
||||
don't change or override this value
|
||||
"""
|
||||
|
||||
change_data = None
|
||||
|
||||
delete_data = {}
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
kwargs_create_item: dict = {
|
||||
'model_notes': 'added model note'
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'model_notes': 'added model note'
|
||||
}
|
||||
|
||||
model = None
|
||||
|
||||
url_kwargs: dict = None
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = None
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
url_name = None
|
||||
|
||||
@ -53,16 +65,15 @@ class ViewSetBase:
|
||||
|
||||
self.different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = organization,
|
||||
model_notes = 'some notes',
|
||||
**self.kwargs_create_item
|
||||
)
|
||||
|
||||
self.other_org_item = self.model.objects.create(
|
||||
organization = self.different_organization,
|
||||
model_notes = 'some more notes',
|
||||
**self.kwargs_create_item_diff_org
|
||||
)
|
||||
|
||||
@ -71,7 +82,9 @@ class ViewSetBase:
|
||||
|
||||
if self.add_data is not None:
|
||||
|
||||
self.add_data.update({'organization': self.organization.id})
|
||||
self.add_data.update({
|
||||
'organization': self.organization.id,
|
||||
})
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
@ -144,7 +157,6 @@ class ViewSetBase:
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
@ -190,98 +202,16 @@ class ViewSetBase:
|
||||
)
|
||||
|
||||
|
||||
|
||||
class PermissionsAPITestCases(
|
||||
ViewSetBase,
|
||||
APIPermissions,
|
||||
):
|
||||
|
||||
|
||||
add_data: dict = {}
|
||||
|
||||
change_data = {'model_notes': 'device'}
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
url_kwargs: dict = None
|
||||
|
||||
url_view_kwargs: dict = None
|
||||
|
||||
url_name = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.add_data.update({ 'model_note': 'added model note' })
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
def test_returned_data_from_user_and_global_organizations_only(self):
|
||||
"""Check items returned
|
||||
|
||||
This test case is a over-ride of a test case with the same name.
|
||||
This model is not a tenancy model making this test not-applicable.
|
||||
|
||||
Items returned from the query Must be from the users organization and
|
||||
global ONLY!
|
||||
def test_sanity_is_asset_sub_model(self):
|
||||
"""Sanity Test
|
||||
|
||||
This test ensures that the model being tested `self.model` is a
|
||||
sub-model of `self.base_model`.
|
||||
This test is required as the same viewset is used for all sub-models
|
||||
of `Entity`
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class EntityPermissionsAPIInheritedCases(
|
||||
PermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.url_kwargs = {
|
||||
'entity_model': self.model._meta.model_name
|
||||
}
|
||||
|
||||
self.url_view_kwargs = {
|
||||
'entity_model': self.model._meta.model_name
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class EntityPermissionsAPITest(
|
||||
PermissionsAPITestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
model = Entity
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
url_name = '_api_v2_entity'
|
||||
|
||||
assert issubclass(self.model, self.base_model)
|
||||
|
||||
|
||||
|
||||
@ -290,17 +220,7 @@ class ViewSetTestCases(
|
||||
SerializersTestCases,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
url_kwargs: dict = None
|
||||
|
||||
url_view_kwargs: dict = None
|
||||
|
||||
url_name = None
|
||||
model = Entity
|
||||
|
||||
|
||||
|
||||
@ -310,22 +230,28 @@ class EntityViewSetInheritedCases(
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
self.url_kwargs = {
|
||||
'entity_model': self.model._meta.model_name
|
||||
'entity_model': self.model._meta.sub_model_type
|
||||
}
|
||||
|
||||
self.url_view_kwargs = {
|
||||
'entity_model': self.model._meta.model_name
|
||||
'entity_model': self.model._meta.sub_model_type
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
@ -337,168 +263,4 @@ class EntityViewSetTest(
|
||||
TestCase,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
model = Entity
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
url_name = '_api_v2_entity'
|
||||
|
||||
|
||||
|
||||
class MetadataTestCases(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
url_kwargs: dict = None
|
||||
|
||||
url_view_kwargs: dict = None
|
||||
|
||||
url_name = None
|
||||
|
||||
|
||||
|
||||
class EntityMetadataInheritedCases(
|
||||
MetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.url_kwargs = {
|
||||
'entity_model': self.model._meta.model_name
|
||||
}
|
||||
|
||||
self.url_view_kwargs = {
|
||||
'entity_model': self.model._meta.model_name
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class EntityMetadataTest(
|
||||
MetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
model = Entity
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
url_name = '_api_v2_entity'
|
||||
|
||||
|
||||
# def test_method_options_request_detail_data_has_key_urls_back(self):
|
||||
# """Test HTTP/Options Method
|
||||
|
||||
# Ensure the request data returned has key `urls.back`
|
||||
# """
|
||||
|
||||
# client = Client()
|
||||
# client.force_login(self.view_user)
|
||||
|
||||
# response = client.options(
|
||||
# reverse(
|
||||
# self.app_namespace + ':' + self.url_name + '-detail',
|
||||
# kwargs=self.url_view_kwargs
|
||||
# ),
|
||||
# content_type='application/json'
|
||||
# )
|
||||
|
||||
# assert 'back' in response.data['urls']
|
||||
|
||||
|
||||
# def test_method_options_request_detail_data_key_urls_back_is_str(self):
|
||||
# """Test HTTP/Options Method
|
||||
|
||||
# Ensure the request data key `urls.back` is str
|
||||
# """
|
||||
|
||||
# client = Client()
|
||||
# client.force_login(self.view_user)
|
||||
|
||||
# response = client.options(
|
||||
# reverse(
|
||||
# self.app_namespace + ':' + self.url_name + '-detail',
|
||||
# kwargs=self.url_view_kwargs
|
||||
# ),
|
||||
# content_type='application/json'
|
||||
# )
|
||||
|
||||
# assert type(response.data['urls']['back']) is str
|
||||
|
||||
|
||||
|
||||
# def test_method_options_request_list_data_has_key_urls_return_url(self):
|
||||
# """Test HTTP/Options Method
|
||||
|
||||
# Ensure the request data returned has key `urls.return_url`
|
||||
# """
|
||||
|
||||
# client = Client()
|
||||
# client.force_login(self.view_user)
|
||||
|
||||
# if self.url_kwargs:
|
||||
|
||||
# url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
# else:
|
||||
|
||||
# url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
# response = client.options( url, content_type='application/json' )
|
||||
|
||||
# assert 'return_url' in response.data['urls']
|
||||
|
||||
|
||||
# def test_method_options_request_list_data_key_urls_return_url_is_str(self):
|
||||
# """Test HTTP/Options Method
|
||||
|
||||
# Ensure the request data key `urls.return_url` is str
|
||||
# """
|
||||
|
||||
# client = Client()
|
||||
# client.force_login(self.view_user)
|
||||
|
||||
# if self.url_kwargs:
|
||||
|
||||
# url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
# else:
|
||||
|
||||
# url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
# response = client.options( url, content_type='application/json' )
|
||||
|
||||
# assert type(response.data['urls']['return_url']) is str
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.organization_history import Organization, OrganizationHistory
|
||||
from access.models.organization_history import Tenant as Organization, OrganizationHistory
|
||||
|
||||
from core.tests.abstract.test_functional_history import HistoryEntriesCommon
|
||||
|
||||
|
@ -1,22 +1,24 @@
|
||||
import django
|
||||
import pytest
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.serializers.organization import (
|
||||
Organization,
|
||||
OrganizationModelSerializer
|
||||
Tenant,
|
||||
TenantModelSerializer
|
||||
)
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class OrganizationValidationAPI(
|
||||
TestCase,
|
||||
):
|
||||
|
||||
model = Organization
|
||||
model = Tenant
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
@ -45,7 +47,7 @@ class OrganizationValidationAPI(
|
||||
Ensure that if creating and no name is provided a validation error occurs
|
||||
"""
|
||||
|
||||
serializer = OrganizationModelSerializer(
|
||||
serializer = TenantModelSerializer(
|
||||
data = self.valid_data
|
||||
)
|
||||
|
||||
@ -65,7 +67,7 @@ class OrganizationValidationAPI(
|
||||
|
||||
with pytest.raises(ValidationError) as err:
|
||||
|
||||
serializer = OrganizationModelSerializer(
|
||||
serializer = TenantModelSerializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
@ -85,7 +87,7 @@ class OrganizationValidationAPI(
|
||||
|
||||
del data['manager']
|
||||
|
||||
serializer = OrganizationModelSerializer(
|
||||
serializer = TenantModelSerializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
@ -17,6 +18,8 @@ from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
@ -315,4 +318,4 @@ class OrganizationMetadata(
|
||||
|
||||
menu_id = 'access'
|
||||
|
||||
menu_entry_id = 'organization'
|
||||
menu_entry_id = 'tenant'
|
@ -3,7 +3,7 @@ from django.test import TestCase
|
||||
|
||||
from core.tests.abstract.model_notes_api_fields import ModelNotesNotesAPIFields
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.organization_notes import OrganizationNotes
|
||||
|
||||
|
||||
|
24
app/access/tests/functional/person/conftest.py
Normal file
24
app/access/tests/functional/person/conftest.py
Normal file
@ -0,0 +1,24 @@
|
||||
import pytest
|
||||
|
||||
from access.models.person import Person
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Person
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def create_serializer():
|
||||
|
||||
from access.serializers.entity_person import ModelSerializer
|
||||
|
||||
|
||||
yield ModelSerializer
|
@ -0,0 +1,83 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.person import Person
|
||||
from access.tests.functional.entity.test_functional_entity_metadata import (
|
||||
EntityMetadataInheritedCases
|
||||
)
|
||||
|
||||
from accounting.models.asset_base import AssetBase
|
||||
|
||||
|
||||
|
||||
class PersonMetadataTestCases(
|
||||
EntityMetadataInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Strange',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Weird',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
model = Person
|
||||
|
||||
|
||||
|
||||
|
||||
class PersonMetadataInheritedCases(
|
||||
PersonMetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {}
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
# self.url_kwargs = {
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# }
|
||||
|
||||
# self.url_view_kwargs = {
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# }
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class PersonMetadataTest(
|
||||
PersonMetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
pass
|
@ -0,0 +1,91 @@
|
||||
import pytest
|
||||
|
||||
from access.tests.functional.entity.test_functional_entity_permission import (
|
||||
EntityPermissionsAPIInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class PersonPermissionsAPITestCases(
|
||||
EntityPermissionsAPIInheritedCases,
|
||||
):
|
||||
|
||||
add_data: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Strange',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
# app_namespace = 'v2'
|
||||
|
||||
# change_data = {}
|
||||
|
||||
# delete_data = {}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Weird',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
# url_kwargs: dict = {}
|
||||
|
||||
# url_name = '_api_v2_entity'
|
||||
|
||||
# url_view_kwargs: dict = {}
|
||||
|
||||
|
||||
|
||||
class PersonPermissionsAPIInheritedCases(
|
||||
PersonPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
# url_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
# @pytest.fixture(scope='class')
|
||||
# def inherited_var_setup(self, request):
|
||||
|
||||
# request.cls.url_kwargs.update({
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# })
|
||||
|
||||
# request.cls.url_view_kwargs.update({
|
||||
# 'entity_model': self.model._meta.sub_model_type
|
||||
# })
|
||||
|
||||
|
||||
|
||||
# @pytest.fixture(scope='class', autouse = True)
|
||||
# def class_setup(self, request, django_db_blocker,
|
||||
# model,
|
||||
# var_setup,
|
||||
# prepare,
|
||||
# inherited_var_setup,
|
||||
# diff_org_model,
|
||||
# create_model,
|
||||
# ):
|
||||
|
||||
# pass
|
||||
|
||||
|
||||
class PersonPermissionsAPIPyTest(
|
||||
PersonPermissionsAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -1,161 +1,88 @@
|
||||
import pytest
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.serializers.person import (
|
||||
Person,
|
||||
ModelSerializer
|
||||
)
|
||||
from access.tests.functional.entity.test_functional_entity_serializer import (
|
||||
MockView,
|
||||
EntitySerializerInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class SerializerTestCases(
|
||||
EntitySerializerInheritedCases,
|
||||
class PersonSerializerTestCases(
|
||||
EntitySerializerInheritedCases
|
||||
):
|
||||
|
||||
create_model_serializer = ModelSerializer
|
||||
"""Serializer to test"""
|
||||
|
||||
duplicate_f_name_l_name_dob: dict = {
|
||||
'f_name': 'fred',
|
||||
'm_name': 'D',
|
||||
'l_name': 'Flinstone',
|
||||
'dob': '2025-04-08',
|
||||
parameterized_test_data: dict = {
|
||||
"model_notes": {
|
||||
'will_create': True,
|
||||
},
|
||||
"f_name": {
|
||||
'will_create': False,
|
||||
'exception_key': 'required'
|
||||
},
|
||||
"m_name": {
|
||||
'will_create': True,
|
||||
},
|
||||
"l_name": {
|
||||
'will_create': False,
|
||||
'exception_key': 'required'
|
||||
},
|
||||
"dob": {
|
||||
'will_create': True,
|
||||
}
|
||||
}
|
||||
|
||||
kwargs_create_item_duplicate_f_name_l_name_dob: dict = {
|
||||
'f_name': 'fred',
|
||||
'm_name': 'D',
|
||||
'l_name': 'Flinstone',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
valid_data: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
model = Person
|
||||
"""Model to test"""
|
||||
|
||||
valid_data: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Strange',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
|
||||
def test_serializer_validation_no_f_name_exception(self):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating with valid data and field f_name is missing
|
||||
a validation error occurs.
|
||||
"""
|
||||
|
||||
data = self.valid_data.copy()
|
||||
|
||||
del data['f_name']
|
||||
|
||||
with pytest.raises(ValidationError) as err:
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
serializer.is_valid(raise_exception = True)
|
||||
|
||||
assert err.value.get_codes()['f_name'][0] == 'required'
|
||||
|
||||
|
||||
|
||||
def test_serializer_validation_no_m_name(self):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating with valid data and field f_name is missing
|
||||
no validation error occurs.
|
||||
"""
|
||||
|
||||
data = self.valid_data.copy()
|
||||
|
||||
del data['m_name']
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
assert serializer.is_valid(raise_exception = True)
|
||||
|
||||
|
||||
|
||||
def test_serializer_validation_no_l_name_exception(self):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating with valid data and field l_name is missing
|
||||
a validation error occurs.
|
||||
"""
|
||||
|
||||
data = self.valid_data.copy()
|
||||
|
||||
del data['l_name']
|
||||
|
||||
with pytest.raises(ValidationError) as err:
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
serializer.is_valid(raise_exception = True)
|
||||
|
||||
assert err.value.get_codes()['l_name'][0] == 'required'
|
||||
|
||||
|
||||
|
||||
def test_serializer_validation_no_dob(self):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating with valid data and field dob is missing
|
||||
no validation error occurs.
|
||||
"""
|
||||
|
||||
data = self.valid_data.copy()
|
||||
|
||||
del data['dob']
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
)
|
||||
|
||||
assert serializer.is_valid(raise_exception = True)
|
||||
|
||||
|
||||
|
||||
def test_serializer_validation_duplicate_f_name_l_name_dob(self):
|
||||
def test_serializer_validation_duplicate_f_name_l_name_dob(self, model, create_serializer):
|
||||
"""Serializer Validation Check
|
||||
|
||||
Ensure that when creating with valid data and fields f_name, l_name and
|
||||
dob already exists in the db a validation error occurs.
|
||||
"""
|
||||
|
||||
self.model.objects.create(
|
||||
organization = self.organization,
|
||||
**self.kwargs_create_item_duplicate_f_name_l_name_dob
|
||||
valid_data = self.valid_data.copy()
|
||||
|
||||
valid_data['f_name'] = 'duplicate'
|
||||
|
||||
valid_data['organization'] = self.organization
|
||||
|
||||
obj = model.objects.create(
|
||||
**valid_data
|
||||
)
|
||||
|
||||
data = self.duplicate_f_name_l_name_dob.copy()
|
||||
valid_data['organization'] = self.organization.id
|
||||
|
||||
if 'email' in valid_data: # Contact Entity
|
||||
|
||||
valid_data['email'] = 'abc@xyz.qwe'
|
||||
|
||||
if 'name' in valid_data: # Company Entity
|
||||
|
||||
valid_data['name'] = 'diff'
|
||||
|
||||
if 'employee_number' in valid_data: # Employee Entity
|
||||
|
||||
valid_data['employee_number'] = 13579
|
||||
|
||||
view_set = MockView()
|
||||
|
||||
with pytest.raises(ValidationError) as err:
|
||||
|
||||
serializer = self.create_model_serializer(
|
||||
data = data
|
||||
serializer = create_serializer(
|
||||
context = {
|
||||
'view': view_set,
|
||||
},
|
||||
data = valid_data
|
||||
)
|
||||
|
||||
serializer.is_valid(raise_exception = True)
|
||||
@ -167,64 +94,18 @@ class SerializerTestCases(
|
||||
|
||||
|
||||
class PersonSerializerInheritedCases(
|
||||
SerializerTestCases,
|
||||
PersonSerializerTestCases,
|
||||
):
|
||||
|
||||
create_model_serializer = None
|
||||
"""Serializer to test"""
|
||||
|
||||
duplicate_f_name_l_name_dob: dict = None
|
||||
""" Duplicate model serializer dict
|
||||
|
||||
used for testing for duplicate f_name, l_name and dob fields.
|
||||
"""
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
""" Model kwargs to create item"""
|
||||
|
||||
kwargs_create_item_duplicate_f_name_l_name_dob: dict = None
|
||||
"""model kwargs to create object
|
||||
|
||||
**None:** Ensure that the fields of sub-model to person do not match
|
||||
`self.duplicate_f_name_l_name_dob`. if they do the wrong exception will be thrown.
|
||||
|
||||
used for testing for duplicate f_name, l_name and dob fields.
|
||||
"""
|
||||
|
||||
model = None
|
||||
"""Model to test"""
|
||||
parameterized_test_data: dict = None
|
||||
|
||||
valid_data: dict = None
|
||||
"""Valid data used by serializer to create object"""
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test"""
|
||||
|
||||
self.duplicate_f_name_l_name_dob.update(
|
||||
super().duplicate_f_name_l_name_dob
|
||||
)
|
||||
|
||||
self.kwargs_create_item_duplicate_f_name_l_name_dob.update(
|
||||
super().kwargs_create_item_duplicate_f_name_l_name_dob
|
||||
)
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
|
||||
self.valid_data.update(
|
||||
super().valid_data
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class PersonSerializerTest(
|
||||
SerializerTestCases,
|
||||
TestCase,
|
||||
class PersonSerializerPyTest(
|
||||
PersonSerializerTestCases,
|
||||
):
|
||||
|
||||
pass
|
||||
parameterized_test_data: dict = None
|
||||
|
@ -2,101 +2,38 @@ from django.test import TestCase
|
||||
|
||||
from access.models.person import Person
|
||||
from access.tests.functional.entity.test_functional_entity_viewset import (
|
||||
EntityMetadataInheritedCases,
|
||||
EntityPermissionsAPIInheritedCases,
|
||||
EntityViewSetInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
class ViewSetTestCases(
|
||||
EntityViewSetInheritedCases,
|
||||
):
|
||||
|
||||
add_data = {
|
||||
add_data: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Strange',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item = {
|
||||
kwargs_create_item: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Weird',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
kwargs_create_item_diff_org: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
model = Person
|
||||
|
||||
url_kwargs: dict = {}
|
||||
|
||||
url_view_kwargs: dict = {}
|
||||
|
||||
|
||||
|
||||
class PermissionsAPITestCases(
|
||||
ViewSetBase,
|
||||
EntityPermissionsAPIInheritedCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class PersonPermissionsAPIInheritedCases(
|
||||
PermissionsAPITestCases,
|
||||
):
|
||||
|
||||
add_data: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.add_data.update(
|
||||
super().add_data
|
||||
)
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
|
||||
self.kwargs_create_item_diff_org.update(
|
||||
super().kwargs_create_item_diff_org
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class PersonPermissionsAPITest(
|
||||
PermissionsAPITestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ViewSetTestCases(
|
||||
ViewSetBase,
|
||||
EntityViewSetInheritedCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class PersonViewSetInheritedCases(
|
||||
@ -105,21 +42,19 @@ class PersonViewSetInheritedCases(
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
self.kwargs_create_item = {
|
||||
**super().kwargs_create_item,
|
||||
**self.kwargs_create_item
|
||||
}
|
||||
|
||||
self.kwargs_create_item_diff_org.update(
|
||||
super().kwargs_create_item_diff_org
|
||||
)
|
||||
self.kwargs_create_item_diff_org = {
|
||||
**super().kwargs_create_item_diff_org,
|
||||
**self.kwargs_create_item_diff_org
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
@ -129,50 +64,4 @@ class PersonViewSetTest(
|
||||
ViewSetTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class MetadataTestCases(
|
||||
ViewSetBase,
|
||||
EntityMetadataInheritedCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class PersonMetadataInheritedCases(
|
||||
MetadataTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
kwargs_create_item_diff_org: dict = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_create_item.update(
|
||||
super().kwargs_create_item
|
||||
)
|
||||
|
||||
self.kwargs_create_item_diff_org.update(
|
||||
super().kwargs_create_item_diff_org
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class PersonMetadataTest(
|
||||
MetadataTestCases,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -5,7 +5,7 @@ from django.test import TestCase
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.serializers.role import Role, ModelSerializer
|
||||
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
from django.contrib.auth.models import Permission, User
|
||||
import django
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.models.role import Role
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
@ -15,6 +16,8 @@ from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
from settings.models.app_settings import AppSettings
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
|
@ -1,16 +1,17 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
@ -19,6 +20,8 @@ from api.tests.abstract.test_metadata_functional import MetadataAttributesFuncti
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
|
@ -1,6 +1,7 @@
|
||||
import django
|
||||
import pytest
|
||||
|
||||
from django.contrib.auth.models import Permission, User
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
@ -8,7 +9,7 @@ from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.middleware.request import Tenancy
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
|
||||
from access.serializers.teams import (
|
||||
Team,
|
||||
@ -17,6 +18,8 @@ from access.serializers.teams import (
|
||||
|
||||
from settings.models.app_settings import AppSettings
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class MockView:
|
||||
|
@ -1,16 +1,17 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
@ -18,6 +19,8 @@ from api.tests.abstract.test_metadata_functional import MetadataAttributesFuncti
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class ViewSetBase:
|
||||
|
@ -1,12 +1,13 @@
|
||||
import django
|
||||
import pytest
|
||||
|
||||
from django.contrib.auth.models import Permission, User
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
|
||||
from access.serializers.team_user import (
|
||||
@ -14,6 +15,8 @@ from access.serializers.team_user import (
|
||||
TeamUserModelSerializer
|
||||
)
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class MockView:
|
||||
|
14
app/access/tests/unit/company/conftest.py
Normal file
14
app/access/tests/unit/company/conftest.py
Normal file
@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
from access.models.company_base import Company
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Company
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
@ -0,0 +1,37 @@
|
||||
from access.tests.unit.entity.test_unit_entity_api_fields import (
|
||||
EntityAPIInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CompanyAPITestCases(
|
||||
EntityAPIInheritedCases,
|
||||
):
|
||||
|
||||
parameterized_test_data = {
|
||||
'name': {
|
||||
'expected': str
|
||||
}
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'name': 'Ian'
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CompanyAPIInheritedCases(
|
||||
CompanyAPITestCases,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class CompanyAPIPyTest(
|
||||
CompanyAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
105
app/access/tests/unit/company/test_unit_company_model.py
Normal file
105
app/access/tests/unit/company/test_unit_company_model.py
Normal file
@ -0,0 +1,105 @@
|
||||
import pytest
|
||||
|
||||
from django.db import models
|
||||
|
||||
from access.models.company_base import Company
|
||||
|
||||
from access.tests.unit.entity.test_unit_entity_model import (
|
||||
EntityModelInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CompanyModelTestCases(
|
||||
EntityModelInheritedCases,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'name': 'Ian',
|
||||
}
|
||||
|
||||
sub_model_type = 'company'
|
||||
"""Sub Model Type
|
||||
|
||||
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
|
||||
parameterized_fields: dict = {
|
||||
"name": {
|
||||
'field_type': models.fields.CharField,
|
||||
'field_parameter_default_exists': False,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
def test_class_inherits_company(self):
|
||||
""" Class inheritence
|
||||
|
||||
TenancyObject must inherit SaveHistory
|
||||
"""
|
||||
|
||||
assert issubclass(self.model, Company)
|
||||
|
||||
|
||||
def test_attribute_value_history_app_label(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_app_label has been set, override this test case with the value
|
||||
of attribute `history_app_label`
|
||||
"""
|
||||
|
||||
assert self.model.history_app_label == 'access'
|
||||
|
||||
|
||||
def test_attribute_value_history_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_model_name has been set, override this test case with the value
|
||||
of attribute `history_model_name`
|
||||
"""
|
||||
|
||||
assert self.model.history_model_name == 'company'
|
||||
|
||||
|
||||
|
||||
def test_function_value_get_url(self):
|
||||
|
||||
assert self.item.get_url() == '/api/v2/access/entity/company/' + str(self.item.id)
|
||||
|
||||
|
||||
|
||||
class CompanyModelInheritedCases(
|
||||
CompanyModelTestCases,
|
||||
):
|
||||
"""Sub-Ticket Test Cases
|
||||
|
||||
Test Cases for Ticket models that inherit from model Entity
|
||||
"""
|
||||
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
model = None
|
||||
|
||||
sub_model_type = None
|
||||
"""Ticket Sub Model Type
|
||||
|
||||
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class CompanyModelPyTest(
|
||||
CompanyModelTestCases,
|
||||
):
|
||||
|
||||
|
||||
def test_function_value_get_related_model(self):
|
||||
"""Function test
|
||||
|
||||
Confirm function `get_related_model` is None for base model
|
||||
"""
|
||||
|
||||
assert self.item.get_related_model() is None
|
36
app/access/tests/unit/company/test_unit_company_viewset.py
Normal file
36
app/access/tests/unit/company/test_unit_company_viewset.py
Normal file
@ -0,0 +1,36 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.company_base import Company
|
||||
from access.tests.unit.entity.test_unit_entity_viewset import (
|
||||
EntityViewsetInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ViewsetTestCases(
|
||||
EntityViewsetInheritedCases,
|
||||
):
|
||||
|
||||
model: str = Company
|
||||
|
||||
|
||||
|
||||
class CompanyViewsetInheritedCases(
|
||||
ViewsetTestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Company
|
||||
"""
|
||||
|
||||
model: str = None
|
||||
"""name of the model to test"""
|
||||
|
||||
|
||||
|
||||
class CompanyViewsetTest(
|
||||
ViewsetTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
14
app/access/tests/unit/contact/conftest.py
Normal file
14
app/access/tests/unit/contact/conftest.py
Normal file
@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
from access.models.contact import Contact
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Contact
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
@ -1,32 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.contact import Contact
|
||||
from access.tests.unit.person.test_unit_person_access_tenancy_object import (
|
||||
PersonTenancyObjectInheritedCases,
|
||||
)
|
||||
|
||||
class TenancyObjectTestCases(
|
||||
PersonTenancyObjectInheritedCases,
|
||||
):
|
||||
|
||||
model = Contact
|
||||
|
||||
|
||||
class ContactTenancyObjectInheritedCases(
|
||||
TenancyObjectTestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Contact
|
||||
"""
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class ContactTenancyObjectTest(
|
||||
TenancyObjectTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
@ -0,0 +1,40 @@
|
||||
from access.tests.unit.person.test_unit_person_api_fields import (
|
||||
PersonAPIInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ContactAPITestCases(
|
||||
PersonAPIInheritedCases,
|
||||
):
|
||||
|
||||
parameterized_test_data = {
|
||||
'email': {
|
||||
'expected': str
|
||||
},
|
||||
'directory': {
|
||||
'expected': bool
|
||||
}
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ContactAPIInheritedCases(
|
||||
ContactAPITestCases,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class ContactAPIPyTest(
|
||||
ContactAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -1,90 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.contact import Contact
|
||||
|
||||
from access.tests.unit.person.test_unit_person_api_v2 import (
|
||||
PersonAPIInheritedCases,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class APITestCases(
|
||||
PersonAPIInheritedCases,
|
||||
):
|
||||
|
||||
model = Contact
|
||||
|
||||
kwargs_item_create: dict = {
|
||||
'email': 'ipfunny@unit.test',
|
||||
}
|
||||
|
||||
url_ns_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
def test_api_field_exists_email(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
email field must exist
|
||||
"""
|
||||
|
||||
assert 'email' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_email(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
email field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['email']) is str
|
||||
|
||||
|
||||
def test_api_field_exists_directory(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
directory field must exist
|
||||
"""
|
||||
|
||||
assert 'directory' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_directory(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
directory field must be bool
|
||||
"""
|
||||
|
||||
assert type(self.api_data['directory']) is bool
|
||||
|
||||
|
||||
|
||||
class ContactAPIInheritedCases(
|
||||
APITestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Contact
|
||||
"""
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_item_create.update(
|
||||
super().kwargs_item_create
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
class ContactAPITest(
|
||||
APITestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
@ -1,100 +1,110 @@
|
||||
from django.db.models.fields import NOT_PROVIDED
|
||||
from django.test import TestCase
|
||||
import pytest
|
||||
|
||||
from django.db import models
|
||||
|
||||
from access.models.contact import Contact
|
||||
from access.tests.unit.person.test_unit_person_model import (
|
||||
Person,
|
||||
PersonModelInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ModelTestCases(
|
||||
class ContactModelTestCases(
|
||||
PersonModelInheritedCases,
|
||||
):
|
||||
|
||||
model = Contact
|
||||
|
||||
kwargs_item_create: dict = {
|
||||
kwargs_create_item: dict = {
|
||||
'email': 'ipweird@unit.test',
|
||||
}
|
||||
|
||||
sub_model_type = 'contact'
|
||||
"""Sub Model Type
|
||||
|
||||
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
|
||||
parameterized_fields: dict = {
|
||||
"email": {
|
||||
'field_type': models.fields.CharField,
|
||||
'field_parameter_default_exists': False,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
},
|
||||
"directory": {
|
||||
'field_type': models.fields.BooleanField,
|
||||
'field_parameter_default_exists': True,
|
||||
'field_parameter_default_value': True,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
def test_model_field_directory_optional(self):
|
||||
"""Test Field
|
||||
def test_class_inherits_contact(self):
|
||||
""" Class inheritence
|
||||
|
||||
Field `dob` must be an optional field
|
||||
TenancyObject must inherit SaveHistory
|
||||
"""
|
||||
|
||||
assert self.model._meta.get_field('directory').blank
|
||||
assert issubclass(self.model, Contact)
|
||||
|
||||
|
||||
def test_model_field_directory_optional_default(self):
|
||||
"""Test Field
|
||||
# def test_attribute_value_history_app_label(self):
|
||||
# """Attribute Type
|
||||
|
||||
Field `directory` default value is `True`
|
||||
# history_app_label has been set, override this test case with the value
|
||||
# of attribute `history_app_label`
|
||||
# """
|
||||
|
||||
# assert self.model.history_app_label == 'access'
|
||||
|
||||
|
||||
def test_attribute_value_history_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_model_name has been set, override this test case with the value
|
||||
of attribute `history_model_name`
|
||||
"""
|
||||
|
||||
assert (
|
||||
self.model._meta.get_field('directory').default is True
|
||||
and self.model._meta.get_field('directory').null is False
|
||||
)
|
||||
assert self.model.history_model_name == 'contact'
|
||||
|
||||
|
||||
def test_model_field_email_mandatory(self):
|
||||
"""Test Field
|
||||
|
||||
Field `email` must be a mandatory field
|
||||
"""
|
||||
|
||||
assert(
|
||||
not (
|
||||
self.model._meta.get_field('email').blank
|
||||
and self.model._meta.get_field('email').null
|
||||
)
|
||||
and self.model._meta.get_field('email').default is NOT_PROVIDED
|
||||
)
|
||||
|
||||
|
||||
def test_model_inherits_person(self):
|
||||
"""Test model inheritence
|
||||
|
||||
model must inherit from Entity sub-model `Person`
|
||||
"""
|
||||
|
||||
assert issubclass(self.model, Person)
|
||||
def test_function_value_get_url(self):
|
||||
|
||||
assert self.item.get_url() == '/api/v2/access/entity/contact/' + str(self.item.id)
|
||||
|
||||
|
||||
|
||||
class ContactModelInheritedCases(
|
||||
ModelTestCases,
|
||||
ContactModelTestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
"""Sub-Ticket Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Contact
|
||||
Test Cases for Ticket models that inherit from model Entity
|
||||
"""
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_item_create.update(
|
||||
super().kwargs_item_create
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
sub_model_type = None
|
||||
"""Ticket Sub Model Type
|
||||
|
||||
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class ContactModelTest(
|
||||
ModelTestCases,
|
||||
TestCase,
|
||||
class ContactModelPyTest(
|
||||
ContactModelTestCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
def test_function_value_get_related_model(self):
|
||||
"""Function test
|
||||
|
||||
Confirm function `get_related_model` is None for base model
|
||||
"""
|
||||
|
||||
assert self.item.get_related_model() is None
|
||||
|
@ -1,14 +1,14 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.contact import Contact
|
||||
from access.tests.unit.entity.test_unit_entity_viewset import (
|
||||
EntityViewsetInheritedCases
|
||||
from access.tests.unit.person.test_unit_person_viewset import (
|
||||
PersonViewsetInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ViewsetTestCases(
|
||||
EntityViewsetInheritedCases,
|
||||
PersonViewsetInheritedCases,
|
||||
):
|
||||
|
||||
model: str = Contact
|
||||
|
14
app/access/tests/unit/entity/conftest.py
Normal file
14
app/access/tests/unit/entity/conftest.py
Normal file
@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
from access.models.entity import Entity
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Entity
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
@ -1,29 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.entity import Entity
|
||||
from access.tests.abstract.tenancy_object import TenancyObject
|
||||
|
||||
|
||||
|
||||
class TenancyObjectTestCases(
|
||||
TenancyObject,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class EntityTenancyObjectInheritedCases(
|
||||
TenancyObjectTestCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class EntityTenancyObjectTest(
|
||||
TenancyObjectTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
model = Entity
|
78
app/access/tests/unit/entity/test_unit_entity_api_fields.py
Normal file
78
app/access/tests/unit/entity/test_unit_entity_api_fields.py
Normal file
@ -0,0 +1,78 @@
|
||||
import pytest
|
||||
|
||||
from access.models.entity import Entity
|
||||
|
||||
from api.tests.unit.test_unit_api_fields import (
|
||||
APIFieldsInheritedCases,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class EntityAPITestCases(
|
||||
APIFieldsInheritedCases,
|
||||
):
|
||||
|
||||
base_model = Entity
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def setup_model(self, request,
|
||||
model,
|
||||
):
|
||||
|
||||
if model != self.base_model:
|
||||
|
||||
request.cls.url_view_kwargs.update({
|
||||
'entity_model': model._meta.sub_model_type,
|
||||
})
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class', autouse = True)
|
||||
def class_setup(self,
|
||||
setup_pre,
|
||||
setup_model,
|
||||
create_model,
|
||||
setup_post,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
parameterized_test_data = {
|
||||
'entity_type': {
|
||||
'expected': str
|
||||
},
|
||||
'_urls.history': {
|
||||
'expected': str
|
||||
},
|
||||
'_urls.knowledge_base': {
|
||||
'expected': str
|
||||
}
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'entity_type': 'entity',
|
||||
}
|
||||
|
||||
url_ns_name = '_api_v2_entity'
|
||||
"""Url namespace (optional, if not required) and url name"""
|
||||
|
||||
|
||||
|
||||
class EntityAPIInheritedCases(
|
||||
EntityAPITestCases,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
url_ns_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
|
||||
class EntityAPIPyTest(
|
||||
EntityAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -1,215 +0,0 @@
|
||||
from django.contrib.auth.models import Permission, User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
|
||||
# from rest_framework.relations import Hyperlink
|
||||
|
||||
from access.models.entity import Entity
|
||||
from access.models.organization import Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from api.tests.abstract.api_fields import APITenancyObject
|
||||
|
||||
|
||||
|
||||
class APITestCases(
|
||||
APITenancyObject,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
|
||||
url_ns_name = None
|
||||
"""Url namespace (optional, if not required) and url name"""
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
2. Create an item
|
||||
|
||||
"""
|
||||
|
||||
self.organization = Organization.objects.create(name='test_org')
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = self.organization,
|
||||
model_notes = 'random notes',
|
||||
**self.kwargs_item_create
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs = {
|
||||
'pk': self.item.id
|
||||
}
|
||||
|
||||
if self.model._meta.model_name != 'entity':
|
||||
|
||||
self.url_view_kwargs.update({
|
||||
'entity_model': self.item.entity_type,
|
||||
})
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = self.organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
client = Client()
|
||||
url = reverse('v2:' + self.url_ns_name + '-detail', kwargs=self.url_view_kwargs)
|
||||
|
||||
|
||||
client.force_login(self.view_user)
|
||||
response = client.get(url)
|
||||
|
||||
self.api_data = response.data
|
||||
|
||||
|
||||
|
||||
def test_api_field_exists_entity_type(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
entity_type field must exist
|
||||
"""
|
||||
|
||||
assert 'entity_type' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_entity_type(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
entity_type field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['entity_type']) is str
|
||||
|
||||
|
||||
|
||||
def test_api_field_exists_url_history(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
_urls.history field must exist
|
||||
"""
|
||||
|
||||
assert 'history' in self.api_data['_urls']
|
||||
|
||||
|
||||
def test_api_field_type_url_history(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
_urls.history field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['_urls']['history']) is str
|
||||
|
||||
|
||||
def test_api_field_type_url_history_value(self):
|
||||
""" Test for url value
|
||||
|
||||
_urls.history field must use the endpoint for entity model
|
||||
"""
|
||||
|
||||
assert str(self.api_data['_urls']['history']).endswith('/access/entity/' + str(self.item.pk) + '/history')
|
||||
|
||||
|
||||
|
||||
def test_api_field_exists_url_knowledge_base(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
_urls.knowledge_base field must exist
|
||||
"""
|
||||
|
||||
assert 'knowledge_base' in self.api_data['_urls']
|
||||
|
||||
|
||||
def test_api_field_type_url_knowledge_base(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
_urls.knowledge_base field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['_urls']['knowledge_base']) is str
|
||||
|
||||
|
||||
def test_api_field_type_url_knowledge_base_value(self):
|
||||
""" Test for url value
|
||||
|
||||
_urls.knowledge_base field must use the endpoint for entity model
|
||||
"""
|
||||
|
||||
assert str(self.api_data['_urls']['knowledge_base']).endswith('/assistance/entity/' + str(self.item.pk) + '/knowledge_base')
|
||||
|
||||
|
||||
|
||||
class EntityAPIInheritedCases(
|
||||
APITestCases,
|
||||
):
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
url_ns_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_item_create.update({
|
||||
'entity_type': self.model._meta.model_name
|
||||
})
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
def test_api_field_exists_entity_value(self):
|
||||
""" Test for value of API Field
|
||||
|
||||
entity_type field must match model name
|
||||
"""
|
||||
|
||||
assert self.api_data['entity_type'] == self.model._meta.model_name
|
||||
|
||||
|
||||
|
||||
class EntityAPITest(
|
||||
APITestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
|
||||
model = Entity
|
||||
|
||||
url_ns_name = '_api_v2_entity'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_item_create = {
|
||||
'entity_type': 'entity'
|
||||
}
|
||||
|
||||
super().setUpTestData()
|
@ -1,64 +1,274 @@
|
||||
from django.test import TestCase
|
||||
import pytest
|
||||
|
||||
from django.db import models
|
||||
|
||||
from access.models.entity import Entity
|
||||
from access.models.organization import Organization
|
||||
|
||||
from app.tests.abstract.models import TenancyModel
|
||||
from app.tests.unit.test_unit_models import (
|
||||
PyTestTenancyObjectInheritedCases,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ModelTestCases(
|
||||
TenancyModel,
|
||||
class EntityModelTestCases(
|
||||
PyTestTenancyObjectInheritedCases,
|
||||
):
|
||||
|
||||
model = Entity
|
||||
base_model = Entity
|
||||
|
||||
kwargs_item_create: dict = {}
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test"""
|
||||
sub_model_type = 'entity'
|
||||
"""Sub Model Type
|
||||
|
||||
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
self.organization = Organization.objects.create(name='test_org')
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
parameterized_fields: dict = {
|
||||
"entity_type": {
|
||||
'field_type': models.fields.CharField,
|
||||
'field_parameter_default_exists': False,
|
||||
# 'field_parameter_default_value': 'entity',
|
||||
'field_parameter_verbose_name_type': str
|
||||
},
|
||||
# "asset_number": {
|
||||
# 'field_type': models.fields.CharField,
|
||||
# 'field_parameter_default_exists': False,
|
||||
# 'field_parameter_verbose_name_type': str,
|
||||
# },
|
||||
# "serial_number": {
|
||||
# 'field_type': models.fields.CharField,
|
||||
# 'field_parameter_default_exists': False,
|
||||
# 'field_parameter_verbose_name_type': str,
|
||||
# }
|
||||
}
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = self.organization,
|
||||
model_notes = 'notes',
|
||||
entity_type = self.model._meta.model_name,
|
||||
**self.kwargs_item_create,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def setup_model(self,
|
||||
request,
|
||||
model,
|
||||
django_db_blocker,
|
||||
organization_one,
|
||||
organization_two
|
||||
):
|
||||
|
||||
with django_db_blocker.unblock():
|
||||
|
||||
request.cls.organization = organization_one
|
||||
|
||||
request.cls.different_organization = organization_two
|
||||
|
||||
kwargs_create_item = {}
|
||||
|
||||
for base in reversed(request.cls.__mro__):
|
||||
|
||||
if hasattr(base, 'kwargs_create_item'):
|
||||
|
||||
if base.kwargs_create_item is None:
|
||||
|
||||
continue
|
||||
|
||||
kwargs_create_item.update(**base.kwargs_create_item)
|
||||
|
||||
|
||||
if len(kwargs_create_item) > 0:
|
||||
|
||||
request.cls.kwargs_create_item = kwargs_create_item
|
||||
|
||||
|
||||
if 'organization' not in request.cls.kwargs_create_item:
|
||||
|
||||
request.cls.kwargs_create_item.update({
|
||||
'organization': request.cls.organization
|
||||
})
|
||||
|
||||
yield
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class', autouse = True)
|
||||
def class_setup(self,
|
||||
setup_model,
|
||||
create_model,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def test_class_inherits_entity(self):
|
||||
""" Class inheritence
|
||||
|
||||
TenancyObject must inherit SaveHistory
|
||||
"""
|
||||
|
||||
assert issubclass(self.model, Entity)
|
||||
|
||||
|
||||
def test_attribute_type_history_app_label(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_app_label is of type str
|
||||
"""
|
||||
|
||||
assert type(self.model.history_app_label) is str
|
||||
|
||||
|
||||
def test_attribute_value_history_app_label(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_app_label has been set, override this test case with the value
|
||||
of attribute `history_app_label`
|
||||
"""
|
||||
|
||||
assert self.model.history_app_label == 'access'
|
||||
|
||||
|
||||
|
||||
def test_attribute_type_history_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_model_name is of type str
|
||||
"""
|
||||
|
||||
assert type(self.model.history_model_name) is str
|
||||
|
||||
|
||||
def test_attribute_value_history_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
history_model_name has been set, override this test case with the value
|
||||
of attribute `history_model_name`
|
||||
"""
|
||||
|
||||
assert self.model.history_model_name == 'entity'
|
||||
|
||||
|
||||
|
||||
def test_attribute_type_kb_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
kb_model_name is of type str
|
||||
"""
|
||||
|
||||
assert type(self.model.kb_model_name) is str
|
||||
|
||||
|
||||
def test_attribute_value_kb_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
kb_model_name has been set, override this test case with the value
|
||||
of attribute `kb_model_name`
|
||||
"""
|
||||
|
||||
assert self.model.kb_model_name == 'entity'
|
||||
|
||||
|
||||
|
||||
def test_attribute_type_note_basename(self):
|
||||
"""Attribute Type
|
||||
|
||||
note_basename is of type str
|
||||
"""
|
||||
|
||||
assert type(self.model.note_basename) is str
|
||||
|
||||
|
||||
def test_attribute_value_note_basename(self):
|
||||
"""Attribute Type
|
||||
|
||||
note_basename has been set, override this test case with the value
|
||||
of attribute `note_basename`
|
||||
"""
|
||||
|
||||
assert self.model.note_basename == '_api_v2_entity_note'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def test_function_is_property_get_model_type(self):
|
||||
# """Function test
|
||||
|
||||
# Confirm function `get_model_type` is a property
|
||||
# """
|
||||
|
||||
# assert type(self.model.get_model_type) is property
|
||||
|
||||
|
||||
# def test_function_value_get_model_type(self):
|
||||
# """Function test
|
||||
|
||||
# Confirm function `get_model_type` does not have a value of None
|
||||
# value should be equaul to Meta.sub_model_type
|
||||
# """
|
||||
|
||||
# assert self.item.get_model_type == self.item._meta.sub_model_type
|
||||
|
||||
|
||||
|
||||
|
||||
def test_function_value_get_related_model(self):
|
||||
"""Function test
|
||||
|
||||
Confirm function `get_related_model` is of the sub-model type
|
||||
"""
|
||||
|
||||
assert type(self.item.get_related_model()) == self.model
|
||||
|
||||
|
||||
def test_function_value_get_url(self):
|
||||
|
||||
assert self.item.get_url() == '/api/v2/access/entity/' + str(self.item.id)
|
||||
|
||||
|
||||
|
||||
class EntityModelInheritedCases(
|
||||
ModelTestCases,
|
||||
EntityModelTestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
"""Sub-Ticket Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Entity
|
||||
Test Cases for Ticket models that inherit from model Entity
|
||||
"""
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
sub_model_type = None
|
||||
"""Ticket Sub Model Type
|
||||
|
||||
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
self.kwargs_item_create.update(
|
||||
super().kwargs_item_create
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
# def test_function_value_get_model_type(self):
|
||||
# """Function test
|
||||
|
||||
# Confirm function `get_model_type` does not have a value of None
|
||||
# value should be equaul to Meta.sub_model_type
|
||||
# """
|
||||
|
||||
# assert self.item.get_model_type == self.item._meta.sub_model_type
|
||||
|
||||
|
||||
|
||||
class EntityModelTest(
|
||||
ModelTestCases,
|
||||
TestCase,
|
||||
class EntityModelPyTest(
|
||||
EntityModelTestCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
def test_function_value_get_related_model(self):
|
||||
"""Function test
|
||||
|
||||
Confirm function `get_related_model` is None for base model
|
||||
"""
|
||||
|
||||
assert self.item.get_related_model() is None
|
||||
|
@ -1,7 +1,9 @@
|
||||
import django
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from django.contrib.auth.models import User, Permission, AnonymousUser
|
||||
from django.contrib.auth.models import Permission, AnonymousUser
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
@ -13,7 +15,7 @@ from api.viewsets.common import ModelViewSet
|
||||
|
||||
from access.mixins.organization import OrganizationMixin
|
||||
from access.mixins.permissions import OrganizationPermissionMixin
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
@ -23,6 +25,8 @@ from core.models.manufacturer import Manufacturer
|
||||
|
||||
from settings.models.app_settings import AppSettings
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class MyMockView(
|
||||
|
@ -1,18 +1,21 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.relations import Hyperlink
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,21 +1,24 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.relations import Hyperlink
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
|
||||
from api.tests.abstract.api_fields import APICommonFields
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
class OrganizationAPI(
|
||||
TestCase,
|
||||
|
@ -1,6 +1,7 @@
|
||||
# from django.conf import settings
|
||||
import django
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase, Client
|
||||
@ -9,15 +10,17 @@ import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
from access.tests.abstract.model_permissions_organization_manager import OrganizationManagerModelPermissionChange, OrganizationManagerModelPermissionView
|
||||
|
||||
from app.tests.abstract.model_permissions import ModelPermissionsView, ModelPermissionsChange
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
class OrganizationPermissions(
|
||||
|
||||
class TenantPermissions(
|
||||
TestCase,
|
||||
ModelPermissionsView,
|
||||
ModelPermissionsChange,
|
||||
@ -25,7 +28,7 @@ class OrganizationPermissions(
|
||||
OrganizationManagerModelPermissionView,
|
||||
):
|
||||
|
||||
model = Organization
|
||||
model = Tenant
|
||||
|
||||
app_namespace = 'Access'
|
||||
|
||||
@ -50,11 +53,11 @@ class OrganizationPermissions(
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
organization = Tenant.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(
|
||||
different_organization = Tenant.objects.create(
|
||||
name='test_different_organization'
|
||||
)
|
||||
|
||||
|
@ -1,18 +1,21 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission, User
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from api.tests.abstract.api_permissions import APIPermissionChange, APIPermissionView
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class OrganizationPermissionsAPI(TestCase, APIPermissionChange, APIPermissionView):
|
||||
|
@ -7,7 +7,7 @@ import unittest
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ from django.test import TestCase
|
||||
|
||||
from core.tests.abstract.test_unit_model_history_api_v2 import PrimaryModelHistoryAPI
|
||||
|
||||
from access.models.organization_history import Organization, OrganizationHistory
|
||||
from access.models.organization_history import Tenant as Organization, OrganizationHistory
|
||||
|
||||
|
||||
|
||||
|
@ -1,36 +1,17 @@
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
# from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
from core.tests.abstract.test_unit_model_notes_model import ModelNotesModel
|
||||
from core.tests.unit.model_notes.test_unit_model_notes_model import (
|
||||
ModelNotesInheritedCases
|
||||
)
|
||||
|
||||
from access.models.organization_notes import OrganizationNotes
|
||||
|
||||
|
||||
|
||||
class OrganizationNotesModel(
|
||||
ModelNotesModel,
|
||||
ModelNotesInheritedCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
model = OrganizationNotes
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test"""
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = self.organization,
|
||||
content = 'a random comment for an exiting item',
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = str(self.model._meta.app_label).lower(),
|
||||
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
|
||||
),
|
||||
model = self.model.model.field.related_model.objects.create(
|
||||
name = 'note model existing item',
|
||||
),
|
||||
created_by = self.user,
|
||||
)
|
||||
|
14
app/access/tests/unit/person/conftest.py
Normal file
14
app/access/tests/unit/person/conftest.py
Normal file
@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
from access.models.person import Person
|
||||
|
||||
|
||||
|
||||
@pytest.fixture( scope = 'class')
|
||||
def model(request):
|
||||
|
||||
request.cls.model = Person
|
||||
|
||||
yield request.cls.model
|
||||
|
||||
del request.cls.model
|
@ -1,32 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.person import Person
|
||||
from access.tests.unit.entity.test_unit_entity_access_tenancy_object import (
|
||||
EntityTenancyObjectInheritedCases,
|
||||
)
|
||||
|
||||
class TenancyObjectTestCases(
|
||||
EntityTenancyObjectInheritedCases,
|
||||
):
|
||||
|
||||
model = Person
|
||||
|
||||
|
||||
class PersonTenancyObjectInheritedCases(
|
||||
TenancyObjectTestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Person
|
||||
"""
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class PersonTenancyObjectTest(
|
||||
TenancyObjectTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
50
app/access/tests/unit/person/test_unit_person_api_fields.py
Normal file
50
app/access/tests/unit/person/test_unit_person_api_fields.py
Normal file
@ -0,0 +1,50 @@
|
||||
from access.tests.unit.entity.test_unit_entity_api_fields import (
|
||||
EntityAPIInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class PersonAPITestCases(
|
||||
EntityAPIInheritedCases,
|
||||
):
|
||||
|
||||
parameterized_test_data = {
|
||||
'f_name': {
|
||||
'expected': str
|
||||
},
|
||||
'm_name': {
|
||||
'expected': str
|
||||
},
|
||||
'l_name': {
|
||||
'expected': str
|
||||
},
|
||||
'dob': {
|
||||
'expected': str
|
||||
}
|
||||
}
|
||||
|
||||
kwargs_create_item: dict = {
|
||||
'entity_type': 'person',
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
|
||||
|
||||
class PersonAPIInheritedCases(
|
||||
PersonAPITestCases,
|
||||
):
|
||||
|
||||
kwargs_create_item: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class PersonAPIPyTest(
|
||||
PersonAPITestCases,
|
||||
):
|
||||
|
||||
pass
|
@ -1,127 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.person import Person
|
||||
|
||||
from access.tests.unit.entity.test_unit_entity_api_v2 import (
|
||||
EntityAPIInheritedCases,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class APITestCases(
|
||||
EntityAPIInheritedCases,
|
||||
):
|
||||
|
||||
model = Person
|
||||
|
||||
kwargs_item_create: dict = {}
|
||||
|
||||
url_ns_name = '_api_v2_entity_sub'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_item_create.update({
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
})
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
|
||||
|
||||
def test_api_field_exists_f_name(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
f_name field must exist
|
||||
"""
|
||||
|
||||
assert 'f_name' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_f_name(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
f_name field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['f_name']) is str
|
||||
|
||||
|
||||
def test_api_field_exists_m_name(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
m_name field must exist
|
||||
"""
|
||||
|
||||
assert 'm_name' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_f_name(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
m_name field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['m_name']) is str
|
||||
|
||||
|
||||
def test_api_field_exists_l_name(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
l_name field must exist
|
||||
"""
|
||||
|
||||
assert 'l_name' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_f_name(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
l_name field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['l_name']) is str
|
||||
|
||||
|
||||
def test_api_field_exists_dob(self):
|
||||
""" Test for existance of API Field
|
||||
|
||||
dob field must exist
|
||||
"""
|
||||
|
||||
assert 'dob' in self.api_data
|
||||
|
||||
|
||||
def test_api_field_type_dob(self):
|
||||
""" Test for type for API Field
|
||||
|
||||
dob field must be str
|
||||
"""
|
||||
|
||||
assert type(self.api_data['dob']) is str
|
||||
|
||||
|
||||
|
||||
class PersonAPIInheritedCases(
|
||||
APITestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Person
|
||||
"""
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
class PersonAPITest(
|
||||
APITestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
@ -1,5 +1,6 @@
|
||||
from django.db.models.fields import NOT_PROVIDED
|
||||
from django.test import TestCase
|
||||
import pytest
|
||||
|
||||
from django.db import models
|
||||
|
||||
from access.models.person import Person
|
||||
from access.tests.unit.entity.test_unit_entity_model import (
|
||||
@ -8,88 +9,114 @@ from access.tests.unit.entity.test_unit_entity_model import (
|
||||
|
||||
|
||||
|
||||
class ModelTestCases(
|
||||
class PersonModelTestCases(
|
||||
EntityModelInheritedCases,
|
||||
):
|
||||
|
||||
model = Person
|
||||
|
||||
kwargs_item_create: dict = {
|
||||
kwargs_create_item: dict = {
|
||||
'f_name': 'Ian',
|
||||
'm_name': 'Peter',
|
||||
'l_name': 'Funny',
|
||||
'dob': '2025-04-08',
|
||||
}
|
||||
|
||||
sub_model_type = 'person'
|
||||
"""Sub Model Type
|
||||
|
||||
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
|
||||
def test_model_field_dob_optional(self):
|
||||
"""Test Field
|
||||
parameterized_fields: dict = {
|
||||
"f_name": {
|
||||
'field_type': models.fields.CharField,
|
||||
'field_parameter_default_exists': False,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
},
|
||||
"m_name": {
|
||||
'field_type': models.fields.CharField,
|
||||
'field_parameter_default_exists': False,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
},
|
||||
"l_name": {
|
||||
'field_type': models.fields.CharField,
|
||||
'field_parameter_default_exists': False,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
},
|
||||
"dob": {
|
||||
'field_type': models.fields.DateField,
|
||||
'field_parameter_default_exists': False,
|
||||
'field_parameter_verbose_name_type': str,
|
||||
},
|
||||
}
|
||||
|
||||
Field `dob` must be an optional field
|
||||
|
||||
|
||||
def test_class_inherits_person(self):
|
||||
""" Class inheritence
|
||||
|
||||
TenancyObject must inherit SaveHistory
|
||||
"""
|
||||
|
||||
assert self.model._meta.get_field('dob').blank
|
||||
assert issubclass(self.model, Person)
|
||||
|
||||
|
||||
def test_model_field_f_name_mandatory(self):
|
||||
"""Test Field
|
||||
def test_attribute_value_history_app_label(self):
|
||||
"""Attribute Type
|
||||
|
||||
Field `f_name` must be a mandatory field
|
||||
history_app_label has been set, override this test case with the value
|
||||
of attribute `history_app_label`
|
||||
"""
|
||||
|
||||
assert(
|
||||
not (
|
||||
self.model._meta.get_field('f_name').blank
|
||||
and self.model._meta.get_field('f_name').null
|
||||
)
|
||||
and self.model._meta.get_field('f_name').default is NOT_PROVIDED
|
||||
)
|
||||
assert self.model.history_app_label == 'access'
|
||||
|
||||
|
||||
def test_model_field_l_name_mandatory(self):
|
||||
"""Test Field
|
||||
def test_attribute_value_history_model_name(self):
|
||||
"""Attribute Type
|
||||
|
||||
Field `l_name` must be a mandatory field
|
||||
history_model_name has been set, override this test case with the value
|
||||
of attribute `history_model_name`
|
||||
"""
|
||||
|
||||
assert (
|
||||
not (
|
||||
self.model._meta.get_field('l_name').blank
|
||||
and self.model._meta.get_field('l_name').null
|
||||
)
|
||||
and self.model._meta.get_field('l_name').default is NOT_PROVIDED
|
||||
)
|
||||
assert self.model.history_model_name == 'person'
|
||||
|
||||
|
||||
|
||||
def test_function_value_get_url(self):
|
||||
|
||||
assert self.item.get_url() == '/api/v2/access/entity/person/' + str(self.item.id)
|
||||
|
||||
|
||||
|
||||
class PersonModelInheritedCases(
|
||||
ModelTestCases,
|
||||
PersonModelTestCases,
|
||||
):
|
||||
"""Sub-Entity Test Cases
|
||||
"""Sub-Ticket Test Cases
|
||||
|
||||
Test Cases for Entity models that inherit from model Person
|
||||
Test Cases for Ticket models that inherit from model Entity
|
||||
"""
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
kwargs_create_item: dict = {}
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
|
||||
self.kwargs_item_create.update(
|
||||
super().kwargs_item_create
|
||||
)
|
||||
|
||||
super().setUpTestData()
|
||||
sub_model_type = None
|
||||
"""Ticket Sub Model Type
|
||||
|
||||
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class PersonModelTest(
|
||||
ModelTestCases,
|
||||
TestCase,
|
||||
class PersonModelPyTest(
|
||||
PersonModelTestCases,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
def test_function_value_get_related_model(self):
|
||||
"""Function test
|
||||
|
||||
Confirm function `get_related_model` is None for base model
|
||||
"""
|
||||
|
||||
assert self.item.get_related_model() is None
|
||||
|
@ -1,21 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.role import Role
|
||||
from access.tests.abstract.tenancy_object import TenancyObject
|
||||
|
||||
|
||||
|
||||
class TenancyObjectTestCases(
|
||||
TenancyObject,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
|
||||
|
||||
class RoleTenancyObjectTest(
|
||||
TenancyObjectTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
model = Role
|
@ -1,4 +1,6 @@
|
||||
from django.contrib.auth.models import Permission, User
|
||||
import django
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
@ -6,12 +8,14 @@ from django.test import Client, TestCase
|
||||
# from rest_framework.relations import Hyperlink
|
||||
|
||||
from access.models.role import Role
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from api.tests.abstract.api_fields import APITenancyObject
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class APITestCases(
|
||||
|
@ -1,38 +1,23 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from access.models.role import Role
|
||||
from access.models.organization import Organization
|
||||
from access.models.tenancy import TenancyObject
|
||||
|
||||
from app.tests.abstract.models import TenancyModel
|
||||
from app.tests.unit.test_unit_models import (
|
||||
TenancyObjectInheritedCases
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ModelTestCases(
|
||||
TenancyModel,
|
||||
class RoleModelTestCases(
|
||||
TenancyObjectInheritedCases,
|
||||
):
|
||||
|
||||
model = None
|
||||
|
||||
kwargs_item_create: dict = None
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test"""
|
||||
|
||||
self.organization = Organization.objects.create(name='test_org')
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization = self.organization,
|
||||
model_notes = 'notes',
|
||||
**self.kwargs_item_create,
|
||||
)
|
||||
|
||||
|
||||
|
||||
def test_field_not_exists_is_global(self):
|
||||
def test_field_exist_is_global(self):
|
||||
"""Test model field not used
|
||||
|
||||
object must not be settable as a global object
|
||||
@ -44,18 +29,8 @@ class ModelTestCases(
|
||||
|
||||
|
||||
|
||||
def test_model_must_be_by_organization(self):
|
||||
"""Test model must be by organization
|
||||
|
||||
This model **must** be by organization.
|
||||
"""
|
||||
|
||||
assert issubclass(self.model, TenancyObject)
|
||||
|
||||
|
||||
|
||||
class RoleModelTest(
|
||||
ModelTestCases,
|
||||
RoleModelTestCases,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user