Compare commits

..

134 Commits

Author SHA1 Message Date
91ed890f68 Well that was odd 2022-01-12 21:06:18 +00:00
e002ab7bed Big pile of minor code cleanups 2022-01-12 20:54:32 +00:00
3abb73872b Oops 2022-01-12 20:26:28 +00:00
7aba26218f Add an interaction test
Just one. Lol.
2022-01-12 20:24:35 +00:00
aa6bb8410e Swap to better method of validating uniqueness of cable types
SCOPE, Arona, damn it
2022-01-12 19:15:38 +00:00
b4c5493705 Risk assessment form now validates power training status where required 2022-01-12 19:09:20 +00:00
9c8d8f077d Fix logic of filtering secure API requests 2022-01-10 18:19:10 +00:00
6414e68231 Migrate to is_supervisor being a database field
More efficient, but it does reduce app seperation. Probably not an issue for us!
2022-01-09 15:06:11 +00:00
b539312538 Reversion should mostly work now 2022-01-09 14:52:59 +00:00
88dee9477b Double whoops 2022-01-08 18:12:04 +00:00
1984725275 Use a fstring 2022-01-08 18:11:25 +00:00
9db122acb8 Whoops 2022-01-08 18:10:30 +00:00
8e00d86023 use get_or_create when confirming level quals for cases where unconfirmed levels existed in old data 2022-01-08 17:58:06 +00:00
3258094a81 Admin register a bunch more stuff 2022-01-08 17:51:11 +00:00
b9ee6abebd Slightly more testing 2022-01-08 17:36:28 +00:00
f15cfa8fce Slight cleanup 2022-01-08 17:25:23 +00:00
1b32dc2db0 Add a test!
Just one
2022-01-08 17:17:25 +00:00
1490d906ca Update lxml 2022-01-05 20:23:55 +00:00
fe854198fa Revamp level list for better grouping 2022-01-05 12:26:00 +00:00
f8ee1ffb0b Mmm 'responsive' tables 2022-01-04 22:37:42 +00:00
af963ac0eb Only show crown on first page 2022-01-04 22:31:49 +00:00
42ea30931e Fix spelling mistake 2022-01-04 22:26:48 +00:00
b8dc56d129 Fix for new django 2022-01-04 20:31:22 +00:00
f333aa2c18 >.> 2022-01-04 20:20:02 +00:00
9bc2c2b509 Squash migrations 2022-01-04 20:09:04 +00:00
9abb76d4fa That didn't work. Skip those for now 2022-01-04 20:04:54 +00:00
e6af66a964 Potentially fix tests 2022-01-04 19:55:11 +00:00
6c484b984c Revert "Let's try this"
This reverts commit 2a66342cd3.
2022-01-04 19:05:06 +00:00
2a66342cd3 Let's try this 2022-01-04 18:59:50 +00:00
7bd32b3ac5 My kingdom for a space 2022-01-04 18:43:10 +00:00
2a61ee2896 Hmmm 2022-01-04 18:36:27 +00:00
3bac6050f1 Fix broken js in assetaudit
Weird that didn't get picked up before...
2022-01-04 12:36:28 +00:00
7aa37c225d Fix sample data command 2022-01-04 12:28:25 +00:00
215c51e718 Merge branch 'master' into training 2022-01-04 12:08:39 +00:00
fbe4d7271f pep8 2022-01-04 12:08:17 +00:00
2a2f010028 Permissions work 2022-01-04 12:04:38 +00:00
6b19d0e8b8 Fix has_required_levels logic being backward 2022-01-03 15:31:54 +00:00
3e8cfe4f11 Repair confirmation logic 2022-01-03 15:28:17 +00:00
7a70270dfd Add ability to view other users progress on a level
That's kind of important huh :p
2022-01-03 14:59:30 +00:00
5160eb7f78 Add confirm button stuff 2022-01-03 14:38:43 +00:00
99e05d91bb Simpler training level list display 2022-01-02 20:55:32 +00:00
f094ace862 Make level description a text field 2022-01-02 20:53:33 +00:00
945fb393c0 Display prerequisite item requirements on level detail 2022-01-02 20:31:23 +00:00
c6157d3e2b Various fixes 2022-01-02 19:15:44 +00:00
2767777d0e Add ability to edit past training records 2022-01-02 15:39:10 +00:00
19e6585e26 Fix importer not working for notes 2022-01-02 15:03:11 +00:00
747575b968 Add ability to search detailed training record 2022-01-02 14:52:07 +00:00
046d0e461d Fix is_supervisor returning true if user has any levels
Whoops!
2022-01-02 11:15:03 +00:00
b73b8401b6 Add ordering to training level qualification 2022-01-02 11:06:58 +00:00
3fe388af26 Fix importer trying to set pk for qualifications
This doesn't work because of the old DB structure
2022-01-02 11:05:08 +00:00
22dc83d595 Do not display qualified levels also as started 2022-01-02 10:37:48 +00:00
70d4c42676 Much versioning work 2022-01-01 19:53:03 +00:00
0727a23236 Some reversion fiddling 2021-12-31 18:23:38 +00:00
f0b3a6daf3 Filter for active training items
Can't easily filter by supervisor, its not a database field, argh...
2021-12-29 13:07:30 +00:00
3c5f6da363 Fix selectpickers disappearing on modal errors 2021-12-29 12:48:34 +00:00
ee9be86465 Do not display items on trainee detail
That's what the detailed view is for...

And definitely nowt to do with my horrifically optimised SQL
2021-12-28 22:23:17 +00:00
5554edf977 Cleanup 2021-12-28 21:58:56 +00:00
14b73f6f50 Somewhat optimised SQL on level detail 2021-12-28 21:35:21 +00:00
732affa0b2 SQL optimisation of detailed training record 2021-12-28 12:13:08 +00:00
7c830ee7e5 Fix sorting of items
W.T.F past self. Char field for a reference number?!
2021-12-28 11:46:52 +00:00
d47d00d79b Rework item list display 2021-12-28 11:36:46 +00:00
3b5b3b84d4 Significant improvements to level list
Added search
Ordered by qualification count
Added display for technician qualifications
2021-12-27 14:59:30 +00:00
aa8be6a6d0 Rework level list display 2021-12-23 13:29:04 +00:00
640362c203 Importer sets up level heirarchy 2021-12-23 13:28:56 +00:00
71a8823ac2 Markdown support on level desc 2021-12-23 11:31:44 +00:00
c6de3dc9e2 Merge branch 'master' into training 2021-12-22 21:52:04 +00:00
8696bf5d94 SQL query optimisation 2021-12-22 11:09:54 +00:00
0d9bf89180 Merge branch 'master' into training
# Conflicts:
#	templates/base.html
2021-12-21 19:53:17 +00:00
f4f2fbdc03 Tweak training level display 2021-12-21 19:07:39 +00:00
67aaada9e8 Import confirmation date for training level qualifications 2021-12-21 19:05:25 +00:00
fcae39c93c Add constraint that training items must have unique reference numbers 2021-12-21 15:51:44 +00:00
d1970edfb3 Change display of 'users with this level' 2021-12-21 15:12:11 +00:00
ce5efff268 Initial work on requirements importer 2021-12-21 13:38:00 +00:00
522837c64e Importer works. Doesn't yet compensate for crap data quality. 2021-10-27 16:42:52 +01:00
e78decdf92 finshed inport old db untested 2021-10-27 14:04:01 +01:00
84a3c9db24 made database importer untested 2021-10-27 13:18:28 +01:00
280a1d9604 begin work on perms 2021-10-22 16:13:08 +01:00
a184bbfa26 Much template wrangling 2021-10-22 15:57:20 +01:00
4416e5bfcb Add RevisionMixin in the right places 2021-10-20 21:15:59 +01:00
21276bcca0 You may not confirm your own training 2021-10-20 21:06:59 +01:00
bc465d67e9 Convert requirement addition to a modal 2021-10-20 21:02:19 +01:00
a644735cd6 Merge branch 'master' into training 2021-10-20 20:22:59 +01:00
10326f884f Fix the modal fuckery 2021-10-20 20:15:13 +01:00
0a0c9f15af Common competencies also do not count for being a supervisor 2021-10-09 10:38:40 +01:00
dbb9e3e530 Add 'is van driver' to trainee list, haulage super doesn't count as a supervisor 2021-10-09 10:29:03 +01:00
55558d1a4a Merge branch 'master' into training
# Conflicts:
#	RIGS/templates/risk_assessment_form.html
#	templates/base.html
2021-10-08 18:40:39 +01:00
081c33ebc8 Various tweaks 2021-09-13 01:07:17 +01:00
75410db752 Refactor is_supervisor 2021-09-13 00:49:02 +01:00
06c6b9a36e Change homepage links to match header ones 2021-09-12 20:26:05 +01:00
13b1cea28b Fancy training level list layout 2021-09-12 18:08:13 +01:00
cddb76bf7e Order training items by number 2021-09-08 20:44:02 +01:00
f4f1fb66a2 Leaderboard of qualifications obtained 2021-09-08 20:44:02 +01:00
d80aeca01f Add training level list
Plus various other fettling
2021-09-03 22:34:25 +01:00
45dfe2db51 Work on trainee reversion 2021-09-02 10:23:53 +01:00
de5997b9da Reversion working for training level 2021-08-29 22:19:30 +01:00
4a121964dc Start training navbar 2021-08-21 11:42:31 +01:00
df5e4c8e0a Level detail tweaking 2021-08-21 01:44:26 +01:00
3601c14ab7 Oops 2021-08-21 01:36:35 +01:00
adde6496f5 Add loads more sample training items
Hopefully the generator won't make levels with no requirements anymore now
2021-08-21 00:45:35 +01:00
ad734d94b2 Display pre pre requisite levels on level detail 2021-08-21 00:32:04 +01:00
7d3ada822d Common competencies sample data 2021-08-21 00:28:24 +01:00
732af53fda Groundwork stuff for common competencies + other fixes 2021-08-21 00:09:00 +01:00
4fb0529cc0 Modalify the training record addition form 2021-08-20 21:52:33 +01:00
aa23b1cd09 Add sharepoint link to new homepage
Good at scope, me
2021-08-20 21:52:17 +01:00
0c4228da57 Add a view for a trainee's item record 2021-08-20 14:26:32 +01:00
246a52d19e Don't try and create existing level qualifications 2021-08-20 13:48:30 +01:00
8b10aaf700 Display users with level on level detail page 2021-08-20 12:48:54 +01:00
4d0d4f02aa Generate a sample supervisor 2021-08-20 12:38:30 +01:00
af987c1ebb Make TrainingLevelRequirement the correct level of unique
Also updates generateSampleData to match
2021-08-19 18:47:38 +01:00
d406a911bb Initial refactoring of profile detail 2021-08-19 18:27:52 +01:00
63c5a68933 Goddamnit 2021-08-19 18:12:15 +01:00
66f7f830db Forgot that needed migrations generating 2021-08-19 18:08:57 +01:00
9590c2066d Validate that only supervisors may be supervisors 2021-08-19 16:19:46 +01:00
8b48b02ca7 Force trainingitemqualifications to be unique 2021-08-19 16:00:31 +01:00
68e7ec2a0d Merge branch 'master' into training 2021-08-19 15:49:16 +01:00
5779ebdf7e Merge branch 'master' into training
# Conflicts:
#	templates/base.html
2021-08-17 21:35:10 +01:00
be648c20d5 Level confirmation works 2021-07-29 23:41:35 +01:00
b6ef7c1d89 Force traininglevelqualifications to be unique 2021-07-29 23:15:09 +01:00
85f40b358a Some attempts at optimising SQL queries
New high score!
2021-07-29 22:49:27 +01:00
2698798035 Percentage complete works
Ain't half slow though!
2021-07-16 04:05:55 +01:00
dbaab5cf8c Autofire of traininglevelqualification basically works 2021-07-16 02:58:42 +01:00
0a9f82e480 Fettling with level granting logic
Untested as all of my forms broke I guess
2021-07-07 17:38:44 +01:00
54f2bd36bd UI for editing training level requirements 2021-07-06 22:10:15 +01:00
e836195fef mild polishing 2021-07-06 14:51:43 +01:00
68a424d62b Some sample data and UX work 2021-07-06 12:16:43 +01:00
5e15b8bb59 Basic UX for adding requirements to training levels 2021-07-06 11:37:04 +01:00
d26c1b535e item ui vaguely working 2021-07-06 00:09:46 +01:00
dff5ac2308 Whee broken HEAD 2021-07-05 23:24:13 +01:00
a3729fa930 Session log form work 2021-07-05 18:24:24 +01:00
458a734331 Machine switch 2021-07-01 09:50:13 +01:00
b1646d556c Start work on sample data command 2021-06-30 15:56:28 +01:00
f8624d3b7a Restructure based on actual thought put in by @mattysmith22 2021-06-30 15:17:00 +01:00
f6836fdab6 Merge branch 'master' into training 2021-06-29 17:17:48 +01:00
b3949f2903 Initial sketching 2021-06-29 17:13:36 +01:00
21 changed files with 132 additions and 156 deletions

View File

@@ -37,7 +37,7 @@ lxml = "~=4.7.1"
Markdown = "~=3.3.3" Markdown = "~=3.3.3"
msgpack = "~=1.0.2" msgpack = "~=1.0.2"
pep517 = "~=0.9.1" pep517 = "~=0.9.1"
Pillow = "~=9.0.0" Pillow = "~=8.3.2"
premailer = "~=3.7.0" premailer = "~=3.7.0"
progress = "~=1.5" progress = "~=1.5"
psutil = "~=5.8.0" psutil = "~=5.8.0"

95
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "7db5b3a9029be79c79efff791a42803a4765fe52c4f264f8a7be48ac4b1bda7a" "sha256": "1e172bcff2ac1fdeeebfb6818abfbed1ebb45508408a9db9fd7ec0616593887c"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@@ -363,11 +363,11 @@
}, },
"django-widget-tweaks": { "django-widget-tweaks": {
"hashes": [ "hashes": [
"sha256:9bfc5c705684754a83cc81da328b39ad1b80f32bd0f4340e2a810cbab4b0c00e", "sha256:01b911a1b47629de0a3a3097774798dee4eb703b94d41666929f688d5f77c723",
"sha256:fe6b17d5d595c63331f300917980db2afcf71f240ab9341b954aea8f45d25b9a" "sha256:07674e32031eda81077f0b8e390ce78d1d415e700cedd0396ef0ce452e95b94d"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.4.12" "version": "==1.4.11"
}, },
"envparse": { "envparse": {
"hashes": [ "hashes": [
@@ -593,41 +593,62 @@
}, },
"pillow": { "pillow": {
"hashes": [ "hashes": [
"sha256:03b27b197deb4ee400ed57d8d4e572d2d8d80f825b6634daf6e2c18c3c6ccfa6", "sha256:0412516dcc9de9b0a1e0ae25a280015809de8270f134cc2c1e32c4eeb397cf30",
"sha256:0b281fcadbb688607ea6ece7649c5d59d4bbd574e90db6cd030e9e85bde9fecc", "sha256:04835e68ef12904bc3e1fd002b33eea0779320d4346082bd5b24bec12ad9c3e9",
"sha256:0ebd8b9137630a7bbbff8c4b31e774ff05bbb90f7911d93ea2c9371e41039b52", "sha256:06d1adaa284696785375fa80a6a8eb309be722cf4ef8949518beb34487a3df71",
"sha256:113723312215b25c22df1fdf0e2da7a3b9c357a7d24a93ebbe80bfda4f37a8d4", "sha256:085a90a99404b859a4b6c3daa42afde17cb3ad3115e44a75f0d7b4a32f06a6c9",
"sha256:2d16b6196fb7a54aff6b5e3ecd00f7c0bab1b56eee39214b2b223a9d938c50af", "sha256:0b9911ec70731711c3b6ebcde26caea620cbdd9dcb73c67b0730c8817f24711b",
"sha256:2fd8053e1f8ff1844419842fd474fc359676b2e2a2b66b11cc59f4fa0a301315", "sha256:10e00f7336780ca7d3653cf3ac26f068fa11b5a96894ea29a64d3dc4b810d630",
"sha256:31b265496e603985fad54d52d11970383e317d11e18e856971bdbb86af7242a4", "sha256:11c27e74bab423eb3c9232d97553111cc0be81b74b47165f07ebfdd29d825875",
"sha256:3586e12d874ce2f1bc875a3ffba98732ebb12e18fb6d97be482bd62b56803281", "sha256:11eb7f98165d56042545c9e6db3ce394ed8b45089a67124298f0473b29cb60b2",
"sha256:47f5cf60bcb9fbc46011f75c9b45a8b5ad077ca352a78185bd3e7f1d294b98bb", "sha256:13654b521fb98abdecec105ea3fb5ba863d1548c9b58831dd5105bb3873569f1",
"sha256:490e52e99224858f154975db61c060686df8a6b3f0212a678e5d2e2ce24675c9", "sha256:15ccb81a6ffc57ea0137f9f3ac2737ffa1d11f786244d719639df17476d399a7",
"sha256:500d397ddf4bbf2ca42e198399ac13e7841956c72645513e8ddf243b31ad2128", "sha256:18a07a683805d32826c09acfce44a90bf474e6a66ce482b1c7fcd3757d588df3",
"sha256:52abae4c96b5da630a8b4247de5428f593465291e5b239f3f843a911a3cf0105", "sha256:19ec4cfe4b961edc249b0e04b5618666c23a83bc35842dea2bfd5dfa0157f81b",
"sha256:6579f9ba84a3d4f1807c4aab4be06f373017fc65fff43498885ac50a9b47a553", "sha256:1c3ff00110835bdda2b1e2b07f4a2548a39744bb7de5946dc8e95517c4fb2ca6",
"sha256:68e06f8b2248f6dc8b899c3e7ecf02c9f413aab622f4d6190df53a78b93d97a5", "sha256:27a330bf7014ee034046db43ccbb05c766aa9e70b8d6c5260bfc38d73103b0ba",
"sha256:6c5439bfb35a89cac50e81c751317faea647b9a3ec11c039900cd6915831064d", "sha256:2b11c9d310a3522b0fd3c35667914271f570576a0e387701f370eb39d45f08a4",
"sha256:72c3110228944019e5f27232296c5923398496b28be42535e3b2dc7297b6e8b6", "sha256:2c661542c6f71dfd9dc82d9d29a8386287e82813b0375b3a02983feac69ef864",
"sha256:72f649d93d4cc4d8cf79c91ebc25137c358718ad75f99e99e043325ea7d56100", "sha256:2cde7a4d3687f21cffdf5bb171172070bb95e02af448c4c8b2f223d783214056",
"sha256:7aaf07085c756f6cb1c692ee0d5a86c531703b6e8c9cae581b31b562c16b98ce", "sha256:2d5e9dc0bf1b5d9048a94c48d0813b6c96fccfa4ccf276d9c36308840f40c228",
"sha256:80fe92813d208ce8aa7d76da878bdc84b90809f79ccbad2a288e9bcbeac1d9bd", "sha256:2f23b2d3079522fdf3c09de6517f625f7a964f916c956527bed805ac043799b8",
"sha256:95545137fc56ce8c10de646074d242001a112a92de169986abd8c88c27566a05", "sha256:35d27687f027ad25a8d0ef45dd5208ef044c588003cdcedf05afb00dbc5c2deb",
"sha256:97b6d21771da41497b81652d44191489296555b761684f82b7b544c49989110f", "sha256:35d409030bf3bd05fa66fb5fdedc39c521b397f61ad04309c90444e893d05f7d",
"sha256:98cb63ca63cb61f594511c06218ab4394bf80388b3d66cd61d0b1f63ee0ea69f", "sha256:4326ea1e2722f3dc00ed77c36d3b5354b8fb7399fb59230249ea6d59cbed90da",
"sha256:9f3b4522148586d35e78313db4db0df4b759ddd7649ef70002b6c3767d0fdeb7", "sha256:4abc247b31a98f29e5224f2d31ef15f86a71f79c7f4d2ac345a5d551d6393073",
"sha256:a09a9d4ec2b7887f7a088bbaacfd5c07160e746e3d47ec5e8050ae3b2a229e9f", "sha256:4d89a2e9219a526401015153c0e9dd48319ea6ab9fe3b066a20aa9aee23d9fd3",
"sha256:b5050d681bcf5c9f2570b93bee5d3ec8ae4cf23158812f91ed57f7126df91762", "sha256:4e59e99fd680e2b8b11bbd463f3c9450ab799305d5f2bafb74fefba6ac058616",
"sha256:bb47a548cea95b86494a26c89d153fd31122ed65255db5dcbc421a2d28eb3379", "sha256:548794f99ff52a73a156771a0402f5e1c35285bd981046a502d7e4793e8facaa",
"sha256:bc462d24500ba707e9cbdef436c16e5c8cbf29908278af053008d9f689f56dee", "sha256:56fd98c8294f57636084f4b076b75f86c57b2a63a8410c0cd172bc93695ee979",
"sha256:c2067b3bb0781f14059b112c9da5a91c80a600a97915b4f48b37f197895dd925", "sha256:59697568a0455764a094585b2551fd76bfd6b959c9f92d4bdec9d0e14616303a",
"sha256:d154ed971a4cc04b93a6d5b47f37948d1f621f25de3e8fa0c26b2d44f24e3e8f", "sha256:6bff50ba9891be0a004ef48828e012babaaf7da204d81ab9be37480b9020a82b",
"sha256:d5dcea1387331c905405b09cdbfb34611050cc52c865d71f2362f354faee1e9f", "sha256:6cb3dd7f23b044b0737317f892d399f9e2f0b3a02b22b2c692851fb8120d82c6",
"sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e", "sha256:7dbfbc0020aa1d9bc1b0b8bcf255a7d73f4ad0336f8fd2533fcc54a4ccfb9441",
"sha256:fd0e5062f11cb3e730450a7d9f323f4051b532781026395c4323b8ad055523c4" "sha256:838eb85de6d9307c19c655c726f8d13b8b646f144ca6b3771fa62b711ebf7624",
"sha256:8b68f565a4175e12e68ca900af8910e8fe48aaa48fd3ca853494f384e11c8bcd",
"sha256:8f284dc1695caf71a74f24993b7c7473d77bc760be45f776a2c2f4e04c170550",
"sha256:963ebdc5365d748185fdb06daf2ac758116deecb2277ec5ae98139f93844bc09",
"sha256:a048dad5ed6ad1fad338c02c609b862dfaa921fcd065d747194a6805f91f2196",
"sha256:a1bd983c565f92779be456ece2479840ec39d386007cd4ae83382646293d681b",
"sha256:a66566f8a22561fc1a88dc87606c69b84fa9ce724f99522cf922c801ec68f5c1",
"sha256:bcb04ff12e79b28be6c9988f275e7ab69f01cc2ba319fb3114f87817bb7c74b6",
"sha256:bd24054aaf21e70a51e2a2a5ed1183560d3a69e6f9594a4bfe360a46f94eba83",
"sha256:be25cb93442c6d2f8702c599b51184bd3ccd83adebd08886b682173e09ef0c3f",
"sha256:c691b26283c3a31594683217d746f1dad59a7ae1d4cfc24626d7a064a11197d4",
"sha256:cc9d0dec711c914ed500f1d0d3822868760954dce98dfb0b7382a854aee55d19",
"sha256:ce2e5e04bb86da6187f96d7bab3f93a7877830981b37f0287dd6479e27a10341",
"sha256:ce651ca46d0202c302a535d3047c55a0131a720cf554a578fc1b8a2aff0e7d96",
"sha256:d0c8ebbfd439c37624db98f3877d9ed12c137cadd99dde2d2eae0dab0bbfc355",
"sha256:d675a876b295afa114ca8bf42d7f86b5fb1298e1b6bb9a24405a3f6c8338811c",
"sha256:dde3f3ed8d00c72631bc19cbfff8ad3b6215062a5eed402381ad365f82f0c18c",
"sha256:e5a31c07cea5edbaeb4bdba6f2b87db7d3dc0f446f379d907e51cc70ea375629",
"sha256:f514c2717012859ccb349c97862568fdc0479aad85b0270d6b5a6509dbc142e2",
"sha256:fc0db32f7223b094964e71729c0361f93db43664dd1ec86d3df217853cedda87",
"sha256:fd4fd83aa912d7b89b4b4a1580d30e2a4242f3936882a3f433586e5ab97ed0d5",
"sha256:feb5db446e96bfecfec078b943cc07744cc759893cef045aa8b8b6d6aaa8274e"
], ],
"index": "pypi", "index": "pypi",
"version": "==9.0.0" "version": "==8.3.2"
}, },
"pluggy": { "pluggy": {
"hashes": [ "hashes": [

View File

@@ -44,7 +44,7 @@ def get_request_url(url):
@pytest.mark.parametrize("command", ['generateSampleAssetsData', 'generateSampleRIGSData', 'generateSampleUserData', @pytest.mark.parametrize("command", ['generateSampleAssetsData', 'generateSampleRIGSData', 'generateSampleUserData',
'deleteSampleData', 'generateSampleTrainingData', 'generate_sample_training_users']) 'deleteSampleData'])
def test_production_exception(command): def test_production_exception(command):
from django.core.management.base import CommandError from django.core.management.base import CommandError
with pytest.raises(CommandError, match=".*production"): with pytest.raises(CommandError, match=".*production"):

View File

@@ -3,7 +3,6 @@
from django.db import models, migrations from django.db import models, migrations
import RIGS.models import RIGS.models
import versioning
class Migration(migrations.Migration): class Migration(migrations.Migration):
@@ -26,6 +25,6 @@ class Migration(migrations.Migration):
], ],
options={ options={
}, },
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
] ]

View File

@@ -3,7 +3,6 @@
from django.db import models, migrations from django.db import models, migrations
import RIGS.models import RIGS.models
import versioning
class Migration(migrations.Migration): class Migration(migrations.Migration):
@@ -22,6 +21,6 @@ class Migration(migrations.Migration):
], ],
options={ options={
}, },
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
] ]

View File

@@ -4,7 +4,6 @@
from django.db import models, migrations from django.db import models, migrations
from django.conf import settings from django.conf import settings
import RIGS.models import RIGS.models
import versioning
class Migration(migrations.Migration): class Migration(migrations.Migration):
@@ -42,7 +41,7 @@ class Migration(migrations.Migration):
], ],
options={ options={
}, },
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
migrations.CreateModel( migrations.CreateModel(
name='EventItem', name='EventItem',
@@ -71,7 +70,7 @@ class Migration(migrations.Migration):
], ],
options={ options={
}, },
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
migrations.AddField( migrations.AddField(
model_name='event', model_name='event',

View File

@@ -4,7 +4,6 @@ import RIGS.models
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import versioning
class Migration(migrations.Migration): class Migration(migrations.Migration):
@@ -59,7 +58,7 @@ class Migration(migrations.Migration):
'ordering': ['event'], 'ordering': ['event'],
'permissions': [('review_eventchecklist', 'Can review Event Checklists')], 'permissions': [('review_eventchecklist', 'Can review Event Checklists')],
}, },
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
migrations.CreateModel( migrations.CreateModel(
name='EventChecklistCrew', name='EventChecklistCrew',
@@ -70,7 +69,7 @@ class Migration(migrations.Migration):
('end', models.DateTimeField()), ('end', models.DateTimeField()),
('checklist', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='crew', to='RIGS.eventchecklist')), ('checklist', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='crew', to='RIGS.eventchecklist')),
], ],
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
migrations.CreateModel( migrations.CreateModel(
name='EventChecklistVehicle', name='EventChecklistVehicle',
@@ -79,7 +78,7 @@ class Migration(migrations.Migration):
('vehicle', models.CharField(max_length=255)), ('vehicle', models.CharField(max_length=255)),
('checklist', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='vehicles', to='RIGS.eventchecklist')), ('checklist', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='vehicles', to='RIGS.eventchecklist')),
], ],
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
migrations.CreateModel( migrations.CreateModel(
name='RiskAssessment', name='RiskAssessment',
@@ -118,7 +117,7 @@ class Migration(migrations.Migration):
'ordering': ['event'], 'ordering': ['event'],
'permissions': [('review_riskassessment', 'Can review Risk Assessments')], 'permissions': [('review_riskassessment', 'Can review Risk Assessments')],
}, },
bases=(models.Model, versioning.versioning.RevisionMixin), bases=(models.Model, RIGS.models.RevisionMixin),
), ),
migrations.RemoveField( migrations.RemoveField(
model_name='eventcrew', model_name='eventcrew',

View File

@@ -0,0 +1,25 @@
# Generated by Django 3.2.11 on 2022-01-09 15:00
from django.db import migrations
from training.models import TrainingLevel
def find_existing_supervisors(apps, schema_editor):
Profile = apps.get_model('RIGS', 'Profile')
for person in Profile.objects.all():
if person.level_qualifications.exclude(confirmed_on=None).select_related('level') \
.filter(level__level__gte=TrainingLevel.SUPERVISOR) \
.exclude(level__department=TrainingLevel.HAULAGE) \
.exclude(level__department__isnull=True).exists():
person.is_supervisor = True
person.save()
class Migration(migrations.Migration):
dependencies = [
('RIGS', '0044_profile_is_supervisor'),
]
operations = [
migrations.RunPython(find_existing_supervisors, migrations.RunPython.noop)
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 MiB

After

Width:  |  Height:  |  Size: 6.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 KiB

After

Width:  |  Height:  |  Size: 852 KiB

View File

@@ -33,7 +33,6 @@ class AssetSearchForm(forms.Form):
category = forms.ModelMultipleChoiceField(models.AssetCategory.objects.all(), required=False) category = forms.ModelMultipleChoiceField(models.AssetCategory.objects.all(), required=False)
status = forms.ModelMultipleChoiceField(models.AssetStatus.objects.all(), required=False) status = forms.ModelMultipleChoiceField(models.AssetStatus.objects.all(), required=False)
is_cable = forms.BooleanField(required=False) is_cable = forms.BooleanField(required=False)
date_acquired = forms.DateField(required=False)
class SupplierForm(forms.ModelForm): class SupplierForm(forms.ModelForm):

View File

@@ -6,8 +6,7 @@ from django.urls import reverse
from reversion import revisions as reversion from reversion import revisions as reversion
from reversion.models import Version from reversion.models import Version
from RIGS.models import Profile from RIGS.models import RevisionMixin, Profile
from versioning.versioning import RevisionMixin
class AssetCategory(models.Model): class AssetCategory(models.Model):

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -61,45 +61,25 @@
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col px-0"> <div class="col px-0">
<form id="asset-search-form" method="GET"> <form id="asset-search-form" method="GET" class="form-inline justify-content-end">
<div class="form-row"> <div class="input-group px-1 mb-2 mb-sm-0 flex-nowrap">
<div class="col"> {% render_field form.q|add_class:'form-control' placeholder='Enter Asset ID/Desc/Serial' %}
<div class="input-group px-1 mb-2 mb-sm-0 flex-nowrap"> <label for="q" class="sr-only">Asset ID/Description/Serial Number:</label>
{% render_field form.q|add_class:'form-control' placeholder='Enter Asset ID/Desc/Serial' %} <span class="input-group-append">{% button 'search' id="id_search" %}</span>
<label for="q" class="sr-only">Asset ID/Description/Serial Number:</label> </div>
<span class="input-group-append">{% button 'search' id="id_search" %}</span> <div id="category-group" class="form-group px-1" style="margin-bottom: 0;">
</div> <label for="category" class="sr-only">Category</label>
</div> {% render_field form.category|attr:'multiple'|add_class:'form-control custom-select selectpicker col-sm' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %}
</div> </div>
<div class="form-row mt-2"> <div id="status-group" class="form-group px-1" style="margin-bottom: 0;">
<div class="col"> <label for="status" class="sr-only">Status</label>
<div id="category-group" class="form-group px-1" style="margin-bottom: 0;"> {% render_field form.status|attr:'multiple'|add_class:'form-control custom-select selectpicker col-sm' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %}
<label for="category" class="sr-only">Category</label> </div>
{% render_field form.category|attr:'multiple'|add_class:'form-control custom-select selectpicker col-sm' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %} <div class="form-check form-check-inline">
</div> {% render_field form.is_cable|add_class:'form-check-input' %}
</div> <label class="form-check-label" for="is_cable">Only Cables?</label>
<div class="col"> </div>
<div id="status-group" class="form-group px-1" style="margin-bottom: 0;"> <button id="filter-submit" type="submit" class="btn btn-secondary" style="width: 6em">Filter</button>
<label for="status" class="sr-only">Status</label>
{% render_field form.status|attr:'multiple'|add_class:'form-control custom-select selectpicker col-sm' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %}
</div>
</div>
<div class="col mt-2">
<div class="form-check form-check-inline">
{% render_field form.is_cable|add_class:'form-check-input' %}
<label class="form-check-label" for="is_cable">Only Cables?</label>
</div>
</div>
<div class="col-auto">
<div class="form-group d-flex flex-nowrap">
<label for="date_acquired" class="text-nowrap mt-auto">Date Acquired</label>
{% render_field form.date_acquired|add_class:'form-control mx-2' %}
</div>
</div>
<div class="col-auto mr-auto">
<button id="filter-submit" type="submit" class="btn btn-secondary" style="width: 6em">Filter</button>
</div>
</div>
</form> </form>
</div> </div>
</div> </div>

View File

@@ -61,9 +61,6 @@ class AssetList(LoginRequiredMixin, generic.ListView):
if form.cleaned_data['is_cable']: if form.cleaned_data['is_cable']:
queryset = queryset.filter(is_cable=True) queryset = queryset.filter(is_cable=True)
if form.cleaned_data['date_acquired']:
queryset = queryset.filter(date_acquired=form.cleaned_data['date_acquired'])
if form.cleaned_data['category']: if form.cleaned_data['category']:
queryset = queryset.filter(category__in=form.cleaned_data['category']) queryset = queryset.filter(category__in=form.cleaned_data['category'])

29
package-lock.json generated
View File

@@ -10173,19 +10173,12 @@
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
}, },
"copy-props": { "copy-props": {
"version": "2.0.5", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz",
"integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==",
"requires": { "requires": {
"each-props": "^1.3.2", "each-props": "^1.3.0",
"is-plain-object": "^5.0.0" "is-plain-object": "^2.0.1"
},
"dependencies": {
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
}
} }
}, },
"core-util-is": { "core-util-is": {
@@ -11178,9 +11171,9 @@
} }
}, },
"follow-redirects": { "follow-redirects": {
"version": "1.14.7", "version": "1.14.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
"dev": true "dev": true
}, },
"for-in": { "for-in": {
@@ -12899,9 +12892,9 @@
} }
}, },
"marked": { "marked": {
"version": "4.0.10", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.8.tgz",
"integrity": "sha512-+QvuFj0nGgO970fySghXGmuw+Fd0gD2x3+MqCWLIPf5oxdv1Ka6b2q+z9RP01P/IaKPMEramy+7cNy/Lw8c3hw==" "integrity": "sha512-dkpJMIlJpc833hbjjg8jraw1t51e/eKDoG8TFOgc5O0Z77zaYKigYekTDop5AplRoKFGIaoazhYEhGkMtU3IeA=="
}, },
"matchdep": { "matchdep": {
"version": "2.0.0", "version": "2.0.0",

View File

@@ -48,7 +48,6 @@ class Command(BaseCommand):
if profile: if profile:
self.id_map[child.find('ID').text] = profile.pk self.id_map[child.find('ID').text] = profile.pk
print(f"Found existing user {profile}, matching data")
tally[0] += 1 tally[0] += 1
else: else:
# PYTHONIC, BABY # PYTHONIC, BABY
@@ -60,7 +59,6 @@ class Command(BaseCommand):
initials=initials) initials=initials)
self.id_map[child.find('ID').text] = new_profile.pk self.id_map[child.find('ID').text] = new_profile.pk
tally[1] += 1 tally[1] += 1
print(f"No match found, creating new user {new_profile}")
except AttributeError: # W.T.F except AttributeError: # W.T.F
print("Trainee #{} is FUBAR".format(child.find('ID').text)) print("Trainee #{} is FUBAR".format(child.find('ID').text))

View File

@@ -97,17 +97,17 @@ class TraineeList(generic.ListView):
def get_queryset(self): def get_queryset(self):
q = self.request.GET.get('q', "") q = self.request.GET.get('q', "")
filt = Q(first_name__icontains=q) | Q(last_name__icontains=q) | Q(initials__icontains=q) fil = Q(first_name__icontains=q) | Q(last_name__icontains=q) | Q(initials__icontains=q)
# try and parse an int # try and parse an int
try: try:
val = int(q) val = int(q)
filt = filt | Q(pk=val) fil = fil | Q(pk=val)
except: # noqa except: # noqa
# not an integer # not an integer
pass pass
return self.model.objects.filter(filt).annotate(num_qualifications=Count('qualifications_obtained')).order_by('-num_qualifications').prefetch_related('level_qualifications', 'qualifications_obtained', 'qualifications_obtained__item') return self.model.objects.filter(filter).annotate(num_qualifications=Count('qualifications_obtained')).order_by('-num_qualifications').prefetch_related('level_qualifications', 'qualifications_obtained', 'qualifications_obtained__item')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)

View File

@@ -1,3 +1,5 @@
import logging
from diff_match_patch import diff_match_patch from diff_match_patch import diff_match_patch
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
@@ -5,42 +7,9 @@ from django.db.models import EmailField, IntegerField, TextField, CharField, Boo
from django.utils.functional import cached_property from django.utils.functional import cached_property
from reversion.models import Version, VersionQuerySet from reversion.models import Version, VersionQuerySet
from RIGS import models
class RevisionMixin: logger = logging.getLogger('tec.pyrigs')
@property
def is_first_version(self):
versions = Version.objects.get_for_object(self)
return len(versions) == 1
@property
def current_version(self):
version = Version.objects.get_for_object(self).select_related('revision').first()
return version
@property
def last_edited_at(self):
version = self.current_version
if version is None:
return None
return version.revision.date_created
@property
def last_edited_by(self):
version = self.current_version
if version is None:
return None
return version.revision.user
@property
def current_version_id(self):
version = self.current_version
if version is None:
return None
return "V{0} | R{1}".format(version.pk, version.revision.pk)
@property
def date_created(self):
return self.current_version.revision.date_created
class FieldComparison: class FieldComparison:
@@ -147,11 +116,10 @@ class ModelComparison:
@cached_property @cached_property
def item_changes(self): def item_changes(self):
from RIGS.models import EventAuthorisation
if self.follow and self.version.object is not None: if self.follow and self.version.object is not None:
item_type = ContentType.objects.get_for_model(self.version.object) item_type = ContentType.objects.get_for_model(self.version.object)
old_item_versions = self.version.parent.revision.version_set.exclude(content_type=item_type) old_item_versions = self.version.parent.revision.version_set.exclude(content_type=item_type)
new_item_versions = self.version.revision.version_set.exclude(content_type=item_type).exclude(content_type=ContentType.objects.get_for_model(EventAuthorisation)) new_item_versions = self.version.revision.version_set.exclude(content_type=item_type).exclude(content_type=ContentType.objects.get_for_model(models.EventAuthorisation))
comparisonParams = {'excluded_keys': ['id', 'event', 'order', 'checklist', 'level', '_order', 'date_joined']} comparisonParams = {'excluded_keys': ['id', 'event', 'order', 'checklist', 'level', '_order', 'date_joined']}