aa-ledger 1.0.3__py3-none-any.whl → 2.0.0__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_ledger-1.0.3.dist-info → aa_ledger-2.0.0.dist-info}/METADATA +6 -6
- aa_ledger-2.0.0.dist-info/RECORD +267 -0
- {aa_ledger-1.0.3.dist-info → aa_ledger-2.0.0.dist-info}/WHEEL +1 -1
- ledger/__init__.py +2 -2
- ledger/admin.py +23 -18
- ledger/api/__init__.py +23 -7
- ledger/api/{ledger/admin.py → admin.py} +25 -31
- ledger/api/alliance.py +755 -0
- ledger/api/character.py +786 -0
- ledger/api/corporation.py +1141 -0
- ledger/api/{helpers.py → helpers/core.py} +33 -33
- ledger/api/helpers/icons.py +372 -0
- ledger/api/helpers/planetary_helper.py +354 -0
- ledger/api/planetary.py +354 -0
- ledger/api/schema.py +240 -15
- ledger/app_settings.py +18 -26
- ledger/auth_hooks.py +2 -2
- ledger/constants.py +50 -177
- ledger/decorators.py +2 -46
- ledger/forms.py +133 -39
- ledger/helpers/billboard.py +194 -144
- ledger/helpers/cache.py +105 -0
- ledger/helpers/discord.py +2 -4
- ledger/helpers/eveonline.py +160 -0
- ledger/helpers/ledger_data.py +23 -0
- ledger/helpers/ref_type.py +53 -78
- ledger/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- ledger/locale/cs_CZ/LC_MESSAGES/django.po +349 -193
- ledger/locale/de/LC_MESSAGES/django.mo +0 -0
- ledger/locale/de/LC_MESSAGES/django.po +528 -379
- ledger/locale/django.pot +717 -553
- ledger/locale/es/LC_MESSAGES/django.mo +0 -0
- ledger/locale/es/LC_MESSAGES/django.po +349 -194
- ledger/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
- ledger/locale/fr_FR/LC_MESSAGES/django.po +349 -193
- ledger/locale/it_IT/LC_MESSAGES/django.mo +0 -0
- ledger/locale/it_IT/LC_MESSAGES/django.po +349 -193
- ledger/locale/ja/LC_MESSAGES/django.mo +0 -0
- ledger/locale/ja/LC_MESSAGES/django.po +348 -193
- ledger/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
- ledger/locale/ko_KR/LC_MESSAGES/django.po +349 -193
- ledger/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
- ledger/locale/nl_NL/LC_MESSAGES/django.po +349 -193
- ledger/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
- ledger/locale/pl_PL/LC_MESSAGES/django.po +350 -193
- ledger/locale/ru/LC_MESSAGES/django.mo +0 -0
- ledger/locale/ru/LC_MESSAGES/django.po +348 -193
- ledger/locale/sk/LC_MESSAGES/django.mo +0 -0
- ledger/locale/sk/LC_MESSAGES/django.po +348 -193
- ledger/locale/uk/LC_MESSAGES/django.mo +0 -0
- ledger/locale/uk/LC_MESSAGES/django.po +348 -193
- ledger/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- ledger/locale/zh_Hans/LC_MESSAGES/django.po +348 -193
- ledger/managers/character_audit_manager.py +28 -20
- ledger/managers/character_journal_manager.py +187 -358
- ledger/managers/character_mining_manager.py +64 -30
- ledger/managers/character_planetary_manager.py +185 -138
- ledger/managers/corporation_audit_manager.py +36 -27
- ledger/managers/corporation_journal_manager.py +94 -57
- ledger/managers/general_manager.py +12 -8
- ledger/migrations/0018_remove_characterplanet_ledger_char_planet__58a5b6_idx_and_more.py +44 -0
- ledger/migrations/0019_rename_characteraudit_characterowner_and_more.py +48 -0
- ledger/models/__init__.py +5 -11
- ledger/models/characteraudit.py +101 -109
- ledger/models/corporationaudit.py +94 -49
- ledger/models/general.py +105 -211
- ledger/models/helpers/update_manager.py +302 -0
- ledger/models/planetary.py +60 -205
- ledger/providers.py +101 -0
- ledger/static/ledger/css/{ledger.css → aa-ledger.css} +54 -28
- ledger/static/ledger/js/aa-ledger.js +124 -0
- ledger/static/ledger/js/charts.js +25 -1
- ledger/static/ledger/js/view-alliance-ledger.js +383 -0
- ledger/static/ledger/js/view-character-ledger.js +388 -0
- ledger/static/ledger/js/view-corporation-ledger.js +402 -0
- ledger/static/ledger/js/view-planetary.js +492 -0
- ledger/static/ledger/libs/amCharts/5.14.4/js/flow.js +2 -0
- ledger/static/ledger/libs/amCharts/5.14.4/js/index.js +2 -0
- ledger/static/ledger/libs/amCharts/5.14.4/js/percent.js +2 -0
- ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Animated.js +2 -0
- ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Dark.js +2 -0
- ledger/static/ledger/libs/amCharts/5.14.4/js/xy.js +2 -0
- ledger/static/ledger/libs/datatables/2.3.5/css/dataTables.bootstrap5.css +610 -0
- ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.bootstrap5.js +122 -0
- ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.js +14127 -0
- ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.css +516 -0
- ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.dataTables.css +529 -0
- ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.js +73 -0
- ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.js +3090 -0
- ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.css +20 -0
- ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.js +1203 -0
- ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.js +59 -0
- ledger/tasks.py +157 -146
- ledger/templates/ledger/base.html +59 -21
- ledger/templates/ledger/bundles/aa-ledger-css.html +3 -0
- ledger/templates/ledger/bundles/aa-ledger-js.html +3 -0
- ledger/templates/ledger/bundles/view-alliance-ledger-js.html +14 -0
- ledger/templates/ledger/bundles/view-character-ledger-js.html +15 -0
- ledger/templates/ledger/bundles/view-character-planetary-css.html +3 -0
- ledger/templates/ledger/bundles/view-character-planetary-js.html +4 -0
- ledger/templates/ledger/bundles/view-corporation-ledger-js.html +15 -0
- ledger/templates/ledger/partials/modal/confirm.html +0 -1
- ledger/templates/ledger/partials/modal/request-accept-delete-alliance.html +38 -0
- ledger/templates/ledger/partials/modal/request-accept-delete-character.html +38 -0
- ledger/templates/ledger/partials/modal/request-accept-delete-corporation.html +38 -0
- ledger/templates/ledger/partials/modal/request-accept-switch-notification.html +38 -0
- ledger/templates/ledger/partials/modal/request-view-alliance-details.html +26 -0
- ledger/templates/ledger/partials/modal/request-view-character-details.html +26 -0
- ledger/templates/ledger/partials/modal/request-view-corporation-details.html +26 -0
- ledger/templates/ledger/partials/modal/request-view-extractor.html +32 -0
- ledger/templates/ledger/partials/modal/request-view-factory.html +31 -0
- ledger/templates/ledger/partials/{menu → navigation}/administration.html +8 -0
- ledger/templates/ledger/partials/{menu → navigation}/navigation.html +2 -2
- ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance_corporations.html +3 -3
- ledger/templates/ledger/partials/view-alliance-administration/dashboard.html +81 -0
- ledger/templates/ledger/partials/view-alliance-ledger/alliance-billboard.html +25 -0
- ledger/templates/ledger/partials/view-alliance-ledger/alliance-ledger-details.html +21 -0
- ledger/templates/ledger/partials/view-alliance-ledger/alliance-table.html +24 -0
- ledger/templates/ledger/partials/view-alliance-ledger/information/daily.html +18 -0
- ledger/templates/ledger/partials/view-alliance-ledger/information/hourly.html +18 -0
- ledger/templates/ledger/partials/view-alliance-ledger/information/summary.html +19 -0
- ledger/templates/ledger/partials/{administration → view-character-administration}/character.html +1 -9
- ledger/templates/ledger/partials/{administration → view-character-administration}/dashboard.html +0 -34
- ledger/templates/ledger/partials/view-character-ledger/character-billboard.html +25 -0
- ledger/templates/ledger/partials/view-character-ledger/character-ledger-details.html +21 -0
- ledger/templates/ledger/partials/view-character-ledger/character-table.html +25 -0
- ledger/templates/ledger/partials/view-character-ledger/information/daily.html +18 -0
- ledger/templates/ledger/partials/view-character-ledger/information/hourly.html +18 -0
- ledger/templates/ledger/partials/view-character-ledger/information/summary.html +19 -0
- ledger/templates/ledger/partials/view-character-planetary/extractor-table.html +24 -0
- ledger/templates/ledger/partials/view-character-planetary/factory-table.html +24 -0
- ledger/templates/ledger/partials/view-character-planetary/planetary-table.html +22 -0
- ledger/templates/ledger/partials/view-character-planetary/storage-table.html +23 -0
- ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation.html +5 -13
- ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation_characters.html +1 -1
- ledger/templates/ledger/partials/view-corporation-administration/dashboard.html +81 -0
- ledger/templates/ledger/partials/view-corporation-ledger/corporation-billboard.html +25 -0
- ledger/templates/ledger/partials/view-corporation-ledger/corporation-ledger-details.html +21 -0
- ledger/templates/ledger/partials/view-corporation-ledger/corporation-table.html +26 -0
- ledger/templates/ledger/partials/view-corporation-ledger/information/daily.html +18 -0
- ledger/templates/ledger/partials/view-corporation-ledger/information/hourly.html +18 -0
- ledger/templates/ledger/partials/view-corporation-ledger/information/summary.html +19 -0
- ledger/templates/ledger/view-administration.html +62 -0
- ledger/templates/ledger/view-alliance-administration.html +49 -0
- ledger/templates/ledger/view-alliance-ledger.html +72 -0
- ledger/templates/ledger/view-alliance-overview.html +131 -0
- ledger/templates/ledger/view-character-administration.html +42 -0
- ledger/templates/ledger/view-character-ledger.html +73 -0
- ledger/templates/ledger/view-character-overview.html +135 -0
- ledger/templates/ledger/view-character-planetary-overview.html +135 -0
- ledger/templates/ledger/view-character-planetary.html +73 -0
- ledger/templates/ledger/view-corporation-administration.html +42 -0
- ledger/templates/ledger/view-corporation-ledger.html +73 -0
- ledger/templates/ledger/view-corporation-overview.html +131 -0
- ledger/templatetags/ledger.py +3 -5
- ledger/tests/__init__.py +187 -0
- ledger/tests/test_admin.py +164 -68
- ledger/tests/test_auth_hook.py +31 -13
- ledger/tests/test_decarators.py +14 -79
- ledger/tests/test_discord_installed.py +0 -1
- ledger/tests/test_helpers/test_ledger_data.py +19 -0
- ledger/tests/test_managers/test_character_audit_manager.py +111 -69
- ledger/tests/test_managers/test_character_journal_manager.py +48 -208
- ledger/tests/test_managers/test_character_mining_manager.py +37 -16
- ledger/tests/test_managers/test_corporation_division_manager.py +66 -28
- ledger/tests/test_managers/test_corporation_journal_manager.py +39 -42
- ledger/tests/test_managers/test_general_manager.py +78 -18
- ledger/tests/test_managers/test_planetary_manager.py +73 -32
- ledger/tests/test_models/test_characteraudit.py +58 -74
- ledger/tests/test_models/test_characterminingledger.py +20 -26
- ledger/tests/test_models/test_characterwalletjournal.py +10 -33
- ledger/tests/test_models/test_corporationaudit.py +41 -35
- ledger/tests/test_models/test_corporationwalletjournal.py +35 -32
- ledger/tests/test_models/test_general.py +44 -11
- ledger/tests/test_models/test_planetary.py +14 -80
- ledger/tests/test_templatetags.py +2 -7
- ledger/tests/test_views/corporation/test_add_corp.py +16 -35
- ledger/tests/test_views/corporation/test_delete_corporation.py +66 -42
- ledger/tests/test_views/test_access.py +512 -545
- ledger/tests/test_views/test_add_ally.py +57 -46
- ledger/tests/test_views/test_add_char.py +21 -33
- ledger/tests/test_views/test_delete_character.py +24 -21
- ledger/tests/testdata/README_ESI_STUB.md +430 -0
- ledger/tests/testdata/esi_stub_openapi.py +511 -0
- ledger/tests/testdata/integrations/__init__.py +0 -0
- ledger/tests/testdata/{load_eveuniverse.py → integrations/eveuniverse.py} +0 -1
- ledger/tests/testdata/integrations/planetary.py +13 -0
- ledger/tests/testdata/json/factory.json +281 -0
- ledger/tests/testdata/json/inactive.json +281 -0
- ledger/tests/testdata/json/pins.json +175 -272
- ledger/tests/testdata/json/route.json +95 -528
- ledger/tests/testdata/test_esi_stub.py +468 -0
- ledger/tests/testdata/utils.py +601 -0
- ledger/thirdparty/charlink_hook.py +60 -30
- ledger/urls.py +0 -135
- ledger/views/alliance/add_ally.py +2 -4
- ledger/views/alliance/alliance_ledger.py +64 -147
- ledger/views/character/add_char.py +8 -10
- ledger/views/character/character_ledger.py +60 -126
- ledger/views/character/planetary.py +5 -98
- ledger/views/corporation/add_corp.py +10 -12
- ledger/views/corporation/corporation_ledger.py +65 -327
- ledger/views/index.py +92 -30
- aa_ledger-1.0.3.dist-info/RECORD +0 -236
- ledger/api/api_helper/planetary_helper.py +0 -107
- ledger/api/ledger/__init__.py +0 -7
- ledger/api/ledger/planetary.py +0 -231
- ledger/helpers/alliance.py +0 -317
- ledger/helpers/character.py +0 -251
- ledger/helpers/core.py +0 -665
- ledger/helpers/corporation.py +0 -427
- ledger/helpers/data_exporter.py +0 -452
- ledger/static/ledger/js/planetary-confirm.js +0 -66
- ledger/static/ledger/js/planetary.js +0 -143
- ledger/templates/ledger/admin.html +0 -43
- ledger/templates/ledger/allyledger/admin/alliance_administration.html +0 -46
- ledger/templates/ledger/allyledger/admin/alliance_overview.html +0 -108
- ledger/templates/ledger/allyledger/alliance_ledger.html +0 -86
- ledger/templates/ledger/bundles/character-ledger-bundles.html +0 -66
- ledger/templates/ledger/bundles/corporation-ledger-bundles.html +0 -75
- ledger/templates/ledger/bundles/ledger-bundles.html +0 -23
- ledger/templates/ledger/bundles/ledger-css.html +0 -3
- ledger/templates/ledger/bundles/planetary-bundles.html +0 -50
- ledger/templates/ledger/bundles/table-css.html +0 -3
- ledger/templates/ledger/charledger/admin/character_administration.html +0 -39
- ledger/templates/ledger/charledger/admin/character_overview.html +0 -106
- ledger/templates/ledger/charledger/character_ledger.html +0 -94
- ledger/templates/ledger/charledger/planetary/admin/planetary_overview.html +0 -123
- ledger/templates/ledger/charledger/planetary/planetary_ledger.html +0 -54
- ledger/templates/ledger/corpledger/admin/corporation_administration.html +0 -39
- ledger/templates/ledger/corpledger/admin/corporation_overview.html +0 -108
- ledger/templates/ledger/corpledger/corporation_ledger.html +0 -129
- ledger/templates/ledger/data-export.html +0 -78
- ledger/templates/ledger/error.html +0 -31
- ledger/templates/ledger/partials/form/error-message.html +0 -1
- ledger/templates/ledger/partials/information/daily.html +0 -56
- ledger/templates/ledger/partials/information/day.html +0 -48
- ledger/templates/ledger/partials/information/error.html +0 -8
- ledger/templates/ledger/partials/information/hourly.html +0 -53
- ledger/templates/ledger/partials/information/summary.html +0 -88
- ledger/templates/ledger/partials/information/view_character_content.html +0 -35
- ledger/templates/ledger/partials/modal/switchalarm_confirm.html +0 -39
- ledger/templates/ledger/partials/modal/view_extractor.html +0 -48
- ledger/templates/ledger/partials/modal/view_factory.html +0 -123
- ledger/templates/ledger/partials/table/char-ledger.html +0 -85
- ledger/templates/ledger/partials/table/corp-ledger.html +0 -66
- ledger/templates/ledger/partials/table/planetary.html +0 -18
- ledger/templates/ledger/partials/thirdparty/billboard.html +0 -22
- ledger/templates/ledger/partials/view/card.html +0 -160
- ledger/templates/ledger/permission.html +0 -2
- ledger/tests/test_helpers/test_billboard.py +0 -11
- ledger/tests/test_helpers/test_data_exporter.py +0 -207
- ledger/tests/test_tasks.py +0 -282
- ledger/tests/test_view_helpers/test_core.py +0 -47
- ledger/tests/test_views/corporation/test_corporation.py +0 -267
- ledger/tests/test_views/test_planetary.py +0 -137
- ledger/tests/testdata/esi_stub.py +0 -109
- ledger/tests/testdata/esi_stub_migration.py +0 -80
- ledger/tests/testdata/generate_characteraudit.py +0 -106
- ledger/tests/testdata/generate_corporationaudit.py +0 -74
- ledger/tests/testdata/generate_events.py +0 -31
- ledger/tests/testdata/generate_miningledger.py +0 -13
- ledger/tests/testdata/generate_planets.py +0 -48
- ledger/tests/testdata/generate_walletjournal.py +0 -42
- ledger/tests/testdata/json/czarno-pins.json +0 -240
- ledger/tests/testdata/json/czarno-routes.json +0 -165
- ledger/tests/testdata/json/pins2.json +0 -538
- {aa_ledger-1.0.3.dist-info → aa_ledger-2.0.0.dist-info}/licenses/LICENSE +0 -0
- /ledger/{tests/test_view_helpers → api/helpers}/__init__.py +0 -0
- /ledger/templates/ledger/bundles/{ally-administration-bundles.html → view-alliance-administration-js.html} +0 -0
- /ledger/templates/ledger/bundles/{char-administration-bundles.html → view-character-administration-js.html} +0 -0
- /ledger/templates/ledger/bundles/{corp-administration-bundles.html → view-corporation-administration-js.html} +0 -0
- /ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance.html +0 -0
- /ledger/tests/testdata/{esi.json → esi_test_data.json} +0 -0
- /ledger/tests/testdata/{allianceauth.json → integrations/allianceauth.json} +0 -0
- /ledger/tests/testdata/{load_allianceauth.py → integrations/allianceauth.py} +0 -0
- /ledger/tests/testdata/{eveentity.json → integrations/eveentity.json} +0 -0
- /ledger/tests/testdata/{load_eveentity.py → integrations/eveentity.py} +0 -0
- /ledger/tests/testdata/{eveuniverse.json → integrations/eveuniverse.json} +0 -0
- /ledger/tests/testdata/{planetary.json → integrations/planetary.json} +0 -0
ledger/api/character.py
ADDED
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
# Standard Library
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
|
|
4
|
+
# Third Party
|
|
5
|
+
from ninja import NinjaAPI, Schema
|
|
6
|
+
|
|
7
|
+
# Django
|
|
8
|
+
from django.contrib.humanize.templatetags.humanize import intcomma
|
|
9
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
10
|
+
from django.db.models import Q, QuerySet
|
|
11
|
+
from django.utils import timezone
|
|
12
|
+
from django.utils.translation import gettext as _
|
|
13
|
+
|
|
14
|
+
# Alliance Auth
|
|
15
|
+
from allianceauth.services.hooks import get_extension_logger
|
|
16
|
+
|
|
17
|
+
# AA Ledger
|
|
18
|
+
from ledger import __title__
|
|
19
|
+
from ledger.api.helpers.core import (
|
|
20
|
+
get_characterowner_or_none,
|
|
21
|
+
)
|
|
22
|
+
from ledger.api.helpers.icons import (
|
|
23
|
+
get_character_details_info_button,
|
|
24
|
+
get_ref_type_details_popover_button,
|
|
25
|
+
)
|
|
26
|
+
from ledger.api.schema import (
|
|
27
|
+
BillboardSchema,
|
|
28
|
+
CategorySchema,
|
|
29
|
+
CharacterLedgerSchema,
|
|
30
|
+
LedgerDetailsResponse,
|
|
31
|
+
LedgerDetailsSummary,
|
|
32
|
+
LedgerResponse,
|
|
33
|
+
OwnerLedgerRequestInfo,
|
|
34
|
+
OwnerSchema,
|
|
35
|
+
UpdateStatusSchema,
|
|
36
|
+
)
|
|
37
|
+
from ledger.helpers.billboard import BillboardSystem
|
|
38
|
+
from ledger.helpers.cache import CacheManager
|
|
39
|
+
from ledger.helpers.ledger_data import get_footer_text_class
|
|
40
|
+
from ledger.helpers.ref_type import RefTypeManager
|
|
41
|
+
from ledger.models.characteraudit import (
|
|
42
|
+
CharacterMiningLedger,
|
|
43
|
+
CharacterOwner,
|
|
44
|
+
CharacterWalletJournalEntry,
|
|
45
|
+
)
|
|
46
|
+
from ledger.providers import AppLogger
|
|
47
|
+
|
|
48
|
+
logger = AppLogger(get_extension_logger(__name__), __title__)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class LedgerCharacterSchema(Schema):
|
|
52
|
+
character: OwnerSchema
|
|
53
|
+
ledger: CharacterLedgerSchema
|
|
54
|
+
update_status: UpdateStatusSchema
|
|
55
|
+
actions: str = ""
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class CharacterLedgerResponse(LedgerResponse):
|
|
59
|
+
"""
|
|
60
|
+
Schema for Character Ledger Response.
|
|
61
|
+
|
|
62
|
+
This schema represents the response structure for a character's ledger,
|
|
63
|
+
extending the base :class:`LedgerResponse` to include character-specific information.
|
|
64
|
+
|
|
65
|
+
Attributes:
|
|
66
|
+
information (OwnerLedgerRequestInfo): Information about the ledger request.
|
|
67
|
+
characters (list[LedgerCharacterSchema]): List of character ledger data.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
information: OwnerLedgerRequestInfo
|
|
71
|
+
characters: list[LedgerCharacterSchema]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class CharacterApiEndpoints:
|
|
75
|
+
tags = ["Character"]
|
|
76
|
+
|
|
77
|
+
# pylint: disable=too-many-statements, function-redefined
|
|
78
|
+
# flake8: noqa: F811
|
|
79
|
+
def __init__(self, api: NinjaAPI):
|
|
80
|
+
self.cache_manager = CacheManager()
|
|
81
|
+
self.billboard = BillboardSystem()
|
|
82
|
+
|
|
83
|
+
@api.get(
|
|
84
|
+
"character/{character_id}/date/{year}/",
|
|
85
|
+
response={200: CharacterLedgerResponse, 403: dict, 404: dict},
|
|
86
|
+
tags=self.tags,
|
|
87
|
+
)
|
|
88
|
+
def get_character_ledger(request: WSGIRequest, character_id: int, year: int):
|
|
89
|
+
"""Get the ledger for a character for a specific year. Admin Endpoint."""
|
|
90
|
+
return self._ledger_api_response(
|
|
91
|
+
request=request,
|
|
92
|
+
character_id=character_id,
|
|
93
|
+
year=year,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
@api.get(
|
|
97
|
+
"character/{character_id}/date/{year}/{month}/",
|
|
98
|
+
response={200: CharacterLedgerResponse, 403: dict, 404: dict},
|
|
99
|
+
tags=self.tags,
|
|
100
|
+
)
|
|
101
|
+
def get_character_ledger(
|
|
102
|
+
request: WSGIRequest, character_id: int, year: int, month: int
|
|
103
|
+
):
|
|
104
|
+
"""Get the ledger for a character for a specific year. Admin Endpoint."""
|
|
105
|
+
return self._ledger_api_response(
|
|
106
|
+
request=request,
|
|
107
|
+
character_id=character_id,
|
|
108
|
+
year=year,
|
|
109
|
+
month=month,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
@api.get(
|
|
113
|
+
"character/{character_id}/date/{year}/{month}/{day}/",
|
|
114
|
+
response={200: CharacterLedgerResponse, 403: dict, 404: dict},
|
|
115
|
+
tags=self.tags,
|
|
116
|
+
)
|
|
117
|
+
def get_character_ledger(
|
|
118
|
+
request: WSGIRequest,
|
|
119
|
+
character_id: int,
|
|
120
|
+
year: int,
|
|
121
|
+
month: int,
|
|
122
|
+
day: int,
|
|
123
|
+
):
|
|
124
|
+
"""Get the ledger for a character for a specific year. Admin Endpoint."""
|
|
125
|
+
return self._ledger_api_response(
|
|
126
|
+
request=request,
|
|
127
|
+
character_id=character_id,
|
|
128
|
+
year=year,
|
|
129
|
+
month=month,
|
|
130
|
+
day=day,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def _create_datatable_footer(
|
|
134
|
+
self,
|
|
135
|
+
characters: list[LedgerCharacterSchema],
|
|
136
|
+
request_info: OwnerLedgerRequestInfo,
|
|
137
|
+
) -> OwnerLedgerRequestInfo:
|
|
138
|
+
"""
|
|
139
|
+
Create the footer HTML for the Ledger datatable.
|
|
140
|
+
|
|
141
|
+
This Helper function creates the footer HTML for the Ledger datatable
|
|
142
|
+
by summing up the respective fields from the list of characters.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
characters (list[LedgerCharacterSchema]): The list of character ledger data.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
str: The generated footer HTML.
|
|
149
|
+
"""
|
|
150
|
+
total_bounty = sum(char.ledger.bounty for char in characters)
|
|
151
|
+
total_ess = sum(char.ledger.ess for char in characters)
|
|
152
|
+
total_mining = sum(char.ledger.mining for char in characters)
|
|
153
|
+
total_costs = sum(char.ledger.costs for char in characters)
|
|
154
|
+
total_miscellaneous = sum(char.ledger.miscellaneous for char in characters)
|
|
155
|
+
total_total = sum(char.ledger.total for char in characters)
|
|
156
|
+
|
|
157
|
+
# Generate Details Link
|
|
158
|
+
url = get_character_details_info_button(
|
|
159
|
+
character_id=request_info.owner_id,
|
|
160
|
+
request_info=request_info,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Skip Footer if no Totals
|
|
164
|
+
if total_total == 0:
|
|
165
|
+
return ""
|
|
166
|
+
|
|
167
|
+
info_title = _("This amount is displayed for information only")
|
|
168
|
+
info_html = f"""
|
|
169
|
+
<i class="fa-regular fa-circle-question"
|
|
170
|
+
data-bs-tooltip="aa-ledger" data-bs-placement="top"
|
|
171
|
+
title="{info_title}"
|
|
172
|
+
>
|
|
173
|
+
</i>
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
footer_html = f"""
|
|
177
|
+
<tr>
|
|
178
|
+
<th class="border-top">{_("Summary")}</th>
|
|
179
|
+
<th class="border-top text-end {get_footer_text_class(total_bounty)}">{intcomma(value=int(total_bounty), use_l10n=True)} ISK</th>
|
|
180
|
+
<th class="border-top text-end {get_footer_text_class(total_ess)}">{intcomma(value=int(total_ess), use_l10n=True)} ISK</th>
|
|
181
|
+
<th class="border-top text-end {get_footer_text_class(total_mining, mining=True)}">{intcomma(value=int(total_mining), use_l10n=True)} ISK {info_html}</th>
|
|
182
|
+
<th class="border-top text-end {get_footer_text_class(total_miscellaneous)}">{intcomma(value=int(total_miscellaneous), use_l10n=True)} ISK</th>
|
|
183
|
+
<th class="border-top text-end {get_footer_text_class(total_costs)}">{intcomma(value=int(total_costs), use_l10n=True)} ISK</th>
|
|
184
|
+
<th class="border-start border-top text-end {get_footer_text_class(total_total)}">{intcomma(value=int(total_total), use_l10n=True)} ISK</th>
|
|
185
|
+
<th class="border-top">{url}</th>
|
|
186
|
+
</tr>
|
|
187
|
+
"""
|
|
188
|
+
request_info.footer_html = footer_html
|
|
189
|
+
return request_info
|
|
190
|
+
|
|
191
|
+
# pylint: disable=too-many-locals
|
|
192
|
+
def generate_character_data(
|
|
193
|
+
self, owner: CharacterOwner, request_info: OwnerLedgerRequestInfo
|
|
194
|
+
) -> list[CharacterLedgerResponse]:
|
|
195
|
+
"""
|
|
196
|
+
Generate the ledger data for all alts of a character owner.
|
|
197
|
+
|
|
198
|
+
This Helper function generates the ledger data for all alts of a character owner
|
|
199
|
+
based on the provided date query.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
owner (CharacterOwner): The character owner object.
|
|
203
|
+
request_info (LedgerRequestInfo): The request information containing date and section details.
|
|
204
|
+
Returns:
|
|
205
|
+
list[LedgerCharacterSchema]: A list of ledger responses for each character.
|
|
206
|
+
"""
|
|
207
|
+
# Get All Alts for this Owner
|
|
208
|
+
characters = CharacterOwner.objects.filter(
|
|
209
|
+
eve_character__character_id__in=owner.alt_ids
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# Create Ledger Response for each Character
|
|
213
|
+
character_ledger_list: list[LedgerCharacterSchema] = []
|
|
214
|
+
for character in characters:
|
|
215
|
+
# Get Journal Data
|
|
216
|
+
wallet_journal = (
|
|
217
|
+
character.ledger_character_journal.filter(
|
|
218
|
+
**request_info.to_date_query(),
|
|
219
|
+
)
|
|
220
|
+
# Exclude Zero Amount Entries
|
|
221
|
+
.exclude(amount=Decimal("0.00"))
|
|
222
|
+
# Exclude Internal Donations between Alts
|
|
223
|
+
.exclude(
|
|
224
|
+
Q(ref_type="player_donation")
|
|
225
|
+
& (
|
|
226
|
+
Q(first_party__in=owner.alt_ids)
|
|
227
|
+
& Q(second_party__in=owner.alt_ids)
|
|
228
|
+
)
|
|
229
|
+
).order_by("-date")
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
mining_journal = character.ledger_character_mining.filter(
|
|
233
|
+
**request_info.to_date_query(),
|
|
234
|
+
).order_by("-date")
|
|
235
|
+
|
|
236
|
+
# Get IDs for Hashing
|
|
237
|
+
entry_ids = wallet_journal.values_list("entry_id", flat=True)
|
|
238
|
+
mining_pks = mining_journal.values_list("type_id", flat=True)
|
|
239
|
+
header_ids = list(entry_ids) + list(mining_pks)
|
|
240
|
+
|
|
241
|
+
# Skip Character if no Ledger Entries
|
|
242
|
+
if len(header_ids) == 0:
|
|
243
|
+
logger.debug(f"Skipping Character {character} - No Ledger Entries")
|
|
244
|
+
continue
|
|
245
|
+
|
|
246
|
+
# Add Character ID to header ids to ensure uniqueness
|
|
247
|
+
header_ids.append(character.eve_character.character_id)
|
|
248
|
+
|
|
249
|
+
# Create Ledger Hash
|
|
250
|
+
wallet_journal_hash = self.cache_manager.create_ledger_hash(header_ids)
|
|
251
|
+
|
|
252
|
+
# Get Cached Ledger if Available
|
|
253
|
+
response_ledger = self.cache_manager.get_cache_key(
|
|
254
|
+
key="character", ledger_hash=wallet_journal_hash
|
|
255
|
+
)
|
|
256
|
+
if response_ledger is False:
|
|
257
|
+
logger.debug(f"Ledger Cache Miss for Character: {character}")
|
|
258
|
+
|
|
259
|
+
# Aggregate Data
|
|
260
|
+
character_bounty = wallet_journal.aggregate_bounty()
|
|
261
|
+
character_ess = wallet_journal.aggregate_ess()
|
|
262
|
+
character_mining = mining_journal.aggregate_mining()
|
|
263
|
+
character_costs = wallet_journal.aggregate_costs()
|
|
264
|
+
character_miscellaneous = wallet_journal.aggregate_miscellaneous()
|
|
265
|
+
|
|
266
|
+
total = sum(
|
|
267
|
+
[
|
|
268
|
+
character_bounty,
|
|
269
|
+
character_ess,
|
|
270
|
+
character_miscellaneous,
|
|
271
|
+
character_costs,
|
|
272
|
+
]
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
response_ledger = LedgerCharacterSchema(
|
|
276
|
+
character=OwnerSchema(
|
|
277
|
+
character_id=character.eve_character.character_id,
|
|
278
|
+
character_name=character.eve_character.character_name,
|
|
279
|
+
icon=character.get_portrait(size=32, as_html=True),
|
|
280
|
+
),
|
|
281
|
+
ledger=CharacterLedgerSchema(
|
|
282
|
+
bounty=character_bounty,
|
|
283
|
+
ess=character_ess,
|
|
284
|
+
mining=character_mining,
|
|
285
|
+
costs=character_costs,
|
|
286
|
+
miscellaneous=character_miscellaneous,
|
|
287
|
+
total=total,
|
|
288
|
+
),
|
|
289
|
+
update_status=UpdateStatusSchema(
|
|
290
|
+
status=owner.get_status,
|
|
291
|
+
),
|
|
292
|
+
actions=get_character_details_info_button(
|
|
293
|
+
character_id=character.eve_character.character_id,
|
|
294
|
+
request_info=request_info,
|
|
295
|
+
section="single",
|
|
296
|
+
),
|
|
297
|
+
)
|
|
298
|
+
# Cache Ledger Response
|
|
299
|
+
self.cache_manager.set_cache_key(
|
|
300
|
+
key="character",
|
|
301
|
+
ledger_hash=wallet_journal_hash,
|
|
302
|
+
ledger_data=response_ledger,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# Add Character Ledger to List
|
|
306
|
+
character_ledger_list.append(response_ledger)
|
|
307
|
+
return character_ledger_list
|
|
308
|
+
|
|
309
|
+
# pylint: disable=too-many-locals
|
|
310
|
+
def generate_billboard_data(
|
|
311
|
+
self,
|
|
312
|
+
owner: CharacterOwner,
|
|
313
|
+
character_ledger_list: list[LedgerCharacterSchema],
|
|
314
|
+
request_info: OwnerLedgerRequestInfo,
|
|
315
|
+
) -> BillboardSchema:
|
|
316
|
+
"""
|
|
317
|
+
Generate the billboard data for the given character IDs.
|
|
318
|
+
|
|
319
|
+
This Helper function generates the billboard data for the given character IDs
|
|
320
|
+
based on the provided date query.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
character_ids (list[int]): The list of character IDs.
|
|
324
|
+
character_ledger_list (list[LedgerCharacterSchema]): The list of character ledger data.
|
|
325
|
+
request_info (LedgerRequestInfo): The request information containing date and section details.
|
|
326
|
+
Returns:
|
|
327
|
+
LedgerBillboard: The generated billboard data.
|
|
328
|
+
"""
|
|
329
|
+
# Get Wallet and Mining Journal Entries
|
|
330
|
+
wallet_journal = (
|
|
331
|
+
CharacterWalletJournalEntry.objects.filter(
|
|
332
|
+
character__eve_character__character_id__in=owner.alt_ids,
|
|
333
|
+
**request_info.to_date_query(),
|
|
334
|
+
)
|
|
335
|
+
# Exclude Zero Amount Entries
|
|
336
|
+
.exclude(amount=Decimal("0.00"))
|
|
337
|
+
# Exclude Internal Donations between Alts
|
|
338
|
+
.exclude(
|
|
339
|
+
Q(ref_type="player_donation")
|
|
340
|
+
& (Q(first_party__in=owner.alt_ids) & Q(second_party__in=owner.alt_ids))
|
|
341
|
+
).order_by("-date")
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
mining_journal = CharacterMiningLedger.objects.filter(
|
|
345
|
+
character__eve_character__character_id__in=owner.alt_ids,
|
|
346
|
+
**request_info.to_date_query(),
|
|
347
|
+
).order_by("-date")
|
|
348
|
+
|
|
349
|
+
# Get IDs for Hashing
|
|
350
|
+
entry_ids = wallet_journal.values_list("entry_id", flat=True)
|
|
351
|
+
mining_pks = mining_journal.values_list("type_id", flat=True)
|
|
352
|
+
header_ids = list(entry_ids) + list(mining_pks)
|
|
353
|
+
|
|
354
|
+
# Skip Character if no Ledger Entries
|
|
355
|
+
if len(header_ids) == 0:
|
|
356
|
+
logger.debug(
|
|
357
|
+
f"No Ledger Entries for Billboard Generation for Character IDs: {owner.alt_ids}"
|
|
358
|
+
)
|
|
359
|
+
return BillboardSchema()
|
|
360
|
+
|
|
361
|
+
# add character ids to header ids to ensure uniqueness
|
|
362
|
+
header_ids.extend(owner.alt_ids)
|
|
363
|
+
|
|
364
|
+
# Create Ledger Hash
|
|
365
|
+
wallet_journal_hash = self.cache_manager.create_ledger_hash(header_ids)
|
|
366
|
+
|
|
367
|
+
# Get Cached Billboard if Available
|
|
368
|
+
response_billboard = self.cache_manager.get_cache_key(
|
|
369
|
+
key="character-billboard", ledger_hash=wallet_journal_hash
|
|
370
|
+
)
|
|
371
|
+
if response_billboard is False:
|
|
372
|
+
logger.debug(f"Billboard Cache Miss for Character IDs: {owner.alt_ids}")
|
|
373
|
+
# Create Timelines
|
|
374
|
+
wallet_timeline = (
|
|
375
|
+
self.billboard.create_timeline(
|
|
376
|
+
journal=wallet_journal, request_info=request_info
|
|
377
|
+
)
|
|
378
|
+
.annotate_bounty_income()
|
|
379
|
+
.annotate_ess_income()
|
|
380
|
+
.annotate_miscellaneous()
|
|
381
|
+
)
|
|
382
|
+
mining_timeline = self.billboard.create_timeline(
|
|
383
|
+
journal=mining_journal, request_info=request_info
|
|
384
|
+
).annotate_mining(with_period=True)
|
|
385
|
+
|
|
386
|
+
# Generate XY Billboard
|
|
387
|
+
xy_results = self.billboard.create_or_update_results(wallet_timeline)
|
|
388
|
+
xy_results = self.billboard.add_category_to_xy_billboard(
|
|
389
|
+
xy_results, category="mining", queryset=mining_timeline
|
|
390
|
+
)
|
|
391
|
+
xy_billboard = self.billboard.create_xy_billboard(
|
|
392
|
+
results=xy_results, request_info=request_info
|
|
393
|
+
)
|
|
394
|
+
# Initialize Chord Billboard
|
|
395
|
+
chord_billboard = self.billboard.create_chord_billboard(
|
|
396
|
+
character_ledger_list
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
response_billboard = BillboardSchema(
|
|
400
|
+
xy_chart=xy_billboard,
|
|
401
|
+
chord_chart=chord_billboard,
|
|
402
|
+
)
|
|
403
|
+
# Cache Billboard Response
|
|
404
|
+
self.cache_manager.set_cache_key(
|
|
405
|
+
key="character-billboard",
|
|
406
|
+
ledger_hash=wallet_journal_hash,
|
|
407
|
+
ledger_data=response_billboard,
|
|
408
|
+
)
|
|
409
|
+
# Billboard Data Generation Logic Here
|
|
410
|
+
return response_billboard
|
|
411
|
+
|
|
412
|
+
# pylint: disable=too-many-positional-arguments
|
|
413
|
+
def _ledger_api_response(
|
|
414
|
+
self,
|
|
415
|
+
request,
|
|
416
|
+
character_id: int,
|
|
417
|
+
year: int,
|
|
418
|
+
month: int = None,
|
|
419
|
+
day: int = None,
|
|
420
|
+
) -> CharacterLedgerResponse | tuple[int, dict]:
|
|
421
|
+
"""
|
|
422
|
+
Helper function to generate ledger response for various date parameters.
|
|
423
|
+
|
|
424
|
+
This function consolidates the common logic for generating the ledger response
|
|
425
|
+
based on the provided date parameters (year, month, day) and section.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
request (WSGIRequest): The incoming request object.
|
|
429
|
+
character_id (int): The character ID.
|
|
430
|
+
year (int): The year for the ledger data.
|
|
431
|
+
month (int, optional): The month for the ledger data. Defaults to None.
|
|
432
|
+
day (int, optional): The day for the ledger data. Defaults to None.
|
|
433
|
+
section (str): The section type ('single' or 'summary').
|
|
434
|
+
|
|
435
|
+
Returns:
|
|
436
|
+
CharacterLedgerResponse | tuple[int, dict]: The ledger response or error tuple.
|
|
437
|
+
"""
|
|
438
|
+
|
|
439
|
+
perms, owner = get_characterowner_or_none(
|
|
440
|
+
request=request, character_id=character_id
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
if owner is None:
|
|
444
|
+
return 404, {"error": _("Character not found in Ledger.")}
|
|
445
|
+
|
|
446
|
+
if perms is False:
|
|
447
|
+
return 403, {
|
|
448
|
+
"error": _("You do not have permission to view this character.")
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
# Build Request Info
|
|
452
|
+
request_info = OwnerLedgerRequestInfo(
|
|
453
|
+
owner_id=owner.eve_character.character_id,
|
|
454
|
+
year=year,
|
|
455
|
+
month=month,
|
|
456
|
+
day=day,
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
# Generate Character Ledger Data
|
|
460
|
+
character_ledger_list = self.generate_character_data(
|
|
461
|
+
owner=owner,
|
|
462
|
+
request_info=request_info,
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
# Generate Billboard Data
|
|
466
|
+
billboard = self.generate_billboard_data(
|
|
467
|
+
owner=owner,
|
|
468
|
+
character_ledger_list=character_ledger_list,
|
|
469
|
+
request_info=request_info,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
# Update Request Info with Available Data
|
|
473
|
+
self._create_datatable_footer(
|
|
474
|
+
characters=character_ledger_list, request_info=request_info
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
response_ledger = CharacterLedgerResponse(
|
|
478
|
+
owner=OwnerSchema(
|
|
479
|
+
character_id=owner.eve_character.character_id,
|
|
480
|
+
character_name=owner.eve_character.character_name,
|
|
481
|
+
icon=owner.get_portrait(as_html=True),
|
|
482
|
+
),
|
|
483
|
+
information=request_info,
|
|
484
|
+
characters=character_ledger_list,
|
|
485
|
+
billboard=billboard,
|
|
486
|
+
actions=get_character_details_info_button(
|
|
487
|
+
character_id=owner.eve_character.character_id,
|
|
488
|
+
request_info=request_info,
|
|
489
|
+
),
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
return response_ledger
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class CharacterDetailsApiEndpoints:
|
|
496
|
+
tags = ["Character Details"]
|
|
497
|
+
|
|
498
|
+
# pylint: disable=too-many-statements, function-redefined
|
|
499
|
+
def __init__(self, api: NinjaAPI):
|
|
500
|
+
@api.get(
|
|
501
|
+
"character/{character_id}/date/{year}/section/{section}/view/details/",
|
|
502
|
+
response={200: LedgerDetailsResponse, 403: dict, 404: dict},
|
|
503
|
+
tags=self.tags,
|
|
504
|
+
)
|
|
505
|
+
def get_character_ledger_details(
|
|
506
|
+
request: WSGIRequest, character_id: int, year: int, section: str
|
|
507
|
+
):
|
|
508
|
+
return self._ledger_details_api_response(
|
|
509
|
+
request=request,
|
|
510
|
+
character_id=character_id,
|
|
511
|
+
year=year,
|
|
512
|
+
section=section,
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
@api.get(
|
|
516
|
+
"character/{character_id}/date/{year}/{month}/section/{section}/view/details/",
|
|
517
|
+
response={200: LedgerDetailsResponse, 403: dict, 404: dict},
|
|
518
|
+
tags=self.tags,
|
|
519
|
+
)
|
|
520
|
+
def get_character_ledger_details(
|
|
521
|
+
request: WSGIRequest, character_id: int, year: int, month: int, section: str
|
|
522
|
+
):
|
|
523
|
+
return self._ledger_details_api_response(
|
|
524
|
+
request=request,
|
|
525
|
+
character_id=character_id,
|
|
526
|
+
year=year,
|
|
527
|
+
month=month,
|
|
528
|
+
section=section,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
@api.get(
|
|
532
|
+
"character/{character_id}/date/{year}/{month}/{day}/section/{section}/view/details/",
|
|
533
|
+
response={200: LedgerDetailsResponse, 403: dict, 404: dict},
|
|
534
|
+
tags=self.tags,
|
|
535
|
+
)
|
|
536
|
+
def get_character_ledger_details(
|
|
537
|
+
request: WSGIRequest,
|
|
538
|
+
character_id: int,
|
|
539
|
+
year: int,
|
|
540
|
+
month: int,
|
|
541
|
+
day: int,
|
|
542
|
+
section: str,
|
|
543
|
+
):
|
|
544
|
+
return self._ledger_details_api_response(
|
|
545
|
+
request=request,
|
|
546
|
+
character_id=character_id,
|
|
547
|
+
year=year,
|
|
548
|
+
month=month,
|
|
549
|
+
day=day,
|
|
550
|
+
section=section,
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
def _create_datatable_footer(self, value: float) -> str:
|
|
554
|
+
"""Create the footer HTML for the datatable."""
|
|
555
|
+
footer_html = f"""
|
|
556
|
+
<tr>
|
|
557
|
+
<th>{_('Summary')}</th>
|
|
558
|
+
<th class="text-end {get_footer_text_class(value)}">{intcomma(value=int(value), use_l10n=True)} ISK</th>
|
|
559
|
+
<th></th>
|
|
560
|
+
</tr>
|
|
561
|
+
"""
|
|
562
|
+
return footer_html
|
|
563
|
+
|
|
564
|
+
# pylint: disable=too-many-locals
|
|
565
|
+
def _create_ledger_details(
|
|
566
|
+
self,
|
|
567
|
+
journal: QuerySet[CharacterWalletJournalEntry],
|
|
568
|
+
mining: QuerySet[CharacterMiningLedger],
|
|
569
|
+
request_info: OwnerLedgerRequestInfo,
|
|
570
|
+
) -> LedgerDetailsResponse:
|
|
571
|
+
"""
|
|
572
|
+
Generate the detailed ledger data for a character.
|
|
573
|
+
This Helper function generates the detailed ledger data for a character
|
|
574
|
+
based on the provided date query.
|
|
575
|
+
|
|
576
|
+
Args:
|
|
577
|
+
journal (QuerySet): The wallet journal entries.
|
|
578
|
+
mining (QuerySet): The mining ledger entries. Defaults to None.
|
|
579
|
+
request_info (LedgerRequestInfo): The request information containing date and section details.
|
|
580
|
+
Returns:
|
|
581
|
+
LedgerDetailsResponse: The generated ledger details response.
|
|
582
|
+
"""
|
|
583
|
+
ref_types = RefTypeManager.get_all_categories()
|
|
584
|
+
|
|
585
|
+
avg = request_info.day if request_info.day else timezone.now().day
|
|
586
|
+
if request_info.section == "summary":
|
|
587
|
+
avg = 365
|
|
588
|
+
|
|
589
|
+
monthly_list = []
|
|
590
|
+
daily_list = []
|
|
591
|
+
hourly_list = []
|
|
592
|
+
summary = 0
|
|
593
|
+
# Income/Cost Ref Types
|
|
594
|
+
for category in RefTypeManager.CategoryChoice:
|
|
595
|
+
category_ref_types = ref_types.get(category.value, [])
|
|
596
|
+
if not category_ref_types:
|
|
597
|
+
continue
|
|
598
|
+
for __, income_flag in (("income", True), ("cost", False)):
|
|
599
|
+
kind_label = _("Income from") if income_flag else _("Cost from")
|
|
600
|
+
name = _("%(kind)s %(category)s") % {
|
|
601
|
+
"category": category.label,
|
|
602
|
+
"kind": kind_label,
|
|
603
|
+
}
|
|
604
|
+
kwargs = {"ref_type": category_ref_types, "income": income_flag}
|
|
605
|
+
amount = journal.aggregate_ref_type(**kwargs)
|
|
606
|
+
if (income_flag and amount > 0) or (not income_flag and amount < 0):
|
|
607
|
+
monthly = CategorySchema(
|
|
608
|
+
name=name,
|
|
609
|
+
amount=amount,
|
|
610
|
+
average=amount / avg / 30,
|
|
611
|
+
average_tick=amount / avg / 30 / 20,
|
|
612
|
+
ref_types=get_ref_type_details_popover_button(
|
|
613
|
+
ref_types=category_ref_types
|
|
614
|
+
),
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
daily = CategorySchema(
|
|
618
|
+
name=name,
|
|
619
|
+
amount=amount / avg,
|
|
620
|
+
average=amount / avg / 30,
|
|
621
|
+
average_tick=amount / avg / 20,
|
|
622
|
+
ref_types=get_ref_type_details_popover_button(
|
|
623
|
+
ref_types=category_ref_types
|
|
624
|
+
),
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
hourly = CategorySchema(
|
|
628
|
+
name=name,
|
|
629
|
+
amount=amount / avg / 24,
|
|
630
|
+
average=amount / avg / 24 / 30,
|
|
631
|
+
average_tick=amount / avg / 24 / 20,
|
|
632
|
+
ref_types=get_ref_type_details_popover_button(
|
|
633
|
+
ref_types=category_ref_types
|
|
634
|
+
),
|
|
635
|
+
)
|
|
636
|
+
# Add Amounts
|
|
637
|
+
summary += amount
|
|
638
|
+
monthly_list.append(monthly)
|
|
639
|
+
daily_list.append(daily)
|
|
640
|
+
hourly_list.append(hourly)
|
|
641
|
+
|
|
642
|
+
# Mining Income from Mining Ledger Journal (Only as Information not counted in Summary)
|
|
643
|
+
mining_income = mining.aggregate_mining()
|
|
644
|
+
if mining_income > 0:
|
|
645
|
+
monthly_mining = CategorySchema(
|
|
646
|
+
name=_("Mining Income"),
|
|
647
|
+
amount=mining_income,
|
|
648
|
+
average=mining_income / avg / 30,
|
|
649
|
+
average_tick=mining_income / avg / 30 / 20,
|
|
650
|
+
ref_types=get_ref_type_details_popover_button(
|
|
651
|
+
ref_types=["mining"],
|
|
652
|
+
),
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
daily_mining = CategorySchema(
|
|
656
|
+
name=_("Mining Income"),
|
|
657
|
+
amount=mining_income,
|
|
658
|
+
average=mining_income / avg,
|
|
659
|
+
average_tick=mining_income / avg / 20,
|
|
660
|
+
ref_types=get_ref_type_details_popover_button(
|
|
661
|
+
ref_types=["mining"],
|
|
662
|
+
),
|
|
663
|
+
)
|
|
664
|
+
|
|
665
|
+
hourly_mining = CategorySchema(
|
|
666
|
+
name=_("Mining Income"),
|
|
667
|
+
amount=mining_income,
|
|
668
|
+
average=mining_income / avg / 24,
|
|
669
|
+
average_tick=mining_income / avg / 24 / 20,
|
|
670
|
+
ref_types=get_ref_type_details_popover_button(
|
|
671
|
+
ref_types=["mining"],
|
|
672
|
+
),
|
|
673
|
+
)
|
|
674
|
+
monthly_list.append(monthly_mining)
|
|
675
|
+
daily_list.append(daily_mining)
|
|
676
|
+
hourly_list.append(hourly_mining)
|
|
677
|
+
|
|
678
|
+
if summary == 0:
|
|
679
|
+
return None
|
|
680
|
+
|
|
681
|
+
return LedgerDetailsResponse(
|
|
682
|
+
summary=monthly_list,
|
|
683
|
+
daily=daily_list,
|
|
684
|
+
hourly=hourly_list,
|
|
685
|
+
total=LedgerDetailsSummary(
|
|
686
|
+
summary=self._create_datatable_footer(summary),
|
|
687
|
+
daily=self._create_datatable_footer(
|
|
688
|
+
summary / avg,
|
|
689
|
+
),
|
|
690
|
+
hourly=self._create_datatable_footer(
|
|
691
|
+
summary / avg / 24,
|
|
692
|
+
),
|
|
693
|
+
),
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
def create_character_details(
|
|
697
|
+
self,
|
|
698
|
+
owner: CharacterOwner,
|
|
699
|
+
request_info: OwnerLedgerRequestInfo,
|
|
700
|
+
) -> dict:
|
|
701
|
+
"""
|
|
702
|
+
Create the character amounts for the Information View.
|
|
703
|
+
"""
|
|
704
|
+
# Determine Character IDs based on Section
|
|
705
|
+
char_ids = (
|
|
706
|
+
owner.alt_ids
|
|
707
|
+
if request_info.section == "summary"
|
|
708
|
+
else [owner.eve_character.character_id]
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
wallet_journal = (
|
|
712
|
+
CharacterWalletJournalEntry.objects.filter(
|
|
713
|
+
character__eve_character__character_id__in=char_ids,
|
|
714
|
+
**request_info.to_date_query(),
|
|
715
|
+
)
|
|
716
|
+
# Exclude Zero Amount Entries
|
|
717
|
+
.exclude(amount=Decimal("0.00"))
|
|
718
|
+
# Exclude Internal Donations between Alts
|
|
719
|
+
.exclude(
|
|
720
|
+
Q(ref_type="player_donation")
|
|
721
|
+
& (Q(first_party__in=owner.alt_ids) & Q(second_party__in=owner.alt_ids))
|
|
722
|
+
).order_by("-date")
|
|
723
|
+
)
|
|
724
|
+
|
|
725
|
+
mining_journal = CharacterMiningLedger.objects.filter(
|
|
726
|
+
character__eve_character__character_id__in=char_ids,
|
|
727
|
+
**request_info.to_date_query(),
|
|
728
|
+
)
|
|
729
|
+
|
|
730
|
+
response_ledger_details: LedgerDetailsResponse = self._create_ledger_details(
|
|
731
|
+
journal=wallet_journal,
|
|
732
|
+
mining=mining_journal,
|
|
733
|
+
request_info=request_info,
|
|
734
|
+
)
|
|
735
|
+
return response_ledger_details
|
|
736
|
+
|
|
737
|
+
# pylint: disable=too-many-positional-arguments
|
|
738
|
+
def _ledger_details_api_response(
|
|
739
|
+
self,
|
|
740
|
+
request: WSGIRequest,
|
|
741
|
+
character_id: int,
|
|
742
|
+
year: int,
|
|
743
|
+
month: int = None,
|
|
744
|
+
day: int = None,
|
|
745
|
+
section: str = "summary",
|
|
746
|
+
):
|
|
747
|
+
"""
|
|
748
|
+
Helper function to generate ledger details response for various date parameters.
|
|
749
|
+
|
|
750
|
+
This function consolidates the common logic for generating the ledger details response
|
|
751
|
+
based on the provided date parameters character_id, (year, month, day) and section.
|
|
752
|
+
|
|
753
|
+
Args:
|
|
754
|
+
request (WSGIRequest): The incoming request object.
|
|
755
|
+
character_id (int): The character ID.
|
|
756
|
+
year (int): The year for the ledger data.
|
|
757
|
+
month (int, optional): The month for the ledger data. Defaults to None.
|
|
758
|
+
day (int, optional): The day for the ledger data. Defaults to None.
|
|
759
|
+
section (str): The section type ('single' or 'summary').
|
|
760
|
+
Returns:
|
|
761
|
+
LedgerDetailsResponse | tuple[int, dict]: The ledger details response or error tuple.
|
|
762
|
+
"""
|
|
763
|
+
perms, owner = get_characterowner_or_none(
|
|
764
|
+
request=request, character_id=character_id
|
|
765
|
+
)
|
|
766
|
+
|
|
767
|
+
if owner is None:
|
|
768
|
+
return 404, {"error": _("Character not found in Ledger.")}
|
|
769
|
+
|
|
770
|
+
if perms is False:
|
|
771
|
+
return 403, {
|
|
772
|
+
"error": _("You do not have permission to view this character.")
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
request_info = OwnerLedgerRequestInfo(
|
|
776
|
+
owner_id=owner.eve_character.character_id,
|
|
777
|
+
year=year,
|
|
778
|
+
month=month,
|
|
779
|
+
day=day,
|
|
780
|
+
section=section,
|
|
781
|
+
)
|
|
782
|
+
|
|
783
|
+
return self.create_character_details(
|
|
784
|
+
owner=owner,
|
|
785
|
+
request_info=request_info,
|
|
786
|
+
)
|