aa-structures 2.13.0__py3-none-any.whl → 2.14.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aa_structures-2.13.0.dist-info → aa_structures-2.14.1.dist-info}/METADATA +1 -1
- {aa_structures-2.13.0.dist-info → aa_structures-2.14.1.dist-info}/RECORD +29 -29
- structures/__init__.py +1 -1
- structures/admin.py +1 -1
- structures/app_settings.py +4 -0
- structures/constants.py +1 -0
- structures/core/notification_timers.py +53 -6
- structures/core/notification_types.py +1 -0
- structures/managers.py +13 -2
- structures/models/owners.py +82 -12
- structures/models/structures_1.py +5 -0
- structures/templates/structures/partials/structures/{poco_list.html → orbital_list.html} +1 -1
- structures/templates/structures/partials/structures/starbase_list.html +1 -1
- structures/templates/structures/public.html +2 -2
- structures/templates/structures/structures.html +5 -5
- structures/tests/core/{test_notifications_timerboard.py → test_notifications_timers.py} +6 -1
- structures/tests/integration/test_tasks.py +102 -1
- structures/tests/integration/test_views.py +1 -1
- structures/tests/models/test_owners_2.py +14 -0
- structures/tests/models/test_owners_5.py +135 -1
- structures/tests/models/test_structures.py +49 -42
- structures/tests/test_managers_1.py +11 -1
- structures/tests/testdata/factories.py +21 -0
- structures/tests/testdata/helpers.py +6 -0
- structures/tests/views/test_structures.py +12 -4
- structures/views/structures.py +6 -6
- {aa_structures-2.13.0.dist-info → aa_structures-2.14.1.dist-info}/LICENSE +0 -0
- {aa_structures-2.13.0.dist-info → aa_structures-2.14.1.dist-info}/WHEEL +0 -0
- /structures/templates/structures/partials/structures/{jump_gates_list.html → jump_gate_list.html} +0 -0
@@ -1,18 +1,18 @@
|
|
1
|
-
structures/__init__.py,sha256=
|
2
|
-
structures/admin.py,sha256=
|
3
|
-
structures/app_settings.py,sha256=
|
1
|
+
structures/__init__.py,sha256=AKjtjd55mt0eK2ld7jC0D_ZbzHd-XxjqCBgxuBaz_vQ,204
|
2
|
+
structures/admin.py,sha256=cA04JFghU-zIGC168fhZ5Hj_FYAQxlF6TFVDb8sgO4A,40066
|
3
|
+
structures/app_settings.py,sha256=aWA2bTcv_vVwIyisx-G7GBSpfM6JDyt2MWcXKtHnjK0,6651
|
4
4
|
structures/apps.py,sha256=MNZH9l3qWCwuS7OGiKGkBVrDzKoOFlqwDdEgyEFzxVA,195
|
5
5
|
structures/auth_hooks.py,sha256=nRbrixFkAE5gphDokB1E8xhH8FY2VtXVwu0XMmSGBAw,1013
|
6
|
-
structures/constants.py,sha256=
|
6
|
+
structures/constants.py,sha256=12iIVgFWSNaH1iYBByrsv3OQKCnNxluuckOdrfgzWzA,995
|
7
7
|
structures/forms.py,sha256=kXs-SGIIj-D9xtFCILKe_PMRU4eHl3-HLNWRhaZKmnQ,391
|
8
8
|
structures/helpers.py,sha256=_dw7j7yobpcV70VwWxoQiptk69b3ksvaDlRQKHg8Kmg,2344
|
9
|
-
structures/managers.py,sha256=
|
9
|
+
structures/managers.py,sha256=6zGvmiP1_TZ1uZlPTxNFYgJ77JIjY3uw2PmYeyrJ10E,20063
|
10
10
|
structures/providers.py,sha256=9QYHd8X5HwBhrbgbX3LUrXXV1KGM3hFhcxK6qIJjJtg,317
|
11
11
|
structures/tasks.py,sha256=INZ3soMYHYfxrQsyTO-ozoxbVX6lpMnF3AUo8ybWIoA,9083
|
12
12
|
structures/urls.py,sha256=An5v27AD_NXMNL66cMVtQNci1C_Aqry32rrvDkMpgYo,1467
|
13
13
|
structures/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
structures/core/notification_timers.py,sha256=
|
15
|
-
structures/core/notification_types.py,sha256=
|
14
|
+
structures/core/notification_timers.py,sha256=KLjkVrlCCKTWtHJNUfI3U6ppAIZN8vPnIx1zCafRkKQ,16748
|
15
|
+
structures/core/notification_types.py,sha256=Ebl4i-mvyGe4luxeNiPmxf7T9bmghe8NU5Giu9pqPCo,13262
|
16
16
|
structures/core/serializers.py,sha256=4W6kA7mhVvc-1OSiTl_w0rSio_HUsjIBm9qbkEr9vCY,20965
|
17
17
|
structures/core/sovereignty.py,sha256=XKgjAFO4BfLpEEUz_hBr2DVDnvWBq9sL9EEQiT4T0n0,730
|
18
18
|
structures/core/starbases.py,sha256=nw7skHYATrnAV-zuPAuxmhM5E4Aqjc_DHSU2TYWgBng,1757
|
@@ -65,8 +65,8 @@ structures/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
65
65
|
structures/models/__init__.py,sha256=Da0-Z4BtsZ_mlnI6XtyvoE0UtTuOA0psGCuVhVPVKrM,916
|
66
66
|
structures/models/eveuniverse.py,sha256=vTIfzZL9guEDuZHQvRdG6pI4zSEdMqfVE-2SkHdqbRo,2213
|
67
67
|
structures/models/notifications.py,sha256=HwQc-ChdP0ULuJgxUym9_CBsCWCmcHT7whlk9tB2vzw,35364
|
68
|
-
structures/models/owners.py,sha256=
|
69
|
-
structures/models/structures_1.py,sha256=
|
68
|
+
structures/models/owners.py,sha256=7CKpwHlw4Nz8lTJUgQZxI-GHon5FrlMEILxe7q7Vfgg,58391
|
69
|
+
structures/models/structures_1.py,sha256=zk380uG2DuQ7exO7THbq5TE5Ro2jr6EyVCIxRJXHIJI,29958
|
70
70
|
structures/models/structures_2.py,sha256=g5Pct5jNmZC-n7fnpLs5UyiP9JLrGdI1vjYucHTV_wQ,10371
|
71
71
|
structures/static/structures/css/global.css,sha256=R4LEH9PwLoN77qkqBK7u2y_vzRC3fq8X_zKnAW7yhiA,1165
|
72
72
|
structures/static/structures/css/main.css,sha256=kNgHhC3tVG376h8-6b71MtiERhYZ48cTIno5Kj6ZFGo,303
|
@@ -134,9 +134,9 @@ structures/static/structures/vendor/datatables/plugins/filterDropDown.min.js,sha
|
|
134
134
|
structures/static/structures/vendor/datatables/plugins/rowGroup.bootstrap.min.css,sha256=mfb-mieZDwLASMlQTUNXrZQr8OXvQyEDfV3Xz3E7DSU,384
|
135
135
|
structures/static/structures/vendor/datatables/plugins/rowGroup.dataTables.min.css,sha256=mfb-mieZDwLASMlQTUNXrZQr8OXvQyEDfV3Xz3E7DSU,384
|
136
136
|
structures/templates/structures/base.html,sha256=ND0JjP2Pa537FXOrIj3cziHfDbTh0ZNzrLFJ_zpVhw8,337
|
137
|
-
structures/templates/structures/public.html,sha256=
|
137
|
+
structures/templates/structures/public.html,sha256=R3kjhr1MLC5r9r8L3t-1-Nh7-ngKbRiiZNIwgpsGg70,3239
|
138
138
|
structures/templates/structures/statistics.html,sha256=rVI_wPW4VXIO3IoWna8_GoqWCc5ra-6Jc9iekfusS78,1736
|
139
|
-
structures/templates/structures/structures.html,sha256=
|
139
|
+
structures/templates/structures/structures.html,sha256=q0c7Wlaxvt2dg1B236JIEmmSBgQyX5F_QlBLokt-W0E,8329
|
140
140
|
structures/templates/structures/modals/fitting_assets.html,sha256=0GSpDAk-wgvaZdxM9JzteUYhoPsek5y-L4TdG2q5Sbg,264
|
141
141
|
structures/templates/structures/modals/fitting_gfx.html,sha256=hmdU1Zv09woGKigUugbBRxScKQun8l81yEPUMGrok2g,9530
|
142
142
|
structures/templates/structures/modals/poco_details.html,sha256=uwaEM0jDvkdu_Lff2mUKwm7pn1KXePcgN9yBwFHsQO4,2705
|
@@ -148,9 +148,9 @@ structures/templates/structures/partials/menu.html,sha256=pxN_Tvo_vON0Fauyg_XPYl
|
|
148
148
|
structures/templates/structures/partials/public/poco_list.html,sha256=tVAsGXS7rh7Qr5x2X26buyt7jwJJ-YoNLs9eMs0gDM4,1222
|
149
149
|
structures/templates/structures/partials/statistics/structure_summary.html,sha256=ZCEBOPhfOUyih7C8TzaQi9OI2AsMzZGBb9ZGHsShzmk,1133
|
150
150
|
structures/templates/structures/partials/structures/active_tags.html,sha256=KhYA6LbAqg-iJJ2J4BGACXdbdiZFM4wAgDEq2RQEu0s,106
|
151
|
-
structures/templates/structures/partials/structures/
|
152
|
-
structures/templates/structures/partials/structures/
|
153
|
-
structures/templates/structures/partials/structures/starbase_list.html,sha256=
|
151
|
+
structures/templates/structures/partials/structures/jump_gate_list.html,sha256=1hhx21fz1YAKTRK0E5FYP8uYTlXCFnm9FAdechiopx8,1470
|
152
|
+
structures/templates/structures/partials/structures/orbital_list.html,sha256=uWV-61WUk1hyTCXgIkMuiAhof4VIP02bnH5N5nqaCCo,1070
|
153
|
+
structures/templates/structures/partials/structures/starbase_list.html,sha256=Djl3nsTSn9TIZ6k4F0hiF-qDv_rLiVSIapnWUz0bvqU,1412
|
154
154
|
structures/templates/structures/partials/structures/structure_list.html,sha256=2EHP1xJrmDNhwENhxGY3L6YbC53qFwhnDHcFzxkNXpI,1421
|
155
155
|
structures/templates/structures/templatetags/detail_title.html,sha256=PWoYNZhTt1ngDEdz_B4TlyC7duO-8MxgznSUb27lUDA,117
|
156
156
|
structures/templates/structures/templatetags/list_asset.html,sha256=6wWndrdBlWbOMIQlGaqeUtSfk-c6F3ZQMYErZJ4H7SM,375
|
@@ -162,13 +162,13 @@ structures/templatetags/structures.py,sha256=vSt5AnfYuo11q1SxiskT4oshSMsZ9ZgM0nY
|
|
162
162
|
structures/tests/__init__.py,sha256=9MrJzKr8DdsQY3-79v188pTpwqT4TDQ46vKnBJAGqic,75
|
163
163
|
structures/tests/test_admin.py,sha256=cb_AbOanp31k-oZhaUXCqnlkUu87EgNddq_VQKbB_Dk,26839
|
164
164
|
structures/tests/test_helpers.py,sha256=BQC-4H-9-v5qW4nugqy0bkxuGlA3UO2clYY2lI2LjoY,4893
|
165
|
-
structures/tests/test_managers_1.py,sha256=
|
165
|
+
structures/tests/test_managers_1.py,sha256=4dnlK7Le04eJUPjJc9ex5BxZWIJGAyEvdKuuYXU2gqY,34846
|
166
166
|
structures/tests/test_managers_2.py,sha256=FISr_NT1Qnu9j1JYYTceNsUk8k9rfCTKwjKi5WUVbPs,3025
|
167
167
|
structures/tests/test_tasks.py,sha256=reL1rPv_kvTgsC4lq5SXulkbEHaJrw5B1-hFI4tiDWY,17269
|
168
168
|
structures/tests/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
169
169
|
structures/tests/core/test_notification_structuretimers.py,sha256=OvldjgIHmRVsqoC9C6VJRqwS9WeRFMgpyutRc69PjAU,10857
|
170
170
|
structures/tests/core/test_notification_types.py,sha256=2J5A8Dr9UHhzLEj6QTMty5iZXlNkQxtFmLvU8Wpdno4,10447
|
171
|
-
structures/tests/core/
|
171
|
+
structures/tests/core/test_notifications_timers.py,sha256=7Os0xmrfDV2zJeBOFYb7K1KGcwpVHq36IglOdjps6Ac,5915
|
172
172
|
structures/tests/core/test_serializers.py,sha256=ACs6x1IhesoJBFG76RmlglDWqaMlOuqq5kPyzvjGeKI,7056
|
173
173
|
structures/tests/core/test_sovereignty.py,sha256=SGgNw6NxmaU3jV-EDhKJRLfHnRnqDCwm4oCoO-8gt9w,821
|
174
174
|
structures/tests/core/test_starbases.py,sha256=Q3EZVIKZGzxUUvvn0TvZYOL9YQ-baiTRTT83xWqTAhQ,3186
|
@@ -176,8 +176,8 @@ structures/tests/core/notification_embeds/__init__.py,sha256=47DEQpj8HBSa-_TImW-
|
|
176
176
|
structures/tests/core/notification_embeds/test_helpers.py,sha256=HG20TC8Bz7NqpaQWo6uvrsxfNIwTL2Zi_NRkh3UyN2Y,1776
|
177
177
|
structures/tests/core/notification_embeds/test_main.py,sha256=rSUm8dGsddjnX_OUwtCh-wd5UhJ6ttTsfxc1soAoDv8,14667
|
178
178
|
structures/tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
179
|
-
structures/tests/integration/test_tasks.py,sha256=
|
180
|
-
structures/tests/integration/test_views.py,sha256=
|
179
|
+
structures/tests/integration/test_tasks.py,sha256=uhl7TJNELrL1vSDaRee0xEKNMLJuVqRIM32cIVUa_h4,27217
|
180
|
+
structures/tests/integration/test_views.py,sha256=qlw1VzlyGW_xnWC-Ii16IHECO-F2x25sYbXeqz2T8IY,4364
|
181
181
|
structures/tests/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
182
182
|
structures/tests/models/test_eveuniverse.py,sha256=bQ1upOLfoivfaa9KCrzjWvSH_EvL2STuvfFfZ9saIMY,1623
|
183
183
|
structures/tests/models/test_notifications_1.py,sha256=xVX4an54sZM8WLUdsAGUG2Nb4Rl7W5FBzhI0hBhJo5g,30300
|
@@ -185,22 +185,22 @@ structures/tests/models/test_notifications_2.py,sha256=wBoB6lHMK4yrd63DSkZ570yXW
|
|
185
185
|
structures/tests/models/test_notifications_3.py,sha256=u11s0k9EmtFgL3kyb4zDyLVliQLOps701ZgEA2T2i0Y,7257
|
186
186
|
structures/tests/models/test_notifications_discord.py,sha256=6maDXjl2C5yH2XRgsvMtb3P-tfOdZLQDaksffiqS8OM,6312
|
187
187
|
structures/tests/models/test_owners_1.py,sha256=o8AJasQ0-Pdb0FRFZcmNcMGjaIk8fH3OZIZw4paJiDw,24433
|
188
|
-
structures/tests/models/test_owners_2.py,sha256=
|
188
|
+
structures/tests/models/test_owners_2.py,sha256=GZYdsFey6bQHuk9BiT1KFT_vW01mUHRtDxJRHPEmrC4,22539
|
189
189
|
structures/tests/models/test_owners_3.py,sha256=cpDkfFkVvC1v4uuXha1vGUmWZ163huYTUDuZyed9Rdc,16947
|
190
190
|
structures/tests/models/test_owners_4.py,sha256=_VP4QsPYGwBnn_bVN4aNX2ZVeJzMAzWObZrgCJkOPgY,19496
|
191
|
-
structures/tests/models/test_owners_5.py,sha256=
|
191
|
+
structures/tests/models/test_owners_5.py,sha256=TIF_SqJqyGja8FBV2lQNAC4yff1usmJ4e0QW7e68zTg,36929
|
192
192
|
structures/tests/models/test_owners_6.py,sha256=R9UE2QGwiGTWLHzzOZwGQPWJrAPwIIl7UwrHH-ki4Ak,940
|
193
|
-
structures/tests/models/test_structures.py,sha256=
|
193
|
+
structures/tests/models/test_structures.py,sha256=iCCa0yYyPHieNfj8TQbdoIv141oLc6hlICZ6AsTnHAw,41849
|
194
194
|
structures/tests/testdata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
195
195
|
structures/tests/testdata/create_eveuniverse.py,sha256=6CYgXtJaEwxWvQFyH-P0SKsRqeMuSyJ92ZJiXe_-nuY,2256
|
196
196
|
structures/tests/testdata/entities.json,sha256=vmb0uhwTpD0gycGAakgYidr3qSbnHiMubAd4u7T2l70,36053
|
197
197
|
structures/tests/testdata/esi_data.json,sha256=DX47oSlRZIPxlPueMfiNElbZbAip2cp3LAUmv8GAPJ0,13864
|
198
198
|
structures/tests/testdata/eveuniverse.json,sha256=3fhD72lUNLj96wO4ASbpNcdH_8VbqcXUvKUXR6j0768,1028885
|
199
|
-
structures/tests/testdata/factories.py,sha256=
|
199
|
+
structures/tests/testdata/factories.py,sha256=UF7Zao2-DjVFLZLEBWaJv4Pg1uw5D6p0TO8ZKuoAI_8,25293
|
200
200
|
structures/tests/testdata/generate_notifications.py,sha256=lhcnbsnE4O6g0OFUAYO2sCfu8vmwBcFtxn-TuTLtFnM,5417
|
201
201
|
structures/tests/testdata/generate_notifications_2.py,sha256=mdoGXd9vgy_opmrwTr9MfGe-QieHV4BHtRA7VFzxFKM,1413
|
202
202
|
structures/tests/testdata/generate_structures.py,sha256=4p2ypDj-goniBnraTP2KfWzEX3YLj0qhKPNTfCXy05g,9134
|
203
|
-
structures/tests/testdata/helpers.py,sha256=
|
203
|
+
structures/tests/testdata/helpers.py,sha256=FSlg7-6Dn3aMQnQPUnH9o9r8WsV1_BYxElm-E9x_5uo,6316
|
204
204
|
structures/tests/testdata/load_eveuniverse.py,sha256=e3XQNYZXwmhfLQdvO4D1dfbSwhF1Zwr3ag9nG9E3XDM,395
|
205
205
|
structures/tests/testdata/tasks_loadtest.py,sha256=Hn0UVeaMfdi5S4W12lsb6g_xwjQcNYDmeXvQdTsPfBM,963
|
206
206
|
structures/tests/testdata/test_generate_structures.py,sha256=vpReGRROduZsGB99Dq7yPKNKSkSLFdLM_esdf5TTnnI,414
|
@@ -208,14 +208,14 @@ structures/tests/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
208
208
|
structures/tests/views/test_public.py,sha256=FTaT3VUOnoT4t9rCCTCGyDrberpa8CRJHsXuqAw2PQE,1372
|
209
209
|
structures/tests/views/test_service_status.py,sha256=mWkP13HnKRa3ltsZ2FKJuZRJjvYic9wjgQ1J3qA8n-k,4197
|
210
210
|
structures/tests/views/test_statistics.py,sha256=MHt31AIX9_jt8-yP8XsbsiRRUKEtY8mQJbk11saFYZc,2626
|
211
|
-
structures/tests/views/test_structures.py,sha256=
|
211
|
+
structures/tests/views/test_structures.py,sha256=KbD3RqUKhWxcRsHfZbgyNHWj7Z9bJt7wOj45s0y17EY,28489
|
212
212
|
structures/tests/views/utils.py,sha256=0ALPjL8d0vcIWa_Pl4_gDl1qtBp71oDqyZLJyvDj-Uc,247
|
213
213
|
structures/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
214
214
|
structures/views/common.py,sha256=Z_hcpEpkGrhwFdMAAMON_DqsfQ_lMyRwOMl5ROo_aSk,818
|
215
215
|
structures/views/public.py,sha256=-Tel-poYKZTy8eQllhsWUxVf7HYBuCfeL9JWlbKhs7s,3035
|
216
216
|
structures/views/statistics.py,sha256=7jj8b9ATsYwE7Cg6gMp-bYx29nV43GdWYun9WBggGkM,4709
|
217
217
|
structures/views/status.py,sha256=gcahbk6dPIZDqkaNHDAsEHyDWLzicTK18Fom0A6xx3c,718
|
218
|
-
structures/views/structures.py,sha256=
|
218
|
+
structures/views/structures.py,sha256=Wb57jFfRa0Zxo6TxKmOCQ-jtopzPtHe0go6gnJn40CA,22584
|
219
219
|
structures/webhooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
220
|
structures/webhooks/core.py,sha256=mP25MbQG8Yv2YayDFcR6x2V30eqXhR2q5u4SRefblf4,6573
|
221
221
|
structures/webhooks/managers.py,sha256=L3G3AmsyDeif_lfpWshmAxQ61UGJ9w8i9lZaF2jbOtQ,1117
|
@@ -223,7 +223,7 @@ structures/webhooks/models.py,sha256=kUkt9rnRQIJIrU9Bjcs34rvkb-TMbUubHdn-kny08kI
|
|
223
223
|
structures/webhooks/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
224
224
|
structures/webhooks/tests/test_core.py,sha256=4NcEAQgK2KhQkFOxYh2ad0S-qUWh1DNGDmLo5Mo5opI,6762
|
225
225
|
structures/webhooks/tests/test_utils.py,sha256=ekADFv0JOEtXeqdiejbeqrABO__Q1flJHzVieQ7L9e0,459
|
226
|
-
aa_structures-2.
|
227
|
-
aa_structures-2.
|
228
|
-
aa_structures-2.
|
229
|
-
aa_structures-2.
|
226
|
+
aa_structures-2.14.1.dist-info/LICENSE,sha256=XZiwB_S_40_HhnvLg5xvtBb3g1oGjPrk0rpFwk8iInE,1070
|
227
|
+
aa_structures-2.14.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
228
|
+
aa_structures-2.14.1.dist-info/METADATA,sha256=9vdeZ6CyZ-97fnE0YXmYsN_w_T8TUBRfj840AVZgN0w,5972
|
229
|
+
aa_structures-2.14.1.dist-info/RECORD,,
|
structures/__init__.py
CHANGED
structures/admin.py
CHANGED
@@ -324,7 +324,7 @@ class NotificationBaseAdmin(admin.ModelAdmin):
|
|
324
324
|
message = format_lazy("{first} {second}", first=first, second=second)
|
325
325
|
else:
|
326
326
|
message = first
|
327
|
-
message = format_lazy(
|
327
|
+
message = format_lazy(first)
|
328
328
|
self.message_user(request, message)
|
329
329
|
|
330
330
|
|
structures/app_settings.py
CHANGED
@@ -49,6 +49,10 @@ STRUCTURES_FEATURE_REFUELED_NOTIFICATIONS = clean_setting(
|
|
49
49
|
)
|
50
50
|
"""Enable / disable refueled notifications feature."""
|
51
51
|
|
52
|
+
STRUCTURES_FEATURE_SKYHOOKS = clean_setting("STRUCTURES_FEATURE_SKYHOOKS", False)
|
53
|
+
"""Show skyhooks in structures list."""
|
54
|
+
|
55
|
+
|
52
56
|
STRUCTURES_FEATURE_STARBASES = clean_setting("STRUCTURES_FEATURE_STARBASES", True)
|
53
57
|
"""Enable / disable starbases feature."""
|
54
58
|
|
structures/constants.py
CHANGED
@@ -53,7 +53,9 @@ def add_or_remove_timer(notif: Notification) -> bool:
|
|
53
53
|
elif notif.notif_type == NotificationType.SOV_STRUCTURE_REINFORCED:
|
54
54
|
timer_processed = _gen_timer_sov_reinforcements(notif)
|
55
55
|
elif notif.notif_type == NotificationType.ORBITAL_REINFORCED:
|
56
|
-
timer_processed =
|
56
|
+
timer_processed = _gen_timer_customs_office_reinforcements(notif)
|
57
|
+
elif notif.notif_type == NotificationType.SKYHOOK_LOST_SHIELDS:
|
58
|
+
timer_processed = _gen_timer_skyhook_reinforcements(notif)
|
57
59
|
elif notif.notif_type in [
|
58
60
|
NotificationType.MOONMINING_EXTRACTION_STARTED,
|
59
61
|
NotificationType.MOONMINING_EXTRACTION_CANCELLED,
|
@@ -65,9 +67,7 @@ def add_or_remove_timer(notif: Notification) -> bool:
|
|
65
67
|
elif notif.notif_type == NotificationType.TOWER_REINFORCED_EXTRA:
|
66
68
|
timer_processed = _gen_timer_tower_reinforcements(notif)
|
67
69
|
else:
|
68
|
-
raise NotImplementedError(
|
69
|
-
f"Unsupported notification type for timers: {notif.notif_type}"
|
70
|
-
)
|
70
|
+
raise NotImplementedError(notif.notif_type)
|
71
71
|
if timer_processed:
|
72
72
|
logger.info("%s: Created timer for notification", notif.notification_id)
|
73
73
|
notif.is_timer_added = True
|
@@ -181,8 +181,8 @@ def _gen_timer_sov_reinforcements(notif: Notification) -> bool:
|
|
181
181
|
return timer_processed
|
182
182
|
|
183
183
|
|
184
|
-
def
|
185
|
-
"""Generate timer for
|
184
|
+
def _gen_timer_customs_office_reinforcements(notif: Notification) -> bool:
|
185
|
+
"""Generate timer for customs office reinforcements."""
|
186
186
|
|
187
187
|
solar_system = notif.eve_solar_system()
|
188
188
|
planet = notif.eve_planet()
|
@@ -231,6 +231,53 @@ def _gen_timer_orbital_reinforcements(notif: Notification) -> bool:
|
|
231
231
|
return timer_processed
|
232
232
|
|
233
233
|
|
234
|
+
def _gen_timer_skyhook_reinforcements(notif: Notification) -> bool:
|
235
|
+
"""Generate timer for skyhook reinforcements."""
|
236
|
+
|
237
|
+
solar_system = notif.eve_solar_system("solarsystemID")
|
238
|
+
structure_type = notif.eve_structure_type("typeID")
|
239
|
+
planet = notif.eve_planet()
|
240
|
+
eve_time = ldap_time_2_datetime(notif.parsed_text()["timestamp"])
|
241
|
+
timer_processed = False
|
242
|
+
|
243
|
+
if AuthTimer:
|
244
|
+
AuthTimer.objects.create(
|
245
|
+
details=gettext("Final timer"),
|
246
|
+
system=solar_system.name,
|
247
|
+
planet_moon=planet.name,
|
248
|
+
structure="POCO", # Auth timer does not support the Skyhook type yet
|
249
|
+
objective="Friendly",
|
250
|
+
eve_time=eve_time,
|
251
|
+
eve_corp=notif.owner.corporation,
|
252
|
+
corp_timer=STRUCTURES_TIMERS_ARE_CORP_RESTRICTED,
|
253
|
+
)
|
254
|
+
timer_processed = True
|
255
|
+
|
256
|
+
if Timer:
|
257
|
+
visibility = (
|
258
|
+
Timer.Visibility.CORPORATION
|
259
|
+
if STRUCTURES_TIMERS_ARE_CORP_RESTRICTED
|
260
|
+
else Timer.Visibility.UNRESTRICTED
|
261
|
+
)
|
262
|
+
Timer.objects.create(
|
263
|
+
eve_solar_system=solar_system,
|
264
|
+
structure_type=structure_type,
|
265
|
+
timer_type=Timer.Type.FINAL,
|
266
|
+
objective=Timer.Objective.FRIENDLY,
|
267
|
+
date=eve_time,
|
268
|
+
location_details=planet.name,
|
269
|
+
eve_corporation=notif.owner.corporation,
|
270
|
+
eve_alliance=notif.owner.corporation.alliance,
|
271
|
+
visibility=visibility,
|
272
|
+
structure_name=structure_type.name,
|
273
|
+
owner_name=notif.owner.corporation.corporation_name,
|
274
|
+
details_notes=_timer_details_notes(notif),
|
275
|
+
)
|
276
|
+
timer_processed = True
|
277
|
+
|
278
|
+
return timer_processed
|
279
|
+
|
280
|
+
|
234
281
|
def _gen_timer_moon_extraction(notif: Notification) -> bool:
|
235
282
|
"""Generate timer for moon mining extractions."""
|
236
283
|
solar_system = notif.eve_solar_system()
|
structures/managers.py
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
# pylint: disable=missing-class-docstring
|
4
4
|
|
5
|
+
from __future__ import annotations
|
6
|
+
|
5
7
|
import datetime as dt
|
6
8
|
import itertools
|
7
|
-
from typing import Any, Iterable, Optional, Set, Tuple
|
9
|
+
from typing import TYPE_CHECKING, Any, Iterable, Optional, Set, Tuple
|
8
10
|
|
9
11
|
from django.contrib.auth.models import User
|
10
12
|
from django.db import models, transaction
|
@@ -24,6 +26,9 @@ from .core.notification_types import NotificationType
|
|
24
26
|
from .providers import esi
|
25
27
|
from .webhooks.managers import WebhookBaseManager
|
26
28
|
|
29
|
+
if TYPE_CHECKING:
|
30
|
+
from .models import Owner
|
31
|
+
|
27
32
|
logger = LoggerAddTag(get_extension_logger(__name__), __title__)
|
28
33
|
|
29
34
|
|
@@ -231,6 +236,10 @@ class StructureQuerySet(models.QuerySet):
|
|
231
236
|
"""Filter for starbases."""
|
232
237
|
return self.filter(eve_type__eve_group__eve_category=EveCategoryId.STARBASE)
|
233
238
|
|
239
|
+
def filter_skyhooks(self) -> models.QuerySet:
|
240
|
+
"""Filter for skyhooks."""
|
241
|
+
return self.filter(eve_type=EveTypeId.ORBITAL_SKYHOOK)
|
242
|
+
|
234
243
|
def ids(self) -> Set[int]:
|
235
244
|
"""Return ids as set."""
|
236
245
|
return set(self.values_list("id", flat=True))
|
@@ -380,7 +389,9 @@ class StructureManagerBase(models.Manager):
|
|
380
389
|
obj, created = self.update_or_create_from_dict(structure=structure, owner=owner)
|
381
390
|
return obj, created
|
382
391
|
|
383
|
-
def update_or_create_from_dict(
|
392
|
+
def update_or_create_from_dict(
|
393
|
+
self, structure: dict, owner: Owner
|
394
|
+
) -> Tuple[Any, bool]:
|
384
395
|
"""update or create structure from given dict"""
|
385
396
|
|
386
397
|
eve_type: EveType = EveType.objects.get_or_create_esi(id=structure["type_id"])[
|
structures/models/owners.py
CHANGED
@@ -37,6 +37,7 @@ from structures.app_settings import (
|
|
37
37
|
STRUCTURES_DEVELOPER_MODE,
|
38
38
|
STRUCTURES_ESI_DIRECTOR_ERROR_MAX_RETRIES,
|
39
39
|
STRUCTURES_FEATURE_CUSTOMS_OFFICES,
|
40
|
+
STRUCTURES_FEATURE_SKYHOOKS,
|
40
41
|
STRUCTURES_FEATURE_STARBASES,
|
41
42
|
STRUCTURES_HOURS_UNTIL_STALE_NOTIFICATION,
|
42
43
|
STRUCTURES_NOTIFICATION_SYNC_GRACE_MINUTES,
|
@@ -545,14 +546,14 @@ class Owner(models.Model):
|
|
545
546
|
)
|
546
547
|
|
547
548
|
def _remove_structures_not_returned_from_esi(
|
548
|
-
self,
|
549
|
+
self, existing_structures: models.QuerySet, new_structures: Iterable[dict]
|
549
550
|
):
|
550
551
|
"""Remove structures no longer returned from ESI."""
|
551
|
-
ids_local = {x.id for x in
|
552
|
+
ids_local = {x.id for x in existing_structures}
|
552
553
|
ids_from_esi = {x["structure_id"] for x in new_structures}
|
553
554
|
ids_to_remove = ids_local - ids_from_esi
|
554
555
|
if len(ids_to_remove) > 0:
|
555
|
-
|
556
|
+
existing_structures.filter(id__in=ids_to_remove).delete()
|
556
557
|
logger.info(
|
557
558
|
"Removed %d structures which apparently no longer exist.",
|
558
559
|
len(ids_to_remove),
|
@@ -591,7 +592,7 @@ class Owner(models.Model):
|
|
591
592
|
is_ok = True
|
592
593
|
# fetch main list of structure for this corporation
|
593
594
|
try:
|
594
|
-
structures = (
|
595
|
+
structures: List[dict] = (
|
595
596
|
esi.client.Corporation.get_corporations_corporation_id_structures(
|
596
597
|
corporation_id=self.corporation.corporation_id,
|
597
598
|
token=token.valid_access_token(),
|
@@ -619,9 +620,19 @@ class Owner(models.Model):
|
|
619
620
|
)
|
620
621
|
).results()
|
621
622
|
except OSError as ex:
|
622
|
-
|
623
|
-
|
624
|
-
|
623
|
+
if isinstance(ex, HTTPForbidden):
|
624
|
+
logger.error(
|
625
|
+
"Failed to fetch structure with ID #%d belonging to %s, "
|
626
|
+
"because the character '%s' is missing "
|
627
|
+
"docking rights for it.",
|
628
|
+
structure["structure_id"],
|
629
|
+
self,
|
630
|
+
token.character_name,
|
631
|
+
)
|
632
|
+
else:
|
633
|
+
self._report_esi_issue(
|
634
|
+
f"fetch structure #{structure['structure_id']}", ex, token
|
635
|
+
)
|
625
636
|
structure["name"] = "(no data)"
|
626
637
|
is_ok = False
|
627
638
|
else:
|
@@ -650,7 +661,7 @@ class Owner(models.Model):
|
|
650
661
|
self._store_raw_data("structures", structures)
|
651
662
|
|
652
663
|
self._remove_structures_not_returned_from_esi(
|
653
|
-
|
664
|
+
existing_structures=self.structures.filter_upwell_structures(),
|
654
665
|
new_structures=structures,
|
655
666
|
)
|
656
667
|
return is_ok
|
@@ -701,7 +712,7 @@ class Owner(models.Model):
|
|
701
712
|
return False
|
702
713
|
|
703
714
|
self._remove_structures_not_returned_from_esi(
|
704
|
-
|
715
|
+
existing_structures=self.structures.filter_customs_offices(),
|
705
716
|
new_structures=structures.values(),
|
706
717
|
)
|
707
718
|
return True
|
@@ -868,7 +879,7 @@ class Owner(models.Model):
|
|
868
879
|
return False
|
869
880
|
|
870
881
|
self._remove_structures_not_returned_from_esi(
|
871
|
-
|
882
|
+
existing_structures=self.structures.filter_starbases(),
|
872
883
|
new_structures=structures,
|
873
884
|
)
|
874
885
|
character.reset_error_counter()
|
@@ -1214,15 +1225,18 @@ class Owner(models.Model):
|
|
1214
1225
|
def update_asset_esi(self, user: Optional[User] = None):
|
1215
1226
|
"""Update assets from ESI."""
|
1216
1227
|
token = self.fetch_token()
|
1217
|
-
assets_data = self.
|
1228
|
+
assets_data = self._fetch_owner_assets_from_esi(token)
|
1218
1229
|
self._store_items_for_upwell_structures(assets_data)
|
1219
1230
|
self._store_items_for_starbases(assets_data)
|
1231
|
+
if STRUCTURES_FEATURE_SKYHOOKS:
|
1232
|
+
self._update_skyhooks_from_assets(assets_data)
|
1233
|
+
self._resolve_skyhook_planets()
|
1220
1234
|
if user:
|
1221
1235
|
self._send_report_to_user(
|
1222
1236
|
topic="assets", topic_count=self.structures.count(), user=user
|
1223
1237
|
)
|
1224
1238
|
|
1225
|
-
def
|
1239
|
+
def _fetch_owner_assets_from_esi(self, token: Token) -> dict:
|
1226
1240
|
assets_raw = esi.client.Assets.get_corporations_corporation_id_assets(
|
1227
1241
|
corporation_id=self.corporation.corporation_id,
|
1228
1242
|
token=token.valid_access_token(),
|
@@ -1306,6 +1320,62 @@ class Owner(models.Model):
|
|
1306
1320
|
)
|
1307
1321
|
structure.update_items(structure_items)
|
1308
1322
|
|
1323
|
+
def _update_skyhooks_from_assets(self, assets_data: dict):
|
1324
|
+
skyhooks = {
|
1325
|
+
item_id: item
|
1326
|
+
for item_id, item in assets_data.items()
|
1327
|
+
if item["type_id"] == EveTypeId.ORBITAL_SKYHOOK
|
1328
|
+
and item["location_type"] == "solar_system"
|
1329
|
+
and item["location_flag"] == "AutoFit"
|
1330
|
+
and item["is_singleton"]
|
1331
|
+
and item["position"]
|
1332
|
+
}
|
1333
|
+
structures = []
|
1334
|
+
for item in skyhooks.values():
|
1335
|
+
structures.append(
|
1336
|
+
{
|
1337
|
+
"corporation_id": self.corporation.corporation_id,
|
1338
|
+
"type_id": item["type_id"],
|
1339
|
+
"position": item["position"],
|
1340
|
+
"structure_id": item["item_id"],
|
1341
|
+
"system_id": item["location_id"],
|
1342
|
+
}
|
1343
|
+
)
|
1344
|
+
|
1345
|
+
for s in structures:
|
1346
|
+
Structure.objects.update_or_create_from_dict(s, self)
|
1347
|
+
|
1348
|
+
self._remove_structures_not_returned_from_esi(
|
1349
|
+
existing_structures=self.structures.filter_skyhooks(),
|
1350
|
+
new_structures=structures,
|
1351
|
+
)
|
1352
|
+
|
1353
|
+
def _resolve_skyhook_planets(self):
|
1354
|
+
"""Add planets to all unresolved Skyhooks."""
|
1355
|
+
s: Structure
|
1356
|
+
for s in self.structures.filter_skyhooks().filter(
|
1357
|
+
eve_planet__isnull=True,
|
1358
|
+
position_x__isnull=False,
|
1359
|
+
position_y__isnull=False,
|
1360
|
+
position_z__isnull=False,
|
1361
|
+
):
|
1362
|
+
try:
|
1363
|
+
celestial = s.eve_solar_system.nearest_celestial(
|
1364
|
+
x=s.position_x,
|
1365
|
+
y=s.position_y,
|
1366
|
+
z=s.position_z,
|
1367
|
+
group_id=EveGroupId.PLANET,
|
1368
|
+
)
|
1369
|
+
except OSError:
|
1370
|
+
continue
|
1371
|
+
|
1372
|
+
if not celestial or not isinstance(celestial.eve_object, EvePlanet):
|
1373
|
+
continue
|
1374
|
+
|
1375
|
+
s.eve_planet = celestial.eve_object
|
1376
|
+
s.name = celestial.eve_type.name
|
1377
|
+
s.save()
|
1378
|
+
|
1309
1379
|
@staticmethod
|
1310
1380
|
def get_esi_scopes() -> List[str]:
|
1311
1381
|
"""Return all required ESI scopes."""
|
@@ -464,6 +464,11 @@ class Structure(models.Model): # pylint: disable = too-many-public-methods
|
|
464
464
|
"""Return True if this structure is a starbase, else False."""
|
465
465
|
return starbases.is_starbase(self.eve_type)
|
466
466
|
|
467
|
+
@property
|
468
|
+
def is_skyhook(self) -> bool:
|
469
|
+
"""Return True if this structure is a skyhook, else False."""
|
470
|
+
return self.eve_type_id == EveTypeId.ORBITAL_SKYHOOK
|
471
|
+
|
467
472
|
@cached_property
|
468
473
|
def is_upwell_structure(self) -> bool:
|
469
474
|
"""Return True if this structure is an upwell structure, else False."""
|
@@ -28,7 +28,7 @@
|
|
28
28
|
<ul id="public-tabs" class="nav nav-tabs" role="tablist">
|
29
29
|
|
30
30
|
<li role="presentation" class="active">
|
31
|
-
<a href="#pocos" aria-controls="
|
31
|
+
<a href="#pocos" aria-controls="orbitals" role="tab" data-toggle="tab">
|
32
32
|
{% translate "Customs Offices" %} <small>({{ pocos_count|default:"-" }})</small>
|
33
33
|
</a>
|
34
34
|
</li>
|
@@ -39,7 +39,7 @@
|
|
39
39
|
<div class="panel-body">
|
40
40
|
<div class="tab-content">
|
41
41
|
|
42
|
-
<div role="tabpanel" class="tab-pane active" id="
|
42
|
+
<div role="tabpanel" class="tab-pane active" id="orbitals">
|
43
43
|
{% include "structures/partials/public/poco_list.html" %}
|
44
44
|
</div>
|
45
45
|
|
@@ -48,8 +48,8 @@
|
|
48
48
|
</li>
|
49
49
|
|
50
50
|
<li role="presentation">
|
51
|
-
<a href="#
|
52
|
-
{% trans "
|
51
|
+
<a href="#orbitals" aria-controls="orbitals" role="tab" data-toggle="tab">
|
52
|
+
{% trans "Orbitals" %} <small>({{ orbitals_count|default:"-" }})</small>
|
53
53
|
</a>
|
54
54
|
</li>
|
55
55
|
|
@@ -77,8 +77,8 @@
|
|
77
77
|
{% include "structures/partials/structures/structure_list.html" %}
|
78
78
|
</div>
|
79
79
|
|
80
|
-
<div role="tabpanel" class="tab-pane" id="
|
81
|
-
{% include "structures/partials/structures/
|
80
|
+
<div role="tabpanel" class="tab-pane" id="orbitals">
|
81
|
+
{% include "structures/partials/structures/orbital_list.html" %}
|
82
82
|
</div>
|
83
83
|
|
84
84
|
<div role="tabpanel" class="tab-pane" id="starbases">
|
@@ -87,7 +87,7 @@
|
|
87
87
|
|
88
88
|
{% if show_jump_gates_tab %}
|
89
89
|
<div role="tabpanel" class="tab-pane" id="jump-gates">
|
90
|
-
{% include "structures/partials/structures/
|
90
|
+
{% include "structures/partials/structures/jump_gate_list.html" %}
|
91
91
|
</div>
|
92
92
|
{% endif %}
|
93
93
|
|
@@ -4,6 +4,7 @@ from app_utils.django import app_labels
|
|
4
4
|
from app_utils.testing import NoSocketsTestCase
|
5
5
|
|
6
6
|
from structures.core import notification_timers
|
7
|
+
from structures.core.notification_types import NotificationType
|
7
8
|
from structures.models import Notification
|
8
9
|
from structures.tests.testdata.factories import (
|
9
10
|
GeneratedNotificationFactory,
|
@@ -107,7 +108,11 @@ if "timerboard" in app_labels():
|
|
107
108
|
@patch(MODULE_PATH + ".STRUCTURES_MOON_EXTRACTION_TIMERS_ENABLED", True)
|
108
109
|
def test_run_all(self):
|
109
110
|
for obj in Notification.objects.all():
|
110
|
-
|
111
|
+
timer_types = NotificationType.relevant_for_timerboard()
|
112
|
+
with self.subTest(notif_type=obj.notif_type):
|
113
|
+
is_timer = obj.notif_type in timer_types
|
114
|
+
is_added = obj.add_or_remove_timer()
|
115
|
+
self.assertEqual(is_timer, is_added)
|
111
116
|
|
112
117
|
@patch(MODULE_PATH + ".STRUCTURES_TIMERS_ARE_CORP_RESTRICTED", False)
|
113
118
|
def test_corp_restriction_1(self):
|
@@ -7,7 +7,7 @@ import yaml
|
|
7
7
|
|
8
8
|
from django.test import TestCase, override_settings
|
9
9
|
from django.utils.timezone import now
|
10
|
-
from eveuniverse.models import EveSolarSystem
|
10
|
+
from eveuniverse.models import EvePlanet, EveSolarSystem
|
11
11
|
|
12
12
|
from app_utils.django import app_labels
|
13
13
|
from app_utils.esi import EsiStatus
|
@@ -22,11 +22,13 @@ from structures.tests.testdata.factories import (
|
|
22
22
|
NotificationFactory,
|
23
23
|
OwnerFactory,
|
24
24
|
RawNotificationFactory,
|
25
|
+
SkyhookFactory,
|
25
26
|
StarbaseFactory,
|
26
27
|
StructureFactory,
|
27
28
|
WebhookFactory,
|
28
29
|
datetime_to_esi,
|
29
30
|
)
|
31
|
+
from structures.tests.testdata.helpers import NearestCelestial
|
30
32
|
from structures.tests.testdata.load_eveuniverse import load_eveuniverse
|
31
33
|
|
32
34
|
if "structuretimers" in app_labels():
|
@@ -613,3 +615,102 @@ class TestTasks(TestCase):
|
|
613
615
|
self.assertEqual(len(embeds), 1)
|
614
616
|
embed = embeds[0]
|
615
617
|
self.assertIn("Territorial Claim Unit", embed.title)
|
618
|
+
|
619
|
+
@patch(OWNERS_PATH + ".STRUCTURES_FEATURE_SKYHOOKS", True)
|
620
|
+
def test_should_fetch_new_skyhooks_from_esi(
|
621
|
+
self, mock_esi_2, mock_esi, mock_execute
|
622
|
+
):
|
623
|
+
# given
|
624
|
+
owner = OwnerFactory()
|
625
|
+
structure = SkyhookFactory(owner=owner)
|
626
|
+
eve_planet = EvePlanet.objects.get(id=40161469)
|
627
|
+
corporation_id = owner.corporation.corporation_id
|
628
|
+
endpoints = [
|
629
|
+
EsiEndpoint(
|
630
|
+
"Assets",
|
631
|
+
"get_corporations_corporation_id_assets",
|
632
|
+
"corporation_id",
|
633
|
+
needs_token=True,
|
634
|
+
data={
|
635
|
+
str(corporation_id): [
|
636
|
+
{
|
637
|
+
"is_singleton": True,
|
638
|
+
"item_id": structure.id,
|
639
|
+
"location_flag": "AutoFit",
|
640
|
+
"location_id": 30002537,
|
641
|
+
"location_type": "solar_system",
|
642
|
+
"quantity": 1,
|
643
|
+
"type_id": 81080,
|
644
|
+
},
|
645
|
+
]
|
646
|
+
},
|
647
|
+
),
|
648
|
+
EsiEndpoint(
|
649
|
+
"Assets",
|
650
|
+
"post_corporations_corporation_id_assets_names",
|
651
|
+
"corporation_id",
|
652
|
+
needs_token=True,
|
653
|
+
data={str(corporation_id): []},
|
654
|
+
),
|
655
|
+
EsiEndpoint(
|
656
|
+
"Assets",
|
657
|
+
"post_corporations_corporation_id_assets_locations",
|
658
|
+
"corporation_id",
|
659
|
+
needs_token=True,
|
660
|
+
data={
|
661
|
+
str(corporation_id): [
|
662
|
+
{"item_id": structure.id, "position": {"x": 1, "y": 2, "z": 3}}
|
663
|
+
]
|
664
|
+
},
|
665
|
+
),
|
666
|
+
EsiEndpoint(
|
667
|
+
"Corporation",
|
668
|
+
"get_corporations_corporation_id_starbases",
|
669
|
+
"corporation_id",
|
670
|
+
needs_token=True,
|
671
|
+
data={str(corporation_id): []},
|
672
|
+
),
|
673
|
+
EsiEndpoint(
|
674
|
+
"Corporation",
|
675
|
+
"get_corporations_corporation_id_structures",
|
676
|
+
"corporation_id",
|
677
|
+
needs_token=True,
|
678
|
+
data={str(corporation_id): []},
|
679
|
+
),
|
680
|
+
EsiEndpoint(
|
681
|
+
"Planetary_Interaction",
|
682
|
+
"get_corporations_corporation_id_customs_offices",
|
683
|
+
"corporation_id",
|
684
|
+
needs_token=True,
|
685
|
+
data={str(corporation_id): []},
|
686
|
+
),
|
687
|
+
EsiEndpoint(
|
688
|
+
"Sovereignty",
|
689
|
+
"get_sovereignty_map",
|
690
|
+
needs_token=False,
|
691
|
+
data=[],
|
692
|
+
),
|
693
|
+
EsiEndpoint(
|
694
|
+
"Universe",
|
695
|
+
"get_universe_structures_structure_id",
|
696
|
+
"structure_id",
|
697
|
+
needs_token=True,
|
698
|
+
data={},
|
699
|
+
),
|
700
|
+
]
|
701
|
+
mock_esi.client = mock_esi_2.client = EsiClientStub.create_from_endpoints(
|
702
|
+
endpoints
|
703
|
+
)
|
704
|
+
structure_id = structure.id
|
705
|
+
structure.delete()
|
706
|
+
# when
|
707
|
+
|
708
|
+
with patch(OWNERS_PATH + ".EveSolarSystem.nearest_celestial") as m:
|
709
|
+
m.return_value = NearestCelestial(
|
710
|
+
eve_object=eve_planet,
|
711
|
+
distance=35_000_000,
|
712
|
+
eve_type=eve_planet.eve_type,
|
713
|
+
)
|
714
|
+
tasks.update_all_structures.delay()
|
715
|
+
# then
|
716
|
+
self.assertTrue(owner.structures.filter(id=structure_id).exists())
|
@@ -46,7 +46,7 @@ class TestStructureListView(TestCase):
|
|
46
46
|
# then
|
47
47
|
self.assertEqual(response.status_code, 200)
|
48
48
|
self.assertEqual(response.context["structures_count"], 2)
|
49
|
-
self.assertEqual(response.context["
|
49
|
+
self.assertEqual(response.context["orbitals_count"], 1)
|
50
50
|
self.assertEqual(response.context["starbases_count"], 1)
|
51
51
|
self.assertEqual(response.context["jump_gates_count"], 1)
|
52
52
|
self.assertIn("data_export", response.context)
|
@@ -376,6 +376,20 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
376
376
|
structure = Structure.objects.get(id=1000000000002)
|
377
377
|
self.assertEqual(structure.name, "(no data)")
|
378
378
|
|
379
|
+
def test_update_will_not_break_on_403_error_from_structure_info(self, mock_esi):
|
380
|
+
# given
|
381
|
+
new_endpoint = EsiEndpoint(
|
382
|
+
"Universe", "get_universe_structures_structure_id", http_error_code=403
|
383
|
+
)
|
384
|
+
mock_esi.client = self.esi_client_stub.replace_endpoints([new_endpoint])
|
385
|
+
owner = OwnerFactory(user=self.user, structures_last_update_at=None)
|
386
|
+
# when
|
387
|
+
owner.update_structures_esi()
|
388
|
+
# then
|
389
|
+
self.assertFalse(owner.is_structure_sync_fresh)
|
390
|
+
structure = Structure.objects.get(id=1000000000002)
|
391
|
+
self.assertEqual(structure.name, "(no data)")
|
392
|
+
|
379
393
|
@patch(MODULE_PATH + ".Structure.objects.update_or_create_from_dict")
|
380
394
|
def test_update_will_not_break_on_http_error_when_creating_structures(
|
381
395
|
self, mock_create_structure, mock_esi
|
@@ -7,18 +7,20 @@ from pytz import utc
|
|
7
7
|
from django.test import override_settings
|
8
8
|
from django.utils.timezone import now
|
9
9
|
from esi.models import Token
|
10
|
+
from eveuniverse.models import EvePlanet
|
10
11
|
|
11
12
|
from app_utils.esi_testing import EsiClientStub, EsiEndpoint
|
12
13
|
from app_utils.testing import BravadoResponseStub, NoSocketsTestCase, queryset_pks
|
13
14
|
|
14
15
|
from structures.core.notification_types import NotificationType
|
15
|
-
from structures.models import Notification, StructureItem
|
16
|
+
from structures.models import Notification, Structure, StructureItem
|
16
17
|
from structures.tests.testdata.factories import (
|
17
18
|
EveCharacterFactory,
|
18
19
|
EveCorporationInfoFactory,
|
19
20
|
EveEntityCorporationFactory,
|
20
21
|
JumpFuelAlertConfigFactory,
|
21
22
|
OwnerFactory,
|
23
|
+
SkyhookFactory,
|
22
24
|
StarbaseFactory,
|
23
25
|
StructureFactory,
|
24
26
|
StructureItemFactory,
|
@@ -27,6 +29,7 @@ from structures.tests.testdata.factories import (
|
|
27
29
|
datetime_to_esi,
|
28
30
|
)
|
29
31
|
from structures.tests.testdata.helpers import (
|
32
|
+
NearestCelestial,
|
30
33
|
load_eve_entities,
|
31
34
|
load_notification_entities,
|
32
35
|
)
|
@@ -711,6 +714,137 @@ class TestOwnerUpdateAssetEsi(NoSocketsTestCase):
|
|
711
714
|
self.assertTrue(structure.items.filter(id=1300000003001).exists())
|
712
715
|
|
713
716
|
|
717
|
+
@patch(OWNERS_PATH + ".STRUCTURES_FEATURE_SKYHOOKS", True)
|
718
|
+
@patch(OWNERS_PATH + ".EveSolarSystem.nearest_celestial")
|
719
|
+
@patch(OWNERS_PATH + ".esi")
|
720
|
+
class TestOwnerUpdateSkyhooks(NoSocketsTestCase):
|
721
|
+
@classmethod
|
722
|
+
def setUpClass(cls):
|
723
|
+
super().setUpClass()
|
724
|
+
load_eveuniverse()
|
725
|
+
cls.corporation = EveCharacterFactory()
|
726
|
+
character = EveCharacterFactory(corporation=cls.corporation)
|
727
|
+
cls.user = UserMainDefaultOwnerFactory(main_character__character=character)
|
728
|
+
cls.planet = EvePlanet.objects.get(id=40161469)
|
729
|
+
endpoints = [
|
730
|
+
EsiEndpoint(
|
731
|
+
"Assets",
|
732
|
+
"get_corporations_corporation_id_assets",
|
733
|
+
"corporation_id",
|
734
|
+
needs_token=True,
|
735
|
+
data={
|
736
|
+
f"{cls.corporation.corporation_id}": [
|
737
|
+
{
|
738
|
+
"is_singleton": True,
|
739
|
+
"item_id": 1000000010001,
|
740
|
+
"location_flag": "AutoFit",
|
741
|
+
"location_id": 30002537,
|
742
|
+
"location_type": "solar_system",
|
743
|
+
"quantity": 1,
|
744
|
+
"type_id": 81080,
|
745
|
+
},
|
746
|
+
],
|
747
|
+
},
|
748
|
+
),
|
749
|
+
EsiEndpoint(
|
750
|
+
"Assets",
|
751
|
+
"post_corporations_corporation_id_assets_locations",
|
752
|
+
"corporation_id",
|
753
|
+
needs_token=True,
|
754
|
+
data={
|
755
|
+
f"{cls.corporation.corporation_id}": [
|
756
|
+
{"item_id": 1000000010001, "position": {"x": 1, "y": 2, "z": 3}}
|
757
|
+
]
|
758
|
+
},
|
759
|
+
),
|
760
|
+
]
|
761
|
+
cls.esi_client_stub = EsiClientStub.create_from_endpoints(endpoints)
|
762
|
+
|
763
|
+
def test_should_create_new_skyhooks_from_scratch(
|
764
|
+
self, mock_esi, mock_nearest_celestial
|
765
|
+
):
|
766
|
+
# given
|
767
|
+
mock_esi.client = self.esi_client_stub
|
768
|
+
mock_nearest_celestial.return_value = NearestCelestial(
|
769
|
+
eve_object=self.planet, distance=35_000_000, eve_type=self.planet.eve_type
|
770
|
+
)
|
771
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
772
|
+
# when
|
773
|
+
owner.update_asset_esi()
|
774
|
+
# then
|
775
|
+
owner.refresh_from_db()
|
776
|
+
self.assertEqual(owner.structures.count(), 1)
|
777
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
778
|
+
self.assertTrue(obj.is_skyhook)
|
779
|
+
self.assertEqual(obj.eve_planet, self.planet)
|
780
|
+
|
781
|
+
def test_should_remove_obsolete_skyhooks(self, mock_esi, mock_nearest_celestial):
|
782
|
+
# given
|
783
|
+
mock_esi.client = self.esi_client_stub
|
784
|
+
mock_nearest_celestial.return_value = NearestCelestial(
|
785
|
+
eve_object=self.planet, distance=35_000_000, eve_type=self.planet.eve_type
|
786
|
+
)
|
787
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
788
|
+
SkyhookFactory.create(owner=owner)
|
789
|
+
# when
|
790
|
+
owner.update_asset_esi()
|
791
|
+
# then
|
792
|
+
owner.refresh_from_db()
|
793
|
+
self.assertEqual(owner.structures.count(), 1)
|
794
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
795
|
+
self.assertTrue(obj.is_skyhook)
|
796
|
+
self.assertEqual(obj.eve_planet, self.planet)
|
797
|
+
|
798
|
+
def test_should_update_existing_skyhook(self, mock_esi, mock_nearest_celestial):
|
799
|
+
# given
|
800
|
+
mock_esi.client = self.esi_client_stub
|
801
|
+
mock_nearest_celestial.return_value = NearestCelestial(
|
802
|
+
eve_object=self.planet, distance=35_000_000, eve_type=self.planet.eve_type
|
803
|
+
)
|
804
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
805
|
+
SkyhookFactory.create(owner=owner, id=1000000010001, eve_planet_name="Thera I")
|
806
|
+
# when
|
807
|
+
owner.update_asset_esi()
|
808
|
+
# then
|
809
|
+
owner.refresh_from_db()
|
810
|
+
self.assertEqual(owner.structures.count(), 1)
|
811
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
812
|
+
self.assertTrue(obj.is_skyhook)
|
813
|
+
self.assertEqual(obj.eve_planet, self.planet)
|
814
|
+
|
815
|
+
def test_should_ignore_os_error_when_resolving_planet(
|
816
|
+
self, mock_esi, mock_nearest_celestial
|
817
|
+
):
|
818
|
+
# given
|
819
|
+
mock_esi.client = self.esi_client_stub
|
820
|
+
mock_nearest_celestial.side_effect = OSError
|
821
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
822
|
+
# when
|
823
|
+
owner.update_asset_esi()
|
824
|
+
# then
|
825
|
+
owner.refresh_from_db()
|
826
|
+
self.assertEqual(owner.structures.count(), 1)
|
827
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
828
|
+
self.assertTrue(obj.is_skyhook)
|
829
|
+
self.assertIsNone(obj.eve_planet)
|
830
|
+
|
831
|
+
def test_should_ignore_no_reply_when_resolving_planet(
|
832
|
+
self, mock_esi, mock_nearest_celestial
|
833
|
+
):
|
834
|
+
# given
|
835
|
+
mock_esi.client = self.esi_client_stub
|
836
|
+
mock_nearest_celestial.return_value = None
|
837
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
838
|
+
# when
|
839
|
+
owner.update_asset_esi()
|
840
|
+
# then
|
841
|
+
owner.refresh_from_db()
|
842
|
+
self.assertEqual(owner.structures.count(), 1)
|
843
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
844
|
+
self.assertTrue(obj.is_skyhook)
|
845
|
+
self.assertIsNone(obj.eve_planet)
|
846
|
+
|
847
|
+
|
714
848
|
class TestOwnerToken(NoSocketsTestCase):
|
715
849
|
def test_should_return_valid_token(self):
|
716
850
|
# given
|
@@ -29,6 +29,7 @@ from structures.tests.testdata.factories import (
|
|
29
29
|
OwnerFactory,
|
30
30
|
PocoDetailsFactory,
|
31
31
|
PocoFactory,
|
32
|
+
SkyhookFactory,
|
32
33
|
StarbaseFactory,
|
33
34
|
StructureFactory,
|
34
35
|
StructureItemFactory,
|
@@ -367,48 +368,6 @@ class TestStructure(NoSocketsTestCase):
|
|
367
368
|
# when/then
|
368
369
|
self.assertEqual(obj.location_name, "?")
|
369
370
|
|
370
|
-
def test_is_poco(self):
|
371
|
-
# given
|
372
|
-
structure = StructureFactory.build(owner=self.owner)
|
373
|
-
poco = PocoFactory.build(owner=self.owner)
|
374
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
375
|
-
# then
|
376
|
-
self.assertFalse(structure.is_poco)
|
377
|
-
self.assertTrue(poco.is_poco)
|
378
|
-
self.assertFalse(starbase.is_poco)
|
379
|
-
|
380
|
-
def test_is_starbase(self):
|
381
|
-
# given
|
382
|
-
structure = StructureFactory.build(owner=self.owner)
|
383
|
-
poco = PocoFactory.build(owner=self.owner)
|
384
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
385
|
-
# then
|
386
|
-
self.assertFalse(structure.is_starbase)
|
387
|
-
self.assertFalse(poco.is_starbase)
|
388
|
-
self.assertTrue(starbase.is_starbase)
|
389
|
-
|
390
|
-
def test_is_upwell_structure(self):
|
391
|
-
# given
|
392
|
-
structure = StructureFactory.build(owner=self.owner)
|
393
|
-
poco = PocoFactory.build(owner=self.owner)
|
394
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
395
|
-
# then
|
396
|
-
self.assertTrue(structure.is_upwell_structure)
|
397
|
-
self.assertFalse(poco.is_upwell_structure)
|
398
|
-
self.assertFalse(starbase.is_upwell_structure)
|
399
|
-
|
400
|
-
def test_is_jump_gate(self):
|
401
|
-
# given
|
402
|
-
normal_structure = StructureFactory.build(owner=self.owner)
|
403
|
-
poco = PocoFactory.build(owner=self.owner)
|
404
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
405
|
-
jump_gate = JumpGateFactory.build(owner=self.owner)
|
406
|
-
# then
|
407
|
-
self.assertFalse(normal_structure.is_jump_gate)
|
408
|
-
self.assertFalse(poco.is_jump_gate)
|
409
|
-
self.assertFalse(starbase.is_jump_gate)
|
410
|
-
self.assertTrue(jump_gate.is_jump_gate)
|
411
|
-
|
412
371
|
# TODO: activate
|
413
372
|
# def test_is_upwell_structure_data_error(self):
|
414
373
|
# # group without a category
|
@@ -490,6 +449,54 @@ class TestStructure(NoSocketsTestCase):
|
|
490
449
|
self.assertFalse(obj.owner_has_sov())
|
491
450
|
|
492
451
|
|
452
|
+
class TestStructureIsX(NoSocketsTestCase):
|
453
|
+
@classmethod
|
454
|
+
def setUpClass(cls):
|
455
|
+
super().setUpClass()
|
456
|
+
load_eveuniverse()
|
457
|
+
cls.owner = OwnerFactory()
|
458
|
+
cls.jump_gate = JumpGateFactory.build(owner=cls.owner)
|
459
|
+
cls.poco = PocoFactory.build(owner=cls.owner)
|
460
|
+
cls.skyhook = SkyhookFactory.build(owner=cls.owner)
|
461
|
+
cls.starbase = StarbaseFactory.build(owner=cls.owner)
|
462
|
+
cls.upwell_structure = StructureFactory.build(owner=cls.owner)
|
463
|
+
|
464
|
+
def test_is_jump_gate(self):
|
465
|
+
self.assertFalse(self.upwell_structure.is_jump_gate)
|
466
|
+
self.assertFalse(self.poco.is_jump_gate)
|
467
|
+
self.assertFalse(self.starbase.is_jump_gate)
|
468
|
+
self.assertTrue(self.jump_gate.is_jump_gate)
|
469
|
+
self.assertFalse(self.skyhook.is_jump_gate)
|
470
|
+
|
471
|
+
def test_is_poco(self):
|
472
|
+
self.assertFalse(self.upwell_structure.is_poco)
|
473
|
+
self.assertTrue(self.poco.is_poco)
|
474
|
+
self.assertFalse(self.starbase.is_poco)
|
475
|
+
self.assertFalse(self.jump_gate.is_poco)
|
476
|
+
self.assertFalse(self.skyhook.is_poco)
|
477
|
+
|
478
|
+
def test_is_starbase(self):
|
479
|
+
self.assertFalse(self.upwell_structure.is_starbase)
|
480
|
+
self.assertFalse(self.poco.is_starbase)
|
481
|
+
self.assertTrue(self.starbase.is_starbase)
|
482
|
+
self.assertFalse(self.jump_gate.is_starbase)
|
483
|
+
self.assertFalse(self.skyhook.is_starbase)
|
484
|
+
|
485
|
+
def test_is_skyhook(self):
|
486
|
+
self.assertFalse(self.upwell_structure.is_skyhook)
|
487
|
+
self.assertFalse(self.poco.is_skyhook)
|
488
|
+
self.assertFalse(self.starbase.is_skyhook)
|
489
|
+
self.assertFalse(self.jump_gate.is_skyhook)
|
490
|
+
self.assertTrue(self.skyhook.is_skyhook)
|
491
|
+
|
492
|
+
def test_is_upwell_structure(self):
|
493
|
+
self.assertTrue(self.upwell_structure.is_upwell_structure)
|
494
|
+
self.assertFalse(self.poco.is_upwell_structure)
|
495
|
+
self.assertFalse(self.starbase.is_upwell_structure)
|
496
|
+
self.assertTrue(self.jump_gate.is_upwell_structure)
|
497
|
+
self.assertFalse(self.skyhook.is_upwell_structure)
|
498
|
+
|
499
|
+
|
493
500
|
class TestStructureFuel(NoSocketsTestCase):
|
494
501
|
@classmethod
|
495
502
|
def setUpClass(cls):
|
@@ -25,6 +25,7 @@ from .testdata.factories import (
|
|
25
25
|
EveSovereigntyMapFactory,
|
26
26
|
OwnerFactory,
|
27
27
|
PocoFactory,
|
28
|
+
SkyhookFactory,
|
28
29
|
StarbaseFactory,
|
29
30
|
StructureFactory,
|
30
31
|
StructureTagFactory,
|
@@ -304,12 +305,15 @@ class TestStructureQuerySet(NoSocketsTestCase):
|
|
304
305
|
cls.structure = StructureFactory(owner=cls.owner)
|
305
306
|
cls.poco = PocoFactory(owner=cls.owner)
|
306
307
|
cls.starbase = StarbaseFactory(owner=cls.owner)
|
308
|
+
cls.skyhook = SkyhookFactory(owner=cls.owner)
|
307
309
|
|
308
310
|
def test_should_return_ids_as_set(self):
|
309
311
|
# when
|
310
312
|
ids = Structure.objects.ids()
|
311
313
|
# then
|
312
|
-
self.assertSetEqual(
|
314
|
+
self.assertSetEqual(
|
315
|
+
ids, {self.structure.id, self.poco.id, self.starbase.id, self.skyhook.id}
|
316
|
+
)
|
313
317
|
|
314
318
|
def test_should_filter_upwell_structures(self):
|
315
319
|
# when
|
@@ -329,6 +333,12 @@ class TestStructureQuerySet(NoSocketsTestCase):
|
|
329
333
|
# then
|
330
334
|
self.assertSetEqual(result_qs.ids(), {self.starbase.id})
|
331
335
|
|
336
|
+
def test_should_filter_skyhooks(self):
|
337
|
+
# when
|
338
|
+
result_qs = Structure.objects.filter_skyhooks()
|
339
|
+
# then
|
340
|
+
self.assertSetEqual(result_qs.ids(), {self.skyhook.id})
|
341
|
+
|
332
342
|
|
333
343
|
class TestStructureQuerySetVisibleForUser(NoSocketsTestCase):
|
334
344
|
@classmethod
|
@@ -476,6 +476,27 @@ class PocoDetailsFactory(
|
|
476
476
|
standing_level = PocoDetails.StandingLevel.BAD
|
477
477
|
|
478
478
|
|
479
|
+
class SkyhookFactory(StructureFactory):
|
480
|
+
class Params:
|
481
|
+
eve_planet_name = "Amamake V"
|
482
|
+
|
483
|
+
has_fitting = None
|
484
|
+
has_core = None
|
485
|
+
state = Structure.State.NA
|
486
|
+
|
487
|
+
@factory.lazy_attribute
|
488
|
+
def eve_planet(self):
|
489
|
+
return EvePlanet.objects.get(name=self.eve_planet_name)
|
490
|
+
|
491
|
+
@factory.lazy_attribute
|
492
|
+
def eve_solar_system(self):
|
493
|
+
return self.eve_planet.eve_solar_system
|
494
|
+
|
495
|
+
@factory.lazy_attribute
|
496
|
+
def eve_type(self):
|
497
|
+
return EveType.objects.get(id=EveTypeId.ORBITAL_SKYHOOK)
|
498
|
+
|
499
|
+
|
479
500
|
class JumpGateFactory(StructureFactory):
|
480
501
|
@factory.lazy_attribute
|
481
502
|
def eve_type(self):
|
@@ -4,6 +4,7 @@ import datetime as dt
|
|
4
4
|
import json
|
5
5
|
import logging
|
6
6
|
import unicodedata
|
7
|
+
from collections import namedtuple
|
7
8
|
from pathlib import Path
|
8
9
|
from random import randrange
|
9
10
|
|
@@ -192,3 +193,8 @@ def datetime_to_ldap(my_dt: dt.datetime) -> int:
|
|
192
193
|
((my_dt - dt.datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds())
|
193
194
|
+ 11644473600
|
194
195
|
) * 10000000
|
196
|
+
|
197
|
+
|
198
|
+
NearestCelestial = namedtuple(
|
199
|
+
"NearestCelestial", ["eve_type", "eve_object", "distance"]
|
200
|
+
)
|
@@ -19,6 +19,7 @@ from structures.tests.testdata.factories import (
|
|
19
19
|
JumpGateFactory,
|
20
20
|
OwnerFactory,
|
21
21
|
PocoFactory,
|
22
|
+
SkyhookFactory,
|
22
23
|
StarbaseFactory,
|
23
24
|
StructureFactory,
|
24
25
|
StructureTagFactory,
|
@@ -148,6 +149,7 @@ class TestStructureListDataFilterVariant(TestCase):
|
|
148
149
|
owner = OwnerFactory(user=cls.user)
|
149
150
|
cls.structure = StructureFactory(owner=owner)
|
150
151
|
cls.poco = PocoFactory(owner=owner)
|
152
|
+
cls.skyhook = SkyhookFactory(owner=owner)
|
151
153
|
cls.starbase = StarbaseFactory(owner=owner)
|
152
154
|
cls.jump_gate = JumpGateFactory(owner=owner)
|
153
155
|
|
@@ -163,17 +165,17 @@ class TestStructureListDataFilterVariant(TestCase):
|
|
163
165
|
structure_ids = set(data.keys())
|
164
166
|
self.assertSetEqual(structure_ids, {self.structure.id, self.jump_gate.id})
|
165
167
|
|
166
|
-
def
|
168
|
+
def test_should_return_orbitals_only(self):
|
167
169
|
# given
|
168
170
|
request = self.factory.get("/")
|
169
171
|
request.user = self.user
|
170
172
|
# when
|
171
|
-
response = structures.structure_list_data(request, "
|
173
|
+
response = structures.structure_list_data(request, "orbitals")
|
172
174
|
# then
|
173
175
|
self.assertEqual(response.status_code, 200)
|
174
176
|
data = json_response_to_dict(response)
|
175
177
|
structure_ids = set(data.keys())
|
176
|
-
self.assertSetEqual(structure_ids, {self.poco.id})
|
178
|
+
self.assertSetEqual(structure_ids, {self.poco.id, self.skyhook.id})
|
177
179
|
|
178
180
|
def test_should_return_starbases_only(self):
|
179
181
|
# given
|
@@ -211,7 +213,13 @@ class TestStructureListDataFilterVariant(TestCase):
|
|
211
213
|
structure_ids = set(data.keys())
|
212
214
|
self.assertSetEqual(
|
213
215
|
structure_ids,
|
214
|
-
{
|
216
|
+
{
|
217
|
+
self.structure.id,
|
218
|
+
self.poco.id,
|
219
|
+
self.starbase.id,
|
220
|
+
self.jump_gate.id,
|
221
|
+
self.skyhook.id,
|
222
|
+
},
|
215
223
|
)
|
216
224
|
|
217
225
|
def test_should_raise_error_when_invalid_variant_requested(self):
|
structures/views/structures.py
CHANGED
@@ -58,7 +58,7 @@ class StructureSelection(str, Enum):
|
|
58
58
|
"""A pre-defined selection to filter structures data."""
|
59
59
|
|
60
60
|
STRUCTURES = "structures"
|
61
|
-
|
61
|
+
ORBITALS = "orbitals"
|
62
62
|
STARBASES = "starbases"
|
63
63
|
JUMP_GATES = "jump_gates"
|
64
64
|
ALL = "all"
|
@@ -118,8 +118,8 @@ def structure_list(request: HttpRequest):
|
|
118
118
|
structures_count = _structures_query(
|
119
119
|
request.user, StructureSelection.STRUCTURES, tags
|
120
120
|
).count()
|
121
|
-
|
122
|
-
request.user, StructureSelection.
|
121
|
+
orbitals_count = _structures_query(
|
122
|
+
request.user, StructureSelection.ORBITALS, tags
|
123
123
|
).count()
|
124
124
|
starbases_count = _structures_query(
|
125
125
|
request.user, StructureSelection.STARBASES, tags
|
@@ -136,7 +136,7 @@ def structure_list(request: HttpRequest):
|
|
136
136
|
"tags_exist": StructureTag.objects.exists(),
|
137
137
|
"show_jump_gates_tab": STRUCTURES_SHOW_JUMP_GATES,
|
138
138
|
"structures_count": structures_count,
|
139
|
-
"
|
139
|
+
"orbitals_count": orbitals_count,
|
140
140
|
"starbases_count": starbases_count,
|
141
141
|
"jump_gates_count": jump_gates_count,
|
142
142
|
"data_export": data_export,
|
@@ -146,7 +146,7 @@ def structure_list(request: HttpRequest):
|
|
146
146
|
|
147
147
|
def _construct_data_export(request, tags):
|
148
148
|
structures_ajax_url = _construct_ajax_url(StructureSelection.STRUCTURES, tags)
|
149
|
-
pocos_ajax_url = _construct_ajax_url(StructureSelection.
|
149
|
+
pocos_ajax_url = _construct_ajax_url(StructureSelection.ORBITALS, tags)
|
150
150
|
starbases_ajax_url = _construct_ajax_url(StructureSelection.STARBASES, tags)
|
151
151
|
jump_gates_ajax_url = _construct_ajax_url(StructureSelection.JUMP_GATES, tags)
|
152
152
|
|
@@ -213,7 +213,7 @@ def _structures_query(
|
|
213
213
|
eve_type__eve_group__eve_category_id=EveCategoryId.STRUCTURE
|
214
214
|
)
|
215
215
|
|
216
|
-
elif selection == StructureSelection.
|
216
|
+
elif selection == StructureSelection.ORBITALS:
|
217
217
|
structures_qs = structures_qs.filter(
|
218
218
|
eve_type__eve_group__eve_category_id=EveCategoryId.ORBITAL
|
219
219
|
).annotate_has_poco_details()
|
File without changes
|
File without changes
|
/structures/templates/structures/partials/structures/{jump_gates_list.html → jump_gate_list.html}
RENAMED
File without changes
|